Forráskód Böngészése

qcacmn: WAR for duplicate buffers in monitor mode

WAR to discard duplicate indications (buffers and link descriptors)
from monitor DMA seen sometimes on RXDMA2SW ring.

Change-Id: I687b782f54fbbf85ae932ee833ac9263b5879ca6
Karunakar Dasineni 6 éve
szülő
commit
700ad73754

+ 4 - 0
dp/inc/cdp_txrx_mon_struct.h

@@ -212,6 +212,8 @@ enum {
  * @status_ppdu_done: status ring PPDU done TLV count
  * @dest_ppdu_done: destination ring PPDU count
  * @dest_mpdu_done: destination ring MPDU count
+ * @dup_mon_linkdesc_cnt: duplicate link descriptor indications from HW
+ * @dup_mon_buf_cnt: duplicate buffer indications from HW
  */
 struct cdp_pdev_mon_stats {
 #ifndef REMOVE_MON_DBG_STATS
@@ -226,5 +228,7 @@ struct cdp_pdev_mon_stats {
 	uint32_t dest_ppdu_done;
 	uint32_t dest_mpdu_done;
 	uint32_t dest_mpdu_drop;
+	uint32_t dup_mon_linkdesc_cnt;
+	uint32_t dup_mon_buf_cnt;
 };
 #endif

+ 4 - 0
dp/wifi3.0/dp_main.c

@@ -5899,6 +5899,10 @@ dp_print_pdev_rx_mon_stats(struct dp_pdev *pdev)
 		       rx_mon_stats->dest_mpdu_done);
 	DP_PRINT_STATS("dest_mpdu_drop_cnt = %d",
 		       rx_mon_stats->dest_mpdu_drop);
+	DP_PRINT_STATS("dup_mon_linkdesc_cnt = %d",
+		       rx_mon_stats->dup_mon_linkdesc_cnt);
+	DP_PRINT_STATS("dup_mon_buf_cnt = %d",
+		       rx_mon_stats->dup_mon_buf_cnt);
 }
 
 /**

+ 3 - 0
dp/wifi3.0/dp_rx.h

@@ -88,6 +88,9 @@ struct dp_rx_desc {
 #define RX_DESC_COOKIE_POOL_ID_SHIFT		18
 #define RX_DESC_COOKIE_POOL_ID_MASK		0x1c0000
 
+#define DP_RX_DESC_COOKIE_MAX	\
+	(RX_DESC_COOKIE_INDEX_MASK | RX_DESC_COOKIE_POOL_ID_MASK)
+
 #define DP_RX_DESC_COOKIE_POOL_ID_GET(_cookie)		\
 	(((_cookie) & RX_DESC_COOKIE_POOL_ID_MASK) >>	\
 			RX_DESC_COOKIE_POOL_ID_SHIFT)

+ 27 - 5
dp/wifi3.0/dp_rx_mon_dest.c

@@ -242,6 +242,7 @@ struct dp_rx_desc *dp_rx_get_mon_desc(struct dp_soc *soc,
  * @ppdu_id: ppdu id of processing ppdu
  * @head: head of descs list to be freed
  * @tail: tail of decs list to be freed
+ *
  * Return: number of msdu in MPDU to be popped
  */
 static inline uint32_t
@@ -295,6 +296,13 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 	is_first_msdu = true;
 
 	do {
+		/* WAR for duplicate link descriptors received from HW */
+		if (qdf_unlikely(dp_pdev->mon_last_linkdesc_paddr ==
+		    buf_info.paddr)) {
+			dp_pdev->rx_mon_stats.dup_mon_linkdesc_cnt++;
+			return rx_bufs_used;
+		}
+
 		rx_msdu_link_desc =
 			dp_rx_cookie_2_mon_link_desc(dp_pdev,
 						     buf_info, mac_id);
@@ -306,12 +314,22 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 
 		for (i = 0; i < num_msdus; i++) {
 			uint32_t l2_hdr_offset;
-			struct dp_rx_desc *rx_desc =
-				dp_rx_get_mon_desc(soc,
-						   msdu_list.sw_cookie[i]);
+			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 (rx_desc->unmapped == 0) {
@@ -373,7 +391,8 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 					*ppdu_id = msdu_ppdu_id;
 					return rx_bufs_used;
 				}
-
+				dp_pdev->mon_last_linkdesc_paddr =
+					buf_info.paddr;
 			}
 
 			if (hal_rx_desc_is_first_msdu(rx_desc_tlv))
@@ -459,6 +478,7 @@ dp_rx_mon_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
 
 			last = msdu;
 next_msdu:
+			dp_pdev->mon_last_buf_cookie = msdu_list.sw_cookie[i];
 			rx_bufs_used++;
 			dp_rx_add_to_free_desc_list(head,
 				tail, rx_desc);
@@ -1410,6 +1430,8 @@ dp_rx_pdev_mon_attach(struct dp_pdev *pdev) {
 			return status;
 		}
 	}
+	pdev->mon_last_linkdesc_paddr = 0;
+	pdev->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
 	qdf_spinlock_create(&pdev->mon_lock);
 	return QDF_STATUS_SUCCESS;
 }

+ 4 - 0
dp/wifi3.0/dp_types.h

@@ -1193,6 +1193,10 @@ struct dp_pdev {
 	struct cdp_mon_status rx_mon_recv_status;
 	/* monitor mode status/destination ring PPDU and MPDU count */
 	struct cdp_pdev_mon_stats rx_mon_stats;
+	/* to track duplicate link descriptor indications by HW for a WAR */
+	uint64_t mon_last_linkdesc_paddr;
+	/* to track duplicate buffer indications by HW for a WAR */
+	uint32_t mon_last_buf_cookie;
 
 	/* pool addr for mcast enhance buff */
 	struct {