From 4924b2aaf5b0f0e7b3501bd8640b4f99512de072 Mon Sep 17 00:00:00 2001 From: Aditya Kodukula Date: Tue, 2 May 2023 06:25:51 -0700 Subject: [PATCH] qcacld-3.0: Extract vdev extended summary stats event In case of MLO connection, firmware sends each vdev's status information via vdev extended stats event. Add support in driver, to extract that information. Change-Id: Ia7a0a92baf008e6549830672b68e58be5a8202df CRs-Fixed: 3483731 --- .../dispatcher/inc/wlan_cp_stats_mc_defs.h | 16 +++++ .../dispatcher/src/wlan_cp_stats_mc_tgt_api.c | 62 +++++++++++++++- .../src/wlan_cp_stats_mc_ucfg_api.c | 3 +- .../cp_stats/src/target_if_mc_cp_stats.c | 70 ++++++++++++++++++- core/hdd/inc/wlan_hdd_main.h | 2 + core/hdd/src/wlan_hdd_stats.c | 4 ++ .../cp_stats/src/wlan_cfg80211_mc_cp_stats.c | 17 +++++ 7 files changed, 169 insertions(+), 5 deletions(-) diff --git a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h index fdb84be128..d017a5a71a 100644 --- a/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h +++ b/components/cp_stats/dispatcher/inc/wlan_cp_stats_mc_defs.h @@ -441,6 +441,16 @@ struct pmf_bcn_protect_stats { uint32_t bcn_replay_cnt; }; +/** + * struct vdev_summary_extd_stats - vdev summary extended stats + * @vdev_id: vdev_id of the event + * @is_mlo_vdev_active: is the mlo vdev currently active + */ +struct vdev_summary_extd_stats { + uint8_t vdev_id; + bool is_mlo_vdev_active; +}; + /** * struct vdev_mc_cp_stats - vdev specific stats * @cca: cca stats @@ -448,6 +458,7 @@ struct pmf_bcn_protect_stats { * @chain_rssi: chain rssi * @vdev_summary_stats: vdev's summary stats * @pmf_bcn_stats: pmf beacon protect stats + * @vdev_extd_stats: vdev summary extended stats */ struct vdev_mc_cp_stats { struct cca_stats cca; @@ -455,6 +466,7 @@ struct vdev_mc_cp_stats { int8_t chain_rssi[MAX_NUM_CHAINS]; struct summary_stats vdev_summary_stats; struct pmf_bcn_protect_stats pmf_bcn_stats; + struct vdev_summary_extd_stats vdev_extd_stats; }; /** @@ -746,6 +758,8 @@ struct peer_stats_info_ext_event { * @num_peer_stats_info_ext: number of peer extended stats info * @peer_stats_info_ext: peer extended stats info * @bcn_protect_stats: pmf bcn protect stats + * @num_vdev_extd_stats: number of vdev extended stats + * @vdev_extd_stats: if populated indicates array of ext summary stats per vdev */ struct stats_event { uint32_t num_pdev_stats; @@ -774,6 +788,8 @@ struct stats_event { uint32_t num_peer_stats_info_ext; struct peer_stats_info_ext_event *peer_stats_info_ext; struct pmf_bcn_protect_stats bcn_protect_stats; + uint32_t num_vdev_extd_stats; + struct vdev_summary_extd_stats *vdev_extd_stats; }; /** diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c index 586f996989..501bda3085 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c +++ b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c @@ -1009,6 +1009,55 @@ static void tgt_mc_cp_stats_extract_vdev_chain_rssi_stats( } } +static void +tgt_mc_cp_stats_extract_vdev_extd_stats(struct wlan_objmgr_psoc *psoc, + struct stats_event *ev) +{ + uint8_t i, vdev_id; + QDF_STATUS status; + struct request_info last_req = {0}; + struct wlan_objmgr_vdev *vdev; + struct vdev_mc_cp_stats *vdev_mc_stats; + struct vdev_cp_stats *vdev_cp_stats_priv; + + if (!ev->vdev_extd_stats) + return; + + status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS, + &last_req); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("ucfg_mc_cp_stats_get_pending_req failed"); + return; + } + + for (i = 0; i < ev->num_vdev_extd_stats; i++) { + vdev_id = ev->vdev_extd_stats[i].vdev_id; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, + WLAN_CP_STATS_ID); + if (!vdev) { + cp_stats_err("vdev is null"); + return; + } + + vdev_cp_stats_priv = wlan_cp_stats_get_vdev_stats_obj(vdev); + if (!vdev_cp_stats_priv) { + cp_stats_err("vdev cp stats object is null"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); + return; + } + + wlan_cp_stats_vdev_obj_lock(vdev_cp_stats_priv); + vdev_mc_stats = vdev_cp_stats_priv->vdev_stats; + qdf_mem_copy(&vdev_mc_stats->vdev_extd_stats, + &ev->vdev_extd_stats[i], + sizeof(vdev_mc_stats->vdev_extd_stats)); + + wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); + } +} + static QDF_STATUS tgt_send_vdev_mc_cp_stats(struct wlan_objmgr_psoc *psoc, struct stats_event *ev, @@ -1046,6 +1095,11 @@ tgt_send_vdev_mc_cp_stats(struct wlan_objmgr_psoc *psoc, ev->tx_rate_flags = vdev_mc_stats->tx_rate_flags; ev->bcn_protect_stats = vdev_mc_stats->pmf_bcn_stats; + + qdf_mem_copy(&ev->vdev_extd_stats[0], + &vdev_mc_stats->vdev_extd_stats, + sizeof(vdev_mc_stats->vdev_extd_stats)); + wlan_cp_stats_vdev_obj_unlock(vdev_cp_stats_priv); wlan_objmgr_vdev_release_ref(vdev, WLAN_CP_STATS_ID); @@ -1171,10 +1225,15 @@ tgt_mc_cp_stats_send_raw_station_stats(struct wlan_objmgr_psoc *psoc, info.num_summary_stats = 1; info.num_chain_rssi_stats = 1; + info.num_vdev_extd_stats = 1; info.vdev_summary_stats = qdf_mem_malloc( sizeof(*info.vdev_summary_stats)); info.vdev_chain_rssi = qdf_mem_malloc(sizeof(*info.vdev_chain_rssi)); - if (!info.vdev_summary_stats || !info.vdev_chain_rssi) + + info.vdev_extd_stats = qdf_mem_malloc(sizeof(*info.vdev_extd_stats)); + + if (!info.vdev_summary_stats || !info.vdev_chain_rssi || + !info.vdev_extd_stats) goto end; status = tgt_send_vdev_mc_cp_stats(psoc, &info, last_req); @@ -1263,6 +1322,7 @@ static void tgt_mc_cp_stats_extract_station_stats( tgt_mc_cp_stats_extract_vdev_summary_stats(psoc, ev); tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(psoc, ev); tgt_mc_cp_stats_extract_pmf_bcn_stats(psoc, ev); + tgt_mc_cp_stats_extract_vdev_extd_stats(psoc, ev); /* * PEER stats are the last stats sent for get_station statistics. diff --git a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c index d51c2e6bf7..af6076db29 100644 --- a/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c +++ b/components/cp_stats/dispatcher/src/wlan_cp_stats_mc_ucfg_api.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -975,6 +975,7 @@ void ucfg_mc_cp_stats_free_stats_resources(struct stats_event *ev) qdf_mem_free(ev->vdev_chain_rssi); qdf_mem_free(ev->peer_extended_stats); ucfg_mc_cp_stats_free_peer_stats_info_ext(ev); + qdf_mem_free(ev->vdev_extd_stats); qdf_mem_zero(ev, sizeof(*ev)); } diff --git a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c index 14243b087f..4f5a01ca10 100644 --- a/components/target_if/cp_stats/src/target_if_mc_cp_stats.c +++ b/components/target_if/cp_stats/src/target_if_mc_cp_stats.c @@ -383,6 +383,8 @@ static void target_if_cp_stats_free_stats_event(struct stats_event *ev) ev->vdev_chain_rssi = NULL; target_if_cp_stats_free_mib_stats(ev); target_if_cp_stats_free_peer_stats_info_ext(ev); + qdf_mem_free(ev->vdev_extd_stats); + ev->vdev_extd_stats = NULL; } static QDF_STATUS target_if_cp_stats_extract_pdev_stats( @@ -858,6 +860,61 @@ static QDF_STATUS target_if_cp_stats_extract_vdev_chain_rssi_stats( return QDF_STATUS_SUCCESS; } +static QDF_STATUS +target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified *wmi_hdl, + wmi_host_stats_event *stats_param, + struct stats_event *ev, + uint8_t *data) +{ + uint8_t i; + QDF_STATUS status; + struct wmi_host_vdev_prb_fils_stats *stats; + + ev->num_vdev_extd_stats = stats_param->num_vdev_extd_stats; + if (!ev->num_vdev_extd_stats) + return QDF_STATUS_SUCCESS; + + if (ev->num_vdev_extd_stats > WLAN_MAX_MLD) { + cp_stats_err("num_vdev_extd_stats is invalid: %u", + ev->num_vdev_extd_stats); + return QDF_STATUS_E_INVAL; + } + + ev->vdev_extd_stats = qdf_mem_malloc(sizeof(*ev->vdev_extd_stats) * + ev->num_vdev_extd_stats); + if (!ev->vdev_extd_stats) + return QDF_STATUS_E_NOMEM; + + stats = qdf_mem_malloc(sizeof(*stats) * ev->num_vdev_extd_stats); + + if (!stats) { + cp_stats_err("malloc failed for vdev extended stats"); + status = QDF_STATUS_E_NOMEM; + goto end; + } + + for (i = 0 ; i < ev->num_vdev_extd_stats; i++) { + status = wmi_extract_vdev_prb_fils_stats(wmi_hdl, data, + i, stats); + if (QDF_IS_STATUS_ERROR(status)) { + cp_stats_err("wmi_extract_vdev_extd_stats failed"); + qdf_mem_free(stats); + goto end; + } + ev->vdev_extd_stats[i].vdev_id = stats[i].vdev_id; + ev->vdev_extd_stats[i].is_mlo_vdev_active = + stats[i].is_mlo_vdev_active; + } + + qdf_mem_free(stats); + return status; + +end: + qdf_mem_free(ev->vdev_extd_stats); + ev->vdev_extd_stats = NULL; + return status; +} + static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, struct stats_event *ev, uint8_t *data) @@ -870,13 +927,14 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, cp_stats_err("stats param extract failed: %d", status); return status; } - cp_stats_nofl_debug("num: pdev: %d, pdev_extd: %d, vdev: %d, peer: %d," - "peer_extd: %d rssi: %d, mib %d, mib_extd %d, " - "bcnflt: %d, channel: %d, bcn: %d, peer_extd2: %d," + cp_stats_nofl_debug("num: pdev: %d, pdev_extd: %d, vdev: %d, vdev_extd: %d, " + "peer: %d, peer_extd: %d rssi: %d, mib %d, mib_extd %d, " + "bcnflt: %d, channel: %d, bcn: %d, peer_extd2: %d, " "last_event: %x, stats id: %d", stats_param.num_pdev_stats, stats_param.num_pdev_ext_stats, stats_param.num_vdev_stats, + stats_param.num_vdev_extd_stats, stats_param.num_peer_stats, stats_param.num_peer_extd_stats, stats_param.num_rssi_stats, @@ -932,7 +990,12 @@ static QDF_STATUS target_if_cp_stats_extract_event(struct wmi_unified *wmi_hdl, status = target_if_cp_stats_extract_pdev_extd_stats(wmi_hdl, &stats_param, ev, data); + if (QDF_IS_STATUS_ERROR(status)) + return status; + status = target_if_cp_stats_extract_vdev_extd_stats(wmi_hdl, + &stats_param, + ev, data); return status; } @@ -1550,6 +1613,7 @@ static uint32_t get_stats_id(enum stats_req_type type) return (WMI_REQUEST_AP_STAT | WMI_REQUEST_PEER_STAT | WMI_REQUEST_VDEV_STAT | + WMI_REQUEST_VDEV_EXTD_STAT | WMI_REQUEST_PDEV_STAT | WMI_REQUEST_PEER_EXTD2_STAT | WMI_REQUEST_RSSI_PER_CHAIN_STAT | diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ce805c9be2..1b93631de7 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1017,6 +1017,7 @@ enum udp_qos_upgrade { * @snr: SNR measured from @rssi * @rssi_on_disconnect: Rssi at disconnection time in STA mode * @rssi_send: Notify RSSI over lpass + * @is_mlo_vdev_active: is the mlo vdev currently active */ struct wlan_hdd_link_info { uint8_t vdev_id; @@ -1035,6 +1036,7 @@ struct wlan_hdd_link_info { #ifdef WLAN_FEATURE_LPSS bool rssi_send; #endif + bool is_mlo_vdev_active; }; /** diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 7c997f4039..4e6ee8750d 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -273,6 +273,10 @@ static int copy_station_stats_to_adapter(struct hdd_adapter *adapter, adapter->tx_power.tx_pwr = stats->pdev_stats->max_pwr; adapter->tx_power.tx_pwr_cached_timestamp = qdf_system_ticks_to_msecs(qdf_system_ticks()); + /* Copy vdev status info sent by FW */ + if (stats->vdev_extd_stats) + adapter->deflink->is_mlo_vdev_active = + stats->vdev_extd_stats[0].is_mlo_vdev_active; dynamic_cfg = mlme_get_dynamic_vdev_config(vdev); if (!dynamic_cfg) { diff --git a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c index 7777d5b849..bacd804268 100644 --- a/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c +++ b/os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c @@ -162,6 +162,7 @@ static void wlan_cfg80211_mc_cp_stats_dealloc(void *priv) qdf_mem_free(stats->peer_adv_stats); wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext(stats); wlan_free_mib_stats(stats); + qdf_mem_free(stats->vdev_extd_stats); } #define QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE \ @@ -586,6 +587,7 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie) struct stats_event *priv; struct osif_request *request; uint32_t summary_size, rssi_size, peer_adv_size = 0, pdev_size; + uint32_t vdev_extd_size; request = osif_request_get(cookie); if (!request) { @@ -644,6 +646,17 @@ static void get_station_stats_cb(struct stats_event *ev, void *cookie) qdf_mem_copy(priv->pdev_stats, ev->pdev_stats, pdev_size); } + if (ev->num_vdev_extd_stats && ev->vdev_extd_stats) { + vdev_extd_size = + sizeof(*ev->vdev_extd_stats) * ev->num_vdev_extd_stats; + priv->vdev_extd_stats = qdf_mem_malloc(vdev_extd_size); + if (!priv->vdev_extd_stats) + goto station_stats_cb_fail; + + qdf_mem_copy(priv->vdev_extd_stats, ev->vdev_extd_stats, + vdev_extd_size); + } + priv->num_summary_stats = ev->num_summary_stats; priv->num_chain_rssi_stats = ev->num_chain_rssi_stats; priv->tx_rate = ev->tx_rate; @@ -1117,6 +1130,9 @@ wlan_cfg80211_mc_cp_stats_get_station_stats(struct wlan_objmgr_vdev *vdev, if (priv->pdev_stats) out->pdev_stats = priv->pdev_stats; priv->pdev_stats = NULL; + if (priv->vdev_extd_stats) + out->vdev_extd_stats = priv->vdev_extd_stats; + priv->vdev_extd_stats = NULL; out->bcn_protect_stats = priv->bcn_protect_stats; osif_request_put(request); @@ -1713,6 +1729,7 @@ void wlan_cfg80211_mc_cp_stats_free_stats_event(struct stats_event *stats) qdf_mem_free(stats->peer_adv_stats); wlan_free_mib_stats(stats); wlan_cfg80211_mc_cp_stats_free_peer_stats_info_ext(stats); + qdf_mem_free(stats->vdev_extd_stats); qdf_mem_free(stats); }