summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelvaraj, Sridhar <sselvara@codeaurora.org>2016-08-25 14:01:31 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-11-21 13:27:13 +0530
commit6e6c68ae4e7765d3e520852b969862333c8e805b (patch)
tree99b1d6549d97bc080b410a16e8fab36662f04b65
parent52e17722b1d4961e955ea21c7b8ddb2c07947670 (diff)
qcacld-2.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/wlan_wcnss/power_stats". Change-Id: I19595ebf5a6870a0ee4d3cc2ff47d18eb24d213c CRs-Fixed: 1045057
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h3
-rw-r--r--CORE/HDD/src/wlan_hdd_debugfs.c295
-rw-r--r--CORE/MAC/inc/sirApi.h22
-rw-r--r--CORE/MAC/src/include/sirParams.h1
-rw-r--r--CORE/SERVICES/WMA/wma.c151
-rw-r--r--CORE/SME/inc/smeInternal.h6
-rw-r--r--CORE/SME/inc/sme_Api.h5
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c44
-rw-r--r--CORE/SYS/legacy/src/utils/src/macTrace.c1
-rw-r--r--Kbuild9
10 files changed, 534 insertions, 3 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 55684c6aabf4..45800ecc2bc0 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -119,6 +119,7 @@
#define WLAN_WAIT_TIME_ABORTSCAN 2000
#define WLAN_WAIT_TIME_EXTSCAN 1000
#define WLAN_WAIT_TIME_LL_STATS 800
+#define WLAN_WAIT_TIME_POWER_STATS 800
#define WLAN_WAIT_SMPS_FORCE_MODE 500
@@ -325,6 +326,7 @@ extern spinlock_t hdd_context_lock;
#define LINK_STATUS_MAGIC 0x4C4B5354 //LINKSTATUS(LNST)
#define TEMP_CONTEXT_MAGIC 0x74656d70 // TEMP (temperature)
#define FW_STATUS_MAGIC 0x46575354 /* FWSTATUS(FWST) */
+#define POWER_STATS_MAGIC 0x14111990
#define BPF_CONTEXT_MAGIC 0x4575354 /* BPF */
#ifdef QCA_LL_TX_FLOW_CT
@@ -1248,6 +1250,7 @@ struct hdd_adapter_s
struct hdd_netif_queue_history
queue_oper_history[WLAN_HDD_MAX_HISTORY_ENTRY];
struct hdd_netif_queue_stats queue_oper_stats[WLAN_REASON_TYPE_MAX];
+ 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 5871ae6a54af..55b83ae52052 100644
--- a/CORE/HDD/src/wlan_hdd_debugfs.c
+++ b/CORE/HDD/src/wlan_hdd_debugfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -29,11 +29,22 @@
#include <wlan_hdd_includes.h>
#include <wlan_hdd_wowl.h>
#include <vos_sched.h>
+#include "wlan_hdd_debugfs.h"
#define MAX_USER_COMMAND_SIZE_WOWL_ENABLE 8
#define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
#define MAX_USER_COMMAND_SIZE_FRAME 4096
+#ifdef MULTI_IF_NAME
+#define HDD_DEBUGFS_DIRNAME "wlan_wcnss" MULTI_IF_NAME
+#else
+#define HDD_DEBUGFS_DIRNAME "wlan_wcnss"
+#endif
+
+#ifdef WLAN_POWER_DEBUGFS
+#define POWER_DEBUGFS_BUFFER_MAX_LEN 4096
+#endif
+
/**
* __wcnss_wowenable_write() - write wow enable
* @file: file pointer
@@ -587,6 +598,249 @@ static int wcnss_debugfs_open(struct inode *inode, 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 (NULL == context) {
+ hddLog(LOGE, FL("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) ||
+ (NULL == adapter) ||
+ (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
+ spin_unlock(&hdd_context_lock);
+ hddLog(LOGE, FL("Invalid context, adapter [%p] magic [%08x]"),
+ adapter, stats_context->magic);
+ return;
+ }
+
+ /* Invalidate the Stats context magic */
+ 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 = vos_mem_malloc(power_stats_len);
+ if (!adapter->chip_power_stats) {
+ hddLog(LOGE, FL("Power stats memory alloc fails!"));
+ goto exit_stats_cb;
+ }
+
+ power_stats = adapter->chip_power_stats;
+ vos_mem_zero(power_stats, power_stats_len);
+
+ 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);
+
+ vos_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;
+ 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 ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) {
+ hddLog(LOGE,
+ FL("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)
+ vos_mem_free(adapter->chip_power_stats);
+
+ adapter->chip_power_stats = NULL;
+ context.pAdapter = adapter;
+ context.magic = POWER_STATS_MAGIC;
+
+ init_completion(&context.completion);
+
+ if (eHAL_STATUS_SUCCESS !=
+ sme_power_debug_stats_req(hdd_ctx->hHal,
+ hdd_power_debugstats_cb,
+ &context)) {
+ hddLog(LOGE, FL("chip power stats request failed"));
+ return -EINVAL;
+ }
+
+ rc = wait_for_completion_timeout(&context.completion,
+ msecs_to_jiffies(WLAN_WAIT_TIME_POWER_STATS));
+ if (!rc) {
+ hddLog(LOGE, FL("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) {
+ hddLog(LOGE, FL("Power stats retrieval fails!"));
+ return -EINVAL;
+ }
+
+ power_debugfs_buf = vos_mem_malloc(POWER_DEBUGFS_BUFFER_MAX_LEN);
+ if (!power_debugfs_buf) {
+ hddLog(LOGE, FL("Power stats buffer alloc fails!"));
+ vos_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;
+ }
+
+ vos_mem_free(chip_power_stats);
+ adapter->chip_power_stats = NULL;
+
+ ret_cnt = simple_read_from_buffer(buf, count, pos,
+ power_debugfs_buf, len);
+ vos_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;
+
+ vos_ssr_protect(__func__);
+ ret = __wlan_hdd_read_power_debugfs(file, buf, count, pos);
+ vos_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;
+
+ vos_ssr_protect(__func__);
+ ret = __wlan_hdd_open_power_debugfs(inode, file);
+ vos_ssr_unprotect(__func__);
+
+ return ret;
+}
+
+#endif
+
+
static const struct file_operations fops_wowenable = {
.write = wcnss_wowenable_write,
.open = wcnss_debugfs_open,
@@ -608,10 +862,43 @@ 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
+ *
+ * Return: VOS_STATUS
+ */
+static VOS_STATUS wlan_hdd_create_power_stats_file(hdd_adapter_t *adapter,
+ hdd_context_t *hdd_ctx)
+{
+ if (NULL == debugfs_create_file("power_stats",
+ S_IRUSR | S_IRGRP | S_IROTH,
+ hdd_ctx->debugfs_phy, adapter,
+ &fops_powerdebugs))
+ return VOS_STATUS_E_FAILURE;
+
+ return VOS_STATUS_SUCCESS;
+}
+
+#else
+static VOS_STATUS wlan_hdd_create_power_stats_file(hdd_adapter_t *adapter,
+ hdd_context_t *hdd_ctx)
+{
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+
VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
{
hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
- pHddCtx->debugfs_phy = debugfs_create_dir("wlan_wcnss", 0);
+ pHddCtx->debugfs_phy = debugfs_create_dir(HDD_DEBUGFS_DIRNAME, 0);
if (NULL == pHddCtx->debugfs_phy)
return VOS_STATUS_E_FAILURE;
@@ -628,6 +915,10 @@ VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
pHddCtx->debugfs_phy, pAdapter, &fops_patterngen))
return VOS_STATUS_E_FAILURE;
+ if (VOS_STATUS_SUCCESS != wlan_hdd_create_power_stats_file(pAdapter,
+ pHddCtx))
+ return VOS_STATUS_E_FAILURE;
+
return VOS_STATUS_SUCCESS;
}
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 0506e238d430..c5074d2042f2 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -5870,6 +5870,28 @@ struct vendor_oui {
uint32_t oui_subtype;
};
+#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
{
tANI_U8 oui[WIFI_SCANNING_MAC_OUI_LENGTH];
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 8c3e15ecae7a..c6c864886b1c 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -791,6 +791,7 @@ typedef struct sSirMbMsgP2p
#define SIR_HAL_SET_REORDER_TIMEOUT_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 368)
#define SIR_HAL_SET_RX_BLOCKSIZE_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 369)
#define SIR_HAL_GET_CHAIN_RSSI_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 370)
+#define SIR_HAL_POWER_DEBUG_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 371)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 8330396537d8..7e6eb0974825 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -5782,6 +5782,94 @@ void wma_tx_failure_cb(void *ctx, uint32_t num_msdu, uint8_t tid, uint32 status)
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
/**
+ * 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
+static int wma_unified_power_debug_stats_event_handler(void *handle,
+ uint8_t *cmd_param_info, uint32_t len)
+{
+ tp_wma_handle wma_handle = (tp_wma_handle) handle;
+ 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)vos_get_context(VOS_MODULE_ID_PE,
+ wma_handle->vos_context);
+ 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 = vos_mem_malloc(power_stats_len);
+ if (NULL == power_stats_results) {
+ WMA_LOGD("%s: could not allocate mem for power stats results",
+ __func__);
+ return -ENOMEM;
+ }
+
+ vos_mem_zero(power_stats_results, power_stats_len);
+ 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);
+
+ vos_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);
+ vos_mem_free(power_stats_results);
+ return 0;
+}
+#else
+static int wma_unified_power_debug_stats_event_handler(void *handle,
+ uint8_t *cmd_param_info, uint32_t len)
+{
+ return 0;
+}
+#endif
+
+/**
* wma_fw_mem_dump_event_handler() - handles fw memory dump event
*
* handle - pointer to wma handle.
@@ -8573,6 +8661,9 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx,
wmi_unified_register_event_handler(wma_handle->wmi_handle,
WMI_BPF_CAPABILIY_INFO_EVENTID,
wma_get_bpf_caps_event_handler);
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_PDEV_CHIP_POWER_STATS_EVENTID,
+ wma_unified_power_debug_stats_event_handler);
WMA_LOGD("%s: Exit", __func__);
@@ -31696,6 +31787,62 @@ static 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: VOS_STATUS
+ */
+#ifdef WLAN_POWER_DEBUGFS
+static VOS_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 VOS_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 VOS_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 VOS_STATUS_E_FAILURE;
+ }
+ return VOS_STATUS_SUCCESS;
+}
+#else
+static VOS_STATUS wma_process_power_debug_stats_req(tp_wma_handle wma_handle)
+{
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+
+/**
* wma_set_rx_reorder_timeout_val() - set rx recorder timeout value
* @wma_handle: pointer to wma handle
* @sir_set_rx_reorder_timeout_val: rx recorder timeout value
@@ -32730,6 +32877,9 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg)
wma_set_rx_blocksize(wma_handle, msg->bodyptr);
vos_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);
/* Do Nothing? MSG Body should be freed at here */
@@ -37836,7 +37986,6 @@ int wma_get_channels(struct ieee80211_channel *ichan,
return chan_list->nchannels;
}
-
/*
* Indicate Radar to SAP/HDD
*/
diff --git a/CORE/SME/inc/smeInternal.h b/CORE/SME/inc/smeInternal.h
index eb6fd44e0e28..23202f2a9129 100644
--- a/CORE/SME/inc/smeInternal.h
+++ b/CORE/SME/inc/smeInternal.h
@@ -191,6 +191,12 @@ typedef struct tagSmeStruct
int indType, void *pRsp);
void (*link_layer_stats_ext_cb)(tSirLLStatsResults *rsp);
#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/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index b57053999f03..9f6b2d5614d6 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4745,4 +4745,9 @@ eHalStatus sme_update_sub20_channel_width(tHalHandle hal_handle,
return eHAL_STATUS_SUCCESS;
}
#endif
+#ifdef WLAN_POWER_DEBUGFS
+eHalStatus 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/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index e5bc5161bc17..35b585462b82 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -16654,6 +16654,50 @@ eHalStatus sme_LLStatsGetReq (tHalHandle hHal,
return status;
}
+#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: eHalStatus
+ */
+eHalStatus sme_power_debug_stats_req(tHalHandle hal, void (*callback_fn)
+ (struct power_stats_response *response,
+ void *context), void *power_stats_context)
+{
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal mac = PMAC_STRUCT(hal);
+ vos_msg_t vos_message;
+
+ if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&mac->sme)) {
+ if (NULL == callback_fn) {
+ smsLog(mac, LOGE,
+ FL("Indication callback did not registered"));
+ sme_ReleaseGlobalLock(&mac->sme);
+ return eHAL_STATUS_FAILURE;
+ }
+
+ mac->sme.power_debug_stats_context = power_stats_context;
+ mac->sme.power_stats_resp_callback = callback_fn;
+ vos_message.bodyptr = NULL;
+ vos_message.type = SIR_HAL_POWER_DEBUG_STATS_REQ;
+ vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_message);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
+ smsLog(mac, LOGE,
+ FL("not able to post WDA_POWER_DEBUG_STATS_REQ"));
+ status = eHAL_STATUS_FAILURE;
+ }
+ sme_ReleaseGlobalLock(&mac->sme);
+ } else {
+ smsLog(mac, LOGE, FL("sme_AcquireGlobalLock error"));
+ status = eHAL_STATUS_FAILURE;
+ }
+ return status;
+}
+#endif
+
/**
* eHalStatus sme_ll_stats_set_thresh - set threshold for mac counters
* @hal, hal layer handle
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index 61048ffeb03d..8a2736331f99 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -999,6 +999,7 @@ tANI_U8* macTraceGetWdaMsgString(tANI_U16 wdaMsg)
CASE_RETURN_STRING(WDA_MIB_STATS_REQ);
CASE_RETURN_STRING(WDA_SET_MIB_STATS_ENABLE);
CASE_RETURN_STRING(WDA_SET_MIB_STATS_DISABLE);
+ CASE_RETURN_STRING(SIR_HAL_POWER_DEBUG_STATS_REQ);
default:
return((tANI_U8*) "UNKNOWN");
break;
diff --git a/Kbuild b/Kbuild
index a73c6ff6a926..be875499043e 100644
--- a/Kbuild
+++ b/Kbuild
@@ -72,6 +72,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 PMKSA patches, hence enabling this flag
CONFIG_PRIMA_WLAN_OKC := y
@@ -1019,6 +1024,10 @@ CDEFINES := -DANI_LITTLE_BYTE_ENDIAN \
-DWLAN_VOWIFI_DEBUG \
-DATH_SUPPORT_DFS
+ifeq ($(CONFIG_WLAN_POWER_DEBUGFS), y)
+CDEFINES += -DWLAN_POWER_DEBUGFS
+endif
+
ifeq ($(CONFIG_SCPC_FEATURE), y)
CDEFINES += -DWLAN_SCPC_FEATURE
endif