qcacmn: fix rx path dma-inv-range, unmap-single issues
In case of duplicated rx descriptors from hardware,
it will hit issues in __dma_inv_range(), __qdf_nbuf_unmap_single.
Detect the duplicates, skip processing them, drop the mpdu.
CRs-Fixed: 2413816
Change-Id: I7efd4b0c1bda5578578927bb22fe9d487758897d
diff --git a/dp/wifi3.0/dp_rx_mon_dest.c b/dp/wifi3.0/dp_rx_mon_dest.c
index b38d469..d297767 100644
--- a/dp/wifi3.0/dp_rx_mon_dest.c
+++ b/dp/wifi3.0/dp_rx_mon_dest.c
@@ -273,6 +273,7 @@
bool is_frag, is_first_msdu;
bool drop_mpdu = false;
uint8_t bm_action = HAL_BM_ACTION_PUT_IN_IDLE_LIST;
+ uint64_t nbuf_paddr = 0;
msdu = 0;
@@ -318,22 +319,30 @@
uint32_t l2_hdr_offset;
struct dp_rx_desc *rx_desc = NULL;
- /* WAR for duplicate buffers received from HW */
- if (qdf_unlikely(dp_pdev->mon_last_buf_cookie ==
- msdu_list.sw_cookie[i])) {
- /* Skip duplicate buffer and drop subsequent
- * buffers in this MPDU
- */
- drop_mpdu = true;
- dp_pdev->rx_mon_stats.dup_mon_buf_cnt++;
- continue;
- }
rx_desc = dp_rx_get_mon_desc(soc,
msdu_list.sw_cookie[i]);
qdf_assert_always(rx_desc);
msdu = rx_desc->nbuf;
+ if (msdu)
+ nbuf_paddr = qdf_nbuf_get_frag_paddr(msdu, 0);
+ /* WAR for duplicate buffers received from HW */
+ if (qdf_unlikely(dp_pdev->mon_last_buf_cookie ==
+ msdu_list.sw_cookie[i] ||
+ !msdu ||
+ msdu_list.paddr[i] != nbuf_paddr ||
+ !rx_desc->in_use)) {
+ /* Skip duplicate buffer and drop subsequent
+ * buffers in this MPDU
+ */
+ drop_mpdu = true;
+ dp_pdev->rx_mon_stats.dup_mon_buf_cnt++;
+ dp_pdev->mon_last_linkdesc_paddr =
+ buf_info.paddr;
+ continue;
+ }
+
if (rx_desc->unmapped == 0) {
qdf_nbuf_unmap_single(soc->osdev, msdu,
QDF_DMA_FROM_DEVICE);
@@ -341,6 +350,8 @@
}
if (drop_mpdu) {
+ dp_pdev->mon_last_linkdesc_paddr =
+ buf_info.paddr;
qdf_nbuf_free(msdu);
msdu = NULL;
goto next_msdu;
diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h
index d3fa0bf..12c70a3 100644
--- a/hal/wifi3.0/hal_rx.h
+++ b/hal/wifi3.0/hal_rx.h
@@ -1941,6 +1941,8 @@
struct hal_rx_msdu_desc_info msdu_info[HAL_RX_NUM_MSDU_DESC];
uint32_t sw_cookie[HAL_RX_NUM_MSDU_DESC];
uint8_t rbm[HAL_RX_NUM_MSDU_DESC];
+ /* physical address of the msdu */
+ uint64_t paddr[HAL_RX_NUM_MSDU_DESC];
};
struct hal_buf_info {
@@ -2038,8 +2040,12 @@
msdu_list->sw_cookie[i] =
HAL_RX_BUF_COOKIE_GET(
&msdu_details[i].buffer_addr_info_details);
- msdu_list->rbm[i] = HAL_RX_BUF_RBM_GET(
+ msdu_list->rbm[i] = HAL_RX_BUF_RBM_GET(
&msdu_details[i].buffer_addr_info_details);
+ msdu_list->paddr[i] = HAL_RX_BUFFER_ADDR_31_0_GET(
+ &msdu_details[i].buffer_addr_info_details) |
+ (uint64_t)HAL_RX_BUFFER_ADDR_39_32_GET(
+ &msdu_details[i].buffer_addr_info_details) << 32;
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
"[%s][%d] i=%d sw_cookie=%d",
__func__, __LINE__, i, msdu_list->sw_cookie[i]);