Эх сурвалжийг харах

qca-wifi: Add WAR to skip status ring entry

STATUS_BUFFRE_DONE tlv written in first word for a status
buffer indicates that DMA is done for that status ring entry.

In existing implementation, for a status ring entry if
STATUS_BUFFRE_DONE tlv is not written by HW, we poll on to status ring
entry until DMA is done by HW.

During lmac reset it may happne that HW will not write STATUS_BUFFRE_DONE
tlv in status buffer, in that case we end up polling infinitely leading
to backpressure on monitor status ring.

As per MAC team's suggestion, when HP + 1 entry is peeked and if DMA
is not done and if HP + 2 entry's DMA done is set,
replenish HP + 1 entry and start processing in next interrupt.

If HP + 2 entry's DMA done is not set,
poll onto HP + 1 entry DMA done to be set.

Change-Id: I2da5a16ec901764fcb88c417f599d7a1344bcea0
CRs-Fixed: 2744602
Amir 5 жил өмнө
parent
commit
b1ab3a6941

+ 45 - 25
dp/wifi3.0/dp_full_mon.c

@@ -62,7 +62,7 @@ dp_rx_mon_status_buf_validate(struct dp_pdev *pdev,
 	uint32_t tlv_tag;
 	void *rx_tlv;
 	struct hal_rx_ppdu_info *ppdu_info;
-	enum dp_mon_reap_status status = dp_mon_status_match;
+	enum dp_mon_reap_status status = DP_MON_STATUS_MATCH;
 	QDF_STATUS buf_status;
 	uint32_t ppdu_id_diff;
 
@@ -94,7 +94,7 @@ dp_rx_mon_status_buf_validate(struct dp_pdev *pdev,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s %d : HAL SRNG entry is NULL srng:-- %pK",
 			  __func__, __LINE__, mon_status_srng);
-		status = dp_mon_status_replenish;
+		status = DP_MON_STATUS_REPLENISH;
 		goto done;
 	}
 
@@ -109,7 +109,7 @@ dp_rx_mon_status_buf_validate(struct dp_pdev *pdev,
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
 			  "%s %d : buf addr is NULL -- %pK",
 			  __func__, __LINE__, mon_status_srng);
-		status = dp_mon_status_replenish;
+		status = DP_MON_STATUS_REPLENISH;
 		goto done;
 	}
 
@@ -135,8 +135,28 @@ dp_rx_mon_status_buf_validate(struct dp_pdev *pdev,
 			  FL("Monitor status ring: DMA is not done "
 			     "for nbuf: %pK buf_addr: %llx"),
 			     status_nbuf, buf_paddr);
-		pdev->rx_mon_stats.tlv_tag_status_err++;
-		status = dp_mon_status_no_dma;
+		status = dp_rx_mon_handle_status_buf_done(pdev,
+							  mon_status_srng);
+
+		if (status == DP_MON_STATUS_REPLENISH) {
+			union dp_rx_desc_list_elem_t *desc_list = NULL;
+			union dp_rx_desc_list_elem_t *tail = NULL;
+
+			/* If this is DMA not done WAR case,
+			 * free buffer and current SW descriptor and
+			 * make buf_addr_info NULL, so that call to
+			 * dp_rx_mon_status_process() replenishes entry to
+			 * status ring
+			 */
+			qdf_nbuf_free(status_nbuf);
+			dp_rx_add_to_free_desc_list(&desc_list,
+						&tail, rx_desc);
+			dp_rx_add_desc_list_to_free_list(soc, &desc_list,
+						&tail, mac_id, rx_desc_pool);
+			hal_rxdma_buff_addr_info_set(
+						ring_entry,
+						0, 0, HAL_RX_BUF_RBM_SW3_BM);
+		}
 		goto done;
 	}
 
@@ -156,22 +176,22 @@ dp_rx_mon_status_buf_validate(struct dp_pdev *pdev,
 	}
 
 	if (pdev->mon_desc->ppdu_id < pdev->mon_desc->status_ppdu_id) {
-		status = dp_mon_status_lead;
+		status = DP_MON_STATUS_LEAD;
 
 		/* For wrap around case */
 		ppdu_id_diff = pdev->mon_desc->status_ppdu_id -
 			       pdev->mon_desc->ppdu_id;
 
 		if (ppdu_id_diff > DP_RX_MON_PPDU_ID_WRAP)
-			status = dp_mon_status_lag;
+			status = DP_MON_STATUS_LAG;
 
 	} else if (pdev->mon_desc->ppdu_id > pdev->mon_desc->status_ppdu_id) {
-		status = dp_mon_status_lag;
+		status = DP_MON_STATUS_LAG;
 		/* For wrap around case */
 		ppdu_id_diff = pdev->mon_desc->ppdu_id -
 			       pdev->mon_desc->status_ppdu_id;
 		if (ppdu_id_diff > DP_RX_MON_PPDU_ID_WRAP)
-			status = dp_mon_status_lead;
+			status = DP_MON_STATUS_LEAD;
 	}
 
 	if ((pdev->mon_desc->status_buf.paddr != buf_paddr) ||
@@ -333,14 +353,14 @@ dp_rx_mon_reap_status_ring(struct dp_soc *soc,
 
 	status = dp_rx_mon_status_buf_validate(pdev, int_ctx, mac_id);
 	switch (status) {
-		case dp_mon_status_no_dma:
+		case DP_MON_STATUS_NO_DMA:
 			/* If DMA is not done for status ring entry,
 			 * hold on to monitor destination ring and
 			 * deliver current ppdu data once DMA is done.
 			 */
 			pdev->hold_mon_dest_ring = true;
 			break;
-		case dp_mon_status_lag:
+		case DP_MON_STATUS_LAG:
 			/* If status_ppdu_id is lagging behind destination,
 			 * a. Hold on to destination ring
 			 * b. Drop status ppdus until ppdu id matches
@@ -351,7 +371,7 @@ dp_rx_mon_reap_status_ring(struct dp_soc *soc,
 			pdev->rx_mon_stats.ppdu_id_mismatch++;
 			pdev->rx_mon_stats.status_ppdu_drop++;
 			break;
-		case dp_mon_status_lead:
+		case DP_MON_STATUS_LEAD:
 			/* If status_ppdu_id is leading ahead destination,
 			 * a. Drop destination ring ppdu until ppdu_id matches
 			 * b. Unhold monitor destination ring so status ppdus
@@ -364,11 +384,11 @@ dp_rx_mon_reap_status_ring(struct dp_soc *soc,
 			pdev->rx_mon_stats.ppdu_id_mismatch++;
 			pdev->rx_mon_stats.dest_ppdu_drop++;
 			break;
-		case dp_mon_status_replenish:
+		case DP_MON_STATUS_REPLENISH:
 			/* If status ring hp entry is NULL, replenish it */
 			work_done = dp_rx_mon_status_process(soc,  int_ctx, mac_id, 1);
 			break;
-		case dp_mon_status_match:
+		case DP_MON_STATUS_MATCH:
 			/* If status ppdu id matches with destnation,
 			 * unhold monitor destination ring and deliver ppdu
 			 */
@@ -381,11 +401,11 @@ dp_rx_mon_reap_status_ring(struct dp_soc *soc,
 	/* If status ring is lagging behind detination ring,
 	 * reap only one status buffer
 	 */
-	if (status == dp_mon_status_lag)
+	if (status == DP_MON_STATUS_LAG)
 		status_buf_count = 1;
 
-	if (status == dp_mon_status_lag ||
-	    status == dp_mon_status_match) {
+	if (status == DP_MON_STATUS_LAG ||
+	    status == DP_MON_STATUS_MATCH) {
 		work_done = dp_rx_mon_status_process(soc,
 						     int_ctx,
 						     mac_id,
@@ -627,14 +647,14 @@ dp_rx_mon_deliver_prev_ppdu(struct dp_pdev *pdev,
 		status = dp_rx_mon_status_buf_validate(pdev, int_ctx, mac_id);
 
 		switch (status) {
-			case dp_mon_status_no_dma:
+			case DP_MON_STATUS_NO_DMA:
 			/* If DMA is not done for status ring entry,
 			 * hold on to monitor destination ring and
 			 * deliver current ppdu data once DMA is done.
 			 */
 			pdev->hold_mon_dest_ring = true;
 			break;
-			case dp_mon_status_lag:
+			case DP_MON_STATUS_LAG:
 			/* If status_ppdu_id is lagging behind destination,
 			 * a. Hold on to destination ring
 			 * b. Drop status ppdus until ppdu id matches
@@ -645,7 +665,7 @@ dp_rx_mon_deliver_prev_ppdu(struct dp_pdev *pdev,
 			pdev->rx_mon_stats.ppdu_id_mismatch++;
 			pdev->rx_mon_stats.status_ppdu_drop++;
 			break;
-			case dp_mon_status_lead:
+			case DP_MON_STATUS_LEAD:
 			/* If status_ppdu_id is leading ahead destination,
 			 * a. Drop destination ring ppdu until ppdu_id matches
 			 * b. Unhold monitor destination ring so status ppdus
@@ -658,11 +678,11 @@ dp_rx_mon_deliver_prev_ppdu(struct dp_pdev *pdev,
 			pdev->rx_mon_stats.ppdu_id_mismatch++;
 			pdev->rx_mon_stats.dest_ppdu_drop++;
 			break;
-			case dp_mon_status_replenish:
+			case DP_MON_STATUS_REPLENISH:
 			/* If status ring hp entry is NULL, replenish it */
 			work = dp_rx_mon_status_process(soc, int_ctx, mac_id, 1);
 			break;
-			case dp_mon_status_match:
+			case DP_MON_STATUS_MATCH:
 			/* If status ppdu id matches with destnation,
 			 * unhold monitor destination ring and deliver ppdu
 			 */
@@ -677,12 +697,12 @@ dp_rx_mon_deliver_prev_ppdu(struct dp_pdev *pdev,
 		 * available for radiotap construction, so return and
 		 * check for status on next interrupt
 		 */
-		if ((status == dp_mon_status_no_dma) ||
-		    (status == dp_mon_status_replenish)) {
+		if ((status == DP_MON_STATUS_NO_DMA) ||
+		    (status == DP_MON_STATUS_REPLENISH)) {
 			return work_done;
 		}
 
-		if (status == dp_mon_status_lag) {
+		if (status == DP_MON_STATUS_LAG) {
 			work = dp_rx_mon_status_process(soc, int_ctx, mac_id, 1);
 
 			if (!work)

+ 0 - 17
dp/wifi3.0/dp_full_mon.h

@@ -57,21 +57,4 @@ dp_rx_mon_is_rxdma_error(struct hal_rx_mon_desc_info *desc_info)
 	}
 	return QDF_STATUS_E_FAILURE;
 }
-
-/*
- * dp_mon_reap_status - monitor status ring ppdu status
- *
- * dp_mon_status_no_dma - DMA not done for status ring entry
- * dp_mon_status_match - status and dest ppdu id mathes
- * dp_mon_status_lag - status ppdu id is lagging
- * dp_mon_status_lead - status ppdu id is leading
- * dp_mon_status_replenish - status ring entry is NULL
- */
-enum dp_mon_reap_status {
-	dp_mon_status_no_dma,
-	dp_mon_status_match,
-	dp_mon_status_lag,
-	dp_mon_status_lead,
-	dp_mon_status_replenish
-};
 #endif /* _DP_FULL_MON_H_ */