From 8f88538e87abdd6d964458a197059850c75501b4 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Mon, 12 Oct 2015 17:11:14 +0530 Subject: [PATCH] qcacld-3.0: Add FW Profiling support Add Profiling stats support in HOST driver to have CPU based profiling for critical data path functions in FW. Change-Id: Ib6d4f0b220f622cf304536c8e538d4dc34c6434b CRs-Fixed: 921950 --- core/hdd/inc/qc_sap_ioctl.h | 5 ++ core/hdd/inc/wlan_hdd_wext.h | 2 + core/hdd/src/wlan_hdd_hostapd.c | 95 +++++++++++++++++++---- core/hdd/src/wlan_hdd_wext.c | 108 ++++++++++++++++++++++++-- core/wma/inc/wma.h | 22 ++++++ core/wma/inc/wma_internal.h | 6 ++ core/wma/src/wma_features.c | 131 ++++++++++++++++++++++++++++++++ core/wma/src/wma_main.c | 50 ++++++++++++ core/wma/src/wma_utils.c | 72 ++++++++++++++++++ 9 files changed, 471 insertions(+), 20 deletions(-) diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h index 5fee04fcc6e3..6983a7a96ff1 100644 --- a/core/hdd/inc/qc_sap_ioctl.h +++ b/core/hdd/inc/qc_sap_ioctl.h @@ -147,6 +147,7 @@ typedef struct { /* Private ioctls and their sub-ioctls */ #define QCSAP_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 13) #define QCSAP_GET_STATS 1 +#define QCSAP_LIST_FW_PROFILE 2 #define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV+14) #define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV+15) @@ -171,6 +172,8 @@ typedef struct { #define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1 #endif #define QCSAP_IOCTL_DUMP_DP_TRACE_LEVEL 2 +#define QCSAP_ENABLE_FW_PROFILE 3 +#define QCSAP_SET_FW_PROFILE_HIST_INTVL 4 #define MAX_VAR_ARGS 7 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31) @@ -237,6 +240,8 @@ enum { QCASAP_DUMP_STATS, QCASAP_CLEAR_STATS, QCASAP_SET_RADAR_DBG, + QCSAP_GET_FW_PROFILE_DATA, + QCSAP_START_FW_PROFILING }; int iw_softap_get_channel_list(struct net_device *dev, diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 1f78e4916586..7bb8606eeac1 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -306,6 +306,8 @@ extern void hdd_wlan_get_version(hdd_adapter_t *pAdapter, extern void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, char *buffer, uint16_t buf_len); +extern void hdd_wlan_list_fw_profile(uint16_t *length, + char *buffer, uint16_t buf_len); extern int iw_set_essid(struct net_device *dev, struct iw_request_info *info, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index c5b595569446..ed0119529662 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2032,29 +2032,36 @@ static iw_softap_get_ini_cfg(struct net_device *dev, return ret; } +/** + * iw_softap_set_two_ints_getnone() - Generic "set two integer" ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_context_t *pHddCtx; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + int ret; int *value = (int *)extra; int sub_cmd = value[0]; - int ret = 0; + hdd_context_t *hdd_ctx; - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ret = wlan_hdd_validate_context(pHddCtx); - if (ret != 0) { - hddLog(LOGE, FL("HDD context is not valid!")); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) goto out; - } switch (sub_cmd) { #ifdef DEBUG case QCSAP_IOCTL_SET_FW_CRASH_INJECT: hddLog(LOGE, "WE_SET_FW_CRASH_INJECT: %d %d", value[1], value[2]); - ret = wma_cli_set2_command(pAdapter->sessionId, + ret = wma_cli_set2_command(adapter->sessionId, GEN_PARAM_CRASH_INJECT, value[1], value[2], GEN_CMD); @@ -2066,6 +2073,19 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, if (value[1] == DUMP_DP_TRACE) cdf_dp_trace_dump_all(value[2]); break; + case QCSAP_ENABLE_FW_PROFILE: + hddLog(LOG1, "QCSAP_ENABLE_FW_PROFILE: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(adapter->sessionId, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + value[1], value[2], DBG_CMD); + break; + case QCSAP_SET_FW_PROFILE_HIST_INTVL: + hddLog(LOG1, "QCSAP_SET_FW_PROFILE_HIST_INTVL: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(adapter->sessionId, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + value[1], value[2], DBG_CMD); default: hddLog(LOGE, FL("Invalid IOCTL command %d"), sub_cmd); break; @@ -2793,6 +2813,12 @@ static __iw_softap_setparam(struct net_device *dev, } break; } + case QCSAP_START_FW_PROFILING: + hddLog(LOG1, "QCSAP_START_FW_PROFILING %d", set_value); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_WLAN_PROFILE_TRIGGER_CMDID, + set_value, DBG_CMD); + break; default: hddLog(LOGE, FL("Invalid setparam command %d value %d"), sub_cmd, set_value); @@ -3007,6 +3033,12 @@ static __iw_softap_getparam(struct net_device *dev, ret = wlan_hdd_get_temperature(pHostapdAdapter, value); break; } + case QCSAP_GET_FW_PROFILE_DATA: + hddLog(LOG1, "QCSAP_GET_FW_PROFILE_DATA"); + ret = wma_cli_set_command(pHostapdAdapter->sessionId, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + 0, DBG_CMD); + break; default: hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd); ret = -EINVAL; @@ -3415,31 +3447,44 @@ static iw_softap_disassoc_sta(struct net_device *dev, return ret; } +/** + * iw_get_char_setnone() - Generic "get char" private ioctl handler + * @dev: device upon which the ioctl was received + * @info: ioctl request information + * @wrqu: ioctl request data + * @extra: ioctl extra data + * + * Return: 0 on success, non-zero on error + */ static int __iw_get_char_setnone(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - CDF_STATUS status; + int ret; int sub_cmd = wrqu->data.flags; hdd_context_t *hdd_ctx; ENTER(); hdd_ctx = WLAN_HDD_GET_CTX(adapter); - status = wlan_hdd_validate_context(hdd_ctx); - if (status != 0) - return status; + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) + return ret; switch (sub_cmd) { case QCSAP_GET_STATS: hdd_wlan_get_stats(adapter, &(wrqu->data.length), extra, WE_MAX_STR_LEN); break; + case QCSAP_LIST_FW_PROFILE: + hdd_wlan_list_fw_profile(&(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; } EXIT(); - return status; + return ret; } static int iw_get_char_setnone(struct net_device *dev, @@ -5464,6 +5509,10 @@ static const struct iw_priv_args hostapd_private_args[] = { QCASAP_CLEAR_STATS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "clearStats" + }, { + QCSAP_START_FW_PROFILING, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "startProfile" }, { QCSAP_IOCTL_GETPARAM, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam" @@ -5529,6 +5578,9 @@ static const struct iw_priv_args hostapd_private_args[] = { }, { QCASAP_GET_TEMP_CMD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_temp" + }, { + QCSAP_GET_FW_PROFILE_DATA, 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getProfileData" }, { QCSAP_IOCTL_GET_STAWPAIE, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, @@ -5571,6 +5623,10 @@ static const struct iw_priv_args hostapd_private_args[] = { QCSAP_GET_STATS, 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats" } + , { + QCSAP_LIST_FW_PROFILE, 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "listProfile" + } , { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, @@ -5677,6 +5733,17 @@ static const struct iw_priv_args hostapd_private_args[] = { 0, "dump_dp_trace" } , + { + QCSAP_ENABLE_FW_PROFILE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "enableProfile" + } + , + { + QCSAP_SET_FW_PROFILE_HIST_INTVL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_hist_intvl" + } }; static const iw_handler hostapd_private[] = { diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 4e68ecb6c9bd..047131f20456 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -213,6 +213,8 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_SET_CTS_CBW 84 #define WE_DUMP_STATS 85 #define WE_CLEAR_STATS 86 +/* Private sub ioctl for starting/stopping the profiling */ +#define WE_START_FW_PROFILE 87 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) @@ -314,6 +316,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_GET_OEM_DATA_CAP 13 #endif #define WE_GET_SNR 14 +#define WE_LIST_FW_PROFILE 15 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) @@ -328,6 +331,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_DUMP_PCIE_LOG 16 #endif #define WE_GET_RECOVERY_STAT 17 +#define WE_GET_FW_PROFILE_DATA 18 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 7) @@ -424,6 +428,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #endif #define WE_DUMP_DP_TRACE_LEVEL 3 #define DUMP_DP_TRACE 0 +/* Private sub ioctl for enabling and setting histogram interval of profiling */ +#define WE_ENABLE_FW_PROFILE 4 +#define WE_SET_FW_PROFILE_HIST_INTVL 5 /* (SIOCIWFIRSTPRIV + 29) is currently unused */ @@ -647,6 +654,41 @@ void hdd_wlan_get_stats(hdd_adapter_t *pAdapter, uint16_t *length, *length = len + 1; } +/** + * hdd_wlan_list_fw_profile() - Get fw profiling points + * @length: Size of the data copied + * @buffer: Pointer to char buffer. + * @buf_len: Length of the char buffer. + * + * This function called when the "iwpriv wlan0 listProfile" command is given. + * It is used to get the supported profiling points in FW. + * + * Return - none + */ +void hdd_wlan_list_fw_profile(uint16_t *length, + char *buffer, uint16_t buf_len) +{ + uint32_t len = 0; + + len = scnprintf(buffer, buf_len, + "PROF_CPU_IDLE: %u\n" + "PROF_PPDU_PROC: %u\n" + "PROF_PPDU_POST: %u\n" + "PROF_HTT_TX_INPUT: %u\n" + "PROF_MSDU_ENQ: %u\n" + "PROF_PPDU_POST_HAL: %u\n" + "PROF_COMPUTE_TX_TIME: %u\n", + PROF_CPU_IDLE, + PROF_PPDU_PROC, + PROF_PPDU_POST, + PROF_HTT_TX_INPUT, + PROF_MSDU_ENQ, + PROF_PPDU_POST_HAL, + PROF_COMPUTE_TX_TIME); + + *length = len + 1; +} + /** * hdd_wlan_dump_stats() - display dump Stats * @adapter: adapter handle @@ -6072,6 +6114,14 @@ static int __iw_setint_getnone(struct net_device *dev, sme_set_scan_disable(WLAN_HDD_GET_HAL_CTX(pAdapter), set_value); break; } + case WE_START_FW_PROFILE: + { + hddLog(LOG1, "WE_START_FW_PROFILE %d", set_value); + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_TRIGGER_CMDID, + set_value, DBG_CMD); + break; + } default: { hddLog(LOGE, "%s: Invalid sub command %d", __func__, @@ -6896,6 +6946,11 @@ static int __iw_get_char_setnone(struct net_device *dev, break; } + case WE_LIST_FW_PROFILE: + hdd_wlan_list_fw_profile(&(wrqu->data.length), + extra, WE_MAX_STR_LEN); + break; + /* The case prints the current state of the HDD, SME, CSR, PE, * TL it can be extended for WDI Global State as well. And * currently it only checks P2P_CLIENT adapter. P2P_DEVICE @@ -7409,6 +7464,12 @@ static int __iw_setnone_getnone(struct net_device *dev, break; } + case WE_GET_FW_PROFILE_DATA: + ret = wma_cli_set_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + 0, DBG_CMD); + break; + case WE_SET_REASSOC_TRIGGER: { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -9431,6 +9492,20 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, value[1], value[2], GEN_CMD); break; #endif + case WE_ENABLE_FW_PROFILE: + hddLog(LOGE, "WE_ENABLE_FW_PROFILE: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + value[1], value[2], DBG_CMD); + break; + case WE_SET_FW_PROFILE_HIST_INTVL: + hddLog(LOGE, "WE_SET_FW_PROFILE_HIST_INTVL: %d %d", + value[1], value[2]); + ret = wma_cli_set2_command(pAdapter->sessionId, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + value[1], value[2], DBG_CMD); + break; case WE_SET_DUAL_MAC_FW_MODE_CONFIG: hdd_debug("Ioctl to set dual fw mode config"); if (hdd_ctx->config->dual_mac_feature_disable) { @@ -9986,6 +10061,10 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "clearStats"}, + {WE_START_FW_PROFILE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "startProfile"}, + {WLAN_PRIV_SET_NONE_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -10322,6 +10401,10 @@ static const struct iw_priv_args we_private_args[] = { 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, "getStats"}, + {WE_LIST_FW_PROFILE, + 0, + IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, + "listProfile"}, {WE_GET_STATES, 0, IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN, @@ -10388,12 +10471,17 @@ static const struct iw_priv_args we_private_args[] = { 0, 0, "getRecoverStat"}, - { - WE_SET_REASSOC_TRIGGER, - 0, - 0, - "reassoc" - }, + + {WE_GET_FW_PROFILE_DATA, + 0, + 0, + "getProfileData"}, + + {WE_SET_REASSOC_TRIGGER, + 0, + 0, + "reassoc"}, + {WE_DUMP_AGC_START, 0, 0, @@ -10608,6 +10696,14 @@ static const struct iw_priv_args we_private_args[] = { 0, "crash_inject"} , #endif + {WE_ENABLE_FW_PROFILE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "enableProfile"} + , + {WE_SET_FW_PROFILE_HIST_INTVL, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "set_hist_intvl"} + , {WE_SET_DUAL_MAC_FW_MODE_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_fw_mode_cfg"} diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index f15e51819f09..b72d9fc433d1 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1630,6 +1630,28 @@ enum uapsd_peer_param_enabled_ac { UAPSD_BE_ENABLED = 0x08 }; +/** + * enum profile_id_t - Firmware profiling index + * @PROF_CPU_IDLE: cpu idle profile + * @PROF_PPDU_PROC: ppdu processing profile + * @PROF_PPDU_POST: ppdu post profile + * @PROF_HTT_TX_INPUT: htt tx input profile + * @PROF_MSDU_ENQ: msdu enqueue profile + * @PROF_PPDU_POST_HAL: ppdu post profile + * @PROF_COMPUTE_TX_TIME: tx time profile + * @PROF_MAX_ID: max profile index + */ +enum profile_id_t { + PROF_CPU_IDLE, + PROF_PPDU_PROC, + PROF_PPDU_POST, + PROF_HTT_TX_INPUT, + PROF_MSDU_ENQ, + PROF_PPDU_POST_HAL, + PROF_COMPUTE_TX_TIME, + PROF_MAX_ID, +}; + /** * struct p2p_ie - P2P IE structural definition. * @p2p_id: p2p id diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index c455e12b77a8..d927a7613984 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -868,6 +868,12 @@ int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, uint32_t value); #endif +int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, + uint32_t len); + +int32_t wmi_unified_fw_profiling_cmd(wmi_unified_t wmi_handle, + uint32_t cmd, uint32_t value1, uint32_t value2); + void wma_wow_tx_complete(void *wma); int wmi_unified_nat_keepalive_enable(tp_wma_handle wma, uint8_t vdev_id); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index d7f54aada7d5..c1e7df5054bc 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1025,6 +1025,137 @@ int32_t wmi_unified_pdev_green_ap_ps_enable_cmd(wmi_unified_t wmi_handle, } #endif /* FEATURE_GREEN_AP */ +/** + * wmi_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW + * @wma: wma handle + * @cmd: Profiling command index + * @value1: parameter1 value + * @value2: parameter2 value + * + * Return: 0 for success else error code + */ +int32_t wmi_unified_fw_profiling_cmd(wmi_unified_t wmi_handle, + uint32_t cmd, uint32_t value1, uint32_t value2) +{ + wmi_buf_t buf; + int32_t len = 0; + int ret; + wmi_wlan_profile_trigger_cmd_fixed_param *prof_trig_cmd; + wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *hist_intvl_cmd; + wmi_wlan_profile_enable_profile_id_cmd_fixed_param *profile_enable_cmd; + wmi_wlan_profile_get_prof_data_cmd_fixed_param *profile_getdata_cmd; + + switch (cmd) { + case WMI_WLAN_PROFILE_TRIGGER_CMDID: + len = sizeof(wmi_wlan_profile_trigger_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + prof_trig_cmd = + (wmi_wlan_profile_trigger_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&prof_trig_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_trigger_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_trigger_cmd_fixed_param)); + prof_trig_cmd->enable = value1; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_TRIGGER_CMDID); + if (ret) { + WMA_LOGE("PROFILE_TRIGGER cmd Failed with value %d", + value1); + cdf_nbuf_free(buf); + return ret; + } + break; + + case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID: + len = sizeof(wmi_wlan_profile_get_prof_data_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + profile_getdata_cmd = + (wmi_wlan_profile_get_prof_data_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&profile_getdata_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_get_prof_data_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_get_prof_data_cmd_fixed_param)); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID); + if (ret) { + WMA_LOGE("PROFILE_DATA cmd Failed for id %d value %d", + value1, value2); + cdf_nbuf_free(buf); + return ret; + } + break; + + case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID: + len = sizeof(wmi_wlan_profile_set_hist_intvl_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + hist_intvl_cmd = + (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&hist_intvl_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_set_hist_intvl_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_set_hist_intvl_cmd_fixed_param)); + hist_intvl_cmd->profile_id = value1; + hist_intvl_cmd->value = value2; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID); + if (ret) { + WMA_LOGE("HIST_INTVL cmd Failed for id %d value %d", + value1, value2); + cdf_nbuf_free(buf); + return ret; + } + break; + + case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID: + len = + sizeof(wmi_wlan_profile_enable_profile_id_cmd_fixed_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: wmi_buf_alloc Failed", __func__); + return -ENOMEM; + } + profile_enable_cmd = + (wmi_wlan_profile_enable_profile_id_cmd_fixed_param *) + wmi_buf_data(buf); + WMITLV_SET_HDR(&profile_enable_cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_wlan_profile_enable_profile_id_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_wlan_profile_enable_profile_id_cmd_fixed_param)); + profile_enable_cmd->profile_id = value1; + profile_enable_cmd->enable = value2; + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID); + if (ret) { + WMA_LOGE("enable cmd Failed for id %d value %d", + value1, value2); + cdf_nbuf_free(buf); + return ret; + } + break; + + default: + WMA_LOGD("%s: invalid profiling command", __func__); + break; + } + + return 0; +} + #ifdef FEATURE_WLAN_LPHB /** * wma_lphb_handler() - send LPHB indication to SME diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index c2eafde3feaa..e9c6bd96bc47 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -955,6 +955,52 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, WMA_LOGE("dbglog_report_enable failed ret %d", ret); break; + case WMI_WLAN_PROFILE_TRIGGER_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_TRIGGER_CMDID, + privcmd->param_value, 0); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_TRIGGER_CMDID, ret); + break; + case WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + privcmd->param_value, + privcmd->param_sec_value); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, + ret); + break; + case WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + privcmd->param_value, + privcmd->param_sec_value); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_SET_HIST_INTVL_CMDID, + ret); + break; + case WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, + 0, 0); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, + ret); + break; + case WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID: + ret = wmi_unified_fw_profiling_cmd(wma->wmi_handle, + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + 0, 0); + if (ret) + WMA_LOGE("Profile cmd failed for %d ret %d", + WMI_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, + ret); + break; #ifdef FEATURE_GREEN_AP case WMI_PDEV_GREEN_AP_PS_ENABLE_CMDID: /* Set the Green AP */ @@ -1640,6 +1686,10 @@ CDF_STATUS wma_open(void *cds_context, wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_DEBUG_PRINT_EVENTID, wma_unified_debug_print_event_handler); + /* Register profiling event Handler */ + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_WLAN_PROFILE_DATA_EVENTID, + wma_profile_data_report_event_handler); wma_handle->tgt_cfg_update_cb = tgt_cfg_cb; wma_handle->dfs_radar_indication_cb = radar_ind_cb; diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index fd34f803a920..a8f81d5ece69 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -381,6 +381,78 @@ int wma_stats_ext_event_handler(void *handle, uint8_t *event_buf, } #endif /* WLAN_FEATURE_STATS_EXT */ +/** + * wma_profile_data_report_event_handler() - fw profiling handler + * @handle: wma handle + * @event_buf: event buffer received from fw + * @len: length of data + * + * Return: 0 for success or error code + */ +int wma_profile_data_report_event_handler(void *handle, uint8_t *event_buf, + uint32_t len) +{ + WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *param_buf; + wmi_wlan_profile_ctx_t *profile_ctx; + wmi_wlan_profile_t *profile_data; + uint32_t i = 0; + uint32_t entries; + uint8_t *buf_ptr; + param_buf = (WMI_WLAN_PROFILE_DATA_EVENTID_param_tlvs *) event_buf; + + if (!param_buf) { + WMA_LOGE("%s: Invalid profile data event buf", __func__); + return -EINVAL; + } + profile_ctx = param_buf->profile_ctx; + buf_ptr = (uint8_t *)profile_ctx; + buf_ptr = buf_ptr + sizeof(wmi_wlan_profile_ctx_t) + WMI_TLV_HDR_SIZE; + profile_data = (wmi_wlan_profile_t *) buf_ptr; + entries = profile_ctx->bin_count; + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Profile data stats\n"); + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "TOT: %d\n" + "tx_msdu_cnt: %d\n" + "tx_mpdu_cnt: %d\n" + "tx_ppdu_cnt: %d\n" + "rx_msdu_cnt: %d\n" + "rx_mpdu_cnt: %d\n" + "bin_count: %d\n", + profile_ctx->tot, + profile_ctx->tx_msdu_cnt, + profile_ctx->tx_mpdu_cnt, + profile_ctx->tx_ppdu_cnt, + profile_ctx->rx_msdu_cnt, + profile_ctx->rx_mpdu_cnt, + profile_ctx->bin_count); + + for (i = 0; i < entries; i++) { + if (i == WMI_WLAN_PROFILE_MAX_BIN_CNT) + break; + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR, + "Profile ID: %d\n" + "Profile Count: %d\n" + "Profile TOT: %d\n" + "Profile Min: %d\n" + "Profile Max: %d\n" + "Profile hist_intvl: %d\n" + "Profile hist[0]: %d\n" + "Profile hist[1]: %d\n" + "Profile hist[2]: %d\n", + profile_data[i].id, + profile_data[i].cnt, + profile_data[i].tot, + profile_data[i].min, + profile_data[i].max, + profile_data[i].hist_intvl, + profile_data[i].hist[0], + profile_data[i].hist[1], + profile_data[i].hist[2]); + } + + return 0; +} #ifdef WLAN_FEATURE_LINK_LAYER_STATS