Browse Source

qcacmn: HW reinjection support for MLO Multicast

Enabling HW based reinjection for MLO Multicast

Change-Id: Ie9663e0e90ae1ae0a07d229fd6d4c66787d4224a
CRs-Fixed: 3142397
Sai Rupesh Chevuru 3 years ago
parent
commit
f179a624a1

+ 77 - 0
dp/wifi3.0/be/dp_be.c

@@ -419,6 +419,52 @@ static QDF_STATUS dp_soc_detach_be(struct dp_soc *soc)
 }
 
 #ifdef WLAN_MLO_MULTI_CHIP
+#ifdef WLAN_MCAST_MLO
+static inline void
+dp_mlo_mcast_init(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+	struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
+
+	be_vdev->mcast_primary = false;
+	be_vdev->seq_num = 0;
+	if (vdev->mlo_vdev)
+		hal_tx_vdev_mcast_ctrl_set(vdev->pdev->soc->hal_soc,
+					   vdev->vdev_id,
+					   HAL_TX_MCAST_CTRL_DROP);
+}
+
+static inline void
+dp_mlo_mcast_deinit(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+	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(
+						be_vdev->vdev.pdev->soc);
+
+	be_vdev->seq_num = 0;
+	if (vdev->mlo_vdev) {
+		hal_tx_vdev_mcast_ctrl_set(vdev->pdev->soc->hal_soc,
+					   vdev->vdev_id,
+					   HAL_TX_MCAST_CTRL_FW_EXCEPTION);
+		vdev->mlo_vdev = false;
+	}
+	if (be_vdev->mcast_primary) {
+		be_vdev->mcast_primary = false;
+		dp_mcast_mlo_iter_ptnr_soc(be_soc,
+					   dp_tx_mcast_mlo_reinject_routing_set,
+					   (void *)&be_vdev->mcast_primary);
+	}
+}
+#else
+static inline void
+dp_mlo_mcast_init(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+}
+
+static inline void
+dp_mlo_mcast_deinit(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+}
+#endif
 static void dp_mlo_init_ptnr_list(struct dp_vdev *vdev)
 {
 	struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev);
@@ -428,6 +474,16 @@ static void dp_mlo_init_ptnr_list(struct dp_vdev *vdev)
 		    CDP_INVALID_VDEV_ID);
 }
 #else
+static inline void
+dp_mlo_mcast_init(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+}
+
+static inline void
+dp_mlo_mcast_deinit(struct dp_soc *soc, struct dp_vdev *vdev)
+{
+}
+
 static void dp_mlo_init_ptnr_list(struct dp_vdev *vdev)
 {
 }
@@ -594,6 +650,9 @@ static QDF_STATUS dp_vdev_attach_be(struct dp_soc *soc, struct dp_vdev *vdev)
 						   HAL_TX_MCAST_CTRL_MEC_NOTIFY);
 	}
 
+	if (vdev->opmode == wlan_op_mode_ap)
+		dp_mlo_mcast_init(soc, vdev);
+
 	dp_mlo_init_ptnr_list(vdev);
 
 	return QDF_STATUS_SUCCESS;
@@ -607,6 +666,9 @@ static QDF_STATUS dp_vdev_detach_be(struct dp_soc *soc, struct dp_vdev *vdev)
 	if (vdev->opmode == wlan_op_mode_monitor)
 		return QDF_STATUS_SUCCESS;
 
+	if (vdev->opmode == wlan_op_mode_ap)
+		dp_mlo_mcast_deinit(soc, vdev);
+
 	dp_tx_put_bank_profile(be_soc, be_vdev);
 	dp_clr_mlo_ptnr_list(soc, vdev);
 
@@ -1403,7 +1465,22 @@ static void dp_txrx_set_mlo_mcast_primary_vdev_param_be(
 					struct dp_vdev_be *be_vdev,
 					cdp_config_param_type val)
 {
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(
+						be_vdev->vdev.pdev->soc);
+	hal_soc_handle_t hal_soc = be_vdev->vdev.pdev->soc->hal_soc;
+	uint8_t vdev_id = be_vdev->vdev.vdev_id;
+
 	be_vdev->mcast_primary = val.cdp_vdev_param_mcast_vdev;
+
+	if (be_vdev->mcast_primary) {
+		hal_tx_vdev_mcast_ctrl_set(hal_soc, vdev_id,
+					   HAL_TX_MCAST_CTRL_NO_SPECIAL);
+		hal_tx_vdev_mcast_ctrl_set(hal_soc, vdev_id + 128,
+					   HAL_TX_MCAST_CTRL_FW_EXCEPTION);
+		dp_mcast_mlo_iter_ptnr_soc(be_soc,
+					   dp_tx_mcast_mlo_reinject_routing_set,
+					   (void *)&be_vdev->mcast_primary);
+	}
 }
 #else
 static void dp_txrx_set_mlo_mcast_primary_vdev_param_be(

+ 13 - 0
dp/wifi3.0/be/dp_be.h

@@ -396,6 +396,8 @@ void  dp_clr_mlo_ptnr_list(struct dp_soc *soc, struct dp_vdev *vdev);
 typedef void dp_ptnr_vdev_iter_func(struct dp_vdev_be *be_vdev,
 				    struct dp_vdev *ptnr_vdev,
 				    void *arg);
+typedef void dp_ptnr_soc_iter_func(struct dp_soc *ptnr_soc,
+				   void *arg);
 /*
  * dp_mcast_mlo_iter_ptnr_vdev - API to iterate through ptnr vdev list
  * @be_soc: dp_soc_be pointer
@@ -411,6 +413,17 @@ void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
 				 dp_ptnr_vdev_iter_func func,
 				 void *arg,
 				 enum dp_mod_id mod_id);
+/*
+ * dp_mcast_mlo_iter_ptnr_soc - API to iterate through ptnr soc list
+ * @be_soc: dp_soc_be pointer
+ * @func        : function to be called for each peer
+ * @arg         : argument need to be passed to func
+ *
+ * Return: None
+ */
+void dp_mcast_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc,
+				dp_ptnr_soc_iter_func func,
+				void *arg);
 /*
  * dp_mlo_get_mcast_primary_vdev- get ref to mcast primary vdev
  * @be_soc: dp_soc_be pointer

+ 5 - 3
dp/wifi3.0/be/dp_be_rx.c

@@ -1109,10 +1109,12 @@ bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 	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);
 
-	if (!(qdf_nbuf_is_ipv4_igmp_pkt(buf) ||
-	      qdf_nbuf_is_ipv6_igmp_pkt(buf)))
+	if (!(qdf_nbuf_is_ipv4_igmp_pkt(nbuf) ||
+	      qdf_nbuf_is_ipv6_igmp_pkt(nbuf)))
 		return false;
 
+	qdf_nbuf_set_next(nbuf, NULL);
+
 	if (vdev->mcast_enhancement_en || be_vdev->mcast_primary)
 		goto send_pkt;
 
@@ -1143,7 +1145,7 @@ send_pkt:
 #else
 bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 			    struct dp_vdev *vdev,
-			    struct dp_peer *peer,
+			    struct dp_txrx_peer *peer,
 			    qdf_nbuf_t nbuf)
 {
 	return false;

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

@@ -237,7 +237,7 @@ dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t reo_ring_num)
  */
 bool dp_rx_mlo_igmp_handler(struct dp_soc *soc,
 			    struct dp_vdev *vdev,
-			    struct dp_peer *peer,
+			    struct dp_txrx_peer *peer,
 			    qdf_nbuf_t nbuf);
 
 /**

+ 15 - 0
dp/wifi3.0/be/dp_be_tx.c

@@ -416,6 +416,21 @@ dp_tx_set_min_rates_for_critical_frames(struct dp_soc *soc,
 
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
 	defined(WLAN_MCAST_MLO)
+void dp_tx_mcast_mlo_reinject_routing_set(struct dp_soc *soc, void *arg)
+{
+	hal_soc_handle_t hal_soc = soc->hal_soc;
+	uint8_t *cmd = (uint8_t *)arg;
+
+	if (*cmd)
+		hal_tx_mcast_mlo_reinject_routing_set(
+					hal_soc,
+					HAL_TX_MCAST_MLO_REINJECT_TQM_NOTIFY);
+	else
+		hal_tx_mcast_mlo_reinject_routing_set(
+					hal_soc,
+					HAL_TX_MCAST_MLO_REINJECT_FW_NOTIFY);
+}
+
 void
 dp_tx_mlo_mcast_pkt_send(struct dp_vdev_be *be_vdev,
 			 struct dp_vdev *ptnr_vdev,

+ 9 - 0
dp/wifi3.0/be/dp_be_tx.h

@@ -181,6 +181,15 @@ void dp_tx_mlo_mcast_handler_be(struct dp_soc *soc,
 void dp_tx_mlo_mcast_pkt_send(struct dp_vdev_be *be_vdev,
 			      struct dp_vdev *ptnr_vdev,
 			      void *arg);
+
+/**
+ * dp_tx_mcast_mlo_reinject_routing_set() - mlo mcast reinject routing handler
+ * @be_vdev: Handle to DP be_vdev structure
+ * @cmd: cmd to set TQM/FW based reinjection
+ *
+ * Return: None
+ */
+void dp_tx_mcast_mlo_reinject_routing_set(struct dp_soc *soc, void *arg);
 #endif
 #endif
 #endif

+ 19 - 0
dp/wifi3.0/be/mlo/dp_mlo.c

@@ -540,6 +540,25 @@ dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t reo_ring_num)
 }
 
 #ifdef WLAN_MCAST_MLO
+void dp_mcast_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc,
+				dp_ptnr_soc_iter_func func,
+				void *arg)
+{
+	int i = 0;
+	struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
+
+	for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) {
+		struct dp_soc *ptnr_soc =
+				dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i);
+
+		if (!ptnr_soc)
+			continue;
+		(*func)(ptnr_soc, arg);
+	}
+}
+
+qdf_export_symbol(dp_mcast_mlo_iter_ptnr_soc);
+
 void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc,
 				 struct dp_vdev_be *be_vdev,
 				 dp_ptnr_vdev_iter_func func,

+ 18 - 0
dp/wifi3.0/dp_main.c

@@ -6428,12 +6428,30 @@ static inline void dp_vdev_register_rx_eapol(struct dp_vdev *vdev,
 #endif
 
 #ifdef WLAN_FEATURE_11BE_MLO
+#if defined(WLAN_MLO_MULTI_CHIP) && defined(WLAN_MCAST_MLO)
+static inline void dp_vdev_save_mld_info(struct dp_vdev *vdev,
+					 struct cdp_vdev_info *vdev_info)
+{
+	if (qdf_is_macaddr_zero((struct qdf_mac_addr *)vdev_info->mld_mac_addr))
+		vdev->mlo_vdev = false;
+	else
+		vdev->mlo_vdev = true;
+}
+#else
+static inline void dp_vdev_save_mld_info(struct dp_vdev *vdev,
+					 struct cdp_vdev_info *vdev_info)
+{
+}
+#endif
 static inline void dp_vdev_save_mld_addr(struct dp_vdev *vdev,
 					 struct cdp_vdev_info *vdev_info)
 {
 	if (vdev_info->mld_mac_addr)
 		qdf_mem_copy(&vdev->mld_mac_addr.raw[0],
 			     vdev_info->mld_mac_addr, QDF_MAC_ADDR_SIZE);
+
+	dp_vdev_save_mld_info(vdev, vdev_info);
+
 }
 #else
 static inline void dp_vdev_save_mld_addr(struct dp_vdev *vdev,

+ 48 - 0
dp/wifi3.0/dp_tx.c

@@ -4792,6 +4792,49 @@ void dp_tx_prefetch_next_nbuf_data(struct dp_tx_desc_s *next)
 }
 #endif
 
+/**
+ * dp_tx_mcast_reinject_handler() - Tx reinjected multicast packets handler
+ * @soc: core txrx main context
+ * @desc: software descriptor
+ *
+ * Return: true when packet is reinjected
+ */
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
+	defined(WLAN_MCAST_MLO)
+static inline bool
+dp_tx_mcast_reinject_handler(struct dp_soc *soc, struct dp_tx_desc_s *desc)
+{
+	struct dp_vdev *vdev = NULL;
+
+	if (desc->tx_status == HAL_TX_TQM_RR_MULTICAST_DROP) {
+		if (!soc->arch_ops.dp_tx_mcast_handler)
+			return false;
+
+		vdev = dp_vdev_get_ref_by_id(soc, desc->vdev_id,
+					     DP_MOD_ID_TX_COMP);
+
+		if (qdf_unlikely(!vdev)) {
+			dp_tx_comp_info_rl("Unable to get vdev ref  %d",
+					   desc->id);
+			return false;
+		}
+		DP_STATS_INC_PKT(vdev, tx_i.reinject_pkts, 1,
+				 qdf_nbuf_len(desc->nbuf));
+		soc->arch_ops.dp_tx_mcast_handler(soc, vdev, desc->nbuf);
+		dp_tx_desc_release(desc, desc->pool_id);
+		return true;
+	}
+
+	return false;
+}
+#else
+static inline bool
+dp_tx_mcast_reinject_handler(struct dp_soc *soc, struct dp_tx_desc_s *desc)
+{
+	return false;
+}
+#endif
+
 /**
  * dp_tx_comp_process_desc_list() - Tx complete software descriptor handler
  * @soc: core txrx main context
@@ -4832,6 +4875,10 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
 							   DP_MOD_ID_TX_COMP);
 		}
 
+		if (dp_tx_mcast_reinject_handler(soc, desc)) {
+			desc = next;
+			continue;
+		}
 		if (qdf_likely(desc->flags & DP_TX_DESC_FLAG_SIMPLE)) {
 			struct dp_pdev *pdev = desc->pdev;
 
@@ -4855,6 +4902,7 @@ dp_tx_comp_process_desc_list(struct dp_soc *soc,
 			desc = next;
 			continue;
 		}
+
 		hal_tx_comp_get_status(&desc->comp, &ts, soc->hal_soc);
 
 		dp_tx_comp_process_tx_status(soc, desc, &ts, txrx_peer,

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

@@ -2996,6 +2996,9 @@ struct dp_vdev {
 #ifdef WLAN_FEATURE_11BE_MLO
 	/* MLO MAC address corresponding to vdev */
 	union dp_align_mac_addr mld_mac_addr;
+#if defined(WLAN_MLO_MULTI_CHIP) && defined(WLAN_MCAST_MLO)
+	bool mlo_vdev;
+#endif
 #endif
 
 	/* node in the pdev's list of vdevs */

+ 49 - 0
hal/wifi3.0/be/hal_be_tx.h

@@ -83,6 +83,16 @@ enum hal_tx_notify_frame_type {
 	TX_SEMI_HARD_NOTIFY_E = 3
 };
 
+/**
+ * enum hal_tx_mcast_mlo_reinject_notify
+ * @HAL_TX_MCAST_MLO_REINJECT_FW_NOTIFY: MLO Mcast reinject routed to FW
+ * @HAL_TX_MCAST_MLO_REINJECT_TQM_NOTIFY: MLO Mcast reinject routed to TQM
+ */
+enum hal_tx_mcast_mlo_reinject_notify {
+	HAL_TX_MCAST_MLO_REINJECT_FW_NOTIFY = 0,
+	HAL_TX_MCAST_MLO_REINJECT_TQM_NOTIFY,
+};
+
 /*---------------------------------------------------------------------------
  * Structures
  * ---------------------------------------------------------------------------
@@ -942,6 +952,45 @@ hal_tx_vdev_mismatch_routing_set(hal_soc_handle_t hal_soc_hdl,
 }
 #endif
 
+/**
+ * hal_tx_mcast_mlo_reinject_routing_set - set MLO multicast reinject routing
+ * @hal_soc: HAL SoC context
+ * @config: HAL_TX_MCAST_MLO_REINJECT_FW_NOTIFY - route via FW
+ *          HAL_TX_MCAST_MLO_REINJECT_TQM_NOTIFY - route via TQM
+ *
+ * Return: void
+ */
+#if defined(HWIO_TCL_R0_CMN_CONFIG_MCAST_CMN_PN_SN_MLO_REINJECT_ENABLE_BMSK) && \
+	defined(WLAN_MCAST_MLO)
+static inline void
+hal_tx_mcast_mlo_reinject_routing_set(
+				hal_soc_handle_t hal_soc_hdl,
+				enum hal_tx_mcast_mlo_reinject_notify config)
+{
+	struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
+	uint32_t reg_addr, reg_val = 0;
+	uint32_t val = 0;
+
+	reg_addr = HWIO_TCL_R0_CMN_CONFIG_ADDR(MAC_TCL_REG_REG_BASE);
+	val = HAL_REG_READ(hal_soc, reg_addr);
+
+	/* reset the corresponding bits in register */
+	val &= (~(HWIO_TCL_R0_CMN_CONFIG_MCAST_CMN_PN_SN_MLO_REINJECT_ENABLE_BMSK));
+
+	/* set config value */
+	reg_val = val | (config << HWIO_TCL_R0_CMN_CONFIG_MCAST_CMN_PN_SN_MLO_REINJECT_ENABLE_SHFT);
+
+	HAL_REG_WRITE(hal_soc, reg_addr, reg_val);
+}
+#else
+static inline void
+hal_tx_mcast_mlo_reinject_routing_set(
+				hal_soc_handle_t hal_soc_hdl,
+				enum hal_tx_mcast_mlo_reinject_notify config)
+{
+}
+#endif
+
 /*
  * hal_tx_get_num_ppe_vp_tbl_entries() - Get the total number of VP table
  * @hal_soc: HAL SoC Context