diff --git a/dp/wifi3.0/be/dp_be.c b/dp/wifi3.0/be/dp_be.c index b2ec69241d..88502d8627 100644 --- a/dp/wifi3.0/be/dp_be.c +++ b/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( diff --git a/dp/wifi3.0/be/dp_be.h b/dp/wifi3.0/be/dp_be.h index bdecca5bfa..0f980f9ec3 100644 --- a/dp/wifi3.0/be/dp_be.h +++ b/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 diff --git a/dp/wifi3.0/be/dp_be_rx.c b/dp/wifi3.0/be/dp_be_rx.c index 8f2badf77a..0af82a2bc0 100644 --- a/dp/wifi3.0/be/dp_be_rx.c +++ b/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; diff --git a/dp/wifi3.0/be/dp_be_rx.h b/dp/wifi3.0/be/dp_be_rx.h index faa2165e9b..a8329da1df 100644 --- a/dp/wifi3.0/be/dp_be_rx.h +++ b/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); /** diff --git a/dp/wifi3.0/be/dp_be_tx.c b/dp/wifi3.0/be/dp_be_tx.c index 82c46d6b80..b7b0654737 100644 --- a/dp/wifi3.0/be/dp_be_tx.c +++ b/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, diff --git a/dp/wifi3.0/be/dp_be_tx.h b/dp/wifi3.0/be/dp_be_tx.h index e5609a3624..ec19505564 100644 --- a/dp/wifi3.0/be/dp_be_tx.h +++ b/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 diff --git a/dp/wifi3.0/be/mlo/dp_mlo.c b/dp/wifi3.0/be/mlo/dp_mlo.c index 2fdb8afed4..489bd361ec 100644 --- a/dp/wifi3.0/be/mlo/dp_mlo.c +++ b/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, diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 9d22ab1131..f503a097f0 100644 --- a/dp/wifi3.0/dp_main.c +++ b/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, diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 2b032e0de2..5f4f06e3bb 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/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, diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 68d98c8c74..b1e7d9eaa8 100644 --- a/dp/wifi3.0/dp_types.h +++ b/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 */ diff --git a/hal/wifi3.0/be/hal_be_tx.h b/hal/wifi3.0/be/hal_be_tx.h index 83ae8e2e8b..e03707c34e 100644 --- a/hal/wifi3.0/be/hal_be_tx.h +++ b/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