Просмотр исходного кода

qcacmn: Handle the nbuf sanity failure gracefully

Th nbuf sanity can fail in case when HW posts the
same buffer twice. This case can be handled gracefully
by just skipping the processing of the corresponding rx
descriptor.

Change-Id: I471bb9f364a51937e85249996e427f15872bda97
CRs-Fixed: 2738558
Rakesh Pillai 5 лет назад
Родитель
Сommit
d7a0b3f14c
4 измененных файлов с 28 добавлено и 8 удалено
  1. 18 7
      dp/wifi3.0/dp_rx.c
  2. 3 1
      dp/wifi3.0/dp_rx.h
  3. 5 0
      dp/wifi3.0/dp_stats.c
  4. 2 0
      dp/wifi3.0/dp_types.h

+ 18 - 7
dp/wifi3.0/dp_rx.c

@@ -287,6 +287,7 @@ QDF_STATUS __dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
 		qdf_assert_always((*desc_list)->rx_desc.in_use == 0);
 
 		(*desc_list)->rx_desc.in_use = 1;
+		(*desc_list)->rx_desc.in_err_state = 0;
 		dp_rx_desc_update_dbg_info(&(*desc_list)->rx_desc,
 					   func_name, RX_DESC_REPLENISHED);
 		dp_verbose_debug("rx_netbuf=%pK, buf=%pK, paddr=0x%llx, cookie=%d",
@@ -1721,21 +1722,25 @@ int dp_wds_rx_policy_check(uint8_t *rx_tlv_hdr,
  * Return: NONE
  */
 static inline
-void dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc,
-				  struct dp_rx_desc *rx_desc)
+QDF_STATUS dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc,
+					struct dp_rx_desc *rx_desc)
 {
 	struct hal_buf_info hbi;
 
 	hal_rx_reo_buf_paddr_get(ring_desc, &hbi);
 	/* Sanity check for possible buffer paddr corruption */
-	qdf_assert_always((&hbi)->paddr ==
-			  qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0));
+	if ((&hbi)->paddr ==
+			  qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0))
+		return QDF_STATUS_SUCCESS;
+
+	return QDF_STATUS_E_FAILURE;
 }
 #else
 static inline
-void dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc,
-				  struct dp_rx_desc *rx_desc)
+QDF_STATUS dp_rx_desc_nbuf_sanity_check(hal_ring_desc_t ring_desc,
+					struct dp_rx_desc *rx_desc)
 {
+	return QDF_STATUS_SUCCESS;
 }
 #endif
 
@@ -2120,7 +2125,13 @@ more_data:
 			continue;
 		}
 
-		dp_rx_desc_nbuf_sanity_check(ring_desc, rx_desc);
+		status = dp_rx_desc_nbuf_sanity_check(ring_desc, rx_desc);
+		if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
+			DP_STATS_INC(soc, rx.err.nbuf_sanity_fail, 1);
+			rx_desc->in_err_state = 1;
+			hal_srng_dst_get_next(hal_soc, hal_ring_hdl);
+			continue;
+		}
 
 		if (qdf_unlikely(!dp_rx_desc_check_magic(rx_desc))) {
 			dp_err("Invalid rx_desc cookie=%d", rx_buf_cookie);

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

@@ -108,6 +108,7 @@ struct dp_rx_desc_dbg_info {
  * @in_use		  rx_desc is in use
  * @unmapped		  used to mark rx_desc an unmapped if the corresponding
  *			  nbuf is already unmapped
+ * @in_err_state	: Nbuf sanity failed for this descriptor.
  */
 struct dp_rx_desc {
 	qdf_nbuf_t nbuf;
@@ -119,7 +120,8 @@ struct dp_rx_desc {
 	struct dp_rx_desc_dbg_info *dbg_info;
 #endif
 	uint8_t	in_use:1,
-	unmapped:1;
+	unmapped:1,
+	in_err_state:1;
 };
 
 /* RX Descriptor Multi Page memory alloc related */

+ 5 - 0
dp/wifi3.0/dp_stats.c

@@ -6055,6 +6055,8 @@ void dp_txrx_path_stats(struct dp_soc *soc)
 			       soc->stats.rx.err.raw_frm_drop);
 		DP_PRINT_STATS("Rx stale link desc cookie: %d",
 			       pdev->soc->stats.rx.err.invalid_link_cookie);
+		DP_PRINT_STATS("Rx nbuf sanity fails: %d",
+			       pdev->soc->stats.rx.err.nbuf_sanity_fail);
 
 		DP_PRINT_STATS("Reo Statistics");
 		DP_PRINT_STATS("near_full: %u ", soc->stats.rx.near_full);
@@ -6617,6 +6619,9 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
 	DP_PRINT_STATS("Rx stale link desc cookie: %d",
 		       soc->stats.rx.err.invalid_link_cookie);
 
+	DP_PRINT_STATS("Rx nbuf sanity fail: %d",
+		       soc->stats.rx.err.nbuf_sanity_fail);
+
 	for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) {
 		index += qdf_snprint(&rxdma_error[index],
 				DP_RXDMA_ERR_LENGTH - index,

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

@@ -857,6 +857,8 @@ struct dp_soc_stats {
 			uint32_t raw_frm_drop;
 			/* Stale link desc cookie count*/
 			uint32_t invalid_link_cookie;
+			/* Nbuf sanity failure */
+			uint32_t nbuf_sanity_fail;
 		} err;
 
 		/* packet count per core - per ring */