Ver código fonte

qcacmn: Use next link_desc instead of msdu_count

MSDU count is not reliable in all cases.Hence it is better
to check whether next_link_desc is valid or not and then
free the MSDUs in the next descriptor and subsequently
release both the current and next link descriptor back to HW.

Change-Id: Ie5ea3be547f9aed6673293221f6b47661cd92cce
Debasis Das 4 anos atrás
pai
commit
59d63401a5
2 arquivos alterados com 84 adições e 26 exclusões
  1. 67 26
      dp/wifi3.0/dp_rx_err.c
  2. 17 0
      hal/wifi3.0/hal_rx.h

+ 67 - 26
dp/wifi3.0/dp_rx_err.c

@@ -297,19 +297,24 @@ dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc,
 	uint8_t *rx_tlv_hdr;
 	uint32_t tid;
 	struct rx_desc_pool *rx_desc_pool;
+	struct dp_rx_desc *rx_desc;
+	/* First field in REO Dst ring Desc is buffer_addr_info */
+	void *buf_addr_info = ring_desc;
+	struct buffer_addr_info cur_link_desc_addr_info = { 0 };
+	struct buffer_addr_info next_link_desc_addr_info = { 0 };
 
 	hal_rx_reo_buf_paddr_get(ring_desc, &buf_info);
 
 	link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &buf_info);
 
+more_msdu_link_desc:
 	/* No UNMAP required -- this is "malloc_consistent" memory */
 	hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list,
 			     &mpdu_desc_info->msdu_count);
 
-	for (i = 0; (i < mpdu_desc_info->msdu_count) && quota--; i++) {
-		struct dp_rx_desc *rx_desc =
-			dp_rx_cookie_2_va_rxdma_buf(soc,
-			msdu_list.sw_cookie[i]);
+	for (i = 0; (i < mpdu_desc_info->msdu_count); i++) {
+		rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc,
+						      msdu_list.sw_cookie[i]);
 
 		qdf_assert_always(rx_desc);
 
@@ -358,9 +363,38 @@ dp_rx_msdus_drop(struct dp_soc *soc, hal_ring_desc_t ring_desc,
 					    &pdev->free_list_tail, rx_desc);
 	}
 
-	/* Return link descriptor through WBM ring (SW2WBM)*/
-	dp_rx_link_desc_return(soc, ring_desc, HAL_BM_ACTION_PUT_IN_IDLE_LIST);
+	/*
+	 * If the msdu's are spread across multiple link-descriptors,
+	 * we cannot depend solely on the msdu_count(e.g., if msdu is
+	 * spread across multiple buffers).Hence, it is
+	 * necessary to check the next link_descriptor and release
+	 * all the msdu's that are part of it.
+	 */
+	hal_rx_get_next_msdu_link_desc_buf_addr_info(
+			link_desc_va,
+			&next_link_desc_addr_info);
+
+	if (hal_rx_is_buf_addr_info_valid(
+				&next_link_desc_addr_info)) {
+		/* Clear the next link desc info for the current link_desc */
+		hal_rx_clear_next_msdu_link_desc_buf_addr_info(link_desc_va);
+
+		dp_rx_link_desc_return_by_addr(soc, buf_addr_info,
+					       HAL_BM_ACTION_PUT_IN_IDLE_LIST);
+		hal_rx_buffer_addr_info_get_paddr(
+				&next_link_desc_addr_info,
+				&buf_info);
+		cur_link_desc_addr_info = next_link_desc_addr_info;
+		buf_addr_info = &cur_link_desc_addr_info;
+
+		link_desc_va =
+			dp_rx_cookie_2_link_desc_va(soc, &buf_info);
 
+		goto more_msdu_link_desc;
+	}
+	quota--;
+	dp_rx_link_desc_return_by_addr(soc, buf_addr_info,
+				       HAL_BM_ACTION_PUT_IN_IDLE_LIST);
 	return rx_bufs_used;
 }
 
@@ -588,28 +622,35 @@ process_next_msdu:
 		tail_nbuf = NULL;
 	}
 
-	if (msdu_processed < mpdu_desc_info->msdu_count) {
-		hal_rx_get_next_msdu_link_desc_buf_addr_info(
-						link_desc_va,
-						&next_link_desc_addr_info);
+	/*
+	 * If the msdu's are spread across multiple link-descriptors,
+	 * we cannot depend solely on the msdu_count(e.g., if msdu is
+	 * spread across multiple buffers).Hence, it is
+	 * necessary to check the next link_descriptor and release
+	 * all the msdu's that are part of it.
+	 */
+	hal_rx_get_next_msdu_link_desc_buf_addr_info(
+			link_desc_va,
+			&next_link_desc_addr_info);
 
-		if (hal_rx_is_buf_addr_info_valid(
+	if (hal_rx_is_buf_addr_info_valid(
 				&next_link_desc_addr_info)) {
-			dp_rx_link_desc_return_by_addr(
-					soc,
-					buf_addr_info,
-					HAL_BM_ACTION_PUT_IN_IDLE_LIST);
-
-			hal_rx_buffer_addr_info_get_paddr(
-						&next_link_desc_addr_info,
-						&buf_info);
-			link_desc_va =
-				dp_rx_cookie_2_link_desc_va(soc, &buf_info);
-			cur_link_desc_addr_info = next_link_desc_addr_info;
-			buf_addr_info = &cur_link_desc_addr_info;
-
-			goto more_msdu_link_desc;
-		}
+		/* Clear the next link desc info for the current link_desc */
+		hal_rx_clear_next_msdu_link_desc_buf_addr_info(link_desc_va);
+		dp_rx_link_desc_return_by_addr(
+				soc,
+				buf_addr_info,
+				HAL_BM_ACTION_PUT_IN_IDLE_LIST);
+
+		hal_rx_buffer_addr_info_get_paddr(
+				&next_link_desc_addr_info,
+				&buf_info);
+		link_desc_va =
+			dp_rx_cookie_2_link_desc_va(soc, &buf_info);
+		cur_link_desc_addr_info = next_link_desc_addr_info;
+		buf_addr_info = &cur_link_desc_addr_info;
+
+		goto more_msdu_link_desc;
 	}
 
 	dp_rx_link_desc_return_by_addr(soc, buf_addr_info,

+ 17 - 0
hal/wifi3.0/hal_rx.h

@@ -3846,6 +3846,23 @@ void hal_rx_get_next_msdu_link_desc_buf_addr_info(
 	*next_addr_info = msdu_link->next_msdu_link_desc_addr_info;
 }
 
+/**
+ * hal_rx_clear_next_msdu_link_desc_buf_addr_info(): clear next msdu link desc
+ *						     buffer addr info
+ * @link_desc_va: pointer to current msdu link Desc
+ *
+ * return: None
+ */
+static inline
+void hal_rx_clear_next_msdu_link_desc_buf_addr_info(void *link_desc_va)
+{
+	struct rx_msdu_link *msdu_link = link_desc_va;
+
+	if (msdu_link)
+		qdf_mem_zero(&msdu_link->next_msdu_link_desc_addr_info,
+			     sizeof(msdu_link->next_msdu_link_desc_addr_info));
+}
+
 /**
  * hal_rx_is_buf_addr_info_valid(): check is the buf_addr_info valid
  *