Procházet zdrojové kódy

qcacmn: Enable intra-bss in Waikiki

In Beryllium the HW does the ast lookup and match
and sets the intra-bss bit in the msdu_desc_info
structure of reo_destination ring and WBM Rx release ring.

So, change the Beryllium code to make use of this
hardware assistance for intra-bss.

Change-Id: Ic7c89efc741fefe35603082309204fbe3c9a97c7
Pavankumar Nandeshwar před 3 roky
rodič
revize
26c6cd1397

+ 126 - 2
dp/wifi3.0/be/dp_be_rx.c

@@ -20,6 +20,7 @@
 #include "hal_hw_headers.h"
 #include "dp_types.h"
 #include "dp_rx.h"
+#include "dp_tx.h"
 #include "dp_be_rx.h"
 #include "dp_peer.h"
 #include "hal_rx.h"
@@ -339,6 +340,9 @@ more_data:
 		if (msdu_desc_info.msdu_flags & HAL_MSDU_F_SA_IS_VALID)
 			qdf_nbuf_set_sa_valid(rx_desc->nbuf, 1);
 
+		if (msdu_desc_info.msdu_flags & HAL_MSDU_F_INTRA_BSS)
+			qdf_nbuf_set_intra_bss(rx_desc->nbuf, 1);
+
 		qdf_nbuf_set_tid_val(rx_desc->nbuf,
 				     HAL_RX_REO_QUEUE_NUMBER_GET(ring_desc));
 #ifdef CONFIG_LITHIUM
@@ -685,8 +689,9 @@ done:
 
 			/* Intrabss-fwd */
 			if (dp_rx_check_ap_bridge(vdev))
-				if (DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr,
-						       nbuf, msdu_metadata)) {
+				if (dp_rx_intrabss_fwd_be(soc, peer, rx_tlv_hdr,
+							  nbuf,
+							  msdu_metadata)) {
 					nbuf = next;
 					tid_stats->intrabss_cnt++;
 					continue; /* Get next desc */
@@ -1025,3 +1030,122 @@ uint32_t dp_rx_nf_process(struct dp_intr *int_ctx,
 	return work_done;
 }
 #endif
+
+#ifndef QCA_HOST_MODE_WIFI_DISABLED
+#if defined(QCA_WIFI_WCN7850) || !defined(INTRA_BSS_FW_OFFLOAD)
+bool dp_rx_intrabss_fwd_be(struct dp_soc *soc, struct dp_peer *ta_peer,
+			   uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf,
+			   struct hal_rx_msdu_metadata msdu_metadata)
+{
+	/* Hamilton V1 uses Lithium path */
+	return dp_rx_intrabss_fwd(soc, ta_peer, rx_tlv_hdr, nbuf,
+				  msdu_metadata);
+}
+#else
+/*
+ * dp_rx_intrabss_fwd_be() - API for intrabss fwd. For EAPOL
+ *  pkt with DA not equal to vdev mac addr, fwd is not allowed.
+ * @soc: core txrx main context
+ * @ta_peer: source peer entry
+ * @rx_tlv_hdr: start address of rx tlvs
+ * @nbuf: nbuf that has to be intrabss forwarded
+ * @msdu_metadata: msdu metadata
+ *
+ * Return: true if it is forwarded else false
+ */
+bool dp_rx_intrabss_fwd_be(struct dp_soc *soc, struct dp_peer *ta_peer,
+			   uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf,
+			   struct hal_rx_msdu_metadata msdu_metadata)
+{
+	uint16_t len;
+	qdf_nbuf_t nbuf_copy;
+	uint8_t tid = qdf_nbuf_get_tid_val(nbuf);
+	uint8_t ring_id = QDF_NBUF_CB_RX_CTX_ID(nbuf);
+	struct cdp_tid_rx_stats *tid_stats = &ta_peer->vdev->pdev->stats.
+					tid_stats.tid_rx_stats[ring_id][tid];
+
+	/* if it is a broadcast pkt (eg: ARP) and it is not its own
+	 * source, then clone the pkt and send the cloned pkt for
+	 * intra BSS forwarding and original pkt up the network stack
+	 * Note: how do we handle multicast pkts. do we forward
+	 * all multicast pkts as is or let a higher layer module
+	 * like igmpsnoop decide whether to forward or not with
+	 * Mcast enhancement.
+	 */
+	if (qdf_nbuf_is_da_mcbc(nbuf) && !ta_peer->bss_peer) {
+		if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr,
+						    nbuf))
+			return true;
+
+		if (!dp_rx_check_ndi_mdns_fwding(ta_peer, nbuf))
+			return false;
+
+		/* If the source peer in the isolation list
+		 * then dont forward instead push to bridge stack
+		 */
+		if (dp_get_peer_isolation(ta_peer))
+			return false;
+
+		nbuf_copy = qdf_nbuf_copy(nbuf);
+		if (!nbuf_copy)
+			return false;
+
+		len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
+		if (dp_tx_send((struct cdp_soc_t *)soc,
+			       ta_peer->vdev->vdev_id, nbuf_copy)) {
+			DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, len);
+			tid_stats->fail_cnt[INTRABSS_DROP]++;
+			qdf_nbuf_free(nbuf_copy);
+		} else {
+			DP_STATS_INC_PKT(ta_peer, rx.intra_bss.pkts, 1, len);
+			tid_stats->intrabss_cnt++;
+		}
+		return false;
+	}
+
+	if (qdf_nbuf_is_intra_bss(nbuf)) {
+		if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr,
+						    nbuf))
+			return true;
+
+		len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
+
+		/* linearize the nbuf just before we send to
+		 * dp_tx_send()
+		 */
+		if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) {
+			if (qdf_nbuf_linearize(nbuf) == -ENOMEM)
+				return false;
+
+			nbuf = qdf_nbuf_unshare(nbuf);
+			if (!nbuf) {
+				DP_STATS_INC_PKT(ta_peer,
+						 rx.intra_bss.fail, 1, len);
+				/* return true even though the pkt is
+				 * not forwarded. Basically skb_unshare
+				 * failed and we want to continue with
+				 * next nbuf.
+				 */
+				tid_stats->fail_cnt[INTRABSS_DROP]++;
+				return true;
+			}
+		}
+
+		if (!dp_tx_send((struct cdp_soc_t *)soc,
+				ta_peer->vdev->vdev_id, nbuf)) {
+			DP_STATS_INC_PKT(ta_peer, rx.intra_bss.pkts, 1,
+					 len);
+		} else {
+			DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1,
+					 len);
+			tid_stats->fail_cnt[INTRABSS_DROP]++;
+			return false;
+		}
+
+		return true;
+	}
+	return false;
+}
+#endif
+#endif
+

+ 21 - 0
dp/wifi3.0/be/dp_be_rx.h

@@ -22,6 +22,27 @@
 #include <dp_types.h>
 #include "dp_be.h"
 
+#ifndef QCA_HOST_MODE_WIFI_DISABLED
+
+/*
+ * dp_rx_intrabss_fwd_be() - API for intrabss fwd. For EAPOL
+ *  pkt with DA not equal to vdev mac addr, fwd is not allowed.
+ * @soc: core txrx main context
+ * @ta_peer: source peer entry
+ * @rx_tlv_hdr: start address of rx tlvs
+ * @nbuf: nbuf that has to be intrabss forwarded
+ * @msdu_metadata: msdu metadata
+ *
+ * Return: true if it is forwarded else false
+ */
+
+bool dp_rx_intrabss_fwd_be(struct dp_soc *soc,
+			   struct dp_peer *ta_peer,
+			   uint8_t *rx_tlv_hdr,
+			   qdf_nbuf_t nbuf,
+			   struct hal_rx_msdu_metadata msdu_metadata);
+#endif
+
 uint32_t dp_rx_process_be(struct dp_intr *int_ctx,
 			  hal_ring_handle_t hal_ring_hdl, uint8_t reo_ring_num,
 			  uint32_t quota);

+ 17 - 33
dp/wifi3.0/dp_rx.c

@@ -39,28 +39,6 @@
 #include "dp_txrx_wds.h"
 #endif
 
-#ifndef QCA_HOST_MODE_WIFI_DISABLED
-
-#ifdef DP_RX_DISABLE_NDI_MDNS_FORWARDING
-static inline
-bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf)
-{
-	if (ta_peer->vdev->opmode == wlan_op_mode_ndi &&
-	    qdf_nbuf_is_ipv6_mdns_pkt(nbuf)) {
-		DP_STATS_INC(ta_peer, rx.intra_bss.mdns_no_fwd, 1);
-		return false;
-	}
-		return true;
-}
-#else
-static inline
-bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf)
-{
-	return true;
-}
-#endif
-#endif /* QCA_HOST_MODE_WIFI_DISABLED */
-
 #ifdef DUP_RX_DESC_WAR
 void dp_rx_dump_info_and_assert(struct dp_soc *soc,
 				hal_ring_handle_t hal_ring,
@@ -566,6 +544,9 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 	 */
 
 	if ((qdf_nbuf_is_da_valid(nbuf) && !qdf_nbuf_is_da_mcbc(nbuf))) {
+		if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr,
+						    nbuf))
+			return true;
 
 		ast_entry = soc->ast_table[msdu_metadata.da_idx];
 		if (!ast_entry)
@@ -594,6 +575,16 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 						DP_MOD_ID_RX);
 		if (!da_peer)
 			return false;
+
+		/* If the source or destination peer in the isolation
+		 * list then dont forward instead push to bridge stack.
+		 */
+		if (dp_get_peer_isolation(ta_peer) ||
+		    dp_get_peer_isolation(da_peer)) {
+			dp_peer_unref_delete(da_peer, DP_MOD_ID_RX);
+			return false;
+		}
+
 		is_da_bss_peer = da_peer->bss_peer;
 		dp_peer_unref_delete(da_peer, DP_MOD_ID_RX);
 
@@ -602,13 +593,6 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 			is_frag = qdf_nbuf_is_frag(nbuf);
 			memset(nbuf->cb, 0x0, sizeof(nbuf->cb));
 
-			/* If the source or destination peer in the isolation
-			 * list then dont forward instead push to bridge stack.
-			 */
-			if (dp_get_peer_isolation(ta_peer) ||
-			    dp_get_peer_isolation(da_peer))
-				return false;
-
 			/* linearize the nbuf just before we send to
 			 * dp_tx_send()
 			 */
@@ -655,6 +639,10 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 	 */
 	else if (qdf_unlikely((qdf_nbuf_is_da_mcbc(nbuf) &&
 			       !ta_peer->bss_peer))) {
+		if (dp_rx_intrabss_eapol_drop_check(soc, ta_peer, rx_tlv_hdr,
+						    nbuf))
+			return true;
+
 		if (!dp_rx_check_ndi_mdns_fwding(ta_peer, nbuf))
 			goto end;
 
@@ -669,10 +657,6 @@ dp_rx_intrabss_fwd(struct dp_soc *soc,
 			goto end;
 
 		len = QDF_NBUF_CB_RX_PKT_LEN(nbuf);
-		memset(nbuf_copy->cb, 0x0, sizeof(nbuf_copy->cb));
-
-		/* Set cb->ftype to intrabss FWD */
-		qdf_nbuf_set_tx_ftype(nbuf_copy, CB_FTYPE_INTRABSS_FWD);
 		if (dp_tx_send((struct cdp_soc_t *)soc,
 			       ta_peer->vdev->vdev_id, nbuf_copy)) {
 			DP_STATS_INC_PKT(ta_peer, rx.intra_bss.fail, 1, len);

+ 34 - 14
dp/wifi3.0/dp_rx.h

@@ -272,6 +272,27 @@ bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer,
 }
 #endif
 
+#ifndef QCA_HOST_MODE_WIFI_DISABLED
+#ifdef DP_RX_DISABLE_NDI_MDNS_FORWARDING
+static inline
+bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf)
+{
+	if (ta_peer->vdev->opmode == wlan_op_mode_ndi &&
+	    qdf_nbuf_is_ipv6_mdns_pkt(nbuf)) {
+		DP_STATS_INC(ta_peer, rx.intra_bss.mdns_no_fwd, 1);
+		return false;
+	}
+		return true;
+}
+#else
+static inline
+bool dp_rx_check_ndi_mdns_fwding(struct dp_peer *ta_peer, qdf_nbuf_t nbuf)
+{
+	return true;
+}
+#endif
+#endif /* QCA_HOST_MODE_WIFI_DISABLED */
+
 /* DOC: Offset to obtain LLC hdr
  *
  * In the case of Wifi parse error
@@ -1101,20 +1122,19 @@ bool dp_rx_intrabss_fwd(struct dp_soc *soc,
 
 #ifdef DISABLE_EAPOL_INTRABSS_FWD
 /*
- * dp_rx_intrabss_fwd_wrapper() - Wrapper API for intrabss fwd. For EAPOL
+ * dp_rx_intrabss_eapol_drop_check() - API For EAPOL
  *  pkt with DA not equal to vdev mac addr, fwd is not allowed.
  * @soc: core txrx main context
  * @ta_peer: source peer entry
  * @rx_tlv_hdr: start address of rx tlvs
  * @nbuf: nbuf that has to be intrabss forwarded
- * @msdu_metadata: msdu metadata
  *
  * Return: true if it is forwarded else false
  */
 static inline
-bool dp_rx_intrabss_fwd_wrapper(struct dp_soc *soc, struct dp_peer *ta_peer,
-				uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf,
-				struct hal_rx_msdu_metadata msdu_metadata)
+bool dp_rx_intrabss_eapol_drop_check(struct dp_soc *soc,
+				     struct dp_peer *ta_peer,
+				     uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf)
 {
 	if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(nbuf) &&
 			 qdf_mem_cmp(qdf_nbuf_data(nbuf) +
@@ -1126,18 +1146,18 @@ bool dp_rx_intrabss_fwd_wrapper(struct dp_soc *soc, struct dp_peer *ta_peer,
 		return true;
 	}
 
-	return dp_rx_intrabss_fwd(soc, ta_peer, rx_tlv_hdr, nbuf,
-				  msdu_metadata);
+	return false;
 }
-
-#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \
-		dp_rx_intrabss_fwd_wrapper(soc, peer, rx_tlv_hdr, nbuf, \
-					   msdu_metadata)
 #else /* DISABLE_EAPOL_INTRABSS_FWD */
-#define DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata) \
-		dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf, msdu_metadata)
-#endif /* DISABLE_EAPOL_INTRABSS_FWD */
 
+static inline
+bool dp_rx_intrabss_eapol_drop_check(struct dp_soc *soc,
+				     struct dp_peer *ta_peer,
+				     uint8_t *rx_tlv_hdr, qdf_nbuf_t nbuf)
+{
+	return false;
+}
+#endif /* DISABLE_EAPOL_INTRABSS_FWD */
 /**
  * dp_rx_defrag_concat() - Concatenate the fragments
  *

+ 1 - 1
dp/wifi3.0/li/dp_li_rx.c

@@ -752,7 +752,7 @@ done:
 
 			/* Intrabss-fwd */
 			if (dp_rx_check_ap_bridge(vdev))
-				if (DP_RX_INTRABSS_FWD(soc, peer, rx_tlv_hdr,
+				if (dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr,
 						       nbuf, msdu_metadata)) {
 					nbuf = next;
 					tid_stats->intrabss_cnt++;

+ 8 - 0
hal/wifi3.0/be/hal_be_rx.h

@@ -166,6 +166,11 @@
 		RX_MSDU_DESC_INFO_DA_IS_MCBC_OFFSET)) &	\
 		RX_MSDU_DESC_INFO_DA_IS_MCBC_MASK)
 
+#define HAL_RX_MSDU_INTRA_BSS_FLAG_GET(msdu_info_ptr)		\
+	((*_OFFSET_TO_WORD_PTR(msdu_info_ptr,			\
+		RX_MSDU_DESC_INFO_INTRA_BSS_OFFSET)) &	\
+		RX_MSDU_DESC_INFO_INTRA_BSS_MASK)
+
 #define HAL_RX_MPDU_ENCRYPT_TYPE_GET(_rx_mpdu_info)	\
 	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_mpdu_info,	\
 	RX_MPDU_INFO_ENCRYPT_TYPE_OFFSET)),		\
@@ -367,6 +372,9 @@ uint32_t hal_rx_msdu_flags_get_be(rx_msdu_desc_info_t msdu_desc_info_hdl)
 	if (HAL_RX_MSDU_DA_IS_MCBC_FLAG_GET(msdu_desc_info))
 		flags |= HAL_MSDU_F_DA_IS_MCBC;
 
+	if (HAL_RX_MSDU_INTRA_BSS_FLAG_GET(msdu_desc_info))
+		flags |= HAL_MSDU_F_INTRA_BSS;
+
 	return flags;
 }
 

+ 3 - 1
hal/wifi3.0/hal_rx.h

@@ -193,6 +193,7 @@ struct hal_rx_msdu_desc_info {
  * @ HAL_MSDU_F_DA_IS_VALID: Found match for DA in AST
  * @ HAL_MSDU_F_DA_IS_MCBC: DA is MC/BC address
  * @ HAL_MSDU_F_DA_IDX_TIMEOUT: AST search for DA timed out
+ * @ HAL_MSDU_F_INTRA_BSS: This is an intrabss packet
  */
 enum hal_rx_msdu_desc_flags {
 	HAL_MSDU_F_FIRST_MSDU_IN_MPDU = (0x1 << 0),
@@ -202,7 +203,8 @@ enum hal_rx_msdu_desc_flags {
 	HAL_MSDU_F_SA_IDX_TIMEOUT = (0x1 << 24),
 	HAL_MSDU_F_DA_IS_VALID = (0x1 << 25),
 	HAL_MSDU_F_DA_IS_MCBC = (0x1 << 26),
-	HAL_MSDU_F_DA_IDX_TIMEOUT = (0x1 << 27)
+	HAL_MSDU_F_DA_IDX_TIMEOUT = (0x1 << 27),
+	HAL_MSDU_F_INTRA_BSS = (0x1 << 28),
 };
 
 /*