Browse Source

qcacmn: Add Cached Descriptor support for DP SRNGs

Add support to configure any HAL SRNG descriptor to
be allocated from cached memory area. This is to
optimize of CPU cycles spent on uncached
memory accesses. Also added prefetch of cached
descriptors

Change-Id: I2544e8596d48e2f5549bf687a764c16d73397545
CRs-fixed: 2267945
Chaithanya Garrepalli 5 years ago
parent
commit
ab234e56f6

+ 118 - 63
dp/wifi3.0/dp_main.c

@@ -118,6 +118,9 @@ static void dp_ppdu_ring_cfg(struct dp_pdev *pdev);
 bool is_dp_verbose_debug_enabled;
 #endif
 
+static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc,
+					    enum hal_ring_type ring_type,
+					    int ring_num);
 #define DP_INTR_POLL_TIMER_MS	10
 /* Generic AST entry aging timer value */
 #define DP_AST_AGING_TIMER_DEFAULT_MS	1000
@@ -1102,13 +1105,23 @@ static void dp_print_peer_table(struct dp_vdev *vdev)
  *         QDF_STATUS_E_NOMEM on failure
  */
 static QDF_STATUS
-dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align)
+dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align,
+		  bool cached)
 {
-	srng->base_vaddr_unaligned =
-		qdf_mem_alloc_consistent(soc->osdev,
-					 soc->osdev->dev,
-					 srng->alloc_size,
-					 &srng->base_paddr_unaligned);
+	uint32_t align_alloc_size;
+
+	if (!cached) {
+		srng->base_vaddr_unaligned =
+			qdf_mem_alloc_consistent(soc->osdev,
+						 soc->osdev->dev,
+						 srng->alloc_size,
+						 &srng->base_paddr_unaligned);
+	} else {
+		srng->base_vaddr_unaligned = qdf_mem_malloc(srng->alloc_size);
+		srng->base_paddr_unaligned =
+			qdf_mem_virt_to_phys(srng->base_vaddr_unaligned);
+	}
+
 	if (!srng->base_vaddr_unaligned) {
 		return QDF_STATUS_E_NOMEM;
 	}
@@ -1127,21 +1140,36 @@ dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align)
 	 */
 	if ((unsigned long)(srng->base_paddr_unaligned) &
 	    (align - 1)) {
-		qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
-					srng->alloc_size,
-					srng->base_vaddr_unaligned,
-					srng->base_paddr_unaligned, 0);
-		srng->alloc_size = srng->alloc_size + align - 1;
-		srng->base_vaddr_unaligned =
-			qdf_mem_alloc_consistent(soc->osdev,
-						 soc->osdev->dev,
-						 srng->alloc_size,
-						 &srng->base_paddr_unaligned);
+		align_alloc_size = srng->alloc_size + align - 1;
+
+		if (!cached) {
+			qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
+						srng->alloc_size,
+						srng->base_vaddr_unaligned,
+						srng->base_paddr_unaligned, 0);
+
+			srng->base_vaddr_unaligned =
+				qdf_mem_alloc_consistent(soc->osdev,
+							 soc->osdev->dev,
+							 align_alloc_size,
+							 &srng->base_paddr_unaligned);
+
+		} else {
+			qdf_mem_free(srng->base_vaddr_unaligned);
+			srng->base_vaddr_unaligned =
+				qdf_mem_malloc(align_alloc_size);
+
+			srng->base_paddr_unaligned =
+				qdf_mem_virt_to_phys(srng->base_vaddr_unaligned);
+		}
+
+		srng->alloc_size = align_alloc_size;
 
 		if (!srng->base_vaddr_unaligned) {
 			return QDF_STATUS_E_NOMEM;
 		}
 	}
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1150,7 +1178,8 @@ dp_srng_mem_alloc(struct dp_soc *soc, struct dp_srng *srng, uint32_t align)
  * dp_setup_srng - Internal function to setup SRNG rings used by data path
  */
 static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng,
-	int ring_type, int ring_num, int mac_id, uint32_t num_entries)
+			 int ring_type, int ring_num, int mac_id,
+			 uint32_t num_entries, bool cached)
 {
 	void *hal_soc = soc->hal_soc;
 	uint32_t entry_size = hal_srng_get_entrysize(hal_soc, ring_type);
@@ -1170,12 +1199,13 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng,
 	srng->num_entries = num_entries;
 
 	if (!dp_is_soc_reinit(soc)) {
-		if (dp_srng_mem_alloc(soc, srng, ring_base_align) !=
+		if (dp_srng_mem_alloc(soc, srng, ring_base_align, cached) !=
 		    QDF_STATUS_SUCCESS) {
 			dp_err("alloc failed - ring_type: %d, ring_num %d",
 			       ring_type, ring_num);
 			return QDF_STATUS_E_NOMEM;
 		}
+
 	}
 
 	ring_params.ring_base_paddr =
@@ -1245,14 +1275,23 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng,
 		ring_params.intr_batch_cntr_thres_entries = 0;
 	}
 
+	if (cached) {
+		ring_params.flags |= HAL_SRNG_CACHED_DESC;
+		srng->cached = 1;
+	}
+
 	srng->hal_srng = hal_srng_setup(hal_soc, ring_type, ring_num,
 		mac_id, &ring_params);
 
 	if (!srng->hal_srng) {
-		qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
-				srng->alloc_size,
-				srng->base_vaddr_unaligned,
-				srng->base_paddr_unaligned, 0);
+		if (cached) {
+			qdf_mem_free(srng->base_vaddr_unaligned);
+		} else {
+			qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
+						srng->alloc_size,
+						srng->base_vaddr_unaligned,
+						srng->base_paddr_unaligned, 0);
+		}
 	}
 
 	return 0;
@@ -1304,12 +1343,17 @@ static void dp_srng_cleanup(struct dp_soc *soc, struct dp_srng *srng,
 	}
 
 	if (srng->alloc_size) {
-		qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
-					srng->alloc_size,
-					srng->base_vaddr_unaligned,
-					srng->base_paddr_unaligned, 0);
+		if (!srng->cached) {
+			qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
+						srng->alloc_size,
+						srng->base_vaddr_unaligned,
+						srng->base_paddr_unaligned, 0);
+		} else {
+			qdf_mem_free(srng->base_vaddr_unaligned);
+		}
 		srng->alloc_size = 0;
 	}
+	srng->hal_srng = NULL;
 }
 
 /* TODO: Need this interface from HIF */
@@ -2000,7 +2044,7 @@ static int dp_hw_link_desc_pool_setup(struct dp_soc *soc)
 		void *desc;
 
 		if (dp_srng_setup(soc, &soc->wbm_idle_link_ring,
-			WBM_IDLE_LINK, 0, 0, total_link_descs)) {
+				  WBM_IDLE_LINK, 0, 0, total_link_descs, 0)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				FL("Link desc idle ring setup failed"));
 			goto fail;
@@ -2695,8 +2739,10 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 
 	/* Setup SRNG rings */
 	/* Common rings */
+	entries = wlan_cfg_get_dp_soc_wbm_release_ring_size(soc_cfg_ctx);
+
 	if (dp_srng_setup(soc, &soc->wbm_desc_rel_ring, SW2WBM_RELEASE, 0, 0,
-		wlan_cfg_get_dp_soc_wbm_release_ring_size(soc_cfg_ctx))) {
+			  entries, 0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("dp_srng_setup failed for wbm_desc_rel_ring"));
 		goto fail1;
@@ -2717,7 +2763,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 			wlan_cfg_tx_ring_size(soc_cfg_ctx);
 		for (i = 0; i < soc->num_tcl_data_rings; i++) {
 			if (dp_srng_setup(soc, &soc->tcl_data_ring[i],
-				TCL_DATA, i, 0, tx_ring_size)) {
+					  TCL_DATA, i, 0, tx_ring_size, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					QDF_TRACE_LEVEL_ERROR,
 					FL("dp_srng_setup failed for tcl_data_ring[%d]"), i);
@@ -2728,7 +2774,9 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 			 * count
 			 */
 			if (dp_srng_setup(soc, &soc->tx_comp_ring[i],
-				WBM2SW_RELEASE, i, 0, tx_comp_ring_size)) {
+					  WBM2SW_RELEASE, i, 0,
+					  tx_comp_ring_size,
+					  WLAN_CFG_DST_RING_CACHED_DESC)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					QDF_TRACE_LEVEL_ERROR,
 					FL("dp_srng_setup failed for tx_comp_ring[%d]"), i);
@@ -2749,7 +2797,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 	entries = wlan_cfg_get_dp_soc_tcl_cmd_ring_size(soc_cfg_ctx);
 	/* TCL command and status rings */
 	if (dp_srng_setup(soc, &soc->tcl_cmd_ring, TCL_CMD, 0, 0,
-			  entries)) {
+			  entries, 0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("dp_srng_setup failed for tcl_cmd_ring"));
 		goto fail1;
@@ -2757,7 +2805,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 
 	entries = wlan_cfg_get_dp_soc_tcl_status_ring_size(soc_cfg_ctx);
 	if (dp_srng_setup(soc, &soc->tcl_status_ring, TCL_STATUS, 0, 0,
-			  entries)) {
+			  entries, 0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("dp_srng_setup failed for tcl_status_ring"));
 		goto fail1;
@@ -2778,7 +2826,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 			FL("num_reo_dest_rings %d"), soc->num_reo_dest_rings);
 		for (i = 0; i < soc->num_reo_dest_rings; i++) {
 			if (dp_srng_setup(soc, &soc->reo_dest_ring[i], REO_DST,
-				i, 0, reo_dst_ring_size)) {
+					  i, 0, reo_dst_ring_size,
+					  WLAN_CFG_DST_RING_CACHED_DESC)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "reo_dest_ring [%d]"), i);
@@ -2798,8 +2847,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 
 		for (i = 0; i < MAX_RX_MAC_RINGS; i++) {
 			if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring[i],
-					  RXDMA_DST, 0, i,
-					  entries)) {
+					  RXDMA_DST, 0, i, entries, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "rxdma_err_dst_ring"));
@@ -2812,7 +2860,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 	/* REO reinjection ring */
 	entries = wlan_cfg_get_dp_soc_reo_reinject_ring_size(soc_cfg_ctx);
 	if (dp_srng_setup(soc, &soc->reo_reinject_ring, REO_REINJECT, 0, 0,
-			  entries)) {
+			  entries, 0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			  FL("dp_srng_setup failed for reo_reinject_ring"));
 		goto fail1;
@@ -2821,7 +2869,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 
 	/* Rx release ring */
 	if (dp_srng_setup(soc, &soc->rx_rel_ring, WBM2SW_RELEASE, 3, 0,
-		wlan_cfg_get_dp_soc_rx_release_ring_size(soc_cfg_ctx))) {
+			  wlan_cfg_get_dp_soc_rx_release_ring_size(soc_cfg_ctx),
+			  0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			  FL("dp_srng_setup failed for rx_rel_ring"));
 		goto fail1;
@@ -2831,7 +2880,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 	/* Rx exception ring */
 	entries = wlan_cfg_get_dp_soc_reo_exception_ring_size(soc_cfg_ctx);
 	if (dp_srng_setup(soc, &soc->reo_exception_ring,
-			  REO_EXCEPTION, 0, MAX_REO_DEST_RINGS, entries)) {
+			  REO_EXCEPTION, 0, MAX_REO_DEST_RINGS, entries, 0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			  FL("dp_srng_setup failed for reo_exception_ring"));
 		goto fail1;
@@ -2840,7 +2889,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 
 	/* REO command and status rings */
 	if (dp_srng_setup(soc, &soc->reo_cmd_ring, REO_CMD, 0, 0,
-		wlan_cfg_get_dp_soc_reo_cmd_ring_size(soc_cfg_ctx))) {
+			  wlan_cfg_get_dp_soc_reo_cmd_ring_size(soc_cfg_ctx),
+			  0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("dp_srng_setup failed for reo_cmd_ring"));
 		goto fail1;
@@ -2851,7 +2901,8 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
 	qdf_spinlock_create(&soc->rx.reo_cmd_lock);
 
 	if (dp_srng_setup(soc, &soc->reo_status_ring, REO_STATUS, 0, 0,
-		wlan_cfg_get_dp_soc_reo_status_ring_size(soc_cfg_ctx))) {
+			  wlan_cfg_get_dp_soc_reo_status_ring_size(soc_cfg_ctx),
+			  0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("dp_srng_setup failed for reo_status_ring"));
 		goto fail1;
@@ -2991,15 +3042,16 @@ static int dp_rxdma_ring_setup(struct dp_soc *soc,
 	struct wlan_cfg_dp_pdev_ctxt *pdev_cfg_ctx;
 	int max_mac_rings;
 	int i;
+	int ring_size;
 
 	pdev_cfg_ctx = pdev->wlan_cfg_ctx;
 	max_mac_rings = wlan_cfg_get_num_mac_rings(pdev_cfg_ctx);
+	ring_size =  wlan_cfg_get_rx_dma_buf_ring_size(pdev_cfg_ctx);
 
 	for (i = 0; i < max_mac_rings; i++) {
 		dp_verbose_debug("pdev_id %d mac_id %d", pdev->pdev_id, i);
 		if (dp_srng_setup(soc, &pdev->rx_mac_buf_ring[i],
-			RXDMA_BUF, 1, i,
-			wlan_cfg_get_rx_dma_buf_ring_size(pdev_cfg_ctx))) {
+				  RXDMA_BUF, 1, i, ring_size, 0)) {
 			QDF_TRACE(QDF_MODULE_ID_DP,
 				 QDF_TRACE_LEVEL_ERROR,
 				 FL("failed rx mac ring setup"));
@@ -3083,9 +3135,8 @@ static int dp_setup_ipa_rx_refill_buf_ring(struct dp_soc *soc,
 
 	/* Setup second Rx refill buffer ring */
 	if (dp_srng_setup(soc, &pdev->rx_refill_buf_ring2, RXDMA_BUF,
-			  IPA_RX_REFILL_BUF_RING_IDX,
-			  pdev->pdev_id,
-			  entries)) {
+			  IPA_RX_REFILL_BUF_RING_IDX, pdev->pdev_id, entries, 0)
+	   ) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			FL("dp_srng_setup failed second rx refill ring"));
 		return QDF_STATUS_E_FAILURE;
@@ -3147,7 +3198,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev)
 			if (dp_srng_setup(soc,
 					  &pdev->rxdma_mon_buf_ring[mac_id],
 					  RXDMA_MONITOR_BUF, 0, mac_for_pdev,
-					  entries)) {
+					  entries, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "rxdma_mon_buf_ring "));
@@ -3159,7 +3210,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev)
 			if (dp_srng_setup(soc,
 					  &pdev->rxdma_mon_dst_ring[mac_id],
 					  RXDMA_MONITOR_DST, 0, mac_for_pdev,
-					  entries)) {
+					  entries, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "rxdma_mon_dst_ring"));
@@ -3171,7 +3222,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev)
 			if (dp_srng_setup(soc,
 					  &pdev->rxdma_mon_status_ring[mac_id],
 					  RXDMA_MONITOR_STATUS, 0, mac_for_pdev,
-					  entries)) {
+					  entries, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "rxdma_mon_status_ring"));
@@ -3183,7 +3234,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev)
 			if (dp_srng_setup(soc,
 					  &pdev->rxdma_mon_desc_ring[mac_id],
 					  RXDMA_MONITOR_DESC, 0, mac_for_pdev,
-					  entries)) {
+					  entries, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "rxdma_mon_desc_ring"));
@@ -3195,7 +3246,7 @@ QDF_STATUS dp_mon_rings_setup(struct dp_soc *soc, struct dp_pdev *pdev)
 			if (dp_srng_setup(soc,
 					  &pdev->rxdma_mon_status_ring[mac_id],
 					  RXDMA_MONITOR_STATUS, 0, mac_for_pdev,
-					  entries)) {
+					  entries, 0)) {
 				QDF_TRACE(QDF_MODULE_ID_DP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL(RNG_ERR "rxdma_mon_status_ring"));
@@ -3274,9 +3325,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 	struct cdp_ctrl_objmgr_pdev *ctrl_pdev,
 	HTC_HANDLE htc_handle, qdf_device_t qdf_osdev, uint8_t pdev_id)
 {
-	int tx_ring_size;
-	int tx_comp_ring_size;
-	int reo_dst_ring_size;
+	int ring_size;
 	int entries;
 	struct wlan_cfg_dp_soc_ctxt *soc_cfg_ctx;
 	int nss_cfg;
@@ -3356,19 +3405,22 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 
 	/* Setup per PDEV TCL rings if configured */
 	if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) {
-		tx_ring_size =
+		ring_size =
 			wlan_cfg_tx_ring_size(soc_cfg_ctx);
-		tx_comp_ring_size =
-			wlan_cfg_tx_comp_ring_size(soc_cfg_ctx);
 
 		if (dp_srng_setup(soc, &soc->tcl_data_ring[pdev_id], TCL_DATA,
-			pdev_id, pdev_id, tx_ring_size)) {
+				  pdev_id, pdev_id, ring_size, 0)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				FL("dp_srng_setup failed for tcl_data_ring"));
 			goto fail1;
 		}
+
+		ring_size =
+			wlan_cfg_tx_comp_ring_size(soc_cfg_ctx);
+
 		if (dp_srng_setup(soc, &soc->tx_comp_ring[pdev_id],
-			WBM2SW_RELEASE, pdev_id, pdev_id, tx_comp_ring_size)) {
+				  WBM2SW_RELEASE, pdev_id, pdev_id,
+				  ring_size, 0)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				FL("dp_srng_setup failed for tx_comp_ring"));
 			goto fail1;
@@ -3383,11 +3435,11 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 		goto fail1;
 	}
 
-	reo_dst_ring_size = wlan_cfg_get_reo_dst_ring_size(soc->wlan_cfg_ctx);
+	ring_size = wlan_cfg_get_reo_dst_ring_size(soc->wlan_cfg_ctx);
 	/* Setup per PDEV REO rings if configured */
 	if (wlan_cfg_per_pdev_rx_ring(soc_cfg_ctx)) {
 		if (dp_srng_setup(soc, &soc->reo_dest_ring[pdev_id], REO_DST,
-			pdev_id, pdev_id, reo_dst_ring_size)) {
+				  pdev_id, pdev_id, ring_size, 0)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				FL("dp_srng_setup failed for reo_dest_ringn"));
 			goto fail1;
@@ -3395,8 +3447,12 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 		soc->num_reo_dest_rings++;
 
 	}
+
+	ring_size =
+		wlan_cfg_get_dp_soc_rxdma_refill_ring_size(soc->wlan_cfg_ctx);
+
 	if (dp_srng_setup(soc, &pdev->rx_refill_buf_ring, RXDMA_BUF, 0, pdev_id,
-		wlan_cfg_get_dp_soc_rxdma_refill_ring_size(soc_cfg_ctx))) {
+			  ring_size, 0)) {
 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 			 FL("dp_srng_setup failed rx refill ring"));
 		goto fail1;
@@ -3417,8 +3473,7 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc,
 	entries = wlan_cfg_get_dp_soc_rxdma_err_dst_ring_size(soc_cfg_ctx);
 	if (wlan_cfg_per_pdev_lmac_ring(soc->wlan_cfg_ctx)) {
 		if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring[0], RXDMA_DST,
-				  0, pdev_id,
-				  entries)) {
+				  0, pdev_id, entries, 0)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
 				  FL(RNG_ERR "rxdma_err_dst_ring"));
 			goto fail1;

+ 0 - 3
dp/wifi3.0/dp_tx.c

@@ -3361,9 +3361,6 @@ more_data:
 		pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >>
 			DP_TX_DESC_ID_POOL_OS;
 
-		if (!dp_tx_is_desc_id_valid(soc, tx_desc_id))
-			continue;
-
 		/* Find Tx descriptor */
 		tx_desc = dp_tx_desc_find(soc, pool_id,
 				(tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >>

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

@@ -478,6 +478,7 @@ struct dp_srng {
 	void *base_vaddr_unaligned;
 	qdf_dma_addr_t base_paddr_unaligned;
 	uint32_t alloc_size;
+	uint8_t cached;
 	int irq;
 	uint32_t num_entries;
 };

+ 52 - 21
hal/wifi3.0/hal_api.h

@@ -312,6 +312,7 @@ enum hal_ring_type {
 #define HAL_SRNG_DATA_TLV_SWAP			0x00000020
 #define HAL_SRNG_LOW_THRES_INTR_ENABLE	0x00010000
 #define HAL_SRNG_MSI_INTR				0x00020000
+#define HAL_SRNG_CACHED_DESC		0x00040000
 
 #define PN_SIZE_24 0
 #define PN_SIZE_48 1
@@ -520,6 +521,26 @@ static inline bool hal_srng_initialized(void *hal_ring)
 	return !!srng->initialized;
 }
 
+/**
+ * hal_srng_dst_peek - Check if there are any entries in the ring (peek)
+ * @hal_soc: Opaque HAL SOC handle
+ * @hal_ring: Destination ring pointer
+ *
+ * Caller takes responsibility for any locking needs.
+ *
+ * Return: Opaque pointer for next ring entry; NULL on failire
+ */
+static inline
+void *hal_srng_dst_peek(void *hal_soc, void *hal_ring)
+{
+	struct hal_srng *srng = (struct hal_srng *)hal_ring;
+
+	if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
+		return (void *)(&srng->ring_base_vaddr[srng->u.dst_ring.tp]);
+
+	return NULL;
+}
+
 /**
  * hal_srng_access_start_unlocked - Start ring access (unlocked). Should use
  * hal_srng_access_start if locked access is required
@@ -532,14 +553,30 @@ static inline bool hal_srng_initialized(void *hal_ring)
 static inline int hal_srng_access_start_unlocked(void *hal_soc, void *hal_ring)
 {
 	struct hal_srng *srng = (struct hal_srng *)hal_ring;
+	struct hal_soc *soc = (struct hal_soc *)hal_soc;
+	uint32_t *desc;
 
 	if (srng->ring_dir == HAL_SRNG_SRC_RING)
 		srng->u.src_ring.cached_tp =
 			*(volatile uint32_t *)(srng->u.src_ring.tp_addr);
-	else
+	else {
 		srng->u.dst_ring.cached_hp =
 			*(volatile uint32_t *)(srng->u.dst_ring.hp_addr);
 
+		if (srng->flags & HAL_SRNG_CACHED_DESC) {
+			desc = hal_srng_dst_peek(hal_soc, hal_ring);
+			if (qdf_likely(desc)) {
+				qdf_mem_dma_cache_sync(soc->qdf_dev,
+						       qdf_mem_virt_to_phys
+						       (desc),
+						       QDF_DMA_FROM_DEVICE,
+						       (srng->entry_size *
+							sizeof(uint32_t)));
+				qdf_prefetch(desc);
+			}
+		}
+	}
+
 	return 0;
 }
 
@@ -577,7 +614,10 @@ static inline int hal_srng_access_start(void *hal_soc, void *hal_ring)
 static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring)
 {
 	struct hal_srng *srng = (struct hal_srng *)hal_ring;
+	struct hal_soc *soc = (struct hal_soc *)hal_soc;
 	uint32_t *desc;
+	uint32_t *desc_next;
+	uint32_t tp;
 
 	if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp) {
 		desc = &(srng->ring_base_vaddr[srng->u.dst_ring.tp]);
@@ -590,6 +630,17 @@ static inline void *hal_srng_dst_get_next(void *hal_soc, void *hal_ring)
 		srng->u.dst_ring.tp = (srng->u.dst_ring.tp + srng->entry_size) %
 			srng->ring_size;
 
+		if (srng->flags & HAL_SRNG_CACHED_DESC) {
+			tp = srng->u.dst_ring.tp;
+			desc_next = &srng->ring_base_vaddr[tp];
+			qdf_mem_dma_cache_sync(soc->qdf_dev,
+					       qdf_mem_virt_to_phys(desc_next),
+					       QDF_DMA_FROM_DEVICE,
+					       (srng->entry_size *
+						sizeof(uint32_t)));
+			qdf_prefetch(desc_next);
+		}
+
 		return (void *)desc;
 	}
 
@@ -627,26 +678,6 @@ static inline void *hal_srng_dst_get_next_hp(void *hal_soc, void *hal_ring)
 	return NULL;
 }
 
-/**
- * hal_srng_dst_peek - Check if there are any entries in the ring (peek)
- * @hal_soc: Opaque HAL SOC handle
- * @hal_ring: Destination ring pointer
- *
- * Caller takes responsibility for any locking needs.
- *
- * Return: Opaque pointer for next ring entry; NULL on failire
- */
-static inline
-void *hal_srng_dst_peek(void *hal_soc, void *hal_ring)
-{
-	struct hal_srng *srng = (struct hal_srng *)hal_ring;
-
-	if (srng->u.dst_ring.tp != srng->u.dst_ring.cached_hp)
-		return (void *)(&srng->ring_base_vaddr[srng->u.dst_ring.tp]);
-
-	return NULL;
-}
-
 /**
  * hal_srng_dst_peek_sync - Check if there are any entries in the ring (peek)
  * @hal_soc: Opaque HAL SOC handle

+ 4 - 9
hal/wifi3.0/hal_rx.h

@@ -466,13 +466,11 @@ static inline void hal_rx_mpdu_desc_info_get(void *desc_addr,
 				struct hal_rx_mpdu_desc_info *mpdu_desc_info)
 {
 	struct reo_destination_ring *reo_dst_ring;
-	uint32_t mpdu_info[NUM_OF_DWORDS_RX_MPDU_DESC_INFO];
+	uint32_t *mpdu_info;
 
 	reo_dst_ring = (struct reo_destination_ring *) desc_addr;
 
-	qdf_mem_copy(&mpdu_info,
-			(const void *)&reo_dst_ring->rx_mpdu_desc_info_details,
-			sizeof(struct rx_mpdu_desc_info));
+	mpdu_info = (uint32_t *)&reo_dst_ring->rx_mpdu_desc_info_details;
 
 	mpdu_desc_info->msdu_count = HAL_RX_MPDU_MSDU_COUNT_GET(mpdu_info);
 	mpdu_desc_info->mpdu_seq = HAL_RX_MPDU_SEQUENCE_NUMBER_GET(mpdu_info);
@@ -498,14 +496,11 @@ static inline void hal_rx_msdu_desc_info_get(void *desc_addr,
 			       struct hal_rx_msdu_desc_info *msdu_desc_info)
 {
 	struct reo_destination_ring *reo_dst_ring;
-	uint32_t msdu_info[NUM_OF_DWORDS_RX_MSDU_DESC_INFO];
+	uint32_t *msdu_info;
 
 	reo_dst_ring = (struct reo_destination_ring *) desc_addr;
 
-	qdf_mem_copy(&msdu_info,
-			(const void *)&reo_dst_ring->rx_msdu_desc_info_details,
-			sizeof(struct rx_msdu_desc_info));
-
+	msdu_info = (uint32_t *)&reo_dst_ring->rx_msdu_desc_info_details;
 	msdu_desc_info->msdu_flags = HAL_RX_MSDU_FLAGS_GET(msdu_info);
 	msdu_desc_info->msdu_len = HAL_RX_MSDU_PKT_LENGTH_GET(msdu_info);
 }

+ 9 - 0
qdf/inc/qdf_mem.h

@@ -310,6 +310,7 @@ void *qdf_aligned_mem_alloc_consistent_fl(
 	void **vaddr_unaligned, qdf_dma_addr_t *paddr_unaligned,
 	qdf_dma_addr_t *paddr_aligned, uint32_t ring_base_align,
 	const char *func, uint32_t line);
+#define qdf_mem_virt_to_phys(vaddr) virt_to_phys(vaddr)
 
 void qdf_mem_set_io(void *ptr, uint32_t num_bytes, uint32_t value);
 
@@ -414,6 +415,14 @@ static inline uint32_t qdf_mem_map_nbytes_single(qdf_device_t osdev, void *buf,
 #endif
 }
 
+static inline void qdf_mem_dma_cache_sync(qdf_device_t osdev,
+					  qdf_dma_addr_t buf,
+					  qdf_dma_dir_t dir,
+					  int nbytes)
+{
+	__qdf_mem_dma_cache_sync(osdev, buf, dir, nbytes);
+}
+
 /**
  * qdf_mem_unmap_nbytes_single() - un_map memory for DMA
  * @osdev: pomter OS device context

+ 7 - 0
qdf/inc/qdf_util.h

@@ -551,6 +551,13 @@ static inline uint8_t *qdf_get_u32(uint8_t *ptr, uint32_t *value)
  */
 #define qdf_ffz(mask) __qdf_ffz(mask)
 
+/**
+ * qdf_prefetch - prefetches the cacheline for read
+ *
+ * @x: address to be prefetched
+ */
+#define qdf_prefetch(x)                   __qdf_prefetch(x)
+
 /**
  * qdf_get_pwr2() - get next power of 2 integer from input value
  * @value: input value to find next power of 2 integer

+ 19 - 0
qdf/linux/src/i_qdf_mem.h

@@ -149,6 +149,25 @@ static inline uint32_t __qdf_mem_map_nbytes_single(qdf_device_t osdev,
 	QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+static inline void __qdf_mem_dma_cache_sync(qdf_device_t osdev,
+					    qdf_dma_addr_t buf,
+					    qdf_dma_dir_t dir,
+					    int nbytes)
+{
+	dma_cache_sync(osdev->dev, buf, nbytes, __qdf_dma_dir_to_os(dir));
+}
+#else
+static inline void __qdf_mem_dma_cache_sync(qdf_device_t osdev,
+					    qdf_dma_addr_t buf,
+					    qdf_dma_dir_t dir,
+					    int nbytes)
+{
+	dma_sync_single_for_cpu(osdev->dev, buf, nbytes,
+				__qdf_dma_dir_to_os(dir));
+}
+#endif
+
 /**
  * __qdf_mem_unmap_nbytes_single() - un_map memory for DMA
  *

+ 2 - 0
qdf/linux/src/i_qdf_util.h

@@ -279,6 +279,8 @@ static inline bool __qdf_is_macaddr_equal(struct qdf_mac_addr *mac_addr1,
 	ewma_rx_rssi_read(rx_rssi)
 #endif
 
+#define __qdf_prefetch(x)     prefetch(x)
+
 #ifdef QCA_CONFIG_SMP
 /**
  * __qdf_get_cpu() - get cpu_index

+ 2 - 0
wlan_cfg/wlan_cfg.h

@@ -24,6 +24,7 @@
  * or platform configuration
  */
 #if defined(CONFIG_MCL)
+#define WLAN_CFG_DST_RING_CACHED_DESC 0
 #define MAX_PDEV_CNT 1
 #define WLAN_CFG_INT_NUM_CONTEXTS 7
 #define WLAN_CFG_RXDMA1_ENABLE 1
@@ -38,6 +39,7 @@
 
 #define NUM_RXDMA_RINGS_PER_PDEV 2
 #else
+#define WLAN_CFG_DST_RING_CACHED_DESC 1
 #define MAX_PDEV_CNT 3
 #define WLAN_CFG_INT_NUM_CONTEXTS 11
 #define WLAN_CFG_RXDMA1_ENABLE 1