ソースを参照

qcacmn: Add RXDMA_DST ring support

Setup & process the RXDMA_DST ring to handle error frames
from RXDMA block. Pro-active fix to handle the WAR for
the WBM stuck issue seen when sending RX_FLUSH command.

Change-Id: Ibf56062da2cd9b5d447f1d43bbae5944426d88c8
CRs-Fixed: 2059870
Pramod Simha 7 年 前
コミット
e382ff88b9
6 ファイル変更201 行追加0 行削除
  1. 8 0
      dp/wifi3.0/dp_htt.c
  2. 24 0
      dp/wifi3.0/dp_main.c
  3. 5 0
      dp/wifi3.0/dp_rx.h
  4. 158 0
      dp/wifi3.0/dp_rx_err.c
  5. 3 0
      dp/wifi3.0/dp_rx_mon.h
  6. 3 0
      dp/wifi3.0/dp_types.h

+ 8 - 0
dp/wifi3.0/dp_htt.c

@@ -316,6 +316,10 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng,
 		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
 		htt_ring_type = HTT_SW_TO_HW_RING;
 		break;
+	case RXDMA_DST:
+		htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
+		htt_ring_type = HTT_HW_TO_SW_RING;
+		break;
 
 	default:
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
@@ -544,6 +548,10 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng,
 		htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
 		htt_ring_type = HTT_SW_TO_HW_RING;
 		break;
+	case RXDMA_DST:
+		htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
+		htt_ring_type = HTT_HW_TO_SW_RING;
+		break;
 
 	default:
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,

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

@@ -330,6 +330,13 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget)
 				dp_mon_process(soc, ring, budget);
 			budget -=  work_done;
 		}
+
+		if (int_ctx->rxdma2host_ring_mask & (1 << ring)) {
+			work_done =
+				dp_rxdma_err_process(soc, ring, budget);
+			budget -=  work_done;
+		}
+
 	}
 
 	qdf_lro_flush(int_ctx->lro_ctx);
@@ -871,6 +878,7 @@ static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc)
 #define RXDMA_MONITOR_DST_RING_SIZE 1024
 #define RXDMA_MONITOR_STATUS_RING_SIZE 1024
 #define RXDMA_MONITOR_DESC_RING_SIZE 1024
+#define RXDMA_ERR_DST_RING_SIZE 1024
 
 /*
  * dp_soc_cmn_setup() - Common SoC level initializion
@@ -1301,6 +1309,13 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 		goto fail1;
 	}
 
+	if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring, RXDMA_DST, 0,
+		pdev_id, RXDMA_ERR_DST_RING_SIZE)) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			FL("dp_srng_setup failed for rxdma_mon_dst_ring"));
+		goto fail1;
+	}
+
 	/* Rx specific init */
 	if (dp_rx_pdev_attach(pdev)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
@@ -1438,6 +1453,8 @@ static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force)
 	dp_srng_cleanup(soc, &pdev->rxdma_mon_desc_ring,
 		RXDMA_MONITOR_DESC, 0);
 
+	dp_srng_cleanup(soc, &pdev->rxdma_err_dst_ring, RXDMA_DST, 0);
+
 	soc->pdev_list[pdev->pdev_id] = NULL;
 	soc->pdev_count--;
 	wlan_cfg_pdev_detach(pdev->wlan_cfg_ctx);
@@ -1633,6 +1650,10 @@ static void dp_rxdma_ring_config(struct dp_soc *soc)
 			htt_srng_setup(soc->htt_handle, i,
 				pdev->rxdma_mon_desc_ring.hal_srng,
 				RXDMA_MONITOR_DESC);
+
+			htt_srng_setup(soc->htt_handle, i,
+					pdev->rxdma_err_dst_ring.hal_srng,
+					RXDMA_DST);
 		}
 	}
 }
@@ -1660,6 +1681,9 @@ static void dp_rxdma_ring_config(struct dp_soc *soc)
 			htt_srng_setup(soc->htt_handle, i,
 				pdev->rxdma_mon_desc_ring.hal_srng,
 				RXDMA_MONITOR_DESC);
+			htt_srng_setup(soc->htt_handle, i,
+					pdev->rxdma_err_dst_ring.hal_srng,
+					RXDMA_DST);
 		}
 	}
 }

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

@@ -582,4 +582,9 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id,
 QDF_STATUS
 dp_rx_link_desc_buf_return(struct dp_soc *soc, struct dp_srng *dp_rxdma_srng,
 				void *buf_addr_info);
+
+
+uint32_t
+dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id,
+						uint32_t quota);
 #endif /* _DP_RX_H */

+ 158 - 0
dp/wifi3.0/dp_rx_err.c

@@ -813,3 +813,161 @@ done:
 
 	return rx_bufs_reaped; /* Assume no scale factor for now */
 }
+
+/**
+ * dp_rx_err_mpdu_pop() - extract the MSDU's from link descs
+ *
+ * @soc: core DP main context
+ * @mac_id: mac id which is one of 3 mac_ids
+ * @rxdma_dst_ring_desc: void pointer to monitor link descriptor buf addr info
+ * @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
+dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id,
+	void *rxdma_dst_ring_desc,
+	union dp_rx_desc_list_elem_t **head,
+	union dp_rx_desc_list_elem_t **tail)
+{
+	void *rx_msdu_link_desc;
+	qdf_nbuf_t msdu;
+	qdf_nbuf_t last;
+	struct hal_rx_msdu_list msdu_list;
+	uint8_t num_msdus;
+	struct hal_buf_info buf_info;
+	void *p_buf_addr_info;
+	void *p_last_buf_addr_info;
+	uint32_t rx_bufs_used = 0;
+	uint32_t msdu_cnt;
+	uint32_t i;
+	bool mpdu_err;
+
+	msdu = 0;
+
+	last = NULL;
+
+	hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info,
+		&p_last_buf_addr_info, &msdu_cnt, &mpdu_err);
+
+	do {
+		rx_msdu_link_desc =
+			dp_rx_cookie_2_link_desc_va(soc, &buf_info);
+
+		qdf_assert(rx_msdu_link_desc);
+
+		num_msdus = (msdu_cnt > HAL_RX_NUM_MSDU_DESC)?
+				HAL_RX_NUM_MSDU_DESC:msdu_cnt;
+
+		hal_rx_msdu_list_get(rx_msdu_link_desc, &msdu_list, num_msdus);
+
+		msdu_cnt -= num_msdus;
+
+		for (i = 0; i < num_msdus; i++) {
+			struct dp_rx_desc *rx_desc =
+				dp_rx_cookie_2_va_rxdma_buf(soc,
+					msdu_list.sw_cookie[i]);
+
+				qdf_assert(rx_desc);
+				msdu = rx_desc->nbuf;
+
+				qdf_nbuf_unmap_single(soc->osdev, msdu,
+					QDF_DMA_FROM_DEVICE);
+
+				QDF_TRACE(QDF_MODULE_ID_DP,
+					QDF_TRACE_LEVEL_DEBUG,
+					"[%s][%d] msdu_nbuf=%p \n",
+					__func__, __LINE__, msdu);
+
+				qdf_nbuf_free(msdu);
+				rx_bufs_used++;
+				dp_rx_add_to_free_desc_list(head,
+					tail, rx_desc);
+		}
+
+		hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info,
+			&p_buf_addr_info);
+
+		dp_rx_link_desc_return(soc, p_last_buf_addr_info);
+		p_last_buf_addr_info = p_buf_addr_info;
+
+	} while (buf_info.paddr && msdu_cnt);
+
+	return rx_bufs_used;
+}
+
+/**
+* dp_rxdma_err_process() - RxDMA error processing functionality
+*
+* @soc: core txrx main contex
+* @mac_id: mac id which is one of 3 mac_ids
+* @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced
+* @quota: No. of units (packets) that can be serviced in one shot.
+
+* Return: num of buffers processed
+*/
+uint32_t
+dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota)
+{
+	struct dp_pdev *pdev = soc->pdev_list[mac_id];
+	uint8_t pdev_id;
+	void *hal_soc;
+	void *rxdma_dst_ring_desc;
+	void *err_dst_srng;
+	union dp_rx_desc_list_elem_t *head = NULL;
+	union dp_rx_desc_list_elem_t *tail = NULL;
+	struct dp_srng *dp_rxdma_srng;
+	struct rx_desc_pool *rx_desc_pool;
+	uint32_t work_done = 0;
+	uint32_t rx_bufs_used = 0;
+
+#ifdef DP_INTR_POLL_BASED
+	if (!pdev)
+		return 0;
+#endif
+	pdev_id = pdev->pdev_id;
+	err_dst_srng = pdev->rxdma_err_dst_ring.hal_srng;
+
+	if (!err_dst_srng) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"%s %d : HAL Monitor Destination Ring Init \
+			Failed -- %p\n",
+			__func__, __LINE__, err_dst_srng);
+		return 0;
+	}
+
+	hal_soc = soc->hal_soc;
+
+	qdf_assert(hal_soc);
+
+	if (qdf_unlikely(hal_srng_access_start(hal_soc, err_dst_srng))) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			"%s %d : HAL Monitor Destination Ring Init \
+			Failed -- %p\n",
+			__func__, __LINE__, err_dst_srng);
+		return 0;
+	}
+
+	while (qdf_likely((rxdma_dst_ring_desc =
+		hal_srng_dst_get_next(hal_soc, err_dst_srng)) && quota--)) {
+
+			rx_bufs_used += dp_rx_err_mpdu_pop(soc, mac_id,
+						rxdma_dst_ring_desc,
+						&head, &tail);
+	}
+
+	hal_srng_access_end(hal_soc, err_dst_srng);
+
+	if (rx_bufs_used) {
+		dp_rxdma_srng = &pdev->rx_refill_buf_ring;
+		rx_desc_pool = &soc->rx_desc_buf[mac_id];
+
+		dp_rx_buffers_replenish(soc, pdev_id, dp_rxdma_srng,
+			rx_desc_pool, rx_bufs_used, &head, &tail,
+			HAL_RX_BUF_RBM_SW3_BM);
+		work_done += rx_bufs_used;
+	}
+
+	return work_done;
+}

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

@@ -48,4 +48,7 @@ QDF_STATUS dp_rx_pdev_mon_status_detach(struct dp_pdev *pdev);
 uint32_t dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota);
 QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id,
 	qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu);
+
+uint32_t dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id,
+	uint32_t quota);
 #endif

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

@@ -723,6 +723,9 @@ struct dp_pdev {
 
 	struct dp_srng rxdma_mon_desc_ring;
 
+	/* RXDMA error destination ring */
+	struct dp_srng rxdma_err_dst_ring;
+
 	/* Link descriptor memory banks */
 	struct {
 		void *base_vaddr_unaligned;