From e1d7e0ecc97db9e7b791c6547a80f0b1114b5cff Mon Sep 17 00:00:00 2001 From: Mohit Khanna Date: Fri, 9 Feb 2018 10:07:43 -0800 Subject: [PATCH] qcacmn: fix double unmap issue in monitor mode Currently while reaping the rxda destination ring in dp_rx_mon_mpdu_pop, we end up un-mapping the nbuf twice when - 1. msdu_ppdu_id > ppdu_id 2. msdu_ppdu_id = ppdu_id For case 1, we exit from the dp_rx_mon_mpdu_pop without reaping the descriptor completely, but we unmap the nbuf corresponding to it. Next, when case 2 happens, we end up un-mapping the nbuf again to reap the same descriptor. Introduce a flag in the rx_desc to keep track of un-mapping the nbuf. If the nbuf is already unmapped, donot unmap it. Change-Id: Icb64fbc00312d6d0e6d41f7b475eb1285530c3d0 CRs-Fixed: 2185301 --- dp/wifi3.0/dp_rx.h | 7 ++++++- dp/wifi3.0/dp_rx_mon_dest.c | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index afe6695af8d2..4d28e3a7f24c 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -61,6 +61,9 @@ * @pool_id : pool Id for which this allocated. * Can only be used if there is no flow * steering + * @in_use rx_desc is in use + * @unmapped used to mark rx_desc an unmapped if the corresponding + * nbuf is already unmapped */ struct dp_rx_desc { qdf_nbuf_t nbuf; @@ -70,7 +73,8 @@ struct dp_rx_desc { #ifdef RX_DESC_DEBUG_CHECK uint32_t magic; #endif - uint8_t in_use:1; + uint8_t in_use:1, + unmapped:1; }; #define RX_DESC_COOKIE_INDEX_SHIFT 0 @@ -325,6 +329,7 @@ void dp_rx_add_to_free_desc_list(union dp_rx_desc_list_elem_t **head, new->nbuf = NULL; new->in_use = 0; + new->unmapped = 0; ((union dp_rx_desc_list_elem_t *)new)->next = *head; *head = (union dp_rx_desc_list_elem_t *)new; diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c index cba079381bb6..c620f2a6bfc3 100644 --- a/dp/wifi3.0/dp_rx_mon_dest.c +++ b/dp/wifi3.0/dp_rx_mon_dest.c @@ -172,16 +172,14 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, qdf_assert(rx_desc); msdu = rx_desc->nbuf; - qdf_nbuf_unmap_single(soc->osdev, msdu, - QDF_DMA_FROM_DEVICE); + if (rx_desc->unmapped == 0) { + qdf_nbuf_unmap_single(soc->osdev, msdu, + QDF_DMA_FROM_DEVICE); + rx_desc->unmapped = 1; + } data = qdf_nbuf_data(msdu); - QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_DEBUG, - "[%s][%d] msdu_nbuf=%pK, data=%pK", - __func__, __LINE__, msdu, data); - rx_desc_tlv = HAL_RX_MON_DEST_GET_DESC(data); if (is_first_msdu) { @@ -191,16 +189,18 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, } QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_DEBUG, - "[%s][%d] i=%d, ppdu_id=%x, msdu_ppdu_id=%x", - __func__, __LINE__, i, *ppdu_id, msdu_ppdu_id); + QDF_TRACE_LEVEL_DEBUG, + "[%s][%d] i=%d, ppdu_id=%x, msdu_ppdu_id=%x last_ppdu_id=%x num msdus = %u", + __func__, __LINE__, i, + *ppdu_id, msdu_ppdu_id, last_ppdu_id, + num_msdus); if (*ppdu_id > msdu_ppdu_id) QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_WARN, - "[%s][%d] ppdu_id=%d msdu_ppdu_id=%d\n", - __func__, __LINE__, *ppdu_id, - msdu_ppdu_id); + QDF_TRACE_LEVEL_WARN, + "[%s][%d] ppdu_id=%d msdu_ppdu_id=%d", + __func__, __LINE__, *ppdu_id, + msdu_ppdu_id); if ((*ppdu_id < msdu_ppdu_id) && (*ppdu_id > last_ppdu_id)) {