Răsfoiți Sursa

qcacmn: Hybrid mld netdev support

-Support to route IGMP packet to correct netdev coming from
 legacy and mld sta.
-Support to detect mld model based on ini setting

Change-Id: I10ea5af9a4315642b262c8404d7bebd88ee06ab1
CRs-Fixed: 3467808
Biswajit Dash 2 ani în urmă
părinte
comite
d62608cb2a

+ 2 - 0
dp/inc/cdp_txrx_cmn_struct.h

@@ -206,11 +206,13 @@ struct cdp_stats_cookie;
  * enum cdp_cfg_param_type - DP configuration parameters
  * @CDP_CFG_MAX_PEER_ID: Maximum peer id
  * @CDP_CFG_CCE_DISABLE: CCE disable
+ * @CDP_CFG_MLD_NETDEV_MODE_AP: Ap's mld netdev model
  * @CDP_CFG_NUM_PARAMS: Total number of params
  */
 enum cdp_cfg_param_type {
 	CDP_CFG_MAX_PEER_ID,
 	CDP_CFG_CCE_DISABLE,
+	CDP_CFG_MLD_NETDEV_MODE_AP,
 	CDP_CFG_NUM_PARAMS
 };
 

+ 55 - 35
dp/wifi3.0/be/dp_be_rx.c

@@ -1133,15 +1133,29 @@ static inline bool dp_rx_mlo_igmp_wds_ext_handler(struct dp_txrx_peer *peer)
 }
 #endif
 
+#ifdef EXT_HYBRID_MLO_MODE
+static inline
+bool dp_rx_check_ext_hybrid_mode(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+	return ((DP_MLD_MODE_HYBRID_NONBOND == soc->mld_mode_ap) &&
+		(wlan_op_mode_ap == vdev->opmode));
+}
+#else
+static inline
+bool dp_rx_check_ext_hybrid_mode(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+	return false;
+}
+#endif
+
 bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 			    struct dp_vdev *vdev,
 			    struct dp_txrx_peer *peer,
 			    qdf_nbuf_t nbuf,
 			    uint8_t link_id)
 {
-	struct dp_vdev *mcast_primary_vdev = NULL;
+	qdf_nbuf_t nbuf_copy;
 	struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
-	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
 	uint8_t tid = qdf_nbuf_get_tid_val(nbuf);
 	struct cdp_tid_rx_stats *tid_stats = &peer->vdev->pdev->stats.
 					tid_stats.tid_rx_wbm_stats[0][tid];
@@ -1165,51 +1179,57 @@ bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 			dp_rx_err("forwarding failed");
 	}
 
-	/*
-	 * In the case of ME6, Backhaul WDS, NAWDS
-	 * send the igmp pkt on the same link where it received,
-	 * as these features will use peer based tcl metadata
-	 */
-
 	qdf_nbuf_set_next(nbuf, NULL);
 
-	if (vdev->mcast_enhancement_en || be_vdev->mcast_primary ||
-	    peer->nawds_enabled)
-		goto send_pkt;
+	/* REO sends IGMP to driver only if AP is operating in hybrid
+	 *  mld mode.
+	 */
 
-	if (qdf_unlikely(dp_rx_mlo_igmp_wds_ext_handler(peer)))
+	if (qdf_unlikely(dp_rx_mlo_igmp_wds_ext_handler(peer))) {
+		/* send the IGMP to the netdev corresponding to the interface
+		 * its received on
+		 */
 		goto send_pkt;
+	}
 
-	mcast_primary_vdev = dp_mlo_get_mcast_primary_vdev(be_soc, be_vdev,
-							   DP_MOD_ID_RX);
-	if (!mcast_primary_vdev) {
-		dp_rx_debug("Non mlo vdev");
+	if (dp_rx_check_ext_hybrid_mode(soc, vdev)) {
+		/* send the IGMP to the netdev corresponding to the interface
+		 * its received on
+		 */
 		goto send_pkt;
 	}
 
-	if (qdf_unlikely(vdev->wrap_vdev)) {
-		/* In the case of qwrap repeater send the original
-		 * packet on the interface where it received,
-		 * packet with dummy src on the mcast primary interface.
+	/*
+	 * In the case of ME5/ME6, Backhaul WDS for a mld peer, NAWDS,
+	 * legacy non-mlo AP vdev & non-AP vdev(which is very unlikely),
+	 * send the igmp pkt on the same link where it received, as these
+	 *  features will use peer based tcl metadata.
+	 */
+	if (vdev->mcast_enhancement_en ||
+	    peer->is_mld_peer ||
+	    peer->nawds_enabled ||
+	    !vdev->mlo_vdev ||
+	    qdf_unlikely(wlan_op_mode_ap != vdev->opmode)) {
+		/* send the IGMP to the netdev corresponding to the interface
+		 * its received on
 		 */
-		qdf_nbuf_t nbuf_copy;
-
-		nbuf_copy = qdf_nbuf_copy(nbuf);
-		if (qdf_likely(nbuf_copy))
-			dp_rx_deliver_to_stack(soc, vdev, peer, nbuf_copy,
-					       NULL);
+		goto send_pkt;
 	}
 
+	/* We are here, it means a legacy non-wds sta is connected
+	 * to a hybrid mld ap, So send a clone of the IGPMP packet
+	 * on the interface where it was received.
+	 */
+	nbuf_copy = qdf_nbuf_copy(nbuf);
+	if (qdf_likely(nbuf_copy))
+		dp_rx_deliver_to_stack(soc, vdev, peer, nbuf_copy, NULL);
+
 	dp_rx_dummy_src_mac(vdev, nbuf);
-	dp_rx_deliver_to_stack(mcast_primary_vdev->pdev->soc,
-			       mcast_primary_vdev,
-			       peer,
-			       nbuf,
-			       NULL);
-	dp_vdev_unref_delete(mcast_primary_vdev->pdev->soc,
-			     mcast_primary_vdev,
-			     DP_MOD_ID_RX);
-	return true;
+	/* Set the ml peer valid bit in skb peer metadata, so that osif
+	 * can deliver the SA mangled IGMP packet to mld netdev.
+	 */
+	QDF_NBUF_CB_RX_SET_ML_PEER_VALID(nbuf);
+	/* Deliver the original IGMP with dummy src on the mld netdev */
 send_pkt:
 	dp_rx_deliver_to_stack(be_vdev->vdev.pdev->soc,
 			       &be_vdev->vdev,

+ 25 - 0
dp/wifi3.0/dp_rings_main.c

@@ -4376,6 +4376,29 @@ static void dp_soc_cfg_init(struct dp_soc *soc)
 	dp_soc_cfg_dump(soc, target_type);
 }
 
+/**
+ * dp_soc_get_ap_mld_mode() - store ap mld mode from ini
+ * @soc: Opaque DP SOC handle
+ *
+ * Return: none
+ */
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+static inline void dp_soc_get_ap_mld_mode(struct dp_soc *soc)
+{
+	if (soc->cdp_soc.ol_ops->get_dp_cfg_param) {
+		soc->mld_mode_ap =
+		soc->cdp_soc.ol_ops->get_dp_cfg_param(soc->ctrl_psoc,
+					CDP_CFG_MLD_NETDEV_MODE_AP);
+	}
+	qdf_info("DP mld_mode_ap-%u\n", soc->mld_mode_ap);
+}
+#else
+static inline void dp_soc_get_ap_mld_mode(struct dp_soc *soc)
+{
+	(void)soc;
+}
+#endif
+
 /**
  * dp_soc_init() - Initialize txrx SOC
  * @soc: Opaque DP SOC handle
@@ -4559,6 +4582,8 @@ void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle,
 
 	soc->vdev_stats_id_map = 0;
 
+	dp_soc_get_ap_mld_mode(soc);
+
 	return soc;
 fail7:
 	dp_soc_tx_desc_sw_pools_deinit(soc);

+ 2 - 1
dp/wifi3.0/dp_rx_err.c

@@ -1534,7 +1534,7 @@ fail:
 }
 
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
-	defined(WLAN_MCAST_MLO) && !defined(CONFIG_MLO_SINGLE_DEV)
+	defined(WLAN_MCAST_MLO)
 static bool dp_rx_igmp_handler(struct dp_soc *soc,
 			       struct dp_vdev *vdev,
 			       struct dp_txrx_peer *peer,
@@ -1649,6 +1649,7 @@ dp_rx_err_route_hdl(struct dp_soc *soc, qdf_nbuf_t nbuf,
 		qdf_nbuf_pull_head(nbuf, (msdu_metadata.l3_hdr_pad +
 				   soc->rx_pkt_tlv_size));
 
+	QDF_NBUF_CB_RX_PEER_ID(nbuf) = txrx_peer->peer_id;
 	if (dp_rx_igmp_handler(soc, vdev, txrx_peer, nbuf, link_id))
 		return;
 

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

@@ -195,6 +195,13 @@
 typedef void dp_ptnr_soc_iter_func(struct dp_soc *ptnr_soc, void *arg,
 				   int chip_id);
 
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+#define DP_MLD_MODE_UNIFIED_NONBOND 0
+#define DP_MLD_MODE_UNIFIED_BOND    1
+#define DP_MLD_MODE_HYBRID_NONBOND  2
+#define DP_MLD_MODE_MAX             DP_MLD_MODE_HYBRID_NONBOND
+#endif
+
 enum rx_pktlog_mode {
 	DP_RX_PKTLOG_DISABLED = 0,
 	DP_RX_PKTLOG_FULL,
@@ -3103,6 +3110,9 @@ struct dp_soc {
 	/* Flag to show if TX ILP is enabled */
 	bool tx_ilp_enable;
 #endif
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+	uint8_t mld_mode_ap;
+#endif
 };
 
 #ifdef IPA_OFFLOAD

+ 12 - 5
qdf/linux/src/i_qdf_nbuf_w.h

@@ -211,8 +211,7 @@ struct qdf_nbuf_cb {
 						 msdu_count:8;
 #endif
 					/* 2nd word rx_mpdu_desc_info */
-					uint32_t peer_id:13,
-						 ml_peer_valid:1,
+					uint32_t peer_id:14,
 						 vdev_id:8,
 						 hw_link_id:4,
 						 chip_id:3,
@@ -431,9 +430,17 @@ QDF_COMPILE_TIME_ASSERT(qdf_nbuf_cb_size,
 	(((struct qdf_nbuf_cb *) \
 	  ((skb)->cb))->u.rx.hw_info.desc_tlv_members.peer_id)
 
-#define QDF_NBUF_CB_RX_ML_PEER_VALID(skb) \
-	(((struct qdf_nbuf_cb *) \
-	  ((skb)->cb))->u.rx.hw_info.desc_tlv_members.ml_peer_valid)
+#define QDF_NBUF_CB_RX_ML_PEER_VALID_MASK  (0x00002000)
+#define QDF_NBUF_CB_RX_ML_PEER_VALID_SHIFT (13)
+
+#define QDF_NBUF_CB_RX_GET_ML_PEER_VALID(skb) \
+	((QDF_NBUF_CB_RX_PEER_ID(skb) & \
+		QDF_NBUF_CB_RX_ML_PEER_VALID_MASK) >> \
+			QDF_NBUF_CB_RX_ML_PEER_VALID_SHIFT)
+
+#define QDF_NBUF_CB_RX_SET_ML_PEER_VALID(skb) \
+	(QDF_NBUF_CB_RX_PEER_ID(nbuf) |= \
+		QDF_NBUF_CB_RX_ML_PEER_VALID_MASK)
 
 #define QDF_NBUF_CB_RX_VDEV_ID(skb) \
 	(((struct qdf_nbuf_cb *) \