summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKabilan Kannan <kabilank@codeaurora.org>2016-12-02 18:49:38 -0800
committerqcabuildsw <qcabuildsw@localhost>2016-12-16 16:08:03 -0800
commitfac8ed2ccc96fc69aff225f8f7a2bd20a0db9dfc (patch)
treec39e8a09c8068261fb6511913d85364eebfc214c
parentadc3b1872a97d0832be2f55bcfa2efe13c301884 (diff)
qcacld-3.0: Add SAR power limit configuration
There is a regulatory requirement for Specific Absorption Rate (SAR) whereby the phone transmit power is reduced when it is determined that the phone is in close proximity to the body. Implement a vendor command interface to set SAR power limits dynamically. Change-Id: I137ce9bde2fa05e363d5af17e155dc739d862c5f CRs-Fixed: 1098102
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c279
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h125
-rw-r--r--core/sme/inc/sme_api.h10
-rw-r--r--core/sme/src/common/sme_api.c15
-rw-r--r--core/wma/inc/wma_api.h12
-rw-r--r--core/wma/src/wma_features.c24
6 files changed, 462 insertions, 3 deletions
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index f995def1716e..2228dba875fe 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -7932,6 +7932,276 @@ static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
return ret;
}
+/**
+ * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
+ * @nl80211_value: Vendor command attribute value
+ * @wmi_value: Pointer to return converted WMI return value
+ *
+ * Convert NL80211 vendor command value for SAR limit set to WMI value
+ * Return: 0 on success, -1 on invalid value
+ */
+static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
+ u32 *wmi_value)
+{
+ int ret = 0;
+
+ switch (nl80211_value) {
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
+ *wmi_value = WMI_SAR_FEATURE_OFF;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
+ *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
+ *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
+ *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
+ *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
+ *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
+ *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
+ * @nl80211_value: Vendor command attribute value
+ * @wmi_value: Pointer to return converted WMI return value
+ *
+ * Convert NL80211 vendor command value for SAR BAND to WMI value
+ * Return: 0 on success, -1 on invalid value
+ */
+static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
+{
+ int ret = 0;
+
+ switch (nl80211_value) {
+ case NL80211_BAND_2GHZ:
+ *wmi_value = WMI_SAR_2G_ID;
+ break;
+ case NL80211_BAND_5GHZ:
+ *wmi_value = WMI_SAR_5G_ID;
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
+ * @nl80211_value: Vendor command attribute value
+ * @wmi_value: Pointer to return converted WMI return value
+ *
+ * Convert NL80211 vendor command value for SAR Modulation to WMI value
+ * Return: 0 on success, -1 on invalid value
+ */
+static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
+ u32 *wmi_value)
+{
+ int ret = 0;
+
+ switch (nl80211_value) {
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
+ *wmi_value = WMI_SAR_MOD_CCK;
+ break;
+ case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
+ *wmi_value = WMI_SAR_MOD_OFDM;
+ break;
+ default:
+ ret = -1;
+ }
+ return ret;
+}
+
+
+/**
+ * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Length of @data
+ *
+ * This function is used to setup Specific Absorption Rate limit specs.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data, int data_len)
+{
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
+ *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
+ *sar_spec_list;
+ struct sar_limit_cmd_params sar_limit_cmd = {0};
+ int ret = -EINVAL, i = 0, rem = 0;
+
+ ENTER();
+
+ if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+ hdd_err("Command not allowed in FTM mode");
+ return -EPERM;
+ }
+
+ if (wlan_hdd_validate_context(hdd_ctx))
+ return -EINVAL;
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
+ data, data_len, NULL)) {
+ hdd_err("Invalid SAR attributes");
+ return -EINVAL;
+ }
+
+ /* Vendor command manadates all SAR Specs in single call */
+ sar_limit_cmd.commit_limits = 1;
+ sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
+ if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
+ if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
+ &sar_limit_cmd.sar_enable) < 0) {
+ hdd_err("Invalid SAR Enable attr");
+ goto fail;
+ }
+ }
+ hdd_info("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
+ sar_limit_cmd.num_limit_rows = nla_get_u32(
+ tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
+ hdd_info("attr sar num_limit_rows %d",
+ sar_limit_cmd.num_limit_rows);
+ }
+ if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
+ hdd_err("SAR Spec list exceed supported size");
+ goto fail;
+ }
+ if (sar_limit_cmd.num_limit_rows == 0)
+ goto send_sar_limits;
+ sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
+ struct sar_limit_cmd_row) *
+ sar_limit_cmd.num_limit_rows);
+ if (!sar_limit_cmd.sar_limit_row_list) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+ if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
+ hdd_err("Invalid SAR SPECs list");
+ goto fail;
+ }
+
+ nla_for_each_nested(sar_spec_list,
+ tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
+ if (i == sar_limit_cmd.num_limit_rows) {
+ hdd_warn("SAR Cmd has excess SPECs in list");
+ break;
+ }
+
+ if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
+ nla_data(sar_spec_list), nla_len(sar_spec_list),
+ NULL)) {
+ hdd_err("nla_parse failed for SAR Spec list");
+ goto fail;
+ }
+ sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
+ if (sar_spec[
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
+ sar_limit_cmd.sar_limit_row_list[i].limit_value =
+ nla_get_u32(sar_spec[
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
+ } else {
+ hdd_err("SAR Spec does not have power limit value");
+ goto fail;
+ }
+
+ if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
+ if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
+ sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
+ &sar_limit_cmd.sar_limit_row_list[i].band_id)
+ < 0) {
+ hdd_err("Invalid SAR Band attr");
+ goto fail;
+ }
+ sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
+ WMI_SAR_BAND_ID_VALID_MASK;
+ }
+ if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
+ sar_limit_cmd.sar_limit_row_list[i].chain_id =
+ nla_get_u32(sar_spec[
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
+ sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
+ WMI_SAR_CHAIN_ID_VALID_MASK;
+ }
+ if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
+ if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
+ sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
+ &sar_limit_cmd.sar_limit_row_list[i].mod_id)
+ < 0) {
+ hdd_err("Invalid SAR Modulation attr");
+ goto fail;
+ }
+ sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
+ WMI_SAR_MOD_ID_VALID_MASK;
+ }
+ hdd_info("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
+ i, sar_limit_cmd.sar_limit_row_list[i].band_id,
+ sar_limit_cmd.sar_limit_row_list[i].chain_id,
+ sar_limit_cmd.sar_limit_row_list[i].mod_id,
+ sar_limit_cmd.sar_limit_row_list[i].limit_value,
+ sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
+ i++;
+ }
+
+ if (i < sar_limit_cmd.num_limit_rows) {
+ hdd_warn("SAR Cmd has less SPECs in list");
+ sar_limit_cmd.num_limit_rows = i;
+ }
+
+send_sar_limits:
+ if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
+ QDF_STATUS_SUCCESS)
+ ret = 0;
+fail:
+ qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
+ return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
+ * @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_sar_power_limits()
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+ ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
+ data_len);
+ cds_ssr_unprotect(__func__);
+
+ return ret;
+}
+
static const struct
nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
@@ -8647,8 +8917,15 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
WIPHY_VENDOR_CMD_NEED_NETDEV |
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_configure_tdls_mode
- }
+ },
#endif
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_set_sar_power_limits
+ },
};
/**
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index a85133831842..b02a32527232 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -298,6 +298,10 @@ typedef enum {
* @QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS: Configure the TDLS behavior
* in the host driver. The different TDLS configurations are defined
* by the attributes in enum qca_wlan_vendor_attr_tdls_configuration.
+ * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS:Set the Specific Absorption Rate
+ * (SAR) power limits. A critical regulation for FCC compliance, OEMs
+ * require methods to set SAR limits on TX power of WLAN/WWAN.
+ * enum qca_vendor_attr_sar_limits attributes are used with this command.
*/
enum qca_nl80211_vendor_subcmds {
@@ -444,6 +448,9 @@ enum qca_nl80211_vendor_subcmds {
/* Configure the TDLS mode from user space */
QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS = 143,
+
+ /* Set Specific Absorption Rate(SAR) Power Limits */
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146,
};
/**
@@ -3148,6 +3155,124 @@ enum qca_wlan_vendor_tdls_trigger_mode {
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL = 1 << 2,
};
+/**
+ * enum qca_vendor_attr_sar_limits_selections - Source of SAR power limits
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0: Select SAR profile #0
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1: Select SAR profile #1
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2: Select SAR profile #2
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3: Select SAR profile #3
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4: Select SAR profile #4
+ * that is hard-coded in the Board Data File (BDF).
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE: Do not select any
+ * source of SAR power limits, thereby disabling the SAR power
+ * limit feature.
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER: Select the SAR power
+ * limits configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR.
+ *
+ * This enumerates the valid set of values that may be supplied for
+ * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT in an instance of
+ * the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command.
+ */
+enum qca_vendor_attr_sar_limits_selections {
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1 = 1,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2 = 2,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3 = 3,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4 = 4,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE = 5,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER = 6,
+};
+
+/**
+ * enum qca_vendor_attr_sar_limits_spec_modulations -
+ * SAR limits specification modulation
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK -
+ * CCK modulation
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM -
+ * OFDM modulation
+ *
+ * This enumerates the valid set of values that may be supplied for
+ * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION in an
+ * instance of attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC in an
+ * instance of the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor
+ * command.
+ */
+enum qca_vendor_attr_sar_limits_spec_modulations {
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM = 1,
+};
+
+/**
+ * enum qca_vendor_attr_sar_limits - Attributes for SAR power limits
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE: Optional (u32) value to
+ * select which SAR power limit table should be used. Valid
+ * values are enumerated in enum
+ * %qca_vendor_attr_sar_limits_selections. The existing SAR
+ * power limit selection is unchanged if this attribute is not
+ * present.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS: Optional (u32) value
+ * which specifies the number of SAR power limit specifications
+ * which will follow.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC: Nested array of SAR power
+ * limit specifications. The number of specifications is
+ * specified by @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS. Each
+ * specification contains a set of
+ * QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_* attributes. A
+ * specification is uniquely identified by the attributes
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND,
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN, and
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION and always
+ * contains as a payload the attribute
+ * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND: Optional (u32) value to
+ * indicate for which band this specification applies. Valid
+ * values are enumerated in enum %nl80211_band (although not all
+ * bands may be supported by a given device). If the attribute is
+ * not supplied then the specification will be applied to all
+ * supported bands.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN: Optional (u32) value
+ * to indicate for which antenna chain this specification
+ * applies, i.e. 1 for chain 1, 2 for chain 2, etc. If the
+ * attribute is not supplied then the specification will be
+ * applied to all chains.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION: Optional (u32)
+ * value to indicate for which modulation scheme this
+ * specification applies. Valid values are enumerated in enum
+ * %qca_vendor_attr_sar_limits_spec_modulations. If the attribute
+ * is not supplied then the specification will be applied to all
+ * modulation schemes.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT: Required (u32)
+ * value to specify the actual power limit value in steps of 0.5
+ * dbm.
+ *
+ * These attributes are used with %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS.
+ */
+enum qca_vendor_attr_sar_limits {
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE = 1,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS = 2,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC = 3,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND = 4,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN = 5,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION = 6,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT = 7,
+
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST - 1
+};
+
struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
tCsrRoamInfo *pRoamInfo);
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 121d5de9e537..1b8bdf4367f0 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1364,7 +1364,15 @@ QDF_STATUS sme_power_debug_stats_req(tHalHandle hal, void (*callback_fn)
(struct power_stats_response *response,
void *context), void *power_stats_context);
#endif
-
+/**
+ * sme_set_sar_power_limits() - set sar limits
+ * @hal: HAL handle
+ * @sar_limit_cmd: struct to send sar limit cmd.
+ *
+ * Return: QDF_STATUS enumeration.
+ */
+QDF_STATUS sme_set_sar_power_limits(tHalHandle hal,
+ struct sar_limit_cmd_params *sar_limit_cmd);
void sme_set_cc_src(tHalHandle hal_handle, enum country_src);
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index d746f633bc0f..ae67f667b5de 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -16856,6 +16856,21 @@ QDF_STATUS sme_set_default_scan_ie(tHalHandle hal, uint16_t session_id,
return status;
}
+QDF_STATUS sme_set_sar_power_limits(tHalHandle hal,
+ struct sar_limit_cmd_params *sar_limit_cmd)
+{
+ void *wma_handle;
+
+ wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
+ if (!wma_handle) {
+ QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+ "wma handle is NULL");
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ return wma_set_sar_limit(wma_handle, sar_limit_cmd);
+}
+
#ifdef WLAN_FEATURE_DISA
/**
* sme_encrypt_decrypt_msg() - handles encrypt/decrypt mesaage
diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h
index d6ca6d14e875..3b2e17495c35 100644
--- a/core/wma/inc/wma_api.h
+++ b/core/wma/inc/wma_api.h
@@ -325,7 +325,17 @@ QDF_STATUS wma_set_cts2self_for_p2p_go(void *wma_handle,
uint32_t cts2self_for_p2p_go);
QDF_STATUS wma_set_tx_rx_aggregation_size
(struct sir_set_tx_rx_aggregation_size *tx_rx_aggregation_size);
-
+/**
+ * wma_set_sar_limit() - set sar limits in the target
+ * @handle: wma handle
+ * @sar_limit_cmd_params: sar limit cmd params
+ *
+ * This function sends WMI command to set SAR limits.
+ *
+ * Return: QDF_STATUS enumeration
+ */
+QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle,
+ struct sar_limit_cmd_params *sar_limit_params);
/**
* wma_set_qpower_config() - update qpower config in wma
* @vdev_id: the Id of the vdev to configure
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index 5e63eb4d574a..231e757a4af6 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -8326,6 +8326,30 @@ QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val)
return QDF_STATUS_SUCCESS;
}
+QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle,
+ struct sar_limit_cmd_params *sar_limit_params)
+{
+ int ret;
+ tp_wma_handle wma = (tp_wma_handle) handle;
+
+ if (!wma || !wma->wmi_handle) {
+ WMA_LOGE("%s: WMA is closed, can not issue set sar limit msg",
+ __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ if (sar_limit_params == NULL) {
+ WMA_LOGE("%s: set sar limit ptr NULL",
+ __func__);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ ret = wmi_unified_send_sar_limit_cmd(wma->wmi_handle,
+ sar_limit_params);
+
+ return ret;
+}
+
#ifdef WLAN_FEATURE_DISA
/**
* wma_encrypt_decrypt_msg() -