diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index b504fa2ed3..01770ec11a 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -846,6 +846,12 @@ void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, void dp_2k_jump_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, uint16_t peer_id, uint8_t tid); +#define DP_RX_HEAD_APPEND(head, elem) \ + do { \ + qdf_nbuf_set_next((elem), (head)); \ + (head) = (elem); \ + } while (0) + #define DP_RX_LIST_APPEND(head, tail, elem) \ do { \ diff --git a/dp/wifi3.0/dp_rx_desc.c b/dp/wifi3.0/dp_rx_desc.c index d6943d5657..59eebb054b 100644 --- a/dp/wifi3.0/dp_rx_desc.c +++ b/dp/wifi3.0/dp_rx_desc.c @@ -148,22 +148,21 @@ union dp_rx_desc_list_elem_t *dp_rx_desc_find(uint16_t page_id, uint16_t offset, rx_desc_pool->elem_size * offset; } -static QDF_STATUS __dp_rx_desc_nbuf_free(struct dp_soc *soc, - struct rx_desc_pool *rx_desc_pool) +static QDF_STATUS dp_rx_desc_nbuf_collect(struct dp_soc *soc, + struct rx_desc_pool *rx_desc_pool, + qdf_nbuf_t *nbuf_unmap_list, + qdf_nbuf_t *nbuf_free_list) { uint32_t i, num_desc, page_id, offset, num_desc_per_page; union dp_rx_desc_list_elem_t *rx_desc_elem; struct dp_rx_desc *rx_desc; - qdf_nbuf_t nbuf; - if (qdf_unlikely(!(rx_desc_pool-> - desc_pages.cacheable_pages))) { + if (qdf_unlikely(!(rx_desc_pool->desc_pages.cacheable_pages))) { qdf_err("No pages found on this desc pool"); return QDF_STATUS_E_INVAL; } num_desc = rx_desc_pool->pool_size; - num_desc_per_page = - rx_desc_pool->desc_pages.num_element_per_page; + num_desc_per_page = rx_desc_pool->desc_pages.num_element_per_page; for (i = 0; i < num_desc; i++) { page_id = i / num_desc_per_page; offset = i % num_desc_per_page; @@ -171,47 +170,72 @@ static QDF_STATUS __dp_rx_desc_nbuf_free(struct dp_soc *soc, rx_desc = &rx_desc_elem->rx_desc; dp_rx_desc_free_dbg_info(rx_desc); if (rx_desc->in_use) { - nbuf = rx_desc->nbuf; if (!rx_desc->unmapped) { - dp_ipa_handle_rx_buf_smmu_mapping( - soc, nbuf, - rx_desc_pool->buf_size, - false); - qdf_nbuf_unmap_nbytes_single( - soc->osdev, - rx_desc->nbuf, - QDF_DMA_BIDIRECTIONAL, - rx_desc_pool->buf_size); + DP_RX_HEAD_APPEND(*nbuf_unmap_list, + rx_desc->nbuf); rx_desc->unmapped = 1; + } else { + DP_RX_HEAD_APPEND(*nbuf_free_list, + rx_desc->nbuf); } - qdf_nbuf_free(nbuf); } } - return QDF_STATUS_SUCCESS; } +static void dp_rx_desc_nbuf_cleanup(struct dp_soc *soc, + qdf_nbuf_t nbuf_unmap_list, + qdf_nbuf_t nbuf_free_list, + uint16_t buf_size) +{ + qdf_nbuf_t nbuf = nbuf_unmap_list; + qdf_nbuf_t next; + + while (nbuf) { + next = nbuf->next; + if (dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf, buf_size, + false)) + dp_info_rl("Unable to unmap nbuf: %pK", nbuf); + qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, + QDF_DMA_BIDIRECTIONAL, buf_size); + qdf_nbuf_free(nbuf); + nbuf = next; + } + + nbuf = nbuf_free_list; + while (nbuf) { + next = nbuf->next; + qdf_nbuf_free(nbuf); + nbuf = next; + } +} + void dp_rx_desc_nbuf_and_pool_free(struct dp_soc *soc, uint32_t pool_id, struct rx_desc_pool *rx_desc_pool) { - QDF_STATUS qdf_status; + qdf_nbuf_t nbuf_unmap_list = NULL; + qdf_nbuf_t nbuf_free_list = NULL; qdf_spin_lock_bh(&rx_desc_pool->lock); - qdf_status = __dp_rx_desc_nbuf_free(soc, rx_desc_pool); - if (QDF_IS_STATUS_SUCCESS(qdf_status)) - dp_rx_desc_pool_free(soc, rx_desc_pool); - + dp_rx_desc_nbuf_collect(soc, rx_desc_pool, + &nbuf_unmap_list, &nbuf_free_list); qdf_spin_unlock_bh(&rx_desc_pool->lock); - + dp_rx_desc_nbuf_cleanup(soc, nbuf_unmap_list, nbuf_free_list, + rx_desc_pool->buf_size); qdf_spinlock_destroy(&rx_desc_pool->lock); } void dp_rx_desc_nbuf_free(struct dp_soc *soc, struct rx_desc_pool *rx_desc_pool) { + qdf_nbuf_t nbuf_unmap_list = NULL; + qdf_nbuf_t nbuf_free_list = NULL; qdf_spin_lock_bh(&rx_desc_pool->lock); - __dp_rx_desc_nbuf_free(soc, rx_desc_pool); + dp_rx_desc_nbuf_collect(soc, rx_desc_pool, + &nbuf_unmap_list, &nbuf_free_list); qdf_spin_unlock_bh(&rx_desc_pool->lock); + dp_rx_desc_nbuf_cleanup(soc, nbuf_unmap_list, nbuf_free_list, + rx_desc_pool->buf_size); } void dp_rx_desc_pool_free(struct dp_soc *soc,