Browse Source

qcacmn: REO descriptor allocation change

Use normal allocation instead of alloc_consistent for REO descriptors to
allow freeing from interrupt context.
Also fixed an issue in ba_window_size setting in REO queues.

Change-Id: I91b06e04c0343eb7fe8580d8655c6bc5e33cfe06
Karunakar Dasineni 8 years ago
parent
commit
7957fa9705
6 changed files with 67 additions and 34 deletions
  1. 5 4
      dp/wifi3.0/dp_main.c
  2. 53 27
      dp/wifi3.0/dp_peer.c
  3. 4 1
      hal/wifi3.0/hal_reo.c
  4. 3 0
      hal/wifi3.0/hal_rx.c
  5. 1 1
      qdf/inc/qdf_mem.h
  6. 1 1
      qdf/linux/src/i_qdf_mem.h

+ 5 - 4
dp/wifi3.0/dp_main.c

@@ -1313,10 +1313,11 @@ static inline void dp_reo_desc_freelist_destroy(struct dp_soc *soc)
 	while (qdf_list_remove_front(&soc->reo_desc_freelist,
 		(qdf_list_node_t **)&desc) == QDF_STATUS_SUCCESS) {
 		rx_tid = &desc->rx_tid;
-		qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
-			rx_tid->hw_qdesc_alloc_size,
-			rx_tid->hw_qdesc_vaddr_unaligned,
-			rx_tid->hw_qdesc_paddr_unaligned, 0);
+		qdf_mem_unmap_nbytes_single(soc->osdev,
+			rx_tid->hw_qdesc_paddr_unaligned,
+			QDF_DMA_BIDIRECTIONAL,
+			rx_tid->hw_qdesc_alloc_size);
+		qdf_mem_free(rx_tid->hw_qdesc_vaddr_unaligned);
 		qdf_mem_free(desc);
 	}
 	qdf_spin_unlock_bh(&soc->reo_desc_freelist_lock);

+ 53 - 27
dp/wifi3.0/dp_peer.c

@@ -534,15 +534,11 @@ static void dp_reo_desc_free(struct dp_soc *soc,
 				(qdf_list_node_t **)&desc);
 		list_size--;
 		rx_tid = &desc->rx_tid;
-	/* Calling qdf_mem_free_consistent() in MCL is resulting in kernel BUG.
-	 * Diasble this temporarily.
-	 */
-#ifndef QCA_WIFI_NAPIER_EMULATION
-		qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
-			rx_tid->hw_qdesc_alloc_size,
-			rx_tid->hw_qdesc_vaddr_unaligned,
-			rx_tid->hw_qdesc_paddr_unaligned, 0);
-#endif
+		qdf_mem_unmap_nbytes_single(soc->osdev,
+			rx_tid->hw_qdesc_paddr_unaligned,
+			QDF_DMA_BIDIRECTIONAL,
+			rx_tid->hw_qdesc_alloc_size);
+		qdf_mem_free(rx_tid->hw_qdesc_vaddr_unaligned);
 		qdf_mem_free(desc);
 
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
@@ -552,6 +548,23 @@ static void dp_reo_desc_free(struct dp_soc *soc,
 	qdf_spin_unlock_bh(&soc->reo_desc_freelist_lock);
 }
 
+#if defined(QCA_WIFI_QCA8074) && defined(BUILD_X86)
+/* Hawkeye emulation requires bus address to be >= 0x50000000 */
+static inline int dp_reo_desc_addr_chk(qdf_dma_addr_t dma_addr)
+{
+	if (dma_addr < 0x50000000)
+		return QDF_STATUS_E_FAILURE;
+	else
+		return QDF_STATUS_SUCCESS;
+}
+#else
+static inline int dp_reo_desc_addr_chk(qdf_dma_addr_t dma_addr)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+
 /*
  * dp_rx_tid_setup_wifi3() – Setup receive TID state
  * @peer: Datapath peer handle
@@ -562,7 +575,7 @@ static void dp_reo_desc_free(struct dp_soc *soc,
  * Return: 0 on success, error code on failure
  */
 int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
-				 uint32_t ba_window_size, uint32_t start_seq)
+	uint32_t ba_window_size, uint32_t start_seq)
 {
 	struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
 	struct dp_vdev *vdev = peer->vdev;
@@ -571,6 +584,7 @@ int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 	uint32_t hw_qdesc_align;
 	int hal_pn_type;
 	void *hw_qdesc_vaddr;
+	uint32_t alloc_tries = 0;
 
 	if (rx_tid->hw_qdesc_vaddr_unaligned != NULL)
 		return dp_rx_tid_update_wifi3(peer, tid, ba_window_size,
@@ -600,9 +614,10 @@ int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 	 * exact size and see if we already have aligned address.
 	 */
 	rx_tid->hw_qdesc_alloc_size = hw_qdesc_size;
-	rx_tid->hw_qdesc_vaddr_unaligned = qdf_mem_alloc_consistent(
-		soc->osdev, soc->osdev->dev, rx_tid->hw_qdesc_alloc_size,
-		&(rx_tid->hw_qdesc_paddr_unaligned));
+
+try_desc_alloc:
+	rx_tid->hw_qdesc_vaddr_unaligned =
+		qdf_mem_malloc(rx_tid->hw_qdesc_alloc_size);
 
 	if (!rx_tid->hw_qdesc_vaddr_unaligned) {
 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
@@ -616,16 +631,11 @@ int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 		/* Address allocated above is not alinged. Allocate extra
 		 * memory for alignment
 		 */
-		qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
-				rx_tid->hw_qdesc_alloc_size,
-				rx_tid->hw_qdesc_vaddr_unaligned,
-				rx_tid->hw_qdesc_paddr_unaligned, 0);
-
+		qdf_mem_free(rx_tid->hw_qdesc_vaddr_unaligned);
 		rx_tid->hw_qdesc_alloc_size =
 			hw_qdesc_size + hw_qdesc_align - 1;
-		rx_tid->hw_qdesc_vaddr_unaligned = qdf_mem_alloc_consistent(
-			soc->osdev, soc->osdev->dev, rx_tid->hw_qdesc_alloc_size,
-			&(rx_tid->hw_qdesc_paddr_unaligned));
+		rx_tid->hw_qdesc_vaddr_unaligned =
+			qdf_mem_malloc(rx_tid->hw_qdesc_alloc_size);
 
 		if (!rx_tid->hw_qdesc_vaddr_unaligned) {
 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
@@ -637,13 +647,8 @@ int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 		hw_qdesc_vaddr = rx_tid->hw_qdesc_vaddr_unaligned +
 			((unsigned long)(rx_tid->hw_qdesc_vaddr_unaligned) %
 			hw_qdesc_align);
-
-		rx_tid->hw_qdesc_paddr = rx_tid->hw_qdesc_paddr_unaligned +
-			((unsigned long)hw_qdesc_vaddr -
-			(unsigned long)(rx_tid->hw_qdesc_vaddr_unaligned));
 	} else {
 		hw_qdesc_vaddr = rx_tid->hw_qdesc_vaddr_unaligned;
-		rx_tid->hw_qdesc_paddr = rx_tid->hw_qdesc_paddr_unaligned;
 	}
 
 	/* TODO: Ensure that sec_type is set before ADDBA is received.
@@ -672,6 +677,27 @@ int dp_rx_tid_setup_wifi3(struct dp_peer *peer, int tid,
 	hal_reo_qdesc_setup(soc->hal_soc, tid, ba_window_size, start_seq,
 		hw_qdesc_vaddr, rx_tid->hw_qdesc_paddr, hal_pn_type);
 
+	qdf_mem_map_nbytes_single(soc->osdev, rx_tid->hw_qdesc_vaddr_unaligned,
+		QDF_DMA_BIDIRECTIONAL, rx_tid->hw_qdesc_alloc_size,
+		&(rx_tid->hw_qdesc_paddr_unaligned));
+
+	if (dp_reo_desc_addr_chk(rx_tid->hw_qdesc_paddr_unaligned) !=
+			QDF_STATUS_SUCCESS) {
+		if (alloc_tries++ < 10)
+			goto try_desc_alloc;
+		else {
+			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
+			"%s: Rx tid HW desc alloc failed (lowmem): tid %d\n",
+			__func__, tid);
+			return QDF_STATUS_E_NOMEM;
+		}
+	}
+
+	rx_tid->hw_qdesc_paddr = rx_tid->hw_qdesc_paddr_unaligned +
+		((unsigned long)hw_qdesc_vaddr -
+		(unsigned long)(rx_tid->hw_qdesc_vaddr_unaligned));
+
+
 	if (soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup) {
 		soc->cdp_soc.ol_ops->peer_rx_reorder_queue_setup(
 			vdev->pdev->osif_pdev,
@@ -944,7 +970,7 @@ int dp_delba_process_wifi3(void *peer_handle,
 	 * replace with a new one without queue extenstion descript to save
 	 * memory
 	 */
-	dp_rx_tid_update_wifi3(peer, tid, 0, 0);
+	dp_rx_tid_update_wifi3(peer, tid, 1, 0);
 
 	rx_tid->ba_status = DP_RX_BA_INACTIVE;
 

+ 4 - 1
hal/wifi3.0/hal_reo.c

@@ -481,8 +481,11 @@ inline int hal_reo_cmd_update_rx_queue(void *reo_ring, struct hal_soc *soc,
 	HAL_DESC_SET_FIELD(reo_desc, REO_UPDATE_RX_REO_QUEUE_3,
 		IGNORE_AMPDU_FLAG, p->ignore_ampdu);
 
+	if (p->ba_window_size < 1)
+		p->ba_window_size = 1;
+
 	HAL_DESC_SET_FIELD(reo_desc, REO_UPDATE_RX_REO_QUEUE_4,
-		BA_WINDOW_SIZE, p->ba_window_size);
+		BA_WINDOW_SIZE, p->ba_window_size - 1);
 
 	HAL_DESC_SET_FIELD(reo_desc, REO_UPDATE_RX_REO_QUEUE_4,
 		PN_SIZE, p->pn_size);

+ 3 - 0
hal/wifi3.0/hal_rx.c

@@ -136,6 +136,9 @@ void hal_reo_qdesc_setup(void *hal_soc, int tid, uint32_t ba_window_size,
 	reg_val = TID_TO_WME_AC(tid);
 	HAL_DESC_SET_FIELD(reo_queue_desc, RX_REO_QUEUE_2, AC, reg_val);
 
+	if (ba_window_size < 1)
+		ba_window_size = 1;
+
 	/* Set RTY bit for non-BA case. Duplicate detection is currently not
 	 * done by HW in non-BA case if RTY bit is not set.
 	 * TODO: This is a temporary War and should be removed once HW fix is

+ 1 - 1
qdf/inc/qdf_mem.h

@@ -210,7 +210,7 @@ static inline uint32_t qdf_mem_map_nbytes_single(qdf_device_t osdev, void *buf,
  * Return: none
  */
 static inline void qdf_mem_unmap_nbytes_single(qdf_device_t osdev,
-					       uint32_t phy_addr,
+					       qdf_dma_addr_t phy_addr,
 					       qdf_dma_dir_t dir,
 					       int nbytes)
 {

+ 1 - 1
qdf/linux/src/i_qdf_mem.h

@@ -160,7 +160,7 @@ static inline uint32_t __qdf_mem_map_nbytes_single(qdf_device_t osdev,
  * @return - none
  */
 static inline void __qdf_mem_unmap_nbytes_single(qdf_device_t osdev,
-						 uint32_t phy_addr,
+						 qdf_dma_addr_t phy_addr,
 						 qdf_dma_dir_t dir, int nbytes)
 {
 	dma_unmap_single(osdev->dev, phy_addr, nbytes, dir);