From e8082534bd043fdbe041549d59c8fe7b63362d02 Mon Sep 17 00:00:00 2001 From: Harsh Kumar Bijlani Date: Tue, 21 Dec 2021 18:32:58 +0530 Subject: [PATCH] qcacmn: Changes to get and reset peer stats Changes to get and reset peer stats as per the new peer stats re-organization architecture and taking MLO scenario into consideration. Change-Id: I1c49e11d502585cc955ad087ffe3a606be23d83e CRs-Fixed: 3092123 --- dp/wifi3.0/dp_internal.h | 6 + dp/wifi3.0/dp_main.c | 253 ++++++++++++++++++++++++++-- dp/wifi3.0/monitor/1.0/dp_mon_1.0.c | 1 + dp/wifi3.0/monitor/2.0/dp_mon_2.0.c | 1 + dp/wifi3.0/monitor/dp_mon.c | 31 ++++ dp/wifi3.0/monitor/dp_mon.h | 51 ++++++ 6 files changed, 331 insertions(+), 12 deletions(-) diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index fbabb4c96e..415ebf5f3b 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -241,6 +241,12 @@ void dp_monitor_peer_reset_stats(struct dp_soc *soc, struct dp_peer *peer) { } +static inline +void dp_monitor_peer_get_stats(struct dp_soc *soc, struct dp_peer *peer, + void *arg, enum cdp_stat_update_type type) +{ +} + static inline QDF_STATUS dp_monitor_pdev_init(struct dp_pdev *pdev) { return QDF_STATUS_SUCCESS; diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index d1559c7c23..a76175dcfc 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -8852,21 +8852,29 @@ dp_txrx_host_peer_stats_clr(struct dp_soc *soc, struct dp_peer *peer, void *arg) { - struct dp_rx_tid *rx_tid; - uint8_t tid; + struct dp_txrx_peer *txrx_peer = NULL; + struct dp_peer *tgt_peer = NULL; + struct cdp_interface_peer_stats peer_stats_intf; - for (tid = 0; tid < DP_MAX_TIDS; tid++) { - rx_tid = &peer->rx_tid[tid]; - DP_STATS_CLR(rx_tid); - } + qdf_mem_zero(&peer_stats_intf, sizeof(struct cdp_interface_peer_stats)); DP_STATS_CLR(peer); + /* Clear monitor peer stats */ + dp_monitor_peer_reset_stats(soc, peer); - dp_txrx_host_peer_delay_stats_clr(peer); + /* Clear MLD peer stats only when link peer is primary */ + if (dp_peer_is_primary_link_peer(peer)) { + tgt_peer = dp_get_tgt_peer_from_peer(peer); + if (tgt_peer) { + DP_STATS_CLR(tgt_peer); + txrx_peer = tgt_peer->txrx_peer; + dp_txrx_peer_stats_clr(txrx_peer); + } + } #if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, peer->vdev->pdev->soc, - &peer->stats, peer->peer_id, + &peer_stats_intf, peer->peer_id, UPDATE_PEER_STATS, peer->vdev->pdev->pdev_id); #endif } @@ -8915,6 +8923,164 @@ dp_txrx_host_stats_clr(struct dp_vdev *vdev, struct dp_soc *soc) return QDF_STATUS_SUCCESS; } +/** + * dp_get_peer_calibr_stats()- Get peer calibrated stats + * @peer: Datapath peer + * @peer_stats: buffer for peer stats + * + * Return: none + */ +static inline +void dp_get_peer_calibr_stats(struct dp_peer *peer, + struct cdp_peer_stats *peer_stats) +{ + peer_stats->tx.last_per = peer->stats.tx.last_per; + peer_stats->tx.tx_bytes_success_last = + peer->stats.tx.tx_bytes_success_last; + peer_stats->tx.tx_data_success_last = + peer->stats.tx.tx_data_success_last; + peer_stats->tx.tx_byte_rate = peer->stats.tx.tx_byte_rate; + peer_stats->tx.tx_data_rate = peer->stats.tx.tx_data_rate; + peer_stats->tx.tx_data_ucast_last = peer->stats.tx.tx_data_ucast_last; + peer_stats->tx.tx_data_ucast_rate = peer->stats.tx.tx_data_ucast_rate; + peer_stats->tx.inactive_time = peer->stats.tx.inactive_time; + peer_stats->rx.rx_bytes_success_last = + peer->stats.rx.rx_bytes_success_last; + peer_stats->rx.rx_data_success_last = + peer->stats.rx.rx_data_success_last; + peer_stats->rx.rx_byte_rate = peer->stats.rx.rx_byte_rate; + peer_stats->rx.rx_data_rate = peer->stats.rx.rx_data_rate; +} + +/** + * dp_get_peer_basic_stats()- Get peer basic stats + * @peer: Datapath peer + * @peer_stats: buffer for peer stats + * + * Return: none + */ +static inline +void dp_get_peer_basic_stats(struct dp_peer *peer, + struct cdp_peer_stats *peer_stats) +{ + struct dp_txrx_peer *txrx_peer; + + txrx_peer = peer->txrx_peer; + if (!txrx_peer) + return; + + peer_stats->tx.comp_pkt.num += txrx_peer->comp_pkt.num; + peer_stats->tx.comp_pkt.bytes += txrx_peer->comp_pkt.bytes; + peer_stats->tx.tx_failed += txrx_peer->tx_failed; + peer_stats->rx.to_stack.num += txrx_peer->to_stack.num; + peer_stats->rx.to_stack.bytes += txrx_peer->to_stack.bytes; +} + +/** + * dp_get_peer_per_pkt_stats()- Get peer per pkt stats + * @peer: Datapath peer + * @peer_stats: buffer for peer stats + * + * Return: none + */ +static inline +void dp_get_peer_per_pkt_stats(struct dp_peer *peer, + struct cdp_peer_stats *peer_stats) +{ + struct dp_txrx_peer *txrx_peer; + struct dp_peer_per_pkt_stats *per_pkt_stats; + + txrx_peer = peer->txrx_peer; + if (!txrx_peer) + return; + + per_pkt_stats = &txrx_peer->stats.per_pkt_stats; + DP_UPDATE_PER_PKT_STATS(peer_stats, per_pkt_stats); +} + +/** + * dp_get_peer_extd_stats()- Get peer extd stats + * @peer: Datapath peer + * @peer_stats: buffer for peer stats + * + * Return: none + */ +#ifdef QCA_ENHANCED_STATS_SUPPORT +#ifdef WLAN_FEATURE_11BE_MLO +static inline +void dp_get_peer_extd_stats(struct dp_peer *peer, + struct cdp_peer_stats *peer_stats) +{ + struct dp_soc *soc = peer->vdev->pdev->soc; + + if (IS_MLO_DP_MLD_PEER(peer)) { + uint8_t i; + struct dp_peer *link_peer; + struct dp_soc *link_peer_soc; + struct dp_mld_link_peers link_peers_info; + + dp_get_link_peers_ref_from_mld_peer(soc, peer, + &link_peers_info, + DP_MOD_ID_CDP); + for (i = 0; i < link_peers_info.num_links; i++) { + link_peer = link_peers_info.link_peers[i]; + link_peer_soc = link_peer->vdev->pdev->soc; + dp_monitor_peer_get_stats(link_peer_soc, link_peer, + peer_stats, + UPDATE_PEER_STATS); + } + dp_release_link_peers_ref(&link_peers_info, DP_MOD_ID_CDP); + } else { + dp_monitor_peer_get_stats(soc, peer, peer_stats, + UPDATE_PEER_STATS); + } +} +#else +static inline +void dp_get_peer_extd_stats(struct dp_peer *peer, + struct cdp_peer_stats *peer_stats) +{ + struct dp_soc *soc = peer->vdev->pdev->soc; + + dp_monitor_peer_get_stats(soc, peer, peer_stats, UPDATE_PEER_STATS); +} +#endif +#else +static inline +void dp_get_peer_extd_stats(struct dp_peer *peer, + struct cdp_peer_stats *peer_stats) +{ + struct dp_txrx_peer *txrx_peer; + struct dp_peer_extd_stats *extd_stats; + + txrx_peer = peer->txrx_peer; + if (!txrx_peer) + return; + + extd_stats = &txrx_peer->stats.extd_stats; + DP_UPDATE_EXTD_STATS(peer_stats, extd_stats); +} +#endif + +/** + * dp_get_peer_stats()- Get peer stats + * @peer: Datapath peer + * @peer_stats: buffer for peer stats + * + * Return: none + */ +static inline +void dp_get_peer_stats(struct dp_peer *peer, struct cdp_peer_stats *peer_stats) +{ + dp_get_peer_calibr_stats(peer, peer_stats); + + dp_get_peer_basic_stats(peer, peer_stats); + + dp_get_peer_per_pkt_stats(peer, peer_stats); + + dp_get_peer_extd_stats(peer, peer_stats); +} + /* * dp_get_host_peer_stats()- function to print peer stats * @soc: dp_soc handle @@ -8926,6 +9092,7 @@ static QDF_STATUS dp_get_host_peer_stats(struct cdp_soc_t *soc, uint8_t *mac_addr) { struct dp_peer *peer = NULL; + struct cdp_peer_stats *peer_stats = NULL; if (!mac_addr) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -8943,9 +9110,23 @@ dp_get_host_peer_stats(struct cdp_soc_t *soc, uint8_t *mac_addr) return QDF_STATUS_E_FAILURE; } - dp_print_peer_stats(peer); + peer_stats = qdf_mem_malloc(sizeof(struct cdp_peer_stats)); + if (!peer_stats) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "%s: Memory allocation failed for cdp_peer_stats\n", + __func__); + dp_peer_unref_delete(peer, DP_MOD_ID_CDP); + return QDF_STATUS_E_NOMEM; + } + + qdf_mem_zero(peer_stats, sizeof(struct cdp_peer_stats)); + + dp_get_peer_stats(peer, peer_stats); + dp_print_peer_stats(peer, peer_stats); + dp_peer_rxtid_stats(peer, dp_rx_tid_stats_cb, NULL); + qdf_mem_free(peer_stats); dp_peer_unref_delete(peer, DP_MOD_ID_CDP); return QDF_STATUS_SUCCESS; @@ -10031,11 +10212,12 @@ dp_txrx_get_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, peer_mac, 0, vdev_id, DP_MOD_ID_CDP); + qdf_mem_zero(peer_stats, sizeof(struct cdp_peer_stats)); + if (!peer) return QDF_STATUS_E_FAILURE; - qdf_mem_copy(peer_stats, &peer->stats, - sizeof(struct cdp_peer_stats)); + dp_get_peer_stats(peer, peer_stats); dp_peer_unref_delete(peer, DP_MOD_ID_CDP); @@ -10130,6 +10312,50 @@ dp_txrx_get_peer_stats_param(struct cdp_soc_t *soc, uint8_t vdev_id, * * return : QDF_STATUS */ +#ifdef WLAN_FEATURE_11BE_MLO +static QDF_STATUS +dp_txrx_reset_peer_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, + uint8_t *peer_mac) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_peer *peer = + dp_peer_get_tgt_peer_hash_find(soc, peer_mac, 0, + vdev_id, DP_MOD_ID_CDP); + + if (!peer) + return QDF_STATUS_E_FAILURE; + + DP_STATS_CLR(peer); + dp_txrx_peer_stats_clr(peer->txrx_peer); + + if (IS_MLO_DP_MLD_PEER(peer)) { + uint8_t i; + struct dp_peer *link_peer; + struct dp_soc *link_peer_soc; + struct dp_mld_link_peers link_peers_info; + + dp_get_link_peers_ref_from_mld_peer(soc, peer, + &link_peers_info, + DP_MOD_ID_CDP); + for (i = 0; i < link_peers_info.num_links; i++) { + link_peer = link_peers_info.link_peers[i]; + link_peer_soc = link_peer->vdev->pdev->soc; + + DP_STATS_CLR(link_peer); + dp_monitor_peer_reset_stats(link_peer_soc, link_peer); + } + + dp_release_link_peers_ref(&link_peers_info, DP_MOD_ID_CDP); + } else { + dp_monitor_peer_reset_stats(soc, peer); + } + + dp_peer_unref_delete(peer, DP_MOD_ID_CDP); + + return status; +} +#else static QDF_STATUS dp_txrx_reset_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, uint8_t *peer_mac) @@ -10142,12 +10368,15 @@ dp_txrx_reset_peer_stats(struct cdp_soc_t *soc, uint8_t vdev_id, if (!peer) return QDF_STATUS_E_FAILURE; - qdf_mem_zero(&peer->stats, sizeof(peer->stats)); + DP_STATS_CLR(peer); + dp_txrx_peer_stats_clr(peer->txrx_peer); + dp_monitor_peer_reset_stats((struct dp_soc *)soc, peer); dp_peer_unref_delete(peer, DP_MOD_ID_CDP); return status; } +#endif /* dp_txrx_get_vdev_stats - Update buffer with cdp_vdev_stats * @vdev_handle: DP_VDEV handle diff --git a/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c b/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c index 9f5a27b374..e52bd94d9d 100644 --- a/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c +++ b/dp/wifi3.0/monitor/1.0/dp_mon_1.0.c @@ -997,6 +997,7 @@ struct dp_mon_ops monitor_ops_1_0 = { .mon_peer_detach = dp_mon_peer_detach, .mon_peer_get_rdkstats_ctx = dp_mon_peer_get_rdkstats_ctx, .mon_peer_reset_stats = dp_mon_peer_reset_stats, + .mon_peer_get_stats = dp_mon_peer_get_stats, .mon_flush_rings = dp_flush_monitor_rings, #if !defined(DISABLE_MON_CONFIG) .mon_pdev_htt_srng_setup = dp_mon_htt_srng_setup_1_0, diff --git a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c index 4171ee9a58..259b605b71 100644 --- a/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c +++ b/dp/wifi3.0/monitor/2.0/dp_mon_2.0.c @@ -1139,6 +1139,7 @@ struct dp_mon_ops monitor_ops_2_0 = { .mon_peer_detach = dp_mon_peer_detach, .mon_peer_get_rdkstats_ctx = dp_mon_peer_get_rdkstats_ctx, .mon_peer_reset_stats = dp_mon_peer_reset_stats, + .mon_peer_get_stats = dp_mon_peer_get_stats, .mon_flush_rings = NULL, #if !defined(DISABLE_MON_CONFIG) .mon_pdev_htt_srng_setup = dp_mon_pdev_htt_srng_setup_2_0, diff --git a/dp/wifi3.0/monitor/dp_mon.c b/dp/wifi3.0/monitor/dp_mon.c index 4fb9b98c83..855a34200d 100644 --- a/dp/wifi3.0/monitor/dp_mon.c +++ b/dp/wifi3.0/monitor/dp_mon.c @@ -5113,6 +5113,37 @@ void dp_mon_peer_reset_stats(struct dp_peer *peer) DP_STATS_CLR(mon_peer); DP_STATS_UPD(mon_peer, rx.avg_snr, CDP_INVALID_SNR); } + +void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg, + enum cdp_stat_update_type type) +{ + struct dp_mon_peer *mon_peer = peer->monitor_peer; + struct dp_mon_peer_stats *mon_peer_stats; + + if (!mon_peer || !arg) + return; + + mon_peer_stats = &mon_peer->stats; + + switch (type) { + case UPDATE_PEER_STATS: + { + struct cdp_peer_stats *peer_stats = + (struct cdp_peer_stats *)arg; + DP_UPDATE_MON_STATS(peer_stats, mon_peer_stats); + break; + } + case UPDATE_VDEV_STATS: + { + struct cdp_vdev_stats *vdev_stats = + (struct cdp_vdev_stats *)arg; + DP_UPDATE_MON_STATS(vdev_stats, mon_peer_stats); + break; + } + default: + dp_mon_err("Invalid stats_update_type"); + } +} #endif void dp_mon_ops_register(struct dp_soc *soc) diff --git a/dp/wifi3.0/monitor/dp_mon.h b/dp/wifi3.0/monitor/dp_mon.h index 64f274cf9e..3944095673 100644 --- a/dp/wifi3.0/monitor/dp_mon.h +++ b/dp/wifi3.0/monitor/dp_mon.h @@ -47,6 +47,9 @@ #ifdef QCA_ENHANCED_STATS_SUPPORT typedef struct dp_peer_extd_tx_stats dp_mon_peer_tx_stats; typedef struct dp_peer_extd_rx_stats dp_mon_peer_rx_stats; + +#define DP_UPDATE_MON_STATS(_tgtobj, _srcobj) \ + DP_UPDATE_EXTD_STATS(_tgtobj, _srcobj) #endif #ifndef WLAN_TX_PKT_CAPTURE_ENH @@ -202,10 +205,28 @@ struct cdp_peer_rate_stats_ctx *dp_mon_peer_get_rdkstats_ctx(struct dp_peer *pee * Return: none */ void dp_mon_peer_reset_stats(struct dp_peer *peer); + +/* + * dp_mon_peer_get_stats() - Get monitor peer stats + * + * @peer: Datapath peer handle + * @arg: Pointer to stats struct + * @type: Update type + * + * Return: none + */ +void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg, + enum cdp_stat_update_type type); #else static inline void dp_mon_peer_reset_stats(struct dp_peer *peer) { } + +static inline +void dp_mon_peer_get_stats(struct dp_peer *peer, void *arg, + enum cdp_stat_update_type type) +{ +} #endif /* @@ -459,6 +480,8 @@ struct dp_mon_ops { QDF_STATUS (*mon_peer_detach)(struct dp_peer *peer); struct cdp_peer_rate_stats_ctx *(*mon_peer_get_rdkstats_ctx)(struct dp_peer *peer); void (*mon_peer_reset_stats)(struct dp_peer *peer); + void (*mon_peer_get_stats)(struct dp_peer *peer, void *arg, + enum cdp_stat_update_type type); QDF_STATUS (*mon_config_debug_sniffer)(struct dp_pdev *pdev, int val); void (*mon_flush_rings)(struct dp_soc *soc); #if !defined(DISABLE_MON_CONFIG) @@ -1701,6 +1724,34 @@ static inline void dp_monitor_peer_reset_stats(struct dp_soc *soc, monitor_ops->mon_peer_reset_stats(peer); } +/* + * dp_monitor_peer_get_stats() - Get monitor peer stats + * @soc: Datapath soc handle + * @peer: Datapath peer handle + * @arg: Pointer to stats struct + * @type: Update type + * + * Return: none + */ +static inline +void dp_monitor_peer_get_stats(struct dp_soc *soc, struct dp_peer *peer, + void *arg, enum cdp_stat_update_type type) +{ + struct dp_mon_ops *monitor_ops; + struct dp_mon_soc *mon_soc = soc->monitor_soc; + + if (!mon_soc) + return; + + monitor_ops = mon_soc->mon_ops; + if (!monitor_ops || !monitor_ops->mon_peer_get_stats) { + dp_mon_debug("callback not registered"); + return; + } + + monitor_ops->mon_peer_get_stats(peer, arg, type); +} + /* * dp_monitor_pdev_init() - Monitor pdev init * @pdev: point to pdev