Ver código fonte

qcacld-3.0: Add detection of non-posted rx buffers

Add detection of non posted RX buffers from FW (rx_in_order_ind msgs)
by marking the higher(16) unused bits of the 64-bit physical addresses.
On reception, if the paddr received does not have the markings, assert,
otherwise clean the markings and proceed.

Duplicate rx-buffers will be detected in the FW.

CRs-Fixed: 2000844
Change-Id: I9c50cce182a12f3edd3c5b2606836d62f684f816
Orhan K AKYILDIZ 8 anos atrás
pai
commit
c8c27be649
1 arquivos alterados com 90 adições e 26 exclusões
  1. 90 26
      core/dp/htt/htt_rx.c

+ 90 - 26
core/dp/htt/htt_rx.c

@@ -345,6 +345,74 @@ htt_rx_msdu_first_msdu_flag_ll(htt_pdev_handle pdev, void *msdu_desc)
 
 #ifndef CONFIG_HL_SUPPORT
 
+#define RX_PADDR_MAGIC_PATTERN 0xDEAD0000
+static qdf_dma_addr_t
+htt_rx_paddr_mark_high_bits(qdf_dma_addr_t paddr)
+{
+#ifdef HELIUMPLUS_PADDR64
+	if (sizeof(qdf_dma_addr_t) > 4) {
+		/* clear high bits, leave lower 37 bits (paddr) */
+		paddr &= 0x01FFFFFFFFF;
+		/* mark upper 16 bits of paddr */
+		paddr |= (((uint64_t)RX_PADDR_MAGIC_PATTERN) << 32);
+	}
+#endif
+	return paddr;
+}
+
+#ifdef HELIUMPLUS_PADDR64
+static qdf_dma_addr_t
+htt_rx_paddr_unmark_high_bits(qdf_dma_addr_t paddr)
+{
+	uint32_t markings;
+
+	if (sizeof(qdf_dma_addr_t) > 4) {
+		markings = (uint32_t)((paddr >> 16) >> 16);
+		/*
+		 * check if it is marked correctly:
+		 * See the mark_high_bits function above for the expected
+		 * pattern.
+		 * the LS 5 bits are the high bits of physical address
+		 * padded (with 0b0) to 8 bits
+		 */
+		if ((markings & 0xFFFF0000) != RX_PADDR_MAGIC_PATTERN) {
+			qdf_print("%s: paddr not marked correctly: 0x%p!\n",
+				  __func__, (void *)paddr);
+			HTT_ASSERT_ALWAYS(0);
+		}
+
+		/* clear markings  for further use */
+		paddr &= (uint64_t)0x1ffffffff; /* LS 37 bits */
+	}
+	return paddr;
+}
+
+static qdf_dma_addr_t
+htt_rx_in_ord_paddr_get(uint32_t *u32p)
+{
+	qdf_dma_addr_t paddr = 0;
+
+	paddr = (qdf_dma_addr_t)HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p);
+	if (sizeof(qdf_dma_addr_t) > 4) {
+		u32p++;
+		paddr |= ((qdf_dma_addr_t)
+			(HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p) << 16) << 16);
+	}
+	paddr = htt_rx_paddr_unmark_high_bits(paddr);
+
+	return paddr;
+}
+#else
+static inline qdf_dma_addr_t
+htt_rx_in_ord_paddr_get(uint32_t *u32p)
+{
+	return HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*u32p);
+}
+#endif /* HELIUMPLUS_PADDR64 */
+#endif /* CONFIG_HL_SUPPORT*/
+
+#ifndef CONFIG_HL_SUPPORT
+
 static int htt_rx_ring_size(struct htt_pdev_t *pdev)
 {
 	int size;
@@ -483,6 +551,7 @@ moretofill:
 			goto fail;
 		}
 		paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0);
+		paddr = htt_rx_paddr_mark_high_bits(paddr);
 		if (pdev->cfg.is_full_reorder_offload) {
 			if (qdf_unlikely(htt_rx_hash_list_insert(
 					pdev, (uint32_t)paddr, rx_netbuf))) {
@@ -503,9 +572,6 @@ moretofill:
 		} else {
 			pdev->rx_ring.buf.netbufs_ring[idx] = rx_netbuf;
 		}
-#if HTT_PADDR64
-		paddr &= 0x1fffffffff; /* trim out higher than 37 bits */
-#endif /* HTT_PADDR64 */
 		pdev->rx_ring.buf.paddrs_ring[idx] = paddr;
 		pdev->rx_ring.fill_cnt++;
 
@@ -858,11 +924,11 @@ static inline qdf_nbuf_t htt_rx_netbuf_pop(htt_pdev_handle pdev)
 }
 
 static inline qdf_nbuf_t
-htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, uint32_t paddr)
+htt_rx_in_order_netbuf_pop(htt_pdev_handle pdev, qdf_dma_addr_t paddr)
 {
 	HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
 	pdev->rx_ring.fill_cnt--;
-	return htt_rx_hash_list_lookup(pdev, paddr);
+	return htt_rx_hash_list_lookup(pdev, (uint32_t)(paddr & 0xffffffff));
 }
 
 /* FIX ME: this function applies only to LL rx descs.
@@ -1417,11 +1483,11 @@ htt_rx_offload_paddr_msdu_pop_ll(htt_pdev_handle pdev,
 	qdf_nbuf_t buf;
 	uint32_t *msdu_hdr, msdu_len;
 	uint32_t *curr_msdu;
-	uint32_t paddr;
+	qdf_dma_addr_t paddr;
 
 	curr_msdu =
 		msg_word + (msdu_iter * HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS);
-	paddr = HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*curr_msdu);
+	paddr = htt_rx_in_ord_paddr_get(curr_msdu);
 	*head_buf = *tail_buf = buf = htt_rx_in_order_netbuf_pop(pdev, paddr);
 
 	if (qdf_unlikely(NULL == buf)) {
@@ -1491,10 +1557,11 @@ int htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu, htt_pdev_handle pdev,
 	qdf_nbuf_t prev_frag_nbuf;
 	uint32_t len;
 	uint32_t last_frag;
+	qdf_dma_addr_t paddr;
 
 	*msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
-	frag_nbuf = htt_rx_in_order_netbuf_pop(pdev,
-				HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(**msg_word));
+	paddr = htt_rx_in_ord_paddr_get(*msg_word);
+	frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr);
 	if (qdf_unlikely(NULL == frag_nbuf)) {
 		qdf_print("%s: netbuf pop failed!\n", __func__);
 		return 0;
@@ -1516,8 +1583,8 @@ int htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu, htt_pdev_handle pdev,
 	prev_frag_nbuf = frag_nbuf;
 	while (!last_frag) {
 		*msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
-		frag_nbuf = htt_rx_in_order_netbuf_pop(pdev,
-				HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(**msg_word));
+		paddr = htt_rx_in_ord_paddr_get(*msg_word);
+		frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, paddr);
 		last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)
 			     *msg_word)->msdu_info;
 
@@ -1804,6 +1871,7 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 	uint32_t amsdu_len;
 	uint32_t len;
 	uint32_t last_frag;
+	qdf_dma_addr_t paddr;
 
 	HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
 
@@ -1821,9 +1889,8 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 
 	msg_word = (uint32_t *)(rx_ind_data +
 				 HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES);
-
-	(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev,
-				HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
+	paddr = htt_rx_in_ord_paddr_get(msg_word);
+	(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, paddr);
 
 	if (qdf_unlikely(NULL == msdu)) {
 		qdf_print("%s: netbuf pop failed!\n", __func__);
@@ -1897,8 +1964,8 @@ static int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 		/* check if this is the last msdu */
 		if (msdu_count) {
 			msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
-			next = htt_rx_in_order_netbuf_pop(pdev,
-				HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
+			paddr = htt_rx_in_ord_paddr_get(msg_word);
+			next = htt_rx_in_order_netbuf_pop(pdev, paddr);
 			if (qdf_unlikely(NULL == next)) {
 				qdf_print("%s: netbuf pop failed!\n",
 					     __func__);
@@ -1955,6 +2022,7 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 	uint8_t peer_id;
 	struct htt_host_rx_desc_base *rx_desc;
 	enum rx_pkt_fate status = RX_PKT_FATE_SUCCESS;
+	qdf_dma_addr_t paddr;
 
 	HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0);
 
@@ -1983,9 +2051,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 		return 0;
 	}
 
-	(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(
-		pdev,
-		HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
+	paddr = htt_rx_in_ord_paddr_get(msg_word);
+	(*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, paddr);
 
 	if (qdf_unlikely(NULL == msdu)) {
 		qdf_print("%s: netbuf pop failed!\n", __func__);
@@ -2077,10 +2144,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 			} else { /* if this is not the last msdu */
 				/* get the next msdu */
 				msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
-				next = htt_rx_in_order_netbuf_pop(
-					pdev,
-					HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(
-						*msg_word));
+				paddr = htt_rx_in_ord_paddr_get(msg_word);
+				next = htt_rx_in_order_netbuf_pop(pdev, paddr);
 				if (qdf_unlikely(NULL == next)) {
 					qdf_print("%s: netbuf pop failed!\n",
 								 __func__);
@@ -2110,9 +2175,8 @@ htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev,
 		/* check if this is the last msdu */
 		if (msdu_count) {
 			msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS;
-			next = htt_rx_in_order_netbuf_pop(
-				pdev,
-				HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word));
+			paddr = htt_rx_in_ord_paddr_get(msg_word);
+			next = htt_rx_in_order_netbuf_pop(pdev, paddr);
 			if (qdf_unlikely(NULL == next)) {
 				qdf_print("%s: netbuf pop failed!\n",
 					  __func__);