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
This commit is contained in:
Mohit Khanna 2018-02-09 10:07:43 -08:00 • committed by snandini
commit e1d7e0ecc9
2 changed files with 20 additions and 15 deletions

View file

@ -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;

View file

@ -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)) {