1 /* 2 * Copyright (c) 2016 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "dp_types.h" 20 #include "dp_rx.h" 21 #include "dp_peer.h" 22 #include "hal_rx.h" 23 #include "hal_api.h" 24 #include "qdf_nbuf.h" 25 #include <ieee80211.h> 26 27 #ifdef RXDMA_OPTIMIZATION 28 #define RX_BUFFER_ALIGNMENT 128 29 #else /* RXDMA_OPTIMIZATION */ 30 #define RX_BUFFER_ALIGNMENT 4 31 #endif /* RXDMA_OPTIMIZATION */ 32 33 #define RX_BUFFER_SIZE 2048 34 #define RX_BUFFER_RESERVATION 0 35 36 /* 37 * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs 38 * called during dp rx initialization 39 * and at the end of dp_rx_process. 40 * 41 * @soc: core txrx main context 42 * @mac_id: mac_id which is one of 3 mac_ids 43 * @desc_list: list of descs if called from dp_rx_process 44 * or NULL during dp rx initialization or out of buffer 45 * interrupt. 46 * @owner: who owns the nbuf (host, NSS etc...) 47 * Return: return success or failure 48 */ 49 QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, 50 uint32_t num_req_buffers, 51 union dp_rx_desc_list_elem_t **desc_list, 52 union dp_rx_desc_list_elem_t **tail, 53 uint8_t owner) 54 { 55 uint32_t num_alloc_desc; 56 uint16_t num_desc_to_free = 0; 57 struct dp_pdev *dp_pdev = dp_soc->pdev_list[mac_id]; 58 uint32_t num_entries_avail; 59 uint32_t count; 60 int sync_hw_ptr = 1; 61 qdf_dma_addr_t paddr; 62 qdf_nbuf_t rx_netbuf; 63 void *rxdma_ring_entry; 64 union dp_rx_desc_list_elem_t *next; 65 struct dp_srng *dp_rxdma_srng = &dp_pdev->rx_refill_buf_ring; 66 void *rxdma_srng = dp_rxdma_srng->hal_srng; 67 68 if (!rxdma_srng) { 69 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 70 "rxdma srng not initialized"); 71 return QDF_STATUS_E_FAILURE; 72 } 73 74 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 75 "requested %d buffers for replenish", num_req_buffers); 76 77 /* 78 * if desc_list is NULL, allocate the descs from freelist 79 */ 80 if (!(*desc_list)) { 81 num_alloc_desc = dp_rx_get_free_desc_list(dp_soc, mac_id, 82 num_req_buffers, 83 desc_list, 84 tail); 85 86 if (!num_alloc_desc) { 87 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 88 "no free rx_descs in freelist"); 89 return QDF_STATUS_E_NOMEM; 90 } 91 92 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 93 "%d rx desc allocated", num_alloc_desc); 94 num_req_buffers = num_alloc_desc; 95 } 96 97 hal_srng_access_start(dp_soc->hal_soc, rxdma_srng); 98 num_entries_avail = hal_srng_src_num_avail(dp_soc->hal_soc, 99 rxdma_srng, 100 sync_hw_ptr); 101 102 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 103 "no of availble entries in rxdma ring: %d", 104 num_entries_avail); 105 106 if (num_entries_avail < num_req_buffers) { 107 num_desc_to_free = num_req_buffers - num_entries_avail; 108 num_req_buffers = num_entries_avail; 109 } 110 111 for (count = 0; count < num_req_buffers; count++) { 112 rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc, 113 rxdma_srng); 114 115 rx_netbuf = qdf_nbuf_alloc(dp_pdev->osif_pdev, 116 RX_BUFFER_SIZE, 117 RX_BUFFER_RESERVATION, 118 RX_BUFFER_ALIGNMENT, 119 FALSE); 120 121 qdf_nbuf_map_single(dp_soc->osdev, rx_netbuf, 122 QDF_DMA_BIDIRECTIONAL); 123 124 paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0); 125 126 next = (*desc_list)->next; 127 128 (*desc_list)->rx_desc.nbuf = rx_netbuf; 129 hal_rxdma_buff_addr_info_set(rxdma_ring_entry, paddr, 130 (*desc_list)->rx_desc.cookie, 131 owner); 132 133 *desc_list = next; 134 } 135 136 hal_srng_access_end(dp_soc->hal_soc, rxdma_srng); 137 138 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 139 "successfully replenished %d buffers", num_req_buffers); 140 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 141 "%d rx desc added back to free list", num_desc_to_free); 142 143 /* 144 * add any available free desc back to the free list 145 */ 146 if (*desc_list) 147 dp_rx_add_desc_list_to_free_list(dp_soc, desc_list, 148 tail, mac_id); 149 150 return QDF_STATUS_SUCCESS; 151 } 152 153 /** 154 * dp_rx_intrabss_fwd() - Implements the Intra-BSS forwarding logic 155 * 156 * @soc: core txrx main context 157 * @rx_desc : Rx descriptor 158 * @msdu_ifno : place holder to store Rx MSDU Details from Rx desc 159 * @osdu_ifno : place holder to store Rx MPDU Details from Rx desc 160 * @is_term: Value filled in by this function, if logic determines this 161 * to be a terminating packet 162 * 163 * Return: bool: true if it is forwarded else false 164 */ 165 static bool 166 dp_rx_intrabss_fwd(struct dp_soc *soc, 167 struct dp_rx_desc *rx_desc, 168 struct hal_rx_msdu_desc_info *msdu_info, 169 struct hal_rx_mpdu_desc_info *mpdu_info, 170 bool *is_term) 171 { 172 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 173 "%s %d : Intra-BSS forwarding not implemented", 174 __func__, __LINE__); 175 return false; 176 } 177 178 179 /** 180 * dp_rx_process() - Brain of the Rx processing functionality 181 * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) 182 * @soc: core txrx main context 183 * @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced 184 * @quota: No. of units (packets) that can be serviced in one shot. 185 * 186 * This function implements the core of Rx functionality. This is 187 * expected to handle only non-error frames. 188 * 189 * Return: uint32_t: No. of elements processed 190 */ 191 uint32_t 192 dp_rx_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) 193 { 194 void *hal_soc; 195 void *ring_desc; 196 struct dp_rx_desc *rx_desc; 197 qdf_nbuf_t nbuf; 198 union dp_rx_desc_list_elem_t *head = NULL; 199 union dp_rx_desc_list_elem_t *tail = NULL; 200 bool is_term; 201 uint32_t rx_bufs_used = 0, rx_buf_cookie, l2_hdr_offset; 202 uint16_t peer_id; 203 struct dp_peer *peer = NULL; 204 struct hal_rx_msdu_desc_info msdu_desc_info; 205 struct hal_rx_mpdu_desc_info mpdu_desc_info; 206 qdf_nbuf_t head_msdu, tail_msdu; 207 enum hal_reo_error_status error; 208 uint32_t pkt_len; 209 210 /* Debug -- Remove later */ 211 qdf_assert(soc && hal_ring); 212 213 hal_soc = soc->hal_soc; 214 215 /* Debug -- Remove later */ 216 qdf_assert(hal_soc); 217 218 if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) { 219 220 /* 221 * Need API to convert from hal_ring pointer to 222 * Ring Type / Ring Id combo 223 */ 224 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 225 "%s %d : HAL RING Access Failed -- %p\n", 226 __func__, __LINE__, hal_ring); 227 hal_srng_access_end(hal_soc, hal_ring); 228 goto done; 229 } 230 231 head_msdu = tail_msdu = NULL; 232 233 while (qdf_likely((ring_desc = 234 hal_srng_dst_get_next(hal_soc, hal_ring)) 235 && quota--)) { 236 237 error = HAL_RX_ERROR_STATUS_GET(ring_desc); 238 239 if (qdf_unlikely(error == HAL_REO_ERROR_DETECTED)) { 240 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 241 "%s %d : HAL RING 0x%p:error %d\n", 242 __func__, __LINE__, hal_ring, error); 243 /* Don't know how to deal with this -- assert */ 244 qdf_assert(0); 245 } 246 247 rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc); 248 249 rx_desc = dp_rx_cookie_2_va(soc, rx_buf_cookie); 250 251 qdf_assert(rx_desc); 252 253 rx_bufs_used++; 254 255 /* Get MSDU DESC info */ 256 hal_rx_msdu_desc_info_get(ring_desc, &msdu_desc_info); 257 258 nbuf = rx_desc->nbuf; 259 /* TODO */ 260 /* 261 * Need a separate API for unmapping based on 262 * phyiscal address 263 */ 264 qdf_nbuf_unmap_single(soc->osdev, nbuf, 265 QDF_DMA_BIDIRECTIONAL); 266 267 rx_desc->rx_buf_start = qdf_nbuf_data(nbuf); 268 269 /* 270 * HW structures call this L3 header padding -- even though 271 * this is actually the offset from the buffer beginning 272 * where the L2 header begins. 273 */ 274 l2_hdr_offset = 275 hal_rx_msdu_end_l3_hdr_padding_get( 276 rx_desc->rx_buf_start); 277 278 pkt_len = msdu_desc_info.msdu_len + 279 l2_hdr_offset + RX_PKT_TLVS_LEN; 280 281 /* Set length in nbuf */ 282 qdf_nbuf_set_pktlen(nbuf, pkt_len); 283 284 /* 285 * Check if DMA completed -- msdu_done is the last bit 286 * to be written 287 */ 288 if (!hal_rx_attn_msdu_done_get(rx_desc->rx_buf_start)) { 289 290 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 291 "%s %d : HAL RING 0x%p\n", 292 __func__, __LINE__, hal_ring); 293 294 print_hex_dump(KERN_ERR, 295 "\t Pkt Desc:", DUMP_PREFIX_NONE, 32, 4, 296 rx_desc->rx_buf_start, 128, false); 297 298 qdf_assert(0); 299 } 300 301 /* 302 * Advance the packet start pointer by total size of 303 * pre-header TLV's 304 */ 305 qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); 306 307 if (l2_hdr_offset) 308 qdf_nbuf_pull_head(nbuf, l2_hdr_offset); 309 310 /* TODO -- Remove -- Just for initial debug */ 311 312 print_hex_dump(KERN_ERR, "\t Pkt Buf:", 313 DUMP_PREFIX_NONE, 32, 4, 314 qdf_nbuf_data(nbuf), 128, false); 315 316 /* Get the MPDU DESC info */ 317 hal_rx_mpdu_info_get(ring_desc, &mpdu_desc_info); 318 319 /* TODO */ 320 /* WDS Source Port Learning */ 321 322 /* Intrabss-fwd */ 323 if (dp_rx_intrabss_fwd(soc, rx_desc, 324 &msdu_desc_info, &mpdu_desc_info, &is_term)) 325 continue; /* Get next descriptor */ 326 327 peer_id = DP_PEER_METADATA_PEER_ID_GET( 328 mpdu_desc_info.peer_meta_data); 329 330 peer = dp_peer_find_by_id(soc, peer_id); 331 332 /* TODO */ 333 /* 334 * In case of roaming peer object may not be 335 * immediately available -- need to handle this 336 * Cannot drop these packets right away. 337 */ 338 /* Peer lookup failed */ 339 if (!peer) { 340 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 341 "%s %d : peer look-up failed peer id %d\n", 342 __func__, __LINE__, peer_id); 343 344 /* Drop & free packet */ 345 qdf_nbuf_free(rx_desc->nbuf); 346 347 /* Statistics */ 348 349 /* Add free rx_desc to a free list */ 350 dp_rx_add_to_free_desc_list(&head, &tail, rx_desc); 351 352 continue; 353 } 354 355 if (qdf_unlikely(!head_msdu)) 356 head_msdu = rx_desc->nbuf; 357 else 358 qdf_nbuf_set_next(tail_msdu, rx_desc->nbuf); 359 360 tail_msdu = rx_desc->nbuf; 361 362 dp_rx_add_to_free_desc_list(&head, &tail, rx_desc); 363 } 364 365 hal_srng_access_end(hal_soc, hal_ring); 366 367 if (!head_msdu) 368 return 0; 369 370 /* Replenish buffers */ 371 /* Assume MAC id = 0, owner = 0 */ 372 dp_rx_buffers_replenish(soc, 0, rx_bufs_used, &head, &tail, 373 HAL_RX_BUF_RBM_SW3_BM); 374 375 qdf_nbuf_set_next(tail_msdu, NULL); 376 377 378 /* 379 * TODO - this assumes all packets reaped belong to one peer/vdev, which 380 * may not be true, call this inside while loop for each change in vdev 381 */ 382 if (qdf_likely(peer->vdev->osif_rx)) 383 peer->vdev->osif_rx(peer->vdev->osif_vdev, head_msdu); 384 385 done: 386 return rx_bufs_used; /* Assume no scale factor for now */ 387 } 388 389 /** 390 * dp_rx_detach() - detach dp rx 391 * @soc: core txrx main context 392 * 393 * This function will detach DP RX into main device context 394 * will free DP Rx resources. 395 * 396 * Return: void 397 */ 398 void 399 dp_rx_pdev_detach(struct dp_pdev *pdev) 400 { 401 uint8_t pdev_id = pdev->pdev_id; 402 struct dp_soc *soc = pdev->soc; 403 404 dp_rx_desc_pool_free(soc, pdev_id); 405 qdf_spinlock_destroy(&soc->rx_desc_mutex[pdev_id]); 406 } 407 408 /** 409 * dp_rx_attach() - attach DP RX 410 * @soc: core txrx main context 411 * 412 * This function will attach a DP RX instance into the main 413 * device (SOC) context. Will allocate dp rx resource and 414 * initialize resources. 415 * 416 * Return: QDF_STATUS_SUCCESS: success 417 * QDF_STATUS_E_RESOURCES: Error return 418 */ 419 QDF_STATUS 420 dp_rx_pdev_attach(struct dp_pdev *pdev) 421 { 422 uint8_t pdev_id = pdev->pdev_id; 423 struct dp_soc *soc = pdev->soc; 424 struct dp_srng rxdma_srng; 425 uint32_t rxdma_entries; 426 union dp_rx_desc_list_elem_t *desc_list = NULL; 427 union dp_rx_desc_list_elem_t *tail = NULL; 428 429 qdf_spinlock_create(&soc->rx_desc_mutex[pdev_id]); 430 pdev = soc->pdev_list[pdev_id]; 431 rxdma_srng = pdev->rx_refill_buf_ring; 432 433 rxdma_entries = rxdma_srng.alloc_size/hal_srng_get_entrysize( 434 soc->hal_soc, RXDMA_BUF); 435 dp_rx_desc_pool_alloc(soc, pdev_id); 436 437 /* For Rx buffers, WBM release ring is SW RING 3,for all pdev's */ 438 dp_rx_buffers_replenish(soc, pdev_id, rxdma_entries, 439 &desc_list, &tail, HAL_RX_BUF_RBM_SW3_BM); 440 441 return QDF_STATUS_SUCCESS; 442 } 443