diff --git a/Kbuild b/Kbuild index e08db33f8af3..44264c04bf4c 100644 --- a/Kbuild +++ b/Kbuild @@ -84,6 +84,10 @@ HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ $(HDD_SRC_DIR)/wlan_hdd_wmm.o \ $(HDD_SRC_DIR)/wlan_hdd_wowl.o +ifeq ($(CONFIG_WLAN_FEATURE_PERIODIC_STA_STATS), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_periodic_sta_stats.o +endif + ifeq ($(CONFIG_WLAN_WEXT_SUPPORT_ENABLE), y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_wext.o \ $(HDD_SRC_DIR)/wlan_hdd_hostapd_wext.o @@ -2390,6 +2394,7 @@ cppflags-y += -DMSM_PLATFORM endif cppflags-$(CONFIG_WLAN_FEATURE_DP_BUS_BANDWIDTH) += -DWLAN_FEATURE_DP_BUS_BANDWIDTH +cppflags-$(CONFIG_WLAN_FEATURE_PERIODIC_STA_STATS) += -DWLAN_FEATURE_PERIODIC_STA_STATS cppflags-y += -DQCA_SUPPORT_TXRX_LOCAL_PEER_ID diff --git a/core/hdd/inc/hdd_config.h b/core/hdd/inc/hdd_config.h index c5dde815b54e..acb902394a2f 100644 --- a/core/hdd/inc/hdd_config.h +++ b/core/hdd/inc/hdd_config.h @@ -1362,6 +1362,70 @@ struct dhcp_server { CFG_VALUE_OR_DEFAULT, \ "Disable wow feature") +#ifdef WLAN_FEATURE_PERIODIC_STA_STATS +/* + * + * periodic_stats_timer_interval - Print selective stats on this specified + * interval + * + * @Min: 0 + * @Max: 10000 + * Default: 3000 + * + * This ini is used to specify interval in milliseconds for periodic stats + * timer. This timer will print selective stats after expiration of each + * interval. STA starts this periodic timer after initial connection or after + * roaming is successful. This will be restarted for every + * periodic_stats_timer_interval till the periodic_stats_timer_duration expires. + * + * Supported Feature: STA + * + * Usage: Internal + * + * + */ +#define CFG_PERIODIC_STATS_TIMER_INTERVAL CFG_INI_UINT( \ + "periodic_stats_timer_interval", \ + 0, \ + 10000, \ + 3000, \ + CFG_VALUE_OR_DEFAULT, \ + "Periodic stats timer interval") + +/* + * + * periodic_stats_timer_duration - Used as duration for which periodic timer + * should run + * + * @Min: 0 + * @Max: 60000 + * Default: 30000 + * + * This ini is used as duration in milliseconds for which periodic stats timer + * should run. This periodic timer will print selective stats for every + * periodic_stats_timer_interval until this duration is reached. + * + * Supported Feature: STA + * + * Usage: Internal + * + * + */ +#define CFG_PERIODIC_STATS_TIMER_DURATION CFG_INI_UINT( \ + "periodic_stats_timer_duration", \ + 0, \ + 60000, \ + 30000, \ + CFG_VALUE_OR_DEFAULT, \ + "Periodic stats timer duration") + +#define CFG_WLAN_STA_PERIODIC_STATS \ + CFG(CFG_PERIODIC_STATS_TIMER_DURATION) \ + CFG(CFG_PERIODIC_STATS_TIMER_INTERVAL) +#else +#define CFG_WLAN_STA_PERIODIC_STATS +#endif /* WLAN_FEATURE_PERIODIC_STA_STATS */ + /** * enum host_log_level - Debug verbose level imposed by user * @HOST_LOG_LEVEL_NONE: no trace will be logged. @@ -1478,6 +1542,7 @@ enum host_log_level { CFG_VC_MODE_BITMAP_ALL \ CFG_WLAN_AUTO_SHUTDOWN_ALL \ CFG_WLAN_LOGGING_SUPPORT_ALL \ + CFG_WLAN_STA_PERIODIC_STATS \ CFG(CFG_ACTION_OUI_CCKM_1X1) \ CFG(CFG_ACTION_OUI_CONNECT_1X1) \ CFG(CFG_ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN) \ diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 069356d61d73..9288c980844f 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -244,6 +244,13 @@ struct hdd_config { #endif bool get_roam_chan_from_fw; uint32_t fisa_enable; + +#ifdef WLAN_FEATURE_PERIODIC_STA_STATS + /* Periodicity of logging */ + uint32_t periodic_stats_timer_interval; + /* Duration for which periodic logging should be done */ + uint32_t periodic_stats_timer_duration; +#endif /* WLAN_FEATURE_PERIODIC_STA_STATS */ }; /** diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 5f20ffc8a3e9..72a19c59d34e 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1315,6 +1315,14 @@ struct hdd_adapter { uint32_t motion_det_baseline_value; #endif /* WLAN_FEATURE_MOTION_DETECTION */ enum qca_disconnect_reason_codes last_disconnect_reason; + +#ifdef WLAN_FEATURE_PERIODIC_STA_STATS + /* Indicate whether to display sta periodic stats */ + bool is_sta_periodic_stats_enabled; + uint16_t periodic_stats_timer_count; + uint32_t periodic_stats_timer_counter; + qdf_mutex_t sta_periodic_stats_lock; +#endif /* WLAN_FEATURE_PERIODIC_STA_STATS */ }; #define WLAN_HDD_GET_STATION_CTX_PTR(adapter) (&(adapter)->session.station) diff --git a/core/hdd/inc/wlan_hdd_periodic_sta_stats.h b/core/hdd/inc/wlan_hdd_periodic_sta_stats.h new file mode 100644 index 000000000000..61725404d760 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_periodic_sta_stats.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020, The Linux Foundation. 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC : wlan_hdd_periodic_sta_stats.h + * + * WLAN Host Device Driver periodic STA statistics related implementation + * + */ + +#if !defined(WLAN_HDD_PERIODIC_STA_STATS_H) +#define WLAN_HDD_PERIODIC_STA_STATS_H + +#ifdef WLAN_FEATURE_PERIODIC_STA_STATS +/* + * Used to get device name from the adapter + */ +#define WLAN_HDD_GET_DEV_NAME(adapter) ((adapter)->dev->name) + +/** + * hdd_periodic_sta_stats_config() - Initialize periodic stats configuration + * @config: Pointer to hdd configuration + * @psoc: Pointer to psoc + * + * Return: none + */ +void hdd_periodic_sta_stats_config(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc); + +/** + * hdd_periodic_sta_stats_init() - Initialize periodic stats display flag + * @adapter: Pointer to the station adapter + * + * Return: none + */ +void hdd_periodic_sta_stats_init(struct hdd_adapter *adapter); + +/** + * hdd_periodic_sta_stats_display() - Display periodic stats at STA + * @hdd_ctx: hdd context + * + * Return: none + */ +void hdd_periodic_sta_stats_display(struct hdd_context *hdd_ctx); + +/** + * hdd_periodic_sta_stats_start() - Start displaying periodic stats for STA + * @adapter: Pointer to the station adapter + * + * Return: none + */ +void hdd_periodic_sta_stats_start(struct hdd_adapter *adapter); + +/** + * hdd_periodic_sta_stats_stop() - Stop displaying periodic stats for STA + * @adapter: Pointer to the station adapter + * + * Return: none + */ +void hdd_periodic_sta_stats_stop(struct hdd_adapter *adapter); + +/** + * hdd_periodic_sta_stats_mutex_create() - Create mutex for STA periodic stats + * @adapter: Pointer to the station adapter + * + * Return: none + */ +void hdd_periodic_sta_stats_mutex_create(struct hdd_adapter *adapter); + +/** + * hdd_periodic_sta_stats_mutex_destroy() - Destroy STA periodic stats mutex + * @adapter: Pointer to the station adapter + * + * Return: none + */ +void hdd_periodic_sta_stats_mutex_destroy(struct hdd_adapter *adapter); + +#else +static inline void +hdd_periodic_sta_stats_display(struct hdd_context *hdd_ctx) {} + +static inline void +hdd_periodic_sta_stats_config(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc) {} + +static inline void hdd_periodic_sta_stats_start(struct hdd_adapter *adapter) {} + +static inline void hdd_periodic_sta_stats_stop(struct hdd_adapter *adapter) {} + +static inline void +hdd_periodic_sta_stats_init(struct hdd_adapter *adapter) {} + +static inline void +hdd_periodic_sta_stats_mutex_create(struct hdd_adapter *adapter) {} + +static inline void +hdd_periodic_sta_stats_mutex_destroy(struct hdd_adapter *adapter) {} + +#endif /* end #ifdef WLAN_FEATURE_PERIODIC_STA_STATS */ + +#endif /* end #if !defined(WLAN_HDD_PERIODIC_STA_STATS_H) */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 10f7b94d4a67..169f2f3b66cd 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -72,6 +72,7 @@ #include "wlan_blm_ucfg_api.h" #include "wlan_hdd_sta_info.h" #include "wlan_hdd_ftm_time_sync.h" +#include "wlan_hdd_periodic_sta_stats.h" #include #include "wlan_pkt_capture_ucfg_api.h" @@ -1722,6 +1723,8 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter, WLAN_IPA_STA_DISCONNECT, sta_ctx->conn_info.bssid.bytes); + hdd_periodic_sta_stats_stop(adapter); + #ifdef FEATURE_WLAN_AUTO_SHUTDOWN wlan_hdd_auto_shutdown_enable(hdd_ctx, true); #endif @@ -3640,6 +3643,8 @@ hdd_association_completion_handler(struct hdd_adapter *adapter, policy_mgr_check_concurrent_intf_and_restart_sap(hdd_ctx->psoc); } + hdd_periodic_sta_stats_start(adapter); + return QDF_STATUS_SUCCESS; } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 7aa815c58d66..b07bf368d0be 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -48,6 +48,7 @@ #include "wlan_hdd_ftm.h" #include "wlan_hdd_power.h" #include "wlan_hdd_stats.h" +#include "wlan_hdd_periodic_sta_stats.h" #include "wlan_hdd_scan.h" #include "wlan_policy_mgr_ucfg.h" #include "wlan_osif_priv.h" @@ -5238,6 +5239,7 @@ static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx, hdd_nud_deinit_tracking(adapter); hdd_mic_deinit_work(adapter); qdf_mutex_destroy(&adapter->disconnection_status_lock); + hdd_periodic_sta_stats_mutex_destroy(adapter); hdd_apf_context_destroy(adapter); qdf_spinlock_destroy(&adapter->vdev_lock); hdd_sta_info_deinit(&adapter->sta_info_list); @@ -5896,6 +5898,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio adapter->device_mode == QDF_P2P_DEVICE_MODE) hdd_sysfs_create_adapter_root_obj(adapter); qdf_mutex_create(&adapter->disconnection_status_lock); + hdd_periodic_sta_stats_mutex_create(adapter); break; @@ -6028,6 +6031,8 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio if (adapter->device_mode == QDF_STA_MODE) wlan_hdd_debugfs_csr_init(adapter); + hdd_periodic_sta_stats_init(adapter); + return adapter; err_free_netdev: @@ -8808,6 +8813,8 @@ static void hdd_pld_request_bus_bandwidth(struct hdd_context *hdd_ctx, } hdd_display_periodic_stats(hdd_ctx, (total_pkts > 0) ? true : false); + + hdd_periodic_sta_stats_display(hdd_ctx); } #ifdef QCA_SUPPORT_TXRX_DRIVER_TCP_DEL_ACK @@ -10614,6 +10621,7 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx) config->enable_sar_conversion = cfg_get(psoc, CFG_SAR_CONVERSION); config->is_wow_disabled = cfg_get(psoc, CFG_WOW_DISABLE); + hdd_periodic_sta_stats_config(config, psoc); hdd_init_vc_mode_cfg_bitmap(config, psoc); hdd_init_runtime_pm(config, psoc); hdd_init_wlan_auto_shutdown(config, psoc); diff --git a/core/hdd/src/wlan_hdd_periodic_sta_stats.c b/core/hdd/src/wlan_hdd_periodic_sta_stats.c new file mode 100644 index 000000000000..1627f8528a1f --- /dev/null +++ b/core/hdd/src/wlan_hdd_periodic_sta_stats.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020, The Linux Foundation. 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 above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC : wlan_hdd_periodic_sta_stats.c + * + * WLAN Host Device Driver periodic STA statistics related implementation + * + */ + +#include "wlan_hdd_main.h" +#include "cfg_ucfg_api.h" +#include "wlan_hdd_periodic_sta_stats.h" + +void hdd_periodic_sta_stats_config(struct hdd_config *config, + struct wlan_objmgr_psoc *psoc) +{ + config->periodic_stats_timer_interval = + cfg_get(psoc, CFG_PERIODIC_STATS_TIMER_INTERVAL); + config->periodic_stats_timer_duration = + cfg_get(psoc, CFG_PERIODIC_STATS_TIMER_DURATION); +} + +void hdd_periodic_sta_stats_init(struct hdd_adapter *adapter) +{ + adapter->is_sta_periodic_stats_enabled = false; +} + +void hdd_periodic_sta_stats_display(struct hdd_context *hdd_ctx) +{ + struct hdd_adapter *adapter; + struct hdd_stats sta_stats; + struct hdd_config *hdd_cfg; + char *dev_name; + bool should_log; + + if (!hdd_ctx) + return; + + hdd_for_each_adapter(hdd_ctx, adapter) { + should_log = false; + + if (adapter->device_mode != QDF_STA_MODE) + continue; + + hdd_cfg = hdd_ctx->config; + qdf_mutex_acquire(&adapter->sta_periodic_stats_lock); + + if (!adapter->is_sta_periodic_stats_enabled) { + qdf_mutex_release(&adapter->sta_periodic_stats_lock); + continue; + } + + adapter->periodic_stats_timer_counter++; + if ((adapter->periodic_stats_timer_counter * + GET_BW_COMPUTE_INTV(hdd_cfg)) >= + hdd_cfg->periodic_stats_timer_interval) { + should_log = true; + + adapter->periodic_stats_timer_count--; + if (adapter->periodic_stats_timer_count == 0) + adapter->is_sta_periodic_stats_enabled = false; + adapter->periodic_stats_timer_counter = 0; + } + qdf_mutex_release(&adapter->sta_periodic_stats_lock); + + if (should_log) { + dev_name = WLAN_HDD_GET_DEV_NAME(adapter); + sta_stats = adapter->hdd_stats; + hdd_nofl_info("%s: Tx ARP requests: %d", dev_name, + sta_stats.hdd_arp_stats.tx_arp_req_count); + hdd_nofl_info("%s: Rx ARP responses: %d", dev_name, + sta_stats.hdd_arp_stats.rx_arp_rsp_count); + hdd_nofl_info("%s: Tx DNS requests: %d", dev_name, + sta_stats.hdd_dns_stats.tx_dns_req_count); + hdd_nofl_info("%s: Rx DNS responses: %d", dev_name, + sta_stats.hdd_dns_stats.rx_dns_rsp_count); + } + } +} + +void hdd_periodic_sta_stats_start(struct hdd_adapter *adapter) +{ + struct hdd_config *hdd_cfg = adapter->hdd_ctx->config; + + if ((adapter->device_mode == QDF_STA_MODE) && + (hdd_cfg->periodic_stats_timer_interval > 0)) { + qdf_mutex_acquire(&adapter->sta_periodic_stats_lock); + + adapter->periodic_stats_timer_count = + hdd_cfg->periodic_stats_timer_duration / + hdd_cfg->periodic_stats_timer_interval; + adapter->periodic_stats_timer_counter = 0; + if (adapter->periodic_stats_timer_count > 0) + adapter->is_sta_periodic_stats_enabled = true; + + qdf_mutex_release(&adapter->sta_periodic_stats_lock); + } +} + +void hdd_periodic_sta_stats_stop(struct hdd_adapter *adapter) +{ + struct hdd_config *hdd_cfg = adapter->hdd_ctx->config; + + if ((adapter->device_mode == QDF_STA_MODE) && + (hdd_cfg->periodic_stats_timer_interval > 0)) { + qdf_mutex_acquire(&adapter->sta_periodic_stats_lock); + + /* Stop the periodic ARP and DNS stats timer */ + adapter->periodic_stats_timer_count = 0; + adapter->is_sta_periodic_stats_enabled = false; + + qdf_mutex_release(&adapter->sta_periodic_stats_lock); + } +} + +void hdd_periodic_sta_stats_mutex_create(struct hdd_adapter *adapter) +{ + qdf_mutex_create(&adapter->sta_periodic_stats_lock); +} + +void hdd_periodic_sta_stats_mutex_destroy(struct hdd_adapter *adapter) +{ + qdf_mutex_destroy(&adapter->sta_periodic_stats_lock); +} +