From 53c2f693ab59ad8fe5bc642b3dd3d960b4c3c970 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Wed, 8 Feb 2017 00:25:11 +0530 Subject: [PATCH] qcacld-3.0: Add Vendor command for QDF Debug Framework There is no vendor command support for QDF Debug Framework. Add vendor command support to dynamically update the trace levels for modules. Change-Id: I807365ec035d75372d4ff0f1ea27ba6f7bbff62d CRs-Fixed: 2003455 --- core/hdd/inc/wlan_hdd_main.h | 2 + core/hdd/src/wlan_hdd_cfg80211.c | 129 +++++++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_cfg80211.h | 27 +++++++ core/hdd/src/wlan_hdd_main.c | 15 ++-- 4 files changed, 166 insertions(+), 7 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 7268d5ea1eac..736cc1ac953a 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1740,6 +1740,8 @@ static inline void hdd_bus_bandwidth_destroy(hdd_context_t *hdd_ctx) } #endif +int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask); + int hdd_init(void); void hdd_deinit(void); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 5e7f8e78bfdd..9380060d288d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8409,6 +8409,126 @@ static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy, return ret; } +static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[ + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED }, + [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 }, +}; + +/** + * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1]; + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1]; + struct nlattr *apth; + int rem; + int ret = 1; + int print_idx = -1; + int module_id = -1; + int bit_mask = -1; + int status; + + ENTER(); + + if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) { + hdd_err("Command not allowed in FTM mode"); + return -EINVAL; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) + return -EINVAL; + + print_idx = qdf_get_pidx(); + if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) { + hdd_err("Invalid print controle object index"); + return -EINVAL; + } + + if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data, + data_len, qca_wlan_vendor_set_trace_level_policy)) { + hdd_err("Invalid attr"); + return -EINVAL; + } + + if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) { + hdd_err("attr trace level param failed"); + return -EINVAL; + } + + nla_for_each_nested(apth, + tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) { + if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, + nla_data(apth), nla_len(apth), NULL)) { + hdd_err("Invalid attr"); + return -EINVAL; + } + + if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) { + hdd_err("attr Module ID failed"); + return -EINVAL; + } + module_id = nla_get_u32 + (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]); + + if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) { + hdd_err("attr Verbose mask failed"); + return -EINVAL; + } + bit_mask = nla_get_u32 + (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]); + + status = hdd_qdf_trace_enable(module_id, bit_mask); + + if (status != 0) + hdd_err("can not set verbose mask %d for the category %d", + bit_mask, module_id); + } + + EXIT(); + return ret; +} + +/** + * wlan_hdd_cfg80211_set_trace_level() - Set the trace level + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * Wrapper function of __wlan_hdd_cfg80211_set_trace_level() + * + * Return: 0 on success, negative errno on failure + */ + +static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, + int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -9048,6 +9168,15 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_set_sar_power_limits }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_trace_level + }, + #ifdef WLAN_UMAC_CONVERGENCE COMMON_VENDOR_COMMANDS #endif diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 9b7ce0d1218f..7a24d23f09f7 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -455,6 +455,33 @@ enum qca_nl80211_vendor_subcmds { /* Set Specific Absorption Rate(SAR) Power Limits */ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146, + /* Set the trace level for QDF */ + QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL = 152, +}; + +/** + * enum qca_vendor_attr_set_trace_level - Config params for QDF set trace level + * @QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_INVALID: Invalid trace level + * @QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM : Trace level parameters + * @QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID : Module of which trace + level needs to be updated. + * @QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK : verbose mask, which need + * to be set. + * @QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_AFTER_LAST : after last. + * @QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX : Max attribute. + */ +enum qca_vendor_attr_set_trace_level { + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_INVALID = 0, + /* + * Array of QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM + * attributes. + */ + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM = 1, + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID = 2, + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK = 3, + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX = + QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_AFTER_LAST - 1, }; /** diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index be74285962d0..9cdbb1123a0b 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -522,7 +522,7 @@ uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, /** * hdd_qdf_trace_enable() - configure initial QDF Trace enable - * @moduleId: Module whose trace level is being configured + * @module_id: Module whose trace level is being configured * @bitmask: Bitmask of log levels to be enabled * * Called immediately after the cfg.ini is read in order to configure @@ -530,7 +530,7 @@ uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, * * Return: None */ -static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask) +int hdd_qdf_trace_enable(QDF_MODULE_ID module_id, uint32_t bitmask) { QDF_TRACE_LEVEL level; int qdf_print_idx = -1; @@ -541,29 +541,30 @@ static void hdd_qdf_trace_enable(QDF_MODULE_ID moduleId, uint32_t bitmask) * will remain at the "compiled in" default value) */ if (CFG_QDF_TRACE_ENABLE_DEFAULT == bitmask) { - return; + return 0; } qdf_print_idx = qdf_get_pidx(); /* a mask was specified. start by disabling all logging */ - status = qdf_print_set_category_verbose(qdf_print_idx, moduleId, + status = qdf_print_set_category_verbose(qdf_print_idx, module_id, QDF_TRACE_LEVEL_NONE, 0); if (QDF_STATUS_SUCCESS != status) - return; + return -EINVAL; /* now cycle through the bitmask until all "set" bits are serviced */ level = QDF_TRACE_LEVEL_FATAL; while (0 != bitmask) { if (bitmask & 1) { status = qdf_print_set_category_verbose(qdf_print_idx, - moduleId, level, 1); + module_id, level, 1); if (QDF_STATUS_SUCCESS != status) - return; + return -EINVAL; } level++; bitmask >>= 1; } + return 0; } /**