1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #ifndef _DP_BE_RX_H_ 21 #define _DP_BE_RX_H_ 22 23 #include <dp_types.h> 24 #include "dp_be.h" 25 #include "dp_peer.h" 26 27 /* 28 * dp_be_intrabss_params 29 * 30 * @dest_soc: dest soc to forward the packet to 31 * @tx_vdev_id: vdev id retrieved from dest peer 32 */ 33 struct dp_be_intrabss_params { 34 struct dp_soc *dest_soc; 35 uint8_t tx_vdev_id; 36 }; 37 38 #ifndef QCA_HOST_MODE_WIFI_DISABLED 39 40 /* 41 * dp_rx_intrabss_fwd_be() - API for intrabss fwd. For EAPOL 42 * pkt with DA not equal to vdev mac addr, fwd is not allowed. 43 * @soc: core txrx main context 44 * @ta_txrx_peer: source peer entry 45 * @rx_tlv_hdr: start address of rx tlvs 46 * @nbuf: nbuf that has to be intrabss forwarded 47 * @msdu_metadata: msdu metadata 48 * 49 * Return: true if it is forwarded else false 50 */ 51 52 bool dp_rx_intrabss_fwd_be(struct dp_soc *soc, 53 struct dp_txrx_peer *ta_txrx_peer, 54 uint8_t *rx_tlv_hdr, 55 qdf_nbuf_t nbuf, 56 struct hal_rx_msdu_metadata msdu_metadata); 57 #endif 58 59 /* 60 * dp_rx_intrabss_handle_nawds_be() - Forward mcbc intrabss pkts in nawds case 61 * @soc: core txrx main context 62 * @ta_txrx_peer: source txrx_peer entry 63 * @nbuf_copy: nbuf that has to be intrabss forwarded 64 * @tid_stats: tid_stats structure 65 * 66 * Return: true if it is forwarded else false 67 */ 68 bool 69 dp_rx_intrabss_handle_nawds_be(struct dp_soc *soc, struct dp_txrx_peer *ta_peer, 70 qdf_nbuf_t nbuf_copy, 71 struct cdp_tid_rx_stats *tid_stats); 72 73 uint32_t dp_rx_process_be(struct dp_intr *int_ctx, 74 hal_ring_handle_t hal_ring_hdl, uint8_t reo_ring_num, 75 uint32_t quota); 76 77 /** 78 * dp_rx_desc_pool_init_be() - Initialize Rx Descriptor pool(s) 79 * @soc: Handle to DP Soc structure 80 * @rx_desc_pool: Rx descriptor pool handler 81 * @pool_id: Rx descriptor pool ID 82 * 83 * Return: QDF_STATUS_SUCCESS - succeeded, others - failed 84 */ 85 QDF_STATUS dp_rx_desc_pool_init_be(struct dp_soc *soc, 86 struct rx_desc_pool *rx_desc_pool, 87 uint32_t pool_id); 88 89 /** 90 * dp_rx_desc_pool_deinit_be() - De-initialize Rx Descriptor pool(s) 91 * @soc: Handle to DP Soc structure 92 * @rx_desc_pool: Rx descriptor pool handler 93 * @pool_id: Rx descriptor pool ID 94 * 95 * Return: None 96 */ 97 void dp_rx_desc_pool_deinit_be(struct dp_soc *soc, 98 struct rx_desc_pool *rx_desc_pool, 99 uint32_t pool_id); 100 101 /** 102 * dp_wbm_get_rx_desc_from_hal_desc_be() - Get corresponding Rx Desc 103 * address from WBM ring Desc 104 * @soc: Handle to DP Soc structure 105 * @ring_desc: ring descriptor structure pointer 106 * @r_rx_desc: pointer to a pointer of Rx Desc 107 * 108 * Return: QDF_STATUS_SUCCESS - succeeded, others - failed 109 */ 110 QDF_STATUS dp_wbm_get_rx_desc_from_hal_desc_be(struct dp_soc *soc, 111 void *ring_desc, 112 struct dp_rx_desc **r_rx_desc); 113 114 /** 115 * dp_rx_desc_cookie_2_va_be() - Convert RX Desc cookie ID to VA 116 * @soc:Handle to DP Soc structure 117 * @cookie: cookie used to lookup virtual address 118 * 119 * Return: Rx descriptor virtual address 120 */ 121 struct dp_rx_desc *dp_rx_desc_cookie_2_va_be(struct dp_soc *soc, 122 uint32_t cookie); 123 124 #if !defined(DP_FEATURE_HW_COOKIE_CONVERSION) || \ 125 defined(DP_HW_COOKIE_CONVERT_EXCEPTION) 126 /** 127 * dp_rx_desc_sw_cc_check() - check if RX desc VA is got correctly, 128 if not, do SW cookie conversion. 129 * @soc:Handle to DP Soc structure 130 * @rx_buf_cookie: RX desc cookie ID 131 * @r_rx_desc: double pointer for RX desc 132 * 133 * Return: None 134 */ 135 static inline void 136 dp_rx_desc_sw_cc_check(struct dp_soc *soc, 137 uint32_t rx_buf_cookie, 138 struct dp_rx_desc **r_rx_desc) 139 { 140 if (qdf_unlikely(!(*r_rx_desc))) { 141 *r_rx_desc = (struct dp_rx_desc *) 142 dp_cc_desc_find(soc, 143 rx_buf_cookie); 144 } 145 } 146 #else 147 static inline void 148 dp_rx_desc_sw_cc_check(struct dp_soc *soc, 149 uint32_t rx_buf_cookie, 150 struct dp_rx_desc **r_rx_desc) 151 { 152 } 153 #endif /* DP_FEATURE_HW_COOKIE_CONVERSION && DP_HW_COOKIE_CONVERT_EXCEPTION */ 154 155 #define DP_PEER_METADATA_OFFLOAD_GET_BE(_peer_metadata) (0) 156 157 #ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH 158 static inline uint16_t 159 dp_rx_peer_metadata_peer_id_get_be(struct dp_soc *soc, uint32_t peer_metadata) 160 { 161 struct htt_rx_peer_metadata_v1 *metadata = 162 (struct htt_rx_peer_metadata_v1 *)&peer_metadata; 163 uint16_t peer_id; 164 165 peer_id = metadata->peer_id | 166 (metadata->ml_peer_valid << soc->peer_id_shift); 167 168 return peer_id; 169 } 170 #else 171 /* Combine ml_peer_valid and peer_id field */ 172 #define DP_BE_PEER_METADATA_PEER_ID_MASK 0x00003fff 173 #define DP_BE_PEER_METADATA_PEER_ID_SHIFT 0 174 175 static inline uint16_t 176 dp_rx_peer_metadata_peer_id_get_be(struct dp_soc *soc, uint32_t peer_metadata) 177 { 178 return ((peer_metadata & DP_BE_PEER_METADATA_PEER_ID_MASK) >> 179 DP_BE_PEER_METADATA_PEER_ID_SHIFT); 180 } 181 #endif 182 183 static inline uint16_t 184 dp_rx_peer_metadata_vdev_id_get_be(struct dp_soc *soc, uint32_t peer_metadata) 185 { 186 struct htt_rx_peer_metadata_v1 *metadata = 187 (struct htt_rx_peer_metadata_v1 *)&peer_metadata; 188 189 return metadata->vdev_id; 190 } 191 192 static inline uint8_t 193 dp_rx_peer_metadata_lmac_id_get_be(uint32_t peer_metadata) 194 { 195 return HTT_RX_PEER_META_DATA_V1_LMAC_ID_GET(peer_metadata); 196 } 197 198 #ifdef WLAN_FEATURE_NEAR_FULL_IRQ 199 /** 200 * dp_rx_nf_process() - Near Full state handler for RX rings. 201 * @int_ctx: interrupt context 202 * @hal_ring_hdl: Rx ring handle 203 * @reo_ring_num: RX ring number 204 * @quota: Quota of work to be done 205 * 206 * Return: work done in the handler 207 */ 208 uint32_t dp_rx_nf_process(struct dp_intr *int_ctx, 209 hal_ring_handle_t hal_ring_hdl, 210 uint8_t reo_ring_num, 211 uint32_t quota); 212 #else 213 static inline 214 uint32_t dp_rx_nf_process(struct dp_intr *int_ctx, 215 hal_ring_handle_t hal_ring_hdl, 216 uint8_t reo_ring_num, 217 uint32_t quota) 218 { 219 return 0; 220 } 221 #endif /*WLAN_FEATURE_NEAR_FULL_IRQ */ 222 223 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 224 struct dp_soc * 225 dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id); 226 #else 227 static inline struct dp_soc * 228 dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id) 229 { 230 return soc; 231 } 232 #endif 233 234 #ifdef WLAN_FEATURE_11BE_MLO 235 /** 236 * dp_rx_mlo_igmp_handler() - Rx handler for Mcast packets 237 * @soc: Handle to DP Soc structure 238 * @vdev: DP vdev handle 239 * @peer: DP peer handle 240 * @nbuf: nbuf to be enqueued 241 * 242 * Return: true when packet sent to stack, false failure 243 */ 244 bool dp_rx_mlo_igmp_handler(struct dp_soc *soc, 245 struct dp_vdev *vdev, 246 struct dp_txrx_peer *peer, 247 qdf_nbuf_t nbuf); 248 249 /** 250 * dp_peer_rx_reorder_queue_setup() - Send reo queue setup wmi cmd to FW 251 per peer type 252 * @soc: DP Soc handle 253 * @peer: dp peer to operate on 254 * @tid: TID 255 * @ba_window_size: BlockAck window size 256 * 257 * Return: 0 - success, others - failure 258 */ 259 static inline 260 QDF_STATUS dp_peer_rx_reorder_queue_setup_be(struct dp_soc *soc, 261 struct dp_peer *peer, 262 int tid, 263 uint32_t ba_window_size) 264 { 265 uint8_t i; 266 struct dp_mld_link_peers link_peers_info; 267 struct dp_peer *link_peer; 268 struct dp_rx_tid *rx_tid; 269 struct dp_soc *link_peer_soc; 270 271 rx_tid = &peer->rx_tid[tid]; 272 if (!rx_tid->hw_qdesc_paddr) 273 return QDF_STATUS_E_INVAL; 274 275 if (!hal_reo_shared_qaddr_is_enable(soc->hal_soc)) { 276 if (IS_MLO_DP_MLD_PEER(peer)) { 277 /* get link peers with reference */ 278 dp_get_link_peers_ref_from_mld_peer(soc, peer, 279 &link_peers_info, 280 DP_MOD_ID_CDP); 281 /* send WMI cmd to each link peers */ 282 for (i = 0; i < link_peers_info.num_links; i++) { 283 link_peer = link_peers_info.link_peers[i]; 284 link_peer_soc = link_peer->vdev->pdev->soc; 285 if (link_peer_soc->cdp_soc.ol_ops-> 286 peer_rx_reorder_queue_setup) { 287 if (link_peer_soc->cdp_soc.ol_ops-> 288 peer_rx_reorder_queue_setup( 289 link_peer_soc->ctrl_psoc, 290 link_peer->vdev->pdev->pdev_id, 291 link_peer->vdev->vdev_id, 292 link_peer->mac_addr.raw, 293 rx_tid->hw_qdesc_paddr, 294 tid, tid, 295 1, ba_window_size)) { 296 dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n", 297 link_peer_soc, tid); 298 return QDF_STATUS_E_FAILURE; 299 } 300 } 301 } 302 /* release link peers reference */ 303 dp_release_link_peers_ref(&link_peers_info, 304 DP_MOD_ID_CDP); 305 } else if (peer->peer_type == CDP_LINK_PEER_TYPE) { 306 if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) { 307 if (soc->cdp_soc.ol_ops-> 308 peer_rx_reorder_queue_setup( 309 soc->ctrl_psoc, 310 peer->vdev->pdev->pdev_id, 311 peer->vdev->vdev_id, 312 peer->mac_addr.raw, 313 rx_tid->hw_qdesc_paddr, 314 tid, tid, 315 1, ba_window_size)) { 316 dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n", 317 soc, tid); 318 return QDF_STATUS_E_FAILURE; 319 } 320 } 321 } else { 322 dp_peer_err("invalid peer type %d", peer->peer_type); 323 return QDF_STATUS_E_FAILURE; 324 } 325 } else { 326 /* Some BE targets dont require WMI and use shared 327 * table managed by host for storing Reo queue ref structs 328 */ 329 if (IS_MLO_DP_LINK_PEER(peer) || 330 peer->peer_id == HTT_INVALID_PEER) { 331 /* Return if this is for MLD link peer and table 332 * is not used in MLD link peer case as MLD peer's 333 * qref is written to LUT in peer setup or peer map. 334 * At this point peer setup for link peer is called 335 * before peer map, hence peer id is not assigned. 336 * This could happen if peer_setup is called before 337 * host receives HTT peer map. In this case return 338 * success with no op and let peer map handle 339 * writing the reo_qref to LUT. 340 */ 341 dp_peer_debug("Invalid peer id for dp_peer:%pK", peer); 342 return QDF_STATUS_SUCCESS; 343 } 344 345 hal_reo_shared_qaddr_write(soc->hal_soc, 346 peer->peer_id, 347 tid, peer->rx_tid[tid].hw_qdesc_paddr); 348 } 349 return QDF_STATUS_SUCCESS; 350 } 351 #else 352 static inline 353 QDF_STATUS dp_peer_rx_reorder_queue_setup_be(struct dp_soc *soc, 354 struct dp_peer *peer, 355 int tid, 356 uint32_t ba_window_size) 357 { 358 struct dp_rx_tid *rx_tid = &peer->rx_tid[tid]; 359 360 if (!rx_tid->hw_qdesc_paddr) 361 return QDF_STATUS_E_INVAL; 362 363 if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) { 364 if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup( 365 soc->ctrl_psoc, 366 peer->vdev->pdev->pdev_id, 367 peer->vdev->vdev_id, 368 peer->mac_addr.raw, rx_tid->hw_qdesc_paddr, tid, tid, 369 1, ba_window_size)) { 370 dp_peer_err("%pK: Failed to send reo queue setup to FW - tid %d\n", 371 soc, tid); 372 return QDF_STATUS_E_FAILURE; 373 } 374 } 375 376 return QDF_STATUS_SUCCESS; 377 } 378 #endif /* WLAN_FEATURE_11BE_MLO */ 379 380 #ifdef QCA_DP_RX_NBUF_AND_NBUF_DATA_PREFETCH 381 static inline 382 void dp_rx_prefetch_nbuf_data_be(qdf_nbuf_t nbuf, qdf_nbuf_t next) 383 { 384 if (next) { 385 /* prefetch skb->next and first few bytes of skb->cb */ 386 qdf_prefetch(next); 387 /* skb->cb spread across 2 cache lines hence below prefetch */ 388 qdf_prefetch(&next->_skb_refdst); 389 qdf_prefetch(&next->len); 390 qdf_prefetch(&next->protocol); 391 qdf_prefetch(next->data); 392 qdf_prefetch(next->data + 64); 393 qdf_prefetch(next->data + 128); 394 } 395 } 396 #else 397 static inline 398 void dp_rx_prefetch_nbuf_data_be(qdf_nbuf_t nbuf, qdf_nbuf_t next) 399 { 400 } 401 #endif 402 #endif 403