From 59d63401a58ca6f5629415f9d59d77a7bc0c2381 Mon Sep 17 00:00:00 2001 From: Debasis Das Date: Fri, 7 Aug 2020 20:11:29 +0530 Subject: [PATCH] qcacmn: Use next link_desc instead of msdu_count MSDU count is not reliable in all cases.Hence it is better to check whether next_link_desc is valid or not and then free the MSDUs in the next descriptor and subsequently release both the current and next link descriptor back to HW. Change-Id: Ie5ea3be547f9aed6673293221f6b47661cd92cce --- dp/wifi3.0/dp_rx_err.c | 89 ++++++++++++++++++++++++++++++------------ hal/wifi3.0/hal_rx.h | 17 ++++++++ 2 files changed, 82 insertions(+), 24 deletions(-) diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 239d2b89fd..7ae3ab779c 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -297,19 +297,24 @@ dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc, uint8_t *rx_tlv_hdr; uint32_t tid; struct rx_desc_pool *rx_desc_pool; + struct dp_rx_desc *rx_desc; + /* First field in REO Dst ring Desc is buffer_addr_info */ + void *buf_addr_info = ring_desc; + struct buffer_addr_info cur_link_desc_addr_info = { 0 }; + struct buffer_addr_info next_link_desc_addr_info = { 0 }; hal_rx_reo_buf_paddr_get(ring_desc, &buf_info); link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info); +more_msdu_link_desc: /* No UNMAP required -- this is "malloc_consistent" memory */ hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list, &mpdu_desc_info->msdu_count); - for (i = 0; (i < mpdu_desc_info->msdu_count) && quota--; i++) { - struct dp_rx_desc *rx_desc = - dp_rx_cookie_2_va_rxdma_buf(soc, - msdu_list.sw_cookie[i]); + for (i = 0; (i < mpdu_desc_info->msdu_count); i++) { + rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, + msdu_list.sw_cookie[i]); qdf_assert_always(rx_desc); @@ -358,9 +363,38 @@ dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc, &pdev->free_list_tail, rx_desc); } - /* Return link descriptor through WBM ring (SW2WBM)*/ - dp_rx_link_desc_return(soc, ring_desc, HAL_BM_ACTION_PUT_IN_IDLE_LIST); + /* + * If the msdu's are spread across multiple link-descriptors, + * we cannot depend solely on the msdu_count(e.g., if msdu is + * spread across multiple buffers).Hence, it is + * necessary to check the next link_descriptor and release + * all the msdu's that are part of it. + */ + hal_rx_get_next_msdu_link_desc_buf_addr_info( + link_desc_va, + &next_link_desc_addr_info); + if (hal_rx_is_buf_addr_info_valid( + &next_link_desc_addr_info)) { + /* Clear the next link desc info for the current link_desc */ + hal_rx_clear_next_msdu_link_desc_buf_addr_info(link_desc_va); + + dp_rx_link_desc_return_by_addr(soc, buf_addr_info, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + hal_rx_buffer_addr_info_get_paddr( + &next_link_desc_addr_info, + &buf_info); + cur_link_desc_addr_info = next_link_desc_addr_info; + buf_addr_info = &cur_link_desc_addr_info; + + link_desc_va = + dp_rx_cookie_2_link_desc_va(soc, &buf_info); + + goto more_msdu_link_desc; + } + quota--; + dp_rx_link_desc_return_by_addr(soc, buf_addr_info, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); return rx_bufs_used; } @@ -588,28 +622,35 @@ process_next_msdu: tail_nbuf = NULL; } - if (msdu_processed < mpdu_desc_info->msdu_count) { - hal_rx_get_next_msdu_link_desc_buf_addr_info( - link_desc_va, - &next_link_desc_addr_info); + /* + * If the msdu's are spread across multiple link-descriptors, + * we cannot depend solely on the msdu_count(e.g., if msdu is + * spread across multiple buffers).Hence, it is + * necessary to check the next link_descriptor and release + * all the msdu's that are part of it. + */ + hal_rx_get_next_msdu_link_desc_buf_addr_info( + link_desc_va, + &next_link_desc_addr_info); - if (hal_rx_is_buf_addr_info_valid( + if (hal_rx_is_buf_addr_info_valid( &next_link_desc_addr_info)) { - dp_rx_link_desc_return_by_addr( - soc, - buf_addr_info, - HAL_BM_ACTION_PUT_IN_IDLE_LIST); + /* Clear the next link desc info for the current link_desc */ + hal_rx_clear_next_msdu_link_desc_buf_addr_info(link_desc_va); + dp_rx_link_desc_return_by_addr( + soc, + buf_addr_info, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); - hal_rx_buffer_addr_info_get_paddr( - &next_link_desc_addr_info, - &buf_info); - link_desc_va = - dp_rx_cookie_2_link_desc_va(soc, &buf_info); - cur_link_desc_addr_info = next_link_desc_addr_info; - buf_addr_info = &cur_link_desc_addr_info; + hal_rx_buffer_addr_info_get_paddr( + &next_link_desc_addr_info, + &buf_info); + link_desc_va = + dp_rx_cookie_2_link_desc_va(soc, &buf_info); + cur_link_desc_addr_info = next_link_desc_addr_info; + buf_addr_info = &cur_link_desc_addr_info; - goto more_msdu_link_desc; - } + goto more_msdu_link_desc; } dp_rx_link_desc_return_by_addr(soc, buf_addr_info, diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index 09c7286ecf..1ef460b529 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -3846,6 +3846,23 @@ void hal_rx_get_next_msdu_link_desc_buf_addr_info( *next_addr_info = msdu_link->next_msdu_link_desc_addr_info; } +/** + * hal_rx_clear_next_msdu_link_desc_buf_addr_info(): clear next msdu link desc + * buffer addr info + * @link_desc_va: pointer to current msdu link Desc + * + * return: None + */ +static inline +void hal_rx_clear_next_msdu_link_desc_buf_addr_info(void *link_desc_va) +{ + struct rx_msdu_link *msdu_link = link_desc_va; + + if (msdu_link) + qdf_mem_zero(&msdu_link->next_msdu_link_desc_addr_info, + sizeof(msdu_link->next_msdu_link_desc_addr_info)); +} + /** * hal_rx_is_buf_addr_info_valid(): check is the buf_addr_info valid *