From 5191713c4b575d200f49ca39f7f6ce1124bd597a Mon Sep 17 00:00:00 2001 From: Bapiraju Alla Date: Mon, 31 Aug 2020 11:52:32 +0530 Subject: [PATCH] qcacld-3.0: Send get_station and ll_stats req in a single command Currently ll_stats and get_station requests are sent back to back from user space. The firmware time difference between these two commands results in extra sleep and wakeup for Q6. To avoid this extra Q6 sleep and wake, send both requests in a single command from the driver if the firmware supports that operation. Cache the get_station results in the driver until user space request reach to the driver. Change-Id: Ic7c6232558b9411106bf3fb88ec8d9b0b28b045d CRs-Fixed: 2778476 --- Kbuild | 1 + configs/default_defconfig | 1 + core/hdd/inc/hdd_config.h | 59 +++++ core/hdd/inc/wlan_hdd_cfg.h | 4 + core/hdd/inc/wlan_hdd_main.h | 8 + core/hdd/src/wlan_hdd_main.c | 51 +++++ core/hdd/src/wlan_hdd_stats.c | 419 +++++++++++++++++++++++++--------- core/hdd/src/wlan_hdd_stats.h | 4 + core/wma/inc/wma_tgt_cfg.h | 5 + core/wma/src/wma_main.c | 19 ++ core/wma/src/wma_utils.c | 38 ++- 11 files changed, 496 insertions(+), 113 deletions(-) diff --git a/Kbuild b/Kbuild index 34ffe69f358c..ad45cfb02b9c 100644 --- a/Kbuild +++ b/Kbuild @@ -2554,6 +2554,7 @@ cppflags-$(CONFIG_FEATURE_WLAN_LPHB) += -DFEATURE_WLAN_LPHB cppflags-$(CONFIG_QCA_SUPPORT_TX_THROTTLE) += -DQCA_SUPPORT_TX_THROTTLE cppflags-$(CONFIG_WMI_INTERFACE_EVENT_LOGGING) += -DWMI_INTERFACE_EVENT_LOGGING cppflags-$(CONFIG_WLAN_FEATURE_LINK_LAYER_STATS) += -DWLAN_FEATURE_LINK_LAYER_STATS +cppflags-$(CONFIG_FEATURE_CLUB_LL_STATS_AND_GET_STATION) += -DFEATURE_CLUB_LL_STATS_AND_GET_STATION cppflags-$(CONFIG_WLAN_FEATURE_MIB_STATS) += -DWLAN_FEATURE_MIB_STATS cppflags-$(CONFIG_FEATURE_WLAN_EXTSCAN) += -DFEATURE_WLAN_EXTSCAN cppflags-$(CONFIG_160MHZ_SUPPORT) += -DCONFIG_160MHZ_SUPPORT diff --git a/configs/default_defconfig b/configs/default_defconfig index ca54414cd7aa..286c9e0b8d7d 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -946,6 +946,7 @@ CONFIG_FEATURE_WLAN_LPHB := y CONFIG_QCA_SUPPORT_TX_THROTTLE := y CONFIG_WMI_INTERFACE_EVENT_LOGGING := y CONFIG_WLAN_FEATURE_LINK_LAYER_STATS := y +CONFIG_FEATURE_CLUB_LL_STATS_AND_GET_STATION := y CONFIG_FEATURE_WLAN_EXTSCAN := n CONFIG_WMI_BCN_OFFLOAD := y CONFIG_160MHZ_SUPPORT := y diff --git a/core/hdd/inc/hdd_config.h b/core/hdd/inc/hdd_config.h index 3d70042bbe41..02ac93802f6a 100644 --- a/core/hdd/inc/hdd_config.h +++ b/core/hdd/inc/hdd_config.h @@ -1536,6 +1536,64 @@ struct dhcp_server { #define CFG_WLAN_STA_PERIODIC_STATS #endif /* WLAN_FEATURE_PERIODIC_STA_STATS */ +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION +/* + * + * club_get_sta_in_ll_stats_req - Flag used to club ll_stats and get_station + * requests in the driver + * + * @Min: 0 + * @Max: 1 + * Default: 1 + * + * This ini param is used to enable/disable the feature for clubbing ll stats + * and get station requests. + * + * Supported Feature: STA + * + * Usage: External + * + * + */ +#define CFG_CLUB_LL_STA_AND_GET_STATION CFG_INI_BOOL( \ + "club_get_sta_in_ll_stats_req", \ + 1, \ + "Club ll_stats and get station requests") + +/* + * + * sta_stats_cache_expiry_time - Expiry time for cached station stats + * + * @Min: 0 + * @Max: 5000 + * Default: 200 + * + * This ini is used as duration in milliseconds for which cached station stats + * are valid. Driver sends the cached information as response, if it gets the + * get_station request with in this duration. Otherwise driver sends new + * request to the firmware to get the updated stats. + * + * Supported Feature: STA + * + * Usage: External + * + * + */ +#define CFG_STA_STATS_CACHE_EXPIRY CFG_INI_UINT( \ + "sta_stats_cache_expiry_time", \ + 0, \ + 5000, \ + 200, \ + CFG_VALUE_OR_DEFAULT, \ + "Station stats cache expiry") + +#define CFG_WLAN_CLUB_GET_STA_IN_LL_STA_REQ \ + CFG(CFG_CLUB_LL_STA_AND_GET_STATION) \ + CFG(CFG_STA_STATS_CACHE_EXPIRY) +#else +#define CFG_WLAN_CLUB_GET_STA_IN_LL_STA_REQ +#endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ + /** * enum host_log_level - Debug verbose level imposed by user * @HOST_LOG_LEVEL_NONE: no trace will be logged. @@ -1652,6 +1710,7 @@ enum host_log_level { CFG_ENABLE_QMI_STATS_ALL \ CFG_VC_MODE_BITMAP_ALL \ CFG_WLAN_AUTO_SHUTDOWN_ALL \ + CFG_WLAN_CLUB_GET_STA_IN_LL_STA_REQ \ CFG_WLAN_LOGGING_SUPPORT_ALL \ CFG_WLAN_STA_PERIODIC_STATS \ CFG(CFG_ACTION_OUI_CCKM_1X1) \ diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 29f9fc86bced..76b602a28be7 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -257,6 +257,10 @@ struct hdd_config { uint32_t periodic_stats_timer_duration; #endif /* WLAN_FEATURE_PERIODIC_STA_STATS */ uint8_t nb_commands_interval; + +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION + uint32_t sta_stats_cache_expiry_time; +#endif }; /** diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index b5417fc8b784..c885a39fa75a 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -701,6 +701,11 @@ struct hdd_stats { struct hdd_eapol_stats_s hdd_eapol_stats; struct hdd_dhcp_stats_s hdd_dhcp_stats; struct pmf_bcn_protect_stats bcn_protect_stats; + +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION + uint32_t sta_stats_cached_timestamp; + bool is_ll_stats_req_in_progress; +#endif }; /** @@ -2072,6 +2077,9 @@ struct hdd_context { qdf_workqueue_t *adapter_ops_wq; struct hdd_adapter_ops_history adapter_ops_history; bool ll_stats_per_chan_rx_tx_time; +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION + bool is_get_station_clubbed_in_ll_stats_req; +#endif #ifdef FEATURE_WPSS_THERMAL_MITIGATION bool multi_client_thermal_mitigation; #endif diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 56831e2e4c70..46f4ddad76e6 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -1596,6 +1596,52 @@ static inline void hdd_update_roam_offload(struct hdd_context *hdd_ctx, } #endif +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION +static void +hdd_club_ll_stats_in_get_sta_cfg_update(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc) +{ + config->sta_stats_cache_expiry_time = + cfg_get(psoc, CFG_STA_STATS_CACHE_EXPIRY); +} + +static void +hdd_update_feature_cfg_club_get_sta_in_ll_stats_req( + struct hdd_context *hdd_ctx, + struct wma_tgt_services *cfg) +{ + hdd_ctx->is_get_station_clubbed_in_ll_stats_req = + cfg->is_get_station_clubbed_in_ll_stats_req && + cfg_get(hdd_ctx->psoc, + CFG_CLUB_LL_STA_AND_GET_STATION); +} + +static void +hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter *adapter) +{ + adapter->hdd_stats.is_ll_stats_req_in_progress = false; + adapter->hdd_stats.sta_stats_cached_timestamp = 0; +} +#else +static void +hdd_club_ll_stats_in_get_sta_cfg_update(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc) +{ +} + +static void +hdd_update_feature_cfg_club_get_sta_in_ll_stats_req( + struct hdd_context *hdd_ctx, + struct wma_tgt_services *cfg) +{ +} + +static void +hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter *adapter) +{ +} +#endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ + static void hdd_update_tgt_services(struct hdd_context *hdd_ctx, struct wma_tgt_services *cfg) { @@ -1672,6 +1718,8 @@ static void hdd_update_tgt_services(struct hdd_context *hdd_ctx, hdd_ctx->roam_ch_from_fw_supported = cfg->is_roam_scan_ch_to_host; hdd_ctx->ll_stats_per_chan_rx_tx_time = cfg->ll_stats_per_chan_rx_tx_time; + + hdd_update_feature_cfg_club_get_sta_in_ll_stats_req(hdd_ctx, cfg); } /** @@ -5136,6 +5184,8 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr, adapter->start_time = qdf_system_ticks(); adapter->last_time = adapter->start_time; + hdd_init_get_sta_in_ll_stats_config(adapter); + return adapter; free_net_dev: @@ -11997,6 +12047,7 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx) hdd_dp_cfg_update(psoc, hdd_ctx); hdd_sar_cfg_update(config, psoc); hdd_init_qmi_stats(config, psoc); + hdd_club_ll_stats_in_get_sta_cfg_update(config, psoc); } struct hdd_context *hdd_context_create(struct device *dev) diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index bc7ba42dee22..cd708851e659 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -180,6 +180,8 @@ static int rssi_mcs_tbl[][12] = { {-76, -73, -71, -68, -64, -60, -59, -58, -53, -51, -46, -42} /* 80 */ }; +static bool get_station_fw_request_needed = true; + #ifdef WLAN_FEATURE_LINK_LAYER_STATS /** @@ -1567,6 +1569,271 @@ static void wlan_hdd_dealloc_ll_stats(void *priv) qdf_list_destroy(&ll_stats_priv->ll_stats_q); } +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION +static void +hdd_update_station_stats_cached_timestamp(struct hdd_adapter *adapter) +{ + adapter->hdd_stats.sta_stats_cached_timestamp = + qdf_system_ticks_to_msecs(qdf_system_ticks()); +} +#else +static void +hdd_update_station_stats_cached_timestamp(struct hdd_adapter *adapter) +{ +} +#endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ + +/* + * copy_station_stats_to_adapter() - Copy station stats to adapter + * @adapter: Pointer to the adapter + * @stats: Pointer to the station stats event + * + * Return: 0 if success, non-zero for failure + */ +static int copy_station_stats_to_adapter(struct hdd_adapter *adapter, + struct stats_event *stats) +{ + int ret = 0; + struct wlan_mlme_nss_chains *dynamic_cfg; + uint32_t tx_nss, rx_nss; + struct wlan_objmgr_vdev *vdev; + + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) + return -EINVAL; + + /* save summary stats to legacy location */ + qdf_mem_copy(adapter->hdd_stats.summary_stat.retry_cnt, + stats->vdev_summary_stats[0].stats.retry_cnt, + sizeof(adapter->hdd_stats.summary_stat.retry_cnt)); + qdf_mem_copy( + adapter->hdd_stats.summary_stat.multiple_retry_cnt, + stats->vdev_summary_stats[0].stats.multiple_retry_cnt, + sizeof(adapter->hdd_stats.summary_stat.multiple_retry_cnt)); + qdf_mem_copy(adapter->hdd_stats.summary_stat.tx_frm_cnt, + stats->vdev_summary_stats[0].stats.tx_frm_cnt, + sizeof(adapter->hdd_stats.summary_stat.tx_frm_cnt)); + qdf_mem_copy(adapter->hdd_stats.summary_stat.fail_cnt, + stats->vdev_summary_stats[0].stats.fail_cnt, + sizeof(adapter->hdd_stats.summary_stat.fail_cnt)); + adapter->hdd_stats.summary_stat.snr = + stats->vdev_summary_stats[0].stats.snr; + adapter->hdd_stats.summary_stat.rssi = + stats->vdev_summary_stats[0].stats.rssi; + adapter->hdd_stats.summary_stat.rx_frm_cnt = + stats->vdev_summary_stats[0].stats.rx_frm_cnt; + adapter->hdd_stats.summary_stat.frm_dup_cnt = + stats->vdev_summary_stats[0].stats.frm_dup_cnt; + adapter->hdd_stats.summary_stat.rts_fail_cnt = + stats->vdev_summary_stats[0].stats.rts_fail_cnt; + adapter->hdd_stats.summary_stat.ack_fail_cnt = + stats->vdev_summary_stats[0].stats.ack_fail_cnt; + adapter->hdd_stats.summary_stat.rts_succ_cnt = + stats->vdev_summary_stats[0].stats.rts_succ_cnt; + adapter->hdd_stats.summary_stat.rx_discard_cnt = + stats->vdev_summary_stats[0].stats.rx_discard_cnt; + adapter->hdd_stats.summary_stat.rx_error_cnt = + stats->vdev_summary_stats[0].stats.rx_error_cnt; + adapter->hdd_stats.peer_stats.rx_count = + stats->peer_adv_stats->rx_count; + adapter->hdd_stats.peer_stats.rx_bytes = + stats->peer_adv_stats->rx_bytes; + adapter->hdd_stats.peer_stats.fcs_count = + stats->peer_adv_stats->fcs_count; + + dynamic_cfg = mlme_get_dynamic_vdev_config(vdev); + if (!dynamic_cfg) { + hdd_err("nss chain dynamic config NULL"); + ret = -EINVAL; + goto out; + } + + switch (hdd_conn_get_connected_band(&adapter->session.station)) { + case BAND_2G: + tx_nss = dynamic_cfg->tx_nss[NSS_CHAINS_BAND_2GHZ]; + rx_nss = dynamic_cfg->rx_nss[NSS_CHAINS_BAND_2GHZ]; + break; + case BAND_5G: + tx_nss = dynamic_cfg->tx_nss[NSS_CHAINS_BAND_5GHZ]; + rx_nss = dynamic_cfg->rx_nss[NSS_CHAINS_BAND_5GHZ]; + break; + default: + tx_nss = wlan_vdev_mlme_get_nss(vdev); + rx_nss = wlan_vdev_mlme_get_nss(vdev); + } + + /* Intersection of self and AP's NSS capability */ + if (tx_nss > wlan_vdev_mlme_get_nss(vdev)) + tx_nss = wlan_vdev_mlme_get_nss(vdev); + + if (rx_nss > wlan_vdev_mlme_get_nss(vdev)) + rx_nss = wlan_vdev_mlme_get_nss(vdev); + + /* save class a stats to legacy location */ + adapter->hdd_stats.class_a_stat.tx_nss = tx_nss; + adapter->hdd_stats.class_a_stat.rx_nss = rx_nss; + adapter->hdd_stats.class_a_stat.tx_rate = stats->tx_rate; + adapter->hdd_stats.class_a_stat.rx_rate = stats->rx_rate; + adapter->hdd_stats.class_a_stat.tx_rx_rate_flags = stats->tx_rate_flags; + adapter->hdd_stats.class_a_stat.tx_mcs_index = + sme_get_mcs_idx(stats->tx_rate, stats->tx_rate_flags, + &adapter->hdd_stats.class_a_stat.tx_nss, + &adapter->hdd_stats.class_a_stat.tx_dcm, + &adapter->hdd_stats.class_a_stat.tx_gi, + &adapter->hdd_stats.class_a_stat. + tx_mcs_rate_flags); + + adapter->hdd_stats.class_a_stat.rx_mcs_index = + sme_get_mcs_idx(stats->rx_rate, stats->tx_rate_flags, + &adapter->hdd_stats.class_a_stat.rx_nss, + &adapter->hdd_stats.class_a_stat.rx_dcm, + &adapter->hdd_stats.class_a_stat.rx_gi, + &adapter->hdd_stats.class_a_stat. + rx_mcs_rate_flags); + + /* save per chain rssi to legacy location */ + qdf_mem_copy(adapter->hdd_stats.per_chain_rssi_stats.rssi, + stats->vdev_chain_rssi[0].chain_rssi, + sizeof(stats->vdev_chain_rssi[0].chain_rssi)); + adapter->hdd_stats.bcn_protect_stats = stats->bcn_protect_stats; +out: + hdd_objmgr_put_vdev(vdev); + return ret; +} + +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION +/** + * cache_station_stats_cb() - cache_station_stats_cb callback function + * @ev: station stats buffer + * @cookie: cookie that contains the address of the adapter corresponding to + * the request + * + * Return: None + */ +static void cache_station_stats_cb(struct stats_event *ev, void *cookie) +{ + struct hdd_adapter *adapter = cookie; + struct hdd_context *hdd_ctx = adapter->hdd_ctx; + uint8_t vdev_id = adapter->vdev_id; + + hdd_for_each_adapter_dev_held(hdd_ctx, adapter) { + if (adapter->vdev_id != vdev_id) { + dev_put(adapter->dev); + continue; + } + copy_station_stats_to_adapter(adapter, ev); + /* dev_put has to be done here */ + dev_put(adapter->dev); + break; + } +} + +static void +wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter) +{ + struct wlan_objmgr_peer *peer; + struct request_info info = {0}; + struct wlan_objmgr_vdev *vdev; + + if (!adapter->hdd_ctx->is_get_station_clubbed_in_ll_stats_req) + return; + + vdev = hdd_objmgr_get_vdev(adapter); + if (!vdev) + return; + + if (adapter->hdd_stats.is_ll_stats_req_in_progress) { + hdd_err("Previous ll_stats request is in progress"); + goto get_station_stats_fail; + } + + adapter->hdd_stats.is_ll_stats_req_in_progress = true; + + info.cookie = adapter; + info.u.get_station_stats_cb = cache_station_stats_cb; + info.vdev_id = adapter->vdev_id; + info.pdev_id = wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)); + peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID); + if (!peer) { + osif_err("peer is null"); + goto get_station_stats_fail; + } + + qdf_mem_copy(info.peer_mac_addr, peer->macaddr, QDF_MAC_ADDR_SIZE); + + wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID); + + ucfg_mc_cp_stats_set_pending_req(wlan_vdev_get_psoc(vdev), + TYPE_STATION_STATS, &info); + +get_station_stats_fail: + hdd_objmgr_put_vdev(vdev); +} + +static void +wlan_hdd_reset_station_stats_request_pending(struct wlan_objmgr_psoc *psoc, + struct hdd_adapter *adapter) +{ + QDF_STATUS status; + struct request_info last_req = {0}; + bool pending = false; + + if (!adapter->hdd_ctx->is_get_station_clubbed_in_ll_stats_req) + return; + + adapter->hdd_stats.is_ll_stats_req_in_progress = false; + + status = ucfg_mc_cp_stats_get_pending_req(psoc, TYPE_STATION_STATS, + &last_req); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("ucfg_mc_cp_stats_get_pending_req failed"); + return; + } + + ucfg_mc_cp_stats_reset_pending_req(psoc, TYPE_STATION_STATS, + &last_req, &pending); +} + +static QDF_STATUS wlan_hdd_stats_request_needed(struct hdd_adapter *adapter) +{ + if (adapter->device_mode != QDF_STA_MODE) + return QDF_STATUS_SUCCESS; + + if (!adapter->hdd_ctx->config) { + hdd_err("Invalid hdd config"); + return QDF_STATUS_E_INVAL; + } + if (adapter->hdd_ctx->is_get_station_clubbed_in_ll_stats_req) { + uint32_t stats_cached_duration; + + stats_cached_duration = + qdf_system_ticks_to_msecs(qdf_system_ticks()) - + adapter->hdd_stats.sta_stats_cached_timestamp; + if (stats_cached_duration <= + adapter->hdd_ctx->config->sta_stats_cache_expiry_time) + return QDF_STATUS_E_ALREADY; + } + return QDF_STATUS_SUCCESS; +} + +#else +static void +wlan_hdd_set_station_stats_request_pending(struct hdd_adapter *adapter) +{ +} + +static void +wlan_hdd_reset_station_stats_request_pending(struct wlan_objmgr_psoc *psoc, + struct hdd_adapter *adapter) +{ +} + +static QDF_STATUS wlan_hdd_stats_request_needed(struct hdd_adapter *adapter) +{ + return QDF_STATUS_SUCCESS; +} +#endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ + static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, tSirLLStatsGetReq *req) { @@ -1584,11 +1851,15 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, .dealloc = wlan_hdd_dealloc_ll_stats, }; - hdd_enter(); + hdd_enter_dev(adapter->dev); + + wlan_hdd_set_station_stats_request_pending(adapter); request = osif_request_alloc(¶ms); if (!request) { hdd_err("Request Allocation Failure"); + wlan_hdd_reset_station_stats_request_pending(hdd_ctx->psoc, + adapter); return -ENOMEM; } @@ -1601,11 +1872,12 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, qdf_spinlock_create(&priv->ll_stats_lock); qdf_list_create(&priv->ll_stats_q, HDD_LINK_STATS_MAX); - if (QDF_STATUS_SUCCESS != - sme_ll_stats_get_req(hdd_ctx->mac_handle, req, - cookie)) { + status = sme_ll_stats_get_req(hdd_ctx->mac_handle, req, cookie); + if (QDF_IS_STATUS_ERROR(status)) { hdd_err("sme_ll_stats_get_req Failed"); - ret = -EINVAL; + ret = qdf_status_to_os_return(status); + wlan_hdd_reset_station_stats_request_pending(hdd_ctx->psoc, + adapter); goto exit; } ret = osif_request_wait_for_response(request); @@ -1616,6 +1888,10 @@ static int wlan_hdd_send_ll_stats_req(struct hdd_adapter *adapter, priv->request_bitmap = 0; qdf_spin_unlock(&priv->ll_stats_lock); ret = -ETIMEDOUT; + wlan_hdd_reset_station_stats_request_pending(hdd_ctx->psoc, + adapter); + } else { + hdd_update_station_stats_cached_timestamp(adapter); } qdf_spin_lock(&priv->ll_stats_lock); status = qdf_list_remove_front(&priv->ll_stats_q, &ll_node); @@ -1643,9 +1919,10 @@ int wlan_hdd_ll_stats_get(struct hdd_adapter *adapter, uint32_t req_id, { int errno; tSirLLStatsGetReq get_req; - struct hdd_station_ctx *hddstactx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct hdd_station_ctx *hddstactx = + WLAN_HDD_GET_STATION_CTX_PTR(adapter); - hdd_enter(); + hdd_enter_dev(adapter->dev); if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { hdd_warn("Command not allowed in FTM mode"); @@ -3239,6 +3516,12 @@ int wlan_hdd_cfg80211_ll_stats_ext_set_param(struct wiphy *wiphy, return errno; } + +#else +static QDF_STATUS wlan_hdd_stats_request_needed(struct hdd_adapter *adapter) +{ + return QDF_STATUS_SUCCESS; +} #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ #ifdef WLAN_FEATURE_STATS_EXT @@ -5256,8 +5539,10 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct station_info *sinfo) { struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); int errno; + QDF_STATUS status; errno = wlan_hdd_validate_context(hdd_ctx); if (errno) @@ -5266,13 +5551,26 @@ static int _wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, if (!qdf_ctx) return -EINVAL; - errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); - if (errno) - return errno; + status = wlan_hdd_stats_request_needed(adapter); + if (QDF_IS_STATUS_ERROR(status)) { + if (status == QDF_STATUS_E_ALREADY) + get_station_fw_request_needed = false; + else + return -EINVAL; + } + + if (get_station_fw_request_needed) { + errno = wlan_hdd_qmi_get_sync_resume(hdd_ctx, qdf_ctx->dev); + if (errno) + return errno; + } errno = __wlan_hdd_cfg80211_get_station(wiphy, dev, mac, sinfo); - wlan_hdd_qmi_put_suspend(hdd_ctx, qdf_ctx->dev); + if (get_station_fw_request_needed) + wlan_hdd_qmi_put_suspend(hdd_ctx, qdf_ctx->dev); + + get_station_fw_request_needed = true; return errno; } @@ -6133,10 +6431,11 @@ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter) { int ret = 0; struct stats_event *stats; - struct wlan_mlme_nss_chains *dynamic_cfg; - uint32_t tx_nss, rx_nss; struct wlan_objmgr_vdev *vdev; + if (!get_station_fw_request_needed) + return 0; + vdev = hdd_objmgr_get_vdev(adapter); if (!vdev) return -EINVAL; @@ -6147,99 +6446,7 @@ int wlan_hdd_get_station_stats(struct hdd_adapter *adapter) goto out; } - /* save summary stats to legacy location */ - qdf_mem_copy(adapter->hdd_stats.summary_stat.retry_cnt, - stats->vdev_summary_stats[0].stats.retry_cnt, - sizeof(adapter->hdd_stats.summary_stat.retry_cnt)); - qdf_mem_copy(adapter->hdd_stats.summary_stat.multiple_retry_cnt, - stats->vdev_summary_stats[0].stats.multiple_retry_cnt, - sizeof(adapter->hdd_stats.summary_stat.multiple_retry_cnt)); - qdf_mem_copy(adapter->hdd_stats.summary_stat.tx_frm_cnt, - stats->vdev_summary_stats[0].stats.tx_frm_cnt, - sizeof(adapter->hdd_stats.summary_stat.tx_frm_cnt)); - qdf_mem_copy(adapter->hdd_stats.summary_stat.fail_cnt, - stats->vdev_summary_stats[0].stats.fail_cnt, - sizeof(adapter->hdd_stats.summary_stat.fail_cnt)); - adapter->hdd_stats.summary_stat.snr = - stats->vdev_summary_stats[0].stats.snr; - adapter->hdd_stats.summary_stat.rssi = - stats->vdev_summary_stats[0].stats.rssi; - adapter->hdd_stats.summary_stat.rx_frm_cnt = - stats->vdev_summary_stats[0].stats.rx_frm_cnt; - adapter->hdd_stats.summary_stat.frm_dup_cnt = - stats->vdev_summary_stats[0].stats.frm_dup_cnt; - adapter->hdd_stats.summary_stat.rts_fail_cnt = - stats->vdev_summary_stats[0].stats.rts_fail_cnt; - adapter->hdd_stats.summary_stat.ack_fail_cnt = - stats->vdev_summary_stats[0].stats.ack_fail_cnt; - adapter->hdd_stats.summary_stat.rts_succ_cnt = - stats->vdev_summary_stats[0].stats.rts_succ_cnt; - adapter->hdd_stats.summary_stat.rx_discard_cnt = - stats->vdev_summary_stats[0].stats.rx_discard_cnt; - adapter->hdd_stats.summary_stat.rx_error_cnt = - stats->vdev_summary_stats[0].stats.rx_error_cnt; - adapter->hdd_stats.peer_stats.rx_count = - stats->peer_adv_stats->rx_count; - adapter->hdd_stats.peer_stats.rx_bytes = - stats->peer_adv_stats->rx_bytes; - adapter->hdd_stats.peer_stats.fcs_count = - stats->peer_adv_stats->fcs_count; - - dynamic_cfg = mlme_get_dynamic_vdev_config(vdev); - if (!dynamic_cfg) { - hdd_err("nss chain dynamic config NULL"); - wlan_cfg80211_mc_cp_stats_free_stats_event(stats); - ret = -EINVAL; - goto out; - } - - switch (hdd_conn_get_connected_band(&adapter->session.station)) { - case BAND_2G: - tx_nss = dynamic_cfg->tx_nss[NSS_CHAINS_BAND_2GHZ]; - rx_nss = dynamic_cfg->rx_nss[NSS_CHAINS_BAND_2GHZ]; - break; - case BAND_5G: - tx_nss = dynamic_cfg->tx_nss[NSS_CHAINS_BAND_5GHZ]; - rx_nss = dynamic_cfg->rx_nss[NSS_CHAINS_BAND_5GHZ]; - break; - default: - tx_nss = wlan_vdev_mlme_get_nss(vdev); - rx_nss = wlan_vdev_mlme_get_nss(vdev); - } - /* Intersection of self and AP's NSS capability */ - if (tx_nss > wlan_vdev_mlme_get_nss(vdev)) - tx_nss = wlan_vdev_mlme_get_nss(vdev); - - if (rx_nss > wlan_vdev_mlme_get_nss(vdev)) - rx_nss = wlan_vdev_mlme_get_nss(vdev); - - /* save class a stats to legacy location */ - adapter->hdd_stats.class_a_stat.tx_nss = tx_nss; - adapter->hdd_stats.class_a_stat.rx_nss = rx_nss; - adapter->hdd_stats.class_a_stat.tx_rate = stats->tx_rate; - adapter->hdd_stats.class_a_stat.rx_rate = stats->rx_rate; - adapter->hdd_stats.class_a_stat.tx_rx_rate_flags = stats->tx_rate_flags; - adapter->hdd_stats.class_a_stat.tx_mcs_index = - sme_get_mcs_idx(stats->tx_rate, stats->tx_rate_flags, - &adapter->hdd_stats.class_a_stat.tx_nss, - &adapter->hdd_stats.class_a_stat.tx_dcm, - &adapter->hdd_stats.class_a_stat.tx_gi, - &adapter->hdd_stats.class_a_stat. - tx_mcs_rate_flags); - - adapter->hdd_stats.class_a_stat.rx_mcs_index = - sme_get_mcs_idx(stats->rx_rate, stats->tx_rate_flags, - &adapter->hdd_stats.class_a_stat.rx_nss, - &adapter->hdd_stats.class_a_stat.rx_dcm, - &adapter->hdd_stats.class_a_stat.rx_gi, - &adapter->hdd_stats.class_a_stat. - rx_mcs_rate_flags); - - /* save per chain rssi to legacy location */ - qdf_mem_copy(adapter->hdd_stats.per_chain_rssi_stats.rssi, - stats->vdev_chain_rssi[0].chain_rssi, - sizeof(stats->vdev_chain_rssi[0].chain_rssi)); - adapter->hdd_stats.bcn_protect_stats = stats->bcn_protect_stats; + copy_station_stats_to_adapter(adapter, stats); wlan_cfg80211_mc_cp_stats_free_stats_event(stats); out: diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index 1a6b5fece30b..00fc80374c6b 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -34,8 +34,12 @@ #define DATA_RATE_11AC_MCS_MASK 0x03 +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION /* LL stats get request time out value */ +#define WLAN_WAIT_TIME_LL_STATS 2000 +#else #define WLAN_WAIT_TIME_LL_STATS 800 +#endif #define WLAN_HDD_TGT_NOISE_FLOOR_DBM (-96) diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index faffe1e7a1ae..e22a0ea7458c 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -45,6 +45,8 @@ * @bcn_reception_stats: Beacon Reception stats capability * @is_roam_scan_ch_to_host: Get roam scan channels from fw supported * @ll_stats_per_chan_rx_tx_time: Per channel tx and rx time support in ll stats + * @is_get_station_clubbed_in_ll_stats_req: Get station req support within ll + * stats req */ struct wma_tgt_services { uint32_t sta_power_save; @@ -79,6 +81,9 @@ struct wma_tgt_services { bool bcn_reception_stats; bool is_roam_scan_ch_to_host; bool ll_stats_per_chan_rx_tx_time; +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION + bool is_get_station_clubbed_in_ll_stats_req; +#endif }; /** diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index ffca70d356aa..04a00a9b25c7 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2822,6 +2822,23 @@ static inline void wma_trace_init(void) } #endif +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION +static void wma_get_service_cap_club_get_sta_in_ll_stats_req( + struct wmi_unified *wmi_handle, + struct wma_tgt_services *cfg) +{ + cfg->is_get_station_clubbed_in_ll_stats_req = + wmi_service_enabled(wmi_handle, + wmi_service_get_station_in_ll_stats_req); +} +#else +static void wma_get_service_cap_club_get_sta_in_ll_stats_req( + struct wmi_unified *wmi_handle, + struct wma_tgt_services *cfg) +{ +} +#endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */ + /** * wma_open() - Allocate wma context and initialize it. * @cds_context: cds context @@ -4647,6 +4664,8 @@ static inline void wma_update_target_services(struct wmi_unified *wmi_handle, cfg->ll_stats_per_chan_rx_tx_time = wmi_service_enabled(wmi_handle, wmi_service_ll_stats_per_chan_rx_tx_time); + + wma_get_service_cap_club_get_sta_in_ll_stats_req(wmi_handle, cfg); } /** diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index edc81f842fa6..6d4e884a8881 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -2341,27 +2341,27 @@ void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle) wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_iface_link_stats_event_id, wma_unified_link_iface_stats_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_peer_link_stats_event_id, wma_unified_link_peer_stats_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_radio_link_stats_link, wma_unified_link_radio_stats_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_radio_tx_power_level_stats_event_id, wma_unified_radio_tx_power_level_stats_event_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_peer_sta_ps_statechg_event_id, wma_peer_ps_evt_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); wmi_unified_register_event_handler(wma_handle->wmi_handle, wmi_report_stats_event_id, wma_ll_stats_evt_handler, - WMA_RX_SERIALIZER_CTX); + WMA_RX_WORK_CTX); } @@ -2440,6 +2440,30 @@ QDF_STATUS wma_process_ll_stats_set_req(tp_wma_handle wma, return QDF_STATUS_SUCCESS; } +#ifdef FEATURE_CLUB_LL_STATS_AND_GET_STATION +static QDF_STATUS +wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle, + struct ll_stats_get_params *cmd) +{ + if (!(cfg_get(wma_handle->psoc, CFG_CLUB_LL_STA_AND_GET_STATION) && + wmi_service_enabled(wma_handle->wmi_handle, + wmi_service_get_station_in_ll_stats_req))) + return wmi_unified_process_ll_stats_get_cmd( + wma_handle->wmi_handle, cmd); + + return wmi_process_unified_ll_stats_get_sta_cmd( + wma_handle->wmi_handle, cmd); +} +#else +static QDF_STATUS +wma_send_ll_stats_get_cmd(tp_wma_handle wma_handle, + struct ll_stats_get_params *cmd) +{ + return wmi_unified_process_ll_stats_get_cmd(wma_handle->wmi_handle, + cmd); +} +#endif + QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma, const tpSirLLStatsGetReq getReq) { @@ -2473,7 +2497,7 @@ QDF_STATUS wma_process_ll_stats_get_req(tp_wma_handle wma, return QDF_STATUS_E_FAILURE; } qdf_mem_copy(cmd.peer_macaddr.bytes, addr, QDF_MAC_ADDR_SIZE); - ret = wmi_unified_process_ll_stats_get_cmd(wma->wmi_handle, &cmd); + ret = wma_send_ll_stats_get_cmd(wma, &cmd); if (ret) { wma_err("Failed to send get link stats request"); return QDF_STATUS_E_FAILURE;