Browse Source

qcacmn: gracefully handle error packets on partner soc

Ideally in MLO, Rx buffers should be routed to error
rings of the SOC which owns the RX buffer or link desc
incase of any error or fragment

But in case of HW issue if the packets are routed to
partner soc. Handle gracefully instead of assert

Change-Id: Ia56188808dfd034e960e1c1345de8f760e4b05f1
CRs-Fixed: 3327959
Chaithanya Garrepalli 2 năm trước cách đây
mục cha
commit
86f7649e19

+ 5 - 3
dp/wifi3.0/be/dp_be.c

@@ -1953,14 +1953,15 @@ dp_initialize_arch_ops_be_mcast_mlo(struct dp_arch_ops *arch_ops)
 
 #ifdef WLAN_MLO_MULTI_CHIP
 static inline void
-dp_initialize_arch_ops_be_mlo_ptnr_chip(struct dp_arch_ops *arch_ops)
+dp_initialize_arch_ops_be_mlo_multi_chip(struct dp_arch_ops *arch_ops)
 {
 	arch_ops->dp_partner_chips_map = dp_mlo_partner_chips_map;
 	arch_ops->dp_partner_chips_unmap = dp_mlo_partner_chips_unmap;
+	arch_ops->dp_soc_get_by_idle_bm_id = dp_soc_get_by_idle_bm_id;
 }
 #else
 static inline void
-dp_initialize_arch_ops_be_mlo_ptnr_chip(struct dp_arch_ops *arch_ops)
+dp_initialize_arch_ops_be_mlo_multi_chip(struct dp_arch_ops *arch_ops)
 {
 }
 #endif
@@ -1969,7 +1970,7 @@ static inline void
 dp_initialize_arch_ops_be_mlo(struct dp_arch_ops *arch_ops)
 {
 	dp_initialize_arch_ops_be_mcast_mlo(arch_ops);
-	dp_initialize_arch_ops_be_mlo_ptnr_chip(arch_ops);
+	dp_initialize_arch_ops_be_mlo_multi_chip(arch_ops);
 	arch_ops->mlo_peer_find_hash_detach =
 	dp_mlo_peer_find_hash_detach_wrapper;
 	arch_ops->mlo_peer_find_hash_attach =
@@ -2135,6 +2136,7 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
 	arch_ops->tx_implicit_rbm_set = dp_tx_implicit_rbm_set_be;
 	arch_ops->txrx_set_vdev_param = dp_txrx_set_vdev_param_be;
 	dp_initialize_arch_ops_be_mlo(arch_ops);
+	arch_ops->dp_rx_replenish_soc_get = dp_rx_replensih_soc_get;
 	arch_ops->dp_peer_rx_reorder_queue_setup =
 					dp_peer_rx_reorder_queue_setup_be;
 	arch_ops->txrx_print_peer_stats = dp_print_peer_txrx_stats_be;

+ 3 - 0
dp/wifi3.0/be/dp_be_rx.h

@@ -243,6 +243,9 @@ uint32_t dp_rx_nf_process(struct dp_intr *int_ctx,
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
 struct dp_soc *
 dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id);
+
+struct dp_soc *
+dp_soc_get_by_idle_bm_id(struct dp_soc *soc, uint8_t idle_bm_id);
 #else
 static inline struct dp_soc *
 dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id)

+ 24 - 0
dp/wifi3.0/be/mlo/dp_mlo.c

@@ -658,6 +658,30 @@ dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id)
 	return replenish_soc;
 }
 
+struct dp_soc *
+dp_soc_get_by_idle_bm_id(struct dp_soc *soc, uint8_t idle_bm_id)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt;
+	struct dp_soc *partner_soc = NULL;
+	uint8_t chip_id;
+
+	if (!be_soc->mlo_enabled || !mlo_ctxt)
+		return soc;
+
+	for (chip_id = 0; chip_id < WLAN_MAX_MLO_CHIPS; chip_id++) {
+		partner_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, chip_id);
+
+		if (!partner_soc)
+			continue;
+
+		if (partner_soc->idle_link_bm_id == idle_bm_id)
+			return partner_soc;
+	}
+
+	return NULL;
+}
+
 #ifdef WLAN_MCAST_MLO
 void dp_mcast_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc,
 				dp_ptnr_soc_iter_func func,

+ 81 - 25
dp/wifi3.0/dp_rx_err.c

@@ -2205,20 +2205,52 @@ static int dp_rx_err_exception(struct dp_soc *soc, hal_ring_desc_t ring_desc)
 #endif /* HANDLE_RX_REROUTE_ERR */
 
 #ifdef WLAN_MLO_MULTI_CHIP
-static void dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm)
+/*
+ * dp_idle_link_bm_id_check() - war for HW issue
+ *
+ * This is a war for HW issue where link descriptor
+ * of partner soc received due to packets wrongly
+ * interpreted as fragments
+ *
+ * @soc: DP SOC handle
+ * @rbm: idle link RBM value
+ * @ring_desc: reo error link descriptor
+ *
+ * returns: true in case link desc is consumed
+ *	    false in other cases
+ */
+static bool dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm,
+				     void *ring_desc)
 {
+	struct dp_soc *replenish_soc = NULL;
+
+	/* return ok incase of link desc of same soc */
+	if (rbm == soc->idle_link_bm_id)
+		return false;
+
+	if (soc->arch_ops.dp_soc_get_by_idle_bm_id)
+		replenish_soc =
+			soc->arch_ops.dp_soc_get_by_idle_bm_id(soc, rbm);
+
+	qdf_assert_always(replenish_soc);
+
 	/*
 	 * For WIN usecase we should only get fragment packets in
 	 * this ring as for MLO case fragmentation is not supported
 	 * we should not see links from other soc.
 	 *
-	 * Adding a assert for link descriptors from local soc
+	 * Drop all packets from partner soc and replenish the descriptors
 	 */
-	qdf_assert_always(rbm == soc->idle_link_bm_id);
+	dp_handle_wbm_internal_error(replenish_soc, ring_desc,
+				     HAL_WBM_RELEASE_RING_2_DESC_TYPE);
+
+	return true;
 }
 #else
-static void dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm)
+static bool dp_idle_link_bm_id_check(struct dp_soc *soc, uint8_t rbm,
+				     void *ring_desc)
 {
+	return false;
 }
 #endif
 
@@ -2323,7 +2355,10 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 		qdf_assert_always((hbi.sw_cookie >> LINK_DESC_ID_SHIFT) &
 					soc->link_desc_id_start);
 
-		dp_idle_link_bm_id_check(soc, hbi.rbm);
+		if (dp_idle_link_bm_id_check(soc, hbi.rbm, ring_desc)) {
+			DP_STATS_INC(soc, rx.err.invalid_link_cookie, 1);
+			goto next_entry;
+		}
 
 		status = dp_rx_link_cookie_check(ring_desc);
 		if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
@@ -2642,10 +2677,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 	hal_ring_desc_t ring_desc;
 	hal_soc_handle_t hal_soc;
 	struct dp_rx_desc *rx_desc;
-	union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT] = { NULL };
-	union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT] = { NULL };
+	union dp_rx_desc_list_elem_t
+		*head[WLAN_MAX_MLO_CHIPS][MAX_PDEV_CNT] = { { NULL } };
+	union dp_rx_desc_list_elem_t
+		*tail[WLAN_MAX_MLO_CHIPS][MAX_PDEV_CNT] = { { NULL } };
 	uint32_t rx_bufs_used = 0;
-	uint32_t rx_bufs_reaped[MAX_PDEV_CNT] = { 0 };
+	uint32_t rx_bufs_reaped[WLAN_MAX_MLO_CHIPS][MAX_PDEV_CNT] = { { 0 } };
 	uint8_t buf_type;
 	uint8_t mac_id;
 	struct dp_pdev *dp_pdev;
@@ -2663,6 +2700,8 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 	bool process_sg_buf = false;
 	uint32_t wbm_err_src;
 	QDF_STATUS status;
+	struct dp_soc *replenish_soc;
+	uint8_t chip_id;
 	struct hal_rx_mpdu_desc_info mpdu_desc_info = { 0 };
 
 	/* Debug -- Remove later */
@@ -2742,11 +2781,12 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 				   nbuf);
 			rx_desc->in_err_state = 1;
 			rx_desc->unmapped = 1;
-			rx_bufs_reaped[rx_desc->pool_id]++;
-			dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
-						    &tail[rx_desc->pool_id],
-						    rx_desc);
+			rx_bufs_reaped[rx_desc->chip_id][rx_desc->pool_id]++;
 
+			dp_rx_add_to_free_desc_list(
+				&head[rx_desc->chip_id][rx_desc->pool_id],
+				&tail[rx_desc->chip_id][rx_desc->pool_id],
+				rx_desc);
 			continue;
 		}
 
@@ -2804,7 +2844,7 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 					    (uint8_t *)&wbm_err_info,
 					    sizeof(wbm_err_info));
 
-		rx_bufs_reaped[rx_desc->pool_id]++;
+		rx_bufs_reaped[rx_desc->chip_id][rx_desc->pool_id]++;
 
 		if (qdf_nbuf_is_rx_chfrag_cont(nbuf) || process_sg_buf) {
 			DP_RX_LIST_APPEND(soc->wbm_sg_param.wbm_sg_nbuf_head,
@@ -2828,9 +2868,9 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 			DP_RX_LIST_APPEND(nbuf_head, nbuf_tail, nbuf);
 		}
 
-		dp_rx_add_to_free_desc_list(&head[rx_desc->pool_id],
-						&tail[rx_desc->pool_id],
-						rx_desc);
+		dp_rx_add_to_free_desc_list
+			(&head[rx_desc->chip_id][rx_desc->pool_id],
+			 &tail[rx_desc->chip_id][rx_desc->pool_id], rx_desc);
 
 		/*
 		 * if continuation bit is set then we have MSDU spread
@@ -2843,15 +2883,30 @@ dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
 done:
 	dp_srng_access_end(int_ctx, soc, hal_ring_hdl);
 
-	for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) {
-		if (rx_bufs_reaped[mac_id]) {
-			dp_rxdma_srng = &soc->rx_refill_buf_ring[mac_id];
-			rx_desc_pool = &soc->rx_desc_buf[mac_id];
+	for (chip_id = 0; chip_id < WLAN_MAX_MLO_CHIPS; chip_id++) {
+		for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) {
+			/*
+			 * continue with next mac_id if no pkts were reaped
+			 * from that pool
+			 */
+			if (!rx_bufs_reaped[chip_id][mac_id])
+				continue;
 
-			dp_rx_buffers_replenish(soc, mac_id, dp_rxdma_srng,
-					rx_desc_pool, rx_bufs_reaped[mac_id],
-					&head[mac_id], &tail[mac_id], false);
-			rx_bufs_used += rx_bufs_reaped[mac_id];
+			replenish_soc =
+			soc->arch_ops.dp_rx_replenish_soc_get(soc, chip_id);
+
+			dp_rxdma_srng =
+				&replenish_soc->rx_refill_buf_ring[mac_id];
+
+			rx_desc_pool = &replenish_soc->rx_desc_buf[mac_id];
+
+			dp_rx_buffers_replenish(replenish_soc, mac_id,
+						dp_rxdma_srng,
+						rx_desc_pool,
+						rx_bufs_reaped[chip_id][mac_id],
+						&head[chip_id][mac_id],
+						&tail[chip_id][mac_id], false);
+			rx_bufs_used += rx_bufs_reaped[chip_id][mac_id];
 		}
 	}
 
@@ -3531,7 +3586,6 @@ dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
 	/* buffer_addr_info is the first element of ring_desc */
 	hal_rx_buf_cookie_rbm_get(soc->hal_soc, (uint32_t *)hal_desc,
 				  &buf_info);
-	pool_id = DP_RX_DESC_COOKIE_POOL_ID_GET(buf_info.sw_cookie);
 
 	if (buf_type == HAL_WBM_RELEASE_RING_2_BUFFER_TYPE) {
 		DP_STATS_INC(soc, tx.wbm_internal_error[WBM_INT_ERROR_REO_NULL_MSDU_BUFF], 1);
@@ -3556,6 +3610,8 @@ dp_handle_wbm_internal_error(struct dp_soc *soc, void *hal_desc,
 			rx_bufs_reaped[rx_desc->pool_id]++;
 		}
 	} else if (buf_type == HAL_WBM_RELEASE_RING_2_DESC_TYPE) {
+		pool_id = DP_RX_DESC_COOKIE_POOL_ID_GET(buf_info.sw_cookie);
+
 		dp_wbm_int_err_mpdu_pop(soc, pool_id, hal_desc,
 					&head, &tail, rx_bufs_reaped);
 	}

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

@@ -1953,12 +1953,16 @@ struct dp_arch_ops {
 	bool (*dp_rx_mcast_handler)(struct dp_soc *soc, struct dp_vdev *vdev,
 				    struct dp_txrx_peer *peer, qdf_nbuf_t nbuf);
 #endif
+	struct dp_soc * (*dp_soc_get_by_idle_bm_id)(struct dp_soc *soc,
+						    uint8_t bm_id);
+
 	void (*mlo_peer_find_hash_detach)(struct dp_soc *soc);
 	QDF_STATUS (*mlo_peer_find_hash_attach)(struct dp_soc *soc);
 	void (*mlo_peer_find_hash_add)(struct dp_soc *soc,
 				       struct dp_peer *peer);
 	void (*mlo_peer_find_hash_remove)(struct dp_soc *soc,
 					  struct dp_peer *peer);
+
 	struct dp_peer *(*mlo_peer_find_hash_find)(struct dp_soc *soc,
 						   uint8_t *peer_mac_addr,
 						   int mac_addr_is_aligned,
@@ -1984,6 +1988,9 @@ struct dp_arch_ops {
 						   uint8_t vdev_id);
 	void (*dp_bank_reconfig)(struct dp_soc *soc, struct dp_vdev *vdev);
 
+	struct dp_soc * (*dp_rx_replenish_soc_get)(struct dp_soc *soc,
+						   uint8_t chip_id);
+
 	void (*dp_reconfig_tx_vdev_mcast_ctrl)(struct dp_soc *soc,
 					       struct dp_vdev *vdev);
 

+ 7 - 0
dp/wifi3.0/li/dp_li.c

@@ -572,6 +572,12 @@ static bool dp_reo_remap_config_li(struct dp_soc *soc,
 	return dp_reo_remap_config(soc, remap0, remap1, remap2);
 }
 
+static struct dp_soc *dp_rx_replensih_soc_get_li(struct dp_soc *soc,
+						 uint8_t chip_id)
+{
+	return soc;
+}
+
 void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops)
 {
 #ifndef QCA_HOST_MODE_WIFI_DISABLED
@@ -629,6 +635,7 @@ void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops)
 	arch_ops->dp_find_peer_by_destmac = dp_find_peer_by_destmac_li;
 	arch_ops->peer_get_reo_hash = dp_peer_get_reo_hash_li;
 	arch_ops->reo_remap_config = dp_reo_remap_config_li;
+	arch_ops->dp_rx_replenish_soc_get = dp_rx_replensih_soc_get_li;
 	arch_ops->dp_txrx_ppeds_rings_status = NULL;
 	arch_ops->txrx_soc_ppeds_start = NULL;
 	arch_ops->txrx_soc_ppeds_stop = NULL;