diff options
| author | Selvaraj, Sridhar <sselvara@codeaurora.org> | 2016-10-18 17:18:03 +0530 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2016-11-29 16:07:08 -0800 |
| commit | ed7c8378e03a509501a664409f50a1e4a9898022 (patch) | |
| tree | 6b1d4d2b163e1c0eb57538516989d50e2739e96f | |
| parent | 45bb2e27f22e03306aaaa90da5939aeab54eba25 (diff) | |
qcacld-3.0: Add Host Driver support for Chip Power stats debugfs
Implementation of Host driver support to collect chip power stats
from firmware and display the stats in
"adb shell cat /sys/kernel/debug/wlan0/power_stats".
Change-Id: I19595ebf5a6870a0ee4d3cc2ff47d18eb24d213c
CRs-Fixed: 1045057
| -rw-r--r-- | Kbuild | 9 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 3 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_debugfs.c | 273 | ||||
| -rw-r--r-- | core/mac/inc/sir_api.h | 22 | ||||
| -rw-r--r-- | core/mac/src/include/sir_params.h | 2 | ||||
| -rw-r--r-- | core/sme/inc/sme_api.h | 5 | ||||
| -rw-r--r-- | core/sme/inc/sme_internal.h | 6 | ||||
| -rw-r--r-- | core/sme/src/common/sme_api.c | 40 | ||||
| -rw-r--r-- | core/wma/inc/wma_internal.h | 2 | ||||
| -rw-r--r-- | core/wma/inc/wma_types.h | 2 | ||||
| -rw-r--r-- | core/wma/src/wma_features.c | 84 | ||||
| -rw-r--r-- | core/wma/src/wma_main.c | 70 |
12 files changed, 517 insertions, 1 deletions
@@ -80,6 +80,11 @@ ifeq ($(KERNEL_BUILD), 0) #Flag to enable Legacy Fast Roaming3(LFR3) CONFIG_QCACLD_WLAN_LFR3 := y + #Enable Power debugfs feature only if debug_fs is enabled + ifeq ($(CONFIG_DEBUG_FS), y) + CONFIG_WLAN_POWER_DEBUGFS := y + endif + # JB kernel has CPU enablement patches, so enable ifeq ($(CONFIG_ROME_IF),pci) CONFIG_PRIMA_WLAN_11AC_HIGH_TP := y @@ -1204,6 +1209,10 @@ ifeq ($(CONFIG_QCACLD_WLAN_LFR2),y) CDEFINES += -DWLAN_FEATURE_HOST_ROAM endif +ifeq ($(CONFIG_WLAN_POWER_DEBUGFS), y) +CDEFINES += -DWLAN_POWER_DEBUGFS +endif + ifeq ($(BUILD_DIAG_VERSION),1) CDEFINES += -DFEATURE_WLAN_DIAG_SUPPORT CDEFINES += -DFEATURE_WLAN_DIAG_SUPPORT_CSR diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index fb033a1417fb..3a6574c1d434 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -118,6 +118,7 @@ #define WLAN_WAIT_TIME_POWER 800 #define WLAN_WAIT_TIME_COUNTRY 1000 #define WLAN_WAIT_TIME_LINK_STATUS 800 +#define WLAN_WAIT_TIME_POWER_STATS 800 /* Amount of time to wait for sme close session callback. This value should be larger than the timeout used by WDI to wait for a response from WCNSS */ @@ -323,6 +324,7 @@ extern spinlock_t hdd_context_lock; #define LINK_STATUS_MAGIC 0x4C4B5354 /* LINKSTATUS(LNST) */ #define TEMP_CONTEXT_MAGIC 0x74656d70 /* TEMP (temperature) */ #define BPF_CONTEXT_MAGIC 0x4575354 /* BPF */ +#define POWER_STATS_MAGIC 0x14111990 /* MAX OS Q block time value in msec * Prevent from permanent stall, resume OS Q if timer expired */ @@ -1127,6 +1129,7 @@ struct hdd_adapter_s { */ uint8_t pre_cac_chan; struct hdd_connect_pm_context connect_rpm_ctx; + struct power_stats_response *chip_power_stats; }; #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) diff --git a/core/hdd/src/wlan_hdd_debugfs.c b/core/hdd/src/wlan_hdd_debugfs.c index e5652b4f1c53..ce21d643c9c8 100644 --- a/core/hdd/src/wlan_hdd_debugfs.c +++ b/core/hdd/src/wlan_hdd_debugfs.c @@ -47,6 +47,10 @@ #define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512 #define MAX_USER_COMMAND_SIZE_FRAME 4096 +#ifdef WLAN_POWER_DEBUGFS +#define POWER_DEBUGFS_BUFFER_MAX_LEN 4096 +#endif + /** * __wcnss_wowenable_write() - wow_enable debugfs handler * @file: debugfs file handle @@ -506,6 +510,241 @@ static ssize_t wcnss_patterngen_write(struct file *file, return ret; } +#ifdef WLAN_POWER_DEBUGFS +/** + * hdd_power_debugstats_cb() - callback routine for Power stats debugs + * @response: Pointer to Power stats response + * @context: Pointer to statsContext + * + * Return: None + */ +static void hdd_power_debugstats_cb(struct power_stats_response *response, + void *context) +{ + struct statsContext *stats_context; + struct power_stats_response *power_stats; + hdd_adapter_t *adapter; + uint32_t power_stats_len; + uint32_t stats_registers_len; + + ENTER(); + if (!context) { + hdd_err("context is NULL"); + return; + } + + stats_context = (struct statsContext *)context; + + spin_lock(&hdd_context_lock); + adapter = stats_context->pAdapter; + if ((POWER_STATS_MAGIC != stats_context->magic) || + (!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) { + spin_unlock(&hdd_context_lock); + hdd_err("Invalid context, adapter [%p] magic [%08x]", + adapter, stats_context->magic); + return; + } + + stats_context->magic = 0; + stats_registers_len = (sizeof(response->debug_registers[0]) * + response->num_debug_register); + power_stats_len = stats_registers_len + sizeof(*power_stats); + adapter->chip_power_stats = qdf_mem_malloc(power_stats_len); + if (!adapter->chip_power_stats) { + hdd_err("Power stats memory alloc fails!"); + goto exit_stats_cb; + } + + power_stats = adapter->chip_power_stats; + power_stats->cumulative_sleep_time_ms + = response->cumulative_sleep_time_ms; + power_stats->cumulative_total_on_time_ms + = response->cumulative_total_on_time_ms; + power_stats->deep_sleep_enter_counter + = response->deep_sleep_enter_counter; + power_stats->last_deep_sleep_enter_tstamp_ms + = response->last_deep_sleep_enter_tstamp_ms; + power_stats->debug_register_fmt + = response->debug_register_fmt; + power_stats->num_debug_register + = response->num_debug_register; + + power_stats->debug_registers = (uint32_t *)(power_stats + 1); + + qdf_mem_copy(power_stats->debug_registers, + response->debug_registers, stats_registers_len); + +exit_stats_cb: + complete(&stats_context->completion); + spin_unlock(&hdd_context_lock); + EXIT(); +} + +/** + * __wlan_hdd_read_power_debugfs() - API to collect Chip power stats from FW + * @file: file pointer + * @buf: buffer + * @count: count + * @pos: position pointer + * + * Return: Number of bytes read on success, error number otherwise + */ +static ssize_t __wlan_hdd_read_power_debugfs(struct file *file, + char __user *buf, + size_t count, loff_t *pos) +{ + hdd_adapter_t *adapter; + hdd_context_t *hdd_ctx; + static struct statsContext context; + struct power_stats_response *chip_power_stats; + ssize_t ret_cnt = 0; + int rc = 0, j; + unsigned int len = 0; + char *power_debugfs_buf; + + ENTER(); + adapter = (hdd_adapter_t *)file->private_data; + if ((!adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) { + hdd_err("Invalid adapter or adapter has invalid magic"); + return -EINVAL; + } + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret_cnt = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret_cnt) + return ret_cnt; + + if (adapter->chip_power_stats) + qdf_mem_free(adapter->chip_power_stats); + + adapter->chip_power_stats = NULL; + context.pAdapter = adapter; + context.magic = POWER_STATS_MAGIC; + + init_completion(&context.completion); + + if (QDF_STATUS_SUCCESS != + sme_power_debug_stats_req(hdd_ctx->hHal, + hdd_power_debugstats_cb, + &context)) { + hdd_err("chip power stats request failed"); + return -EINVAL; + } + + rc = wait_for_completion_timeout(&context.completion, + msecs_to_jiffies(WLAN_WAIT_TIME_POWER_STATS)); + if (!rc) { + hdd_err("Target response timed out Power stats"); + /* Invalidate the Stats context magic */ + spin_lock(&hdd_context_lock); + context.magic = 0; + spin_unlock(&hdd_context_lock); + return -ETIMEDOUT; + } + + chip_power_stats = adapter->chip_power_stats; + if (!chip_power_stats) { + hdd_err("Power stats retrieval fails!"); + return -EINVAL; + } + + power_debugfs_buf = qdf_mem_malloc(POWER_DEBUGFS_BUFFER_MAX_LEN); + if (!power_debugfs_buf) { + hdd_err("Power stats buffer alloc fails!"); + qdf_mem_free(chip_power_stats); + adapter->chip_power_stats = NULL; + return -EINVAL; + } + + len += scnprintf(power_debugfs_buf, POWER_DEBUGFS_BUFFER_MAX_LEN, + "POWER DEBUG STATS\n=================\n" + "cumulative_sleep_time_ms: %d\n" + "cumulative_total_on_time_ms: %d\n" + "deep_sleep_enter_counter: %d\n" + "last_deep_sleep_enter_tstamp_ms: %d\n" + "debug_register_fmt: %d\n" + "num_debug_register: %d\n", + chip_power_stats->cumulative_sleep_time_ms, + chip_power_stats->cumulative_total_on_time_ms, + chip_power_stats->deep_sleep_enter_counter, + chip_power_stats->last_deep_sleep_enter_tstamp_ms, + chip_power_stats->debug_register_fmt, + chip_power_stats->num_debug_register); + + for (j = 0; j < chip_power_stats->num_debug_register; j++) { + if ((POWER_DEBUGFS_BUFFER_MAX_LEN - len) > 0) + len += scnprintf(power_debugfs_buf + len, + POWER_DEBUGFS_BUFFER_MAX_LEN - len, + "debug_registers[%d]: 0x%x\n", j, + chip_power_stats->debug_registers[j]); + else + j = chip_power_stats->num_debug_register; + } + + qdf_mem_free(chip_power_stats); + adapter->chip_power_stats = NULL; + + ret_cnt = simple_read_from_buffer(buf, count, pos, + power_debugfs_buf, len); + qdf_mem_free(power_debugfs_buf); + return ret_cnt; +} + +/** + * wlan_hdd_read_power_debugfs() - SSR wrapper function to read power debugfs + * @file: file pointer + * @buf: buffer + * @count: count + * @pos: position pointer + * + * Return: Number of bytes read on success, error number otherwise + */ +static ssize_t wlan_hdd_read_power_debugfs(struct file *file, + char __user *buf, + size_t count, loff_t *pos) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_read_power_debugfs(file, buf, count, pos); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * __wlan_hdd_open_power_debugfs() - Function to save private on open + * @inode: Pointer to inode structure + * @file: file pointer + * + * Return: zero + */ +static int __wlan_hdd_open_power_debugfs(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + + +/** + * wlan_hdd_open_power_debugfs() - SSR wrapper function to save private on open + * @inode: Pointer to inode structure + * @file: file pointer + * + * Return: zero + */ +static int wlan_hdd_open_power_debugfs(struct inode *inode, struct file *file) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_open_power_debugfs(inode, file); + cds_ssr_unprotect(__func__); + + return ret; +} +#endif + /** * __wcnss_debugfs_open() - Generic debugfs open() handler * @inode: inode of the debugfs file @@ -577,6 +816,37 @@ static const struct file_operations fops_patterngen = { .llseek = default_llseek, }; +#ifdef WLAN_POWER_DEBUGFS +static const struct file_operations fops_powerdebugs = { + .read = wlan_hdd_read_power_debugfs, + .open = wlan_hdd_open_power_debugfs, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +/** + * wlan_hdd_create_power_stats_file() - API to create power stats file + * @adapter: interface adapter pointer + * + * Return: QDF_STATUS + */ +static QDF_STATUS wlan_hdd_create_power_stats_file(hdd_adapter_t *adapter) +{ + if (!debugfs_create_file("power_stats", S_IRUSR | S_IRGRP | S_IROTH, + adapter->debugfs_phy, adapter, + &fops_powerdebugs)) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +#else +static QDF_STATUS wlan_hdd_create_power_stats_file(hdd_adapter_t *adapter) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * hdd_debugfs_init() - Initialize debugfs interface * @adapter: interface adapter pointer @@ -612,6 +882,9 @@ QDF_STATUS hdd_debugfs_init(hdd_adapter_t *adapter) &fops_patterngen)) return QDF_STATUS_E_FAILURE; + if (QDF_STATUS_SUCCESS != wlan_hdd_create_power_stats_file(adapter)) + return QDF_STATUS_E_FAILURE; + return QDF_STATUS_SUCCESS; } diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index ba90feaec7f9..b38d08ed4ff2 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -4847,6 +4847,28 @@ typedef struct { uint8_t stopReq; } tSirLLStatsClearReq, *tpSirLLStatsClearReq; +#ifdef WLAN_POWER_DEBUGFS +/** + * struct power_stats_response - Power stats response + * @cumulative_sleep_time_ms: cumulative sleep time in ms + * @cumulative_total_on_time_ms: total awake time in ms + * @deep_sleep_enter_counter: deep sleep enter counter + * @last_deep_sleep_enter_tstamp_ms: last deep sleep enter timestamp + * @debug_register_fmt: debug registers format + * @num_debug_register: number of debug registers + * @debug_registers: Pointer to the debug registers buffer + */ +struct power_stats_response { + uint32_t cumulative_sleep_time_ms; + uint32_t cumulative_total_on_time_ms; + uint32_t deep_sleep_enter_counter; + uint32_t last_deep_sleep_enter_tstamp_ms; + uint32_t debug_register_fmt; + uint32_t num_debug_register; + uint32_t *debug_registers; +}; +#endif + typedef struct { uint8_t oui[WIFI_SCANNING_MAC_OUI_LENGTH]; } tSirScanMacOui, *tpSirScanMacOui; diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 3fe1af30659f..e91e6ca08b29 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -640,6 +640,8 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_SHORT_RETRY_LIMIT_CNT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 365) #define SIR_HAL_LONG_RETRY_LIMIT_CNT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 366) #define SIR_HAL_UPDATE_TX_FAIL_CNT_TH (SIR_HAL_ITC_MSG_TYPES_BEGIN + 367) +#define SIR_HAL_POWER_DEBUG_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 368) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 7ba3abefc750..b362cd3aa4e5 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1355,4 +1355,9 @@ QDF_STATUS sme_update_sta_inactivity_timeout(tHalHandle hal_handle, */ QDF_STATUS sme_set_lost_link_info_cb(tHalHandle hal, void (*cb)(void *, struct sir_lost_link_info *)); +#ifdef WLAN_POWER_DEBUGFS +QDF_STATUS sme_power_debug_stats_req(tHalHandle hal, void (*callback_fn) + (struct power_stats_response *response, + void *context), void *power_stats_context); +#endif #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index dfc972d8f30e..b44340416eea 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -183,6 +183,12 @@ typedef struct tagSmeStruct { void (*pLinkLayerStatsIndCallback)(void *callbackContext, int indType, void *pRsp); #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ + +#ifdef WLAN_POWER_DEBUGFS + void *power_debug_stats_context; + void (*power_stats_resp_callback)(struct power_stats_response *rsp, + void *callback_context); +#endif #ifdef FEATURE_WLAN_AUTO_SHUTDOWN void (*pAutoShutdownNotificationCb)(void); #endif diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 6dcfdbb5aa1b..010fd77ffe5d 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -14324,6 +14324,46 @@ QDF_STATUS sme_reset_link_layer_stats_ind_cb(tHalHandle h_hal) #endif /* WLAN_FEATURE_LINK_LAYER_STATS */ +#ifdef WLAN_POWER_DEBUGFS +/** + * sme_power_debug_stats_req() - SME API to collect Power debug stats + * @callback_fn: Pointer to the callback function for Power stats event + * @power_stats_context: Pointer to context + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_power_debug_stats_req(tHalHandle hal, void (*callback_fn) + (struct power_stats_response *response, + void *context), void *power_stats_context) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + cds_msg_t msg; + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + if (!callback_fn) { + sms_log(mac_ctx, LOGE, + FL("Indication callback did not registered")); + sme_release_global_lock(&mac_ctx->sme); + return QDF_STATUS_E_FAILURE; + } + + mac_ctx->sme.power_debug_stats_context = power_stats_context; + mac_ctx->sme.power_stats_resp_callback = callback_fn; + msg.bodyptr = NULL; + msg.type = WMA_POWER_DEBUG_STATS_REQ; + status = cds_mq_post_message(QDF_MODULE_ID_WMA, &msg); + if (!QDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac_ctx, LOGE, + FL("not able to post WDA_POWER_DEBUG_STATS_REQ")); + } + sme_release_global_lock(&mac_ctx->sme); + } + return status; +} +#endif + /** * sme_fw_mem_dump_register_cb() - Register fw memory dump callback * diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 6521e5d21612..b6ed027b7df7 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1231,4 +1231,6 @@ static inline int wma_encrypt_decrypt_msg_handler(void *handle, uint8_t *data, */ void wma_lost_link_info_handler(tp_wma_handle wma, uint32_t vdev_id, int32_t rssi); +int wma_unified_power_debug_stats_event_handler(void *handle, + uint8_t *cmd_param_info, uint32_t len); #endif diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index cfd4d2ffb520..af7d2a13c1bd 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -477,6 +477,8 @@ #define WMA_UPDATE_WEP_DEFAULT_KEY SIR_HAL_UPDATE_WEP_DEFAULT_KEY #define WMA_SEND_FREQ_RANGE_CONTROL_IND SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND #define WMA_ENCRYPT_DECRYPT_MSG SIR_HAL_ENCRYPT_DECRYPT_MSG +#define WMA_POWER_DEBUG_STATS_REQ SIR_HAL_POWER_DEBUG_STATS_REQ + /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 0f8e534a0fb0..5e817443a536 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -8419,3 +8419,87 @@ int wma_encrypt_decrypt_msg_handler(void *handle, uint8_t *data, return 0; } #endif + +/** + * wma_unified_power_debug_stats_event_handler() - WMA handler function to + * handle Power stats event from firmware + * @handle: Pointer to wma handle + * @cmd_param_info: Pointer to Power stats event TLV + * @len: Length of the cmd_param_info + * + * Return: 0 on success, error number otherwise + */ +#ifdef WLAN_POWER_DEBUGFS +int wma_unified_power_debug_stats_event_handler(void *handle, + uint8_t *cmd_param_info, uint32_t len) +{ + WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *param_tlvs; + struct power_stats_response *power_stats_results; + wmi_pdev_chip_power_stats_event_fixed_param *param_buf; + uint32_t power_stats_len, stats_registers_len, *debug_registers; + + tpAniSirGlobal mac = (tpAniSirGlobal)cds_get_context(QDF_MODULE_ID_PE); + param_tlvs = + (WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *) cmd_param_info; + + param_buf = (wmi_pdev_chip_power_stats_event_fixed_param *) + param_tlvs->fixed_param; + if (!mac || !mac->sme.power_stats_resp_callback) { + WMA_LOGD("%s: NULL mac ptr or HDD callback is null", __func__); + return -EINVAL; + } + + if (!param_buf) { + WMA_LOGD("%s: NULL power stats event fixed param", __func__); + return -EINVAL; + } + + debug_registers = param_tlvs->debug_registers; + stats_registers_len = + (sizeof(uint32_t) * param_buf->num_debug_register); + power_stats_len = stats_registers_len + sizeof(*power_stats_results); + power_stats_results = qdf_mem_malloc(power_stats_len); + if (!power_stats_results) { + WMA_LOGD("%s: could not allocate mem for power stats results", + __func__); + return -ENOMEM; + } + WMA_LOGD("Cumulative sleep time %d cumulative total on time %d deep sleep enter counter %d last deep sleep enter tstamp ts %d debug registers fmt %d num debug register %d", + param_buf->cumulative_sleep_time_ms, + param_buf->cumulative_total_on_time_ms, + param_buf->deep_sleep_enter_counter, + param_buf->last_deep_sleep_enter_tstamp_ms, + param_buf->debug_register_fmt, + param_buf->num_debug_register); + + power_stats_results->cumulative_sleep_time_ms + = param_buf->cumulative_sleep_time_ms; + power_stats_results->cumulative_total_on_time_ms + = param_buf->cumulative_total_on_time_ms; + power_stats_results->deep_sleep_enter_counter + = param_buf->deep_sleep_enter_counter; + power_stats_results->last_deep_sleep_enter_tstamp_ms + = param_buf->last_deep_sleep_enter_tstamp_ms; + power_stats_results->debug_register_fmt + = param_buf->debug_register_fmt; + power_stats_results->num_debug_register + = param_buf->num_debug_register; + + power_stats_results->debug_registers + = (uint32_t *)(power_stats_results + 1); + + qdf_mem_copy(power_stats_results->debug_registers, + debug_registers, stats_registers_len); + + mac->sme.power_stats_resp_callback(power_stats_results, + mac->sme.power_debug_stats_context); + qdf_mem_free(power_stats_results); + return 0; +} +#else +int wma_unified_power_debug_stats_event_handler(void *handle, + uint8_t *cmd_param_info, uint32_t len) +{ + return 0; +} +#endif diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 91e4fc6be238..e43eae06b71e 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2172,6 +2172,15 @@ QDF_STATUS wma_open(void *cds_context, WMI_UPDATE_STATS_EVENTID, wma_stats_event_handler, WMA_RX_SERIALIZER_CTX); + +#ifdef WLAN_POWER_DEBUGFS + /* register for Chip Power stats event */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_PDEV_CHIP_POWER_STATS_EVENTID, + wma_unified_power_debug_stats_event_handler, + WMA_RX_SERIALIZER_CTX); +#endif + /* register for linkspeed response event */ wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_PEER_ESTIMATED_LINKSPEED_EVENTID, @@ -6080,6 +6089,62 @@ void wma_update_sta_inactivity_timeout(tp_wma_handle wma, } /** + * wma_process_power_debug_stats_req() - Process the Chip Power stats collect + * request and pass the Power stats request to Fw + * @wma_handle: WMA handle + * + * Return: QDF_STATUS + */ +#ifdef WLAN_POWER_DEBUGFS +static QDF_STATUS wma_process_power_debug_stats_req(tp_wma_handle wma_handle) +{ + wmi_pdev_get_chip_power_stats_cmd_fixed_param *cmd; + int32_t len; + wmi_buf_t buf; + uint8_t *buf_ptr; + int ret; + + if (!wma_handle) { + WMA_LOGE("%s: input pointer is NULL", __func__); + return QDF_STATUS_E_FAILURE; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s: Failed allocate wmi buffer", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + cmd = (wmi_pdev_get_chip_power_stats_cmd_fixed_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_get_chip_power_stats_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_pdev_get_chip_power_stats_cmd_fixed_param)); + cmd->pdev_id = 0; + + WMA_LOGD("POWER_DEBUG_STATS - Get Request Params; Pdev id - %d", + cmd->pdev_id); + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_PDEV_GET_CHIP_POWER_STATS_CMDID); + if (ret) { + WMA_LOGE("%s: Failed to send power debug stats request", + __func__); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS wma_process_power_debug_stats_req(tp_wma_handle wma_handle) +{ + return QDF_STATUS_SUCCESS; +} +#endif + +/** * wma_mc_process_msg() - process wma messages and call appropriate function. * @cds_context: cds context * @msg: message @@ -6906,8 +6971,11 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) wma_update_short_retry_limit(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case SIR_HAL_POWER_DEBUG_STATS_REQ: + wma_process_power_debug_stats_req(wma_handle); + break; default: - WMA_LOGD("unknow msg type %x", msg->type); + WMA_LOGD("unknown msg type %x", msg->type); /* Do Nothing? MSG Body should be freed at here */ if (NULL != msg->bodyptr) { qdf_mem_free(msg->bodyptr); |
