From ef68ac521f19810808f6c948b4929a74fe0c9141 Mon Sep 17 00:00:00 2001 From: Kenvish Butani Date: Wed, 5 Apr 2023 18:58:01 +0530 Subject: [PATCH] qcacmn: vdev stats Support for MLO Hybrid Mode Add vdev stats support for DP MLO Unified and Hybrid Mode. Add new CDP API for getting vdev stats for NON_MLD interface. Add support to get vdev stats for specific vdev which is a part of MLO. Change-Id: I72c8b25958649d473e1b65cee21810cd86951187 CRs-Fixed: 3455607 --- dp/inc/cdp_txrx_host_stats.h | 28 +++++ dp/inc/cdp_txrx_mlo.h | 9 +- dp/inc/cdp_txrx_ops.h | 10 +- dp/wifi3.0/be/dp_be.c | 20 +++ dp/wifi3.0/be/dp_be.h | 2 + dp/wifi3.0/be/mlo/dp_mlo.c | 227 ++++++++++++++++++++++++++++++++--- dp/wifi3.0/dp_internal.h | 32 +++++ dp/wifi3.0/dp_main.c | 21 ++-- dp/wifi3.0/dp_peer.h | 45 +++++++ dp/wifi3.0/dp_stats.c | 5 + dp/wifi3.0/dp_types.h | 18 +++ dp/wifi3.0/li/dp_li.c | 9 ++ 12 files changed, 398 insertions(+), 28 deletions(-) diff --git a/dp/inc/cdp_txrx_host_stats.h b/dp/inc/cdp_txrx_host_stats.h index d78219de13..c9ccdea308 100644 --- a/dp/inc/cdp_txrx_host_stats.h +++ b/dp/inc/cdp_txrx_host_stats.h @@ -1240,4 +1240,32 @@ static inline QDF_STATUS cdp_clear_pdev_obss_pd_stats( return soc->ops->host_stats_ops->clear_pdev_obss_pd_stats( soc, pdev_id, req); } + +/* + * cdp_host_get_interface_stats - Get vdev stats for ath interface + * @soc: soc handle + * @vdev_id: vdev_id + * @buf: buffer to hold vdev_stats + * + * return: QDF_STATUS + */ +static inline QDF_STATUS +cdp_host_get_interface_stats(ol_txrx_soc_handle soc, + uint8_t vdev_id, + struct cdp_vdev_stats *buf) +{ + if (!soc || !soc->ops) { + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + if (!soc->ops->host_stats_ops || + !soc->ops->host_stats_ops->txrx_get_interface_stats) + return QDF_STATUS_E_FAILURE; + + return soc->ops->host_stats_ops->txrx_get_interface_stats(soc, + vdev_id, + buf, + true); +} #endif /* _CDP_TXRX_HOST_STATS_H_ */ diff --git a/dp/inc/cdp_txrx_mlo.h b/dp/inc/cdp_txrx_mlo.h index da5f289d04..3dbfd78dec 100644 --- a/dp/inc/cdp_txrx_mlo.h +++ b/dp/inc/cdp_txrx_mlo.h @@ -190,12 +190,14 @@ static inline void cdp_mlo_update_delta_tqm(ol_txrx_soc_handle soc, * @soc: soc handle * @vdev_id: vdev_id of one of the vdev's of the MLD group * @buf: buffer to hold vdev_stats + * @link_vdev_only: flag to indicate if stats are required for specific vdev * * return: QDF_STATUS */ static inline QDF_STATUS cdp_mlo_get_mld_vdev_stats(ol_txrx_soc_handle soc, - uint8_t vdev_id, struct cdp_vdev_stats *buf) + uint8_t vdev_id, struct cdp_vdev_stats *buf, + bool link_vdev_only) { if (!soc || !soc->ops) { QDF_BUG(0); @@ -205,6 +207,9 @@ cdp_mlo_get_mld_vdev_stats(ol_txrx_soc_handle soc, if (!soc->ops->mlo_ops || !soc->ops->mlo_ops->mlo_get_mld_vdev_stats) return QDF_STATUS_E_FAILURE; - return soc->ops->mlo_ops->mlo_get_mld_vdev_stats(soc, vdev_id, buf); + return soc->ops->mlo_ops->mlo_get_mld_vdev_stats(soc, + vdev_id, + buf, + link_vdev_only); } #endif /*_CDP_TXRX_MLO_H_*/ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index f713dbb9c6..fb89958efa 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -180,7 +180,8 @@ struct cdp_mlo_ops { void (*mlo_update_mlo_ts_offset)(struct cdp_soc_t *soc_hdl, uint64_t offset); QDF_STATUS (*mlo_get_mld_vdev_stats)(struct cdp_soc_t *soc, - uint8_t vdev_id, void *buf); + uint8_t vdev_id, void *buf, + bool link_vdev_only); }; #endif @@ -1167,6 +1168,7 @@ struct cdp_mon_ops { * @txrx_get_peer_extd_rate_link_stats: * @get_pdev_obss_stats: * @clear_pdev_obss_pd_stats: + * @txrx_get_interface_stats: */ struct cdp_host_stats_ops { int (*txrx_host_stats_get)(struct cdp_soc_t *soc, uint8_t vdev_id, @@ -1253,7 +1255,7 @@ struct cdp_host_stats_ops { QDF_STATUS (*txrx_reset_peer_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t *peer_mac); - int + QDF_STATUS (*txrx_get_vdev_stats)(struct cdp_soc_t *soc, uint8_t vdev_id, void *buf, bool is_aggregate); int @@ -1366,6 +1368,10 @@ struct cdp_host_stats_ops { QDF_STATUS (*clear_pdev_obss_pd_stats)(struct cdp_soc_t *soc, uint8_t pdev_id, struct cdp_txrx_stats_req *req); + QDF_STATUS (*txrx_get_interface_stats)(struct cdp_soc_t *soc, + uint8_t vdev_id, + void *buf, + bool is_aggregate); }; /** diff --git a/dp/wifi3.0/be/dp_be.c b/dp/wifi3.0/be/dp_be.c index acc0504d2c..a306476353 100644 --- a/dp/wifi3.0/be/dp_be.c +++ b/dp/wifi3.0/be/dp_be.c @@ -2379,6 +2379,17 @@ static void dp_txrx_set_mlo_mcast_primary_vdev_param_be( WDI_NO_VAL, params.pdev_id); } } + +static +void dp_get_vdev_stats_for_unmap_peer_be(struct dp_vdev *vdev, + struct dp_peer *peer, + struct cdp_vdev_stats **vdev_stats) +{ + struct dp_vdev_be *be_vdev = dp_get_be_vdev_from_dp_vdev(vdev); + + if (!IS_DP_LEGACY_PEER(peer)) + *vdev_stats = &be_vdev->mlo_stats; +} #else static void dp_txrx_set_mlo_mcast_primary_vdev_param_be( struct dp_vdev *vdev, @@ -2470,6 +2481,13 @@ QDF_STATUS dp_txrx_get_vdev_mcast_param_be(struct dp_soc *soc, { return QDF_STATUS_SUCCESS; } + +static +void dp_get_vdev_stats_for_unmap_peer_be(struct dp_vdev *vdev, + struct dp_peer *peer, + struct cdp_vdev_stats **vdev_stats) +{ +} #endif #ifdef DP_TX_IMPLICIT_RBM_MAPPING @@ -2902,6 +2920,8 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops) arch_ops->reo_remap_config = dp_reo_remap_config_be; arch_ops->txrx_get_vdev_mcast_param = dp_txrx_get_vdev_mcast_param_be; arch_ops->txrx_srng_init = dp_srng_init_be; + arch_ops->dp_get_vdev_stats_for_unmap_peer = + dp_get_vdev_stats_for_unmap_peer_be; #if defined(DP_POWER_SAVE) || defined(FEATURE_RUNTIME_PM) arch_ops->dp_update_ring_hptp = dp_update_ring_hptp; #endif diff --git a/dp/wifi3.0/be/dp_be.h b/dp/wifi3.0/be/dp_be.h index f6e2458a8f..ab1474d25c 100644 --- a/dp/wifi3.0/be/dp_be.h +++ b/dp/wifi3.0/be/dp_be.h @@ -399,6 +399,7 @@ struct dp_pdev_be { * @bank_id: bank_id to be used for TX * @vdev_id_check_en: flag if HW vdev_id check is enabled for vdev * @partner_vdev_list: partner list used for Intra-BSS + * @mlo_stats: structure to hold stats for mlo unmapped peers * @seq_num: DP MLO seq number * @mcast_primary: MLO Mcast primary vdev */ @@ -408,6 +409,7 @@ struct dp_vdev_be { uint8_t vdev_id_check_en; #ifdef WLAN_MLO_MULTI_CHIP uint8_t partner_vdev_list[WLAN_MAX_MLO_CHIPS][WLAN_MAX_MLO_LINKS_PER_SOC]; + struct cdp_vdev_stats mlo_stats; #ifdef WLAN_FEATURE_11BE_MLO #ifdef WLAN_MCAST_MLO uint16_t seq_num; diff --git a/dp/wifi3.0/be/mlo/dp_mlo.c b/dp/wifi3.0/be/mlo/dp_mlo.c index 1b38f7930b..cefb9abd93 100644 --- a/dp/wifi3.0/be/mlo/dp_mlo.c +++ b/dp/wifi3.0/be/mlo/dp_mlo.c @@ -544,27 +544,178 @@ static void dp_mlo_update_mlo_ts_offset(struct cdp_soc_t *soc_hdl, } #ifdef CONFIG_MLO_SINGLE_DEV -static void dp_mlo_aggregate_mld_vdev_stats(struct dp_vdev_be *be_vdev, - struct dp_vdev *ptnr_vdev, - void *arg) +/** + * dp_aggregate_vdev_ingress_stats() - aggregate vdev ingress stats + * @tgt_vdev_stats: target vdev buffer + * @src_vdev_stats: source vdev buffer + * + * return: void + */ +static inline +void dp_aggregate_vdev_ingress_stats( + struct cdp_vdev_stats *tgt_vdev_stats, + struct cdp_vdev_stats *src_vdev_stats) { - struct cdp_vdev_stats *tgt_vdev_stats = (struct cdp_vdev_stats *)arg; - struct cdp_vdev_stats *src_vdev_stats = &ptnr_vdev->stats; - /* Aggregate vdev ingress stats */ DP_UPDATE_INGRESS_STATS(tgt_vdev_stats, src_vdev_stats); +} +/** + * dp_aggregate_vdev_stats_for_unmapped_peers() - aggregate unmap peer stats + * @tgt_vdev_stats: target vdev buffer + * @src_vdev_stats: source vdev buffer + * + * return: void + */ +static inline +void dp_aggregate_vdev_stats_for_unmapped_peers( + struct cdp_vdev_stats *tgt_vdev_stats, + struct cdp_vdev_stats *src_vdev_stats) +{ /* Aggregate unmapped peers stats */ - DP_UPDATE_PER_PKT_STATS(tgt_vdev_stats, src_vdev_stats); - DP_UPDATE_EXTD_STATS(tgt_vdev_stats, src_vdev_stats); + DP_UPDATE_VDEV_STATS_FOR_UNMAPPED_PEERS(tgt_vdev_stats, src_vdev_stats); +} - /* Aggregate associated peers stats */ - dp_vdev_iterate_peer(ptnr_vdev, dp_update_vdev_stats, tgt_vdev_stats, +/** + * dp_aggregate_all_vdev_stats() - aggregate vdev ingress and unmap peer stats + * @tgt_vdev_stats: target vdev buffer + * @src_vdev_stats: source vdev buffer + * + * return: void + */ +static inline +void dp_aggregate_all_vdev_stats( + struct cdp_vdev_stats *tgt_vdev_stats, + struct cdp_vdev_stats *src_vdev_stats) +{ + dp_aggregate_vdev_ingress_stats(tgt_vdev_stats, src_vdev_stats); + dp_aggregate_vdev_stats_for_unmapped_peers(tgt_vdev_stats, + src_vdev_stats); +} + +/** + * dp_aggregate_interface_stats_based_on_peer_type() - aggregate stats at + * VDEV level based on peer type connected to vdev + * @vdev: DP VDEV handle + * @vdev_stats: target vdev stats pointer + * @peer_type: type of peer - MLO Link or Legacy peer + * + * return: void + */ +static +void dp_aggregate_interface_stats_based_on_peer_type( + struct dp_vdev *vdev, + struct cdp_vdev_stats *vdev_stats, + enum dp_peer_type peer_type) +{ + struct cdp_vdev_stats *tgt_vdev_stats = NULL; + struct dp_vdev_be *be_vdev = NULL; + + if (!vdev || !vdev->pdev) + return; + + tgt_vdev_stats = vdev_stats; + be_vdev = dp_get_be_vdev_from_dp_vdev(vdev); + if (!be_vdev) + return; + + if (peer_type == DP_PEER_TYPE_LEGACY) { + dp_aggregate_all_vdev_stats(tgt_vdev_stats, + &vdev->stats); + } else { + dp_aggregate_vdev_ingress_stats(tgt_vdev_stats, + &vdev->stats); + dp_aggregate_vdev_stats_for_unmapped_peers( + tgt_vdev_stats, + &be_vdev->mlo_stats); + } + + /* Aggregate associated peer stats */ + dp_vdev_iterate_specific_peer_type(vdev, + dp_update_vdev_stats, + vdev_stats, + DP_MOD_ID_GENERIC_STATS, + peer_type); +} + +/** + * dp_aggregate_interface_stats() - aggregate stats at VDEV level + * @vdev: DP VDEV handle + * @vdev_stats: target vdev stats pointer + * + * return: void + */ +static +void dp_aggregate_interface_stats(struct dp_vdev *vdev, + struct cdp_vdev_stats *vdev_stats) +{ + struct dp_vdev_be *be_vdev = NULL; + + if (!vdev || !vdev->pdev) + return; + + be_vdev = dp_get_be_vdev_from_dp_vdev(vdev); + if (!be_vdev) + return; + + dp_aggregate_all_vdev_stats(vdev_stats, &be_vdev->mlo_stats); + dp_aggregate_all_vdev_stats(vdev_stats, &vdev->stats); + + dp_vdev_iterate_peer(vdev, dp_update_vdev_stats, vdev_stats, DP_MOD_ID_GENERIC_STATS); + + dp_update_vdev_rate_stats(vdev_stats, &vdev->stats); + +#if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE + dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, vdev->pdev->soc, + vdev_stats, vdev->vdev_id, + UPDATE_VDEV_STATS, vdev->pdev->pdev_id); +#endif +} + +/** + * dp_mlo_aggr_ptnr_iface_stats() - aggregate mlo partner vdev stats + * @be_vdev: vdev handle + * @ptnr_vdev: partner vdev handle + * @arg: target buffer for aggregation + * + * return: void + */ +static +void dp_mlo_aggr_ptnr_iface_stats(struct dp_vdev_be *be_vdev, + struct dp_vdev *ptnr_vdev, + void *arg) +{ + struct cdp_vdev_stats *tgt_vdev_stats = (struct cdp_vdev_stats *)arg; + + dp_aggregate_interface_stats(ptnr_vdev, tgt_vdev_stats); +} + +/** + * dp_mlo_aggr_ptnr_iface_stats_mlo_links() - aggregate mlo partner vdev stats + * based on peer type + * @be_vdev: vdev handle + * @ptnr_vdev: partner vdev handle + * @arg: target buffer for aggregation + * + * return: void + */ +static +void dp_mlo_aggr_ptnr_iface_stats_mlo_links( + struct dp_vdev_be *be_vdev, + struct dp_vdev *ptnr_vdev, + void *arg) +{ + struct cdp_vdev_stats *tgt_vdev_stats = (struct cdp_vdev_stats *)arg; + + dp_aggregate_interface_stats_based_on_peer_type(ptnr_vdev, + tgt_vdev_stats, + DP_PEER_TYPE_MLO_LINK); } static QDF_STATUS dp_mlo_get_mld_vdev_stats(struct cdp_soc_t *soc_hdl, - uint8_t vdev_id, void *buf) + uint8_t vdev_id, void *buf, + bool link_vdev_only) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); @@ -584,12 +735,56 @@ static QDF_STATUS dp_mlo_get_mld_vdev_stats(struct cdp_soc_t *soc_hdl, vdev_stats = (struct cdp_vdev_stats *)buf; - dp_aggregate_vdev_stats(vdev, buf); + if (DP_MLD_MODE_HYBRID_NONBOND == soc->mld_mode_ap && + vdev->opmode == wlan_op_mode_ap) { + dp_aggregate_interface_stats_based_on_peer_type( + vdev, buf, + DP_PEER_TYPE_MLO_LINK); + if (link_vdev_only) + goto complete; - /* Aggregate stats from partner vdevs */ - dp_mlo_iter_ptnr_vdev(be_soc, vdev_be, - dp_mlo_aggregate_mld_vdev_stats, buf, - DP_MOD_ID_GENERIC_STATS); + /* Aggregate stats from partner vdevs */ + dp_mlo_iter_ptnr_vdev(be_soc, vdev_be, + dp_mlo_aggr_ptnr_iface_stats_mlo_links, + buf, + DP_MOD_ID_GENERIC_STATS); + } else { + dp_aggregate_interface_stats(vdev, buf); + + if (link_vdev_only) + goto complete; + + /* Aggregate stats from partner vdevs */ + dp_mlo_iter_ptnr_vdev(be_soc, vdev_be, + dp_mlo_aggr_ptnr_iface_stats, buf, + DP_MOD_ID_GENERIC_STATS); + } + +complete: + dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_GENERIC_STATS); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +dp_txrx_get_interface_stats(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + void *buf, + bool is_aggregate) +{ + struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); + struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id, + DP_MOD_ID_GENERIC_STATS); + if (!vdev) + return QDF_STATUS_E_FAILURE; + + if (DP_MLD_MODE_HYBRID_NONBOND == soc->mld_mode_ap && + vdev->opmode == wlan_op_mode_ap) { + dp_aggregate_interface_stats_based_on_peer_type( + vdev, buf, + DP_PEER_TYPE_LEGACY); + } else { + dp_aggregate_interface_stats(vdev, buf); + } dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_GENERIC_STATS); diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 9dc00c10ea..88be50e1e0 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -1891,6 +1891,15 @@ void dp_update_vdev_stats_on_peer_unmap(struct dp_vdev *vdev, #define DP_UPDATE_11BE_STATS(_tgtobj, _srcobj) #endif +#define DP_UPDATE_BASIC_STATS(_tgtobj, _srcobj) \ + do { \ + _tgtobj->tx.comp_pkt.num += _srcobj->tx.comp_pkt.num; \ + _tgtobj->tx.comp_pkt.bytes += _srcobj->tx.comp_pkt.bytes; \ + _tgtobj->tx.tx_failed += _srcobj->tx.tx_failed; \ + _tgtobj->rx.to_stack.num += _srcobj->rx.to_stack.num; \ + _tgtobj->rx.to_stack.bytes += _srcobj->rx.to_stack.bytes; \ + } while (0) + #define DP_UPDATE_PER_PKT_STATS(_tgtobj, _srcobj) \ do { \ uint8_t i; \ @@ -2176,6 +2185,13 @@ void dp_update_vdev_stats_on_peer_unmap(struct dp_vdev *vdev, DP_UPDATE_11BE_STATS(_tgtobj, _srcobj); \ } while (0) +#define DP_UPDATE_VDEV_STATS_FOR_UNMAPPED_PEERS(_tgtobj, _srcobj) \ + do { \ + DP_UPDATE_BASIC_STATS(_tgtobj, _srcobj); \ + DP_UPDATE_PER_PKT_STATS(_tgtobj, _srcobj); \ + DP_UPDATE_EXTD_STATS(_tgtobj, _srcobj); \ + } while (0) + #define DP_UPDATE_INGRESS_STATS(_tgtobj, _srcobj) \ do { \ uint8_t i = 0; \ @@ -2832,6 +2848,22 @@ uint32_t dp_reo_status_ring_handler(struct dp_intr *int_ctx, void dp_aggregate_vdev_stats(struct dp_vdev *vdev, struct cdp_vdev_stats *vdev_stats); +/** + * dp_txrx_get_interface_stats() - get vdev stats for ath interface + * @soc_hdl: CDP SoC handle + * @vdev_id: vdev Id + * @buf: buffer for vdev stats + * @is_aggregate: for aggregation + * + * Return: QDF_STATUS + */ + +QDF_STATUS +dp_txrx_get_interface_stats(struct cdp_soc_t *soc_hdl, + uint8_t vdev_id, + void *buf, + bool is_aggregate); + /** * dp_rx_bar_stats_cb() - BAR received stats callback * @soc: SOC handle diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 802511a90f..5fa99db474 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5737,7 +5737,6 @@ bool dp_check_pdev_exists(struct dp_soc *soc, struct dp_pdev *data) void dp_aggregate_vdev_stats(struct dp_vdev *vdev, struct cdp_vdev_stats *vdev_stats) { - if (!vdev || !vdev->pdev) return; @@ -5752,8 +5751,8 @@ void dp_aggregate_vdev_stats(struct dp_vdev *vdev, #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, vdev->pdev->soc, - vdev_stats, vdev->vdev_id, - UPDATE_VDEV_STATS, vdev->pdev->pdev_id); + vdev_stats, vdev->vdev_id, + UPDATE_VDEV_STATS, vdev->pdev->pdev_id); #endif } @@ -8190,10 +8189,11 @@ dp_txrx_reset_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, * @buf: buffer for vdev stats * @is_aggregate: are aggregate stats being collected * - * Return: int + * Return: QDF_STATUS */ -static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, - void *buf, bool is_aggregate) +static QDF_STATUS +dp_txrx_get_vdev_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + void *buf, bool is_aggregate) { struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); struct cdp_vdev_stats *vdev_stats; @@ -8201,7 +8201,7 @@ static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, DP_MOD_ID_CDP); if (!vdev) - return 1; + return QDF_STATUS_E_RESOURCES; vdev_stats = (struct cdp_vdev_stats *)buf; @@ -8212,7 +8212,7 @@ static int dp_txrx_get_vdev_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, } dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP); - return 0; + return QDF_STATUS_SUCCESS; } /** @@ -10908,6 +10908,11 @@ static struct cdp_host_stats_ops dp_ops_host_stats = { dp_get_peer_extd_rate_link_stats, .get_pdev_obss_stats = dp_get_obss_stats, .clear_pdev_obss_pd_stats = dp_clear_pdev_obss_pd_stats, +#ifdef CONFIG_MLO_SINGLE_DEV + .txrx_get_interface_stats = dp_txrx_get_interface_stats, +#else + .txrx_get_interface_stats = dp_txrx_get_vdev_stats, +#endif /* TODO */ }; diff --git a/dp/wifi3.0/dp_peer.h b/dp/wifi3.0/dp_peer.h index c866f9d5ce..07b01d9be4 100644 --- a/dp/wifi3.0/dp_peer.h +++ b/dp/wifi3.0/dp_peer.h @@ -2330,6 +2330,51 @@ dp_peer_update_state(struct dp_soc *soc, QDF_MAC_ADDR_REF(peer->mac_addr.raw)); } +/** + * dp_vdev_iterate_specific_peer_type() - API to iterate through vdev peer + * list based on type of peer (Legacy or MLD peer) + * + * @vdev: DP vdev context + * @func: function to be called for each peer + * @arg: argument need to be passed to func + * @mod_id: module_id + * @peer_type: type of peer - MLO Link Peer or Legacy Peer + * + * Return: void + */ +static inline void +dp_vdev_iterate_specific_peer_type(struct dp_vdev *vdev, + dp_peer_iter_func *func, + void *arg, enum dp_mod_id mod_id, + enum dp_peer_type peer_type) +{ + struct dp_peer *peer; + struct dp_peer *tmp_peer; + struct dp_soc *soc = NULL; + + if (!vdev || !vdev->pdev || !vdev->pdev->soc) + return; + + soc = vdev->pdev->soc; + + qdf_spin_lock_bh(&vdev->peer_list_lock); + TAILQ_FOREACH_SAFE(peer, &vdev->peer_list, + peer_list_elem, + tmp_peer) { + if (dp_peer_get_ref(soc, peer, mod_id) == + QDF_STATUS_SUCCESS) { + if ((peer_type == DP_PEER_TYPE_LEGACY && + (IS_DP_LEGACY_PEER(peer))) || + (peer_type == DP_PEER_TYPE_MLO_LINK && + (IS_MLO_DP_LINK_PEER(peer)))) { + (*func)(soc, peer, arg); + } + dp_peer_unref_delete(peer, mod_id); + } + } + qdf_spin_unlock_bh(&vdev->peer_list_lock); +} + #ifdef REO_SHARED_QREF_TABLE_EN void dp_peer_rx_reo_shared_qaddr_delete(struct dp_soc *soc, struct dp_peer *peer); diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index 81ce4d6f5e..c4aa163883 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -8661,6 +8661,11 @@ void dp_update_vdev_stats_on_peer_unmap(struct dp_vdev *vdev, uint8_t link_id = 0; struct dp_pdev *pdev = vdev->pdev; + if (soc && soc->arch_ops.dp_get_vdev_stats_for_unmap_peer) + soc->arch_ops.dp_get_vdev_stats_for_unmap_peer(vdev, + peer, + &vdev_stats); + txrx_peer = dp_get_txrx_peer(peer); if (!txrx_peer) goto link_stats; diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 2286b754fe..9c87d76821 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -328,6 +328,18 @@ enum dp_mod_id { DP_MOD_ID_MAX, }; +/** + * enum dp_peer_type - DP peer type + * @DP_PEER_TYPE_LEGACY: + * @DP_PEER_TYPE_MLO_LINK: + * @DP_PEER_TYPE_MLO: + */ +enum dp_peer_type { + DP_PEER_TYPE_LEGACY, + DP_PEER_TYPE_MLO_LINK, + DP_PEER_TYPE_MLO, +}; + #define DP_PDEV_ITERATE_VDEV_LIST(_pdev, _vdev) \ TAILQ_FOREACH((_vdev), &(_pdev)->vdev_list, vdev_list_elem) @@ -2247,6 +2259,7 @@ enum dp_context_type { * @dp_tx_desc_pool_alloc: Allocate arch specific TX descriptor pool * @dp_tx_desc_pool_free: Free arch specific TX descriptor pool * @txrx_srng_init: Init txrx srng + * @dp_get_vdev_stats_for_unmap_peer: Get vdev stats pointer for unmap peer * @ppeds_handle_attached: * @txrx_soc_ppeds_interrupt_stop: * @txrx_soc_ppeds_interrupt_start: @@ -2493,6 +2506,11 @@ struct dp_arch_ops { QDF_STATUS (*txrx_srng_init)(struct dp_soc *soc, struct dp_srng *srng, int ring_type, int ring_num, int mac_id); + + void (*dp_get_vdev_stats_for_unmap_peer)( + struct dp_vdev *vdev, + struct dp_peer *peer, + struct cdp_vdev_stats **vdev_stats); #ifdef WLAN_SUPPORT_PPEDS void (*txrx_soc_ppeds_interrupt_stop)(struct dp_soc *soc); void (*txrx_soc_ppeds_interrupt_start)(struct dp_soc *soc); diff --git a/dp/wifi3.0/li/dp_li.c b/dp/wifi3.0/li/dp_li.c index affd62dc12..0e60004155 100644 --- a/dp/wifi3.0/li/dp_li.c +++ b/dp/wifi3.0/li/dp_li.c @@ -635,6 +635,13 @@ static uint8_t dp_get_hw_link_id_li(struct dp_pdev *pdev) return 0; } +static void dp_get_vdev_stats_for_unmap_peer_li( + struct dp_vdev *vdev, + struct dp_peer *peer, + struct cdp_vdev_stats **vdev_stats) +{ +} + void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops) { #ifndef QCA_HOST_MODE_WIFI_DISABLED @@ -710,6 +717,8 @@ void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops) arch_ops->txrx_get_vdev_mcast_param = dp_txrx_get_vdev_mcast_param_li; arch_ops->get_hw_link_id = dp_get_hw_link_id_li; arch_ops->txrx_srng_init = dp_srng_init_li; + arch_ops->dp_get_vdev_stats_for_unmap_peer = + dp_get_vdev_stats_for_unmap_peer_li; #if defined(DP_POWER_SAVE) || defined(FEATURE_RUNTIME_PM) arch_ops->dp_update_ring_hptp = dp_update_ring_hptp; #endif