diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 3a737ec779fc..27470f3ee0b4 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1883,7 +1883,9 @@ struct hdd_context { unsigned long derived_intf_addr_mask; struct sar_limit_cmd_params *sar_cmd_params; - +#ifdef SAR_SAFETY_FEATURE + qdf_mc_timer_t sar_safety_timer; +#endif qdf_time_t runtime_resume_start_time_stamp; qdf_time_t runtime_suspend_done_time_stamp; #if defined(CLD_PM_QOS) && \ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index a289e13180ce..63dce137a037 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -12102,6 +12102,8 @@ static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy, if (!sar_limit_cmd) return -ENOMEM; + wlan_hdd_sar_timers_reset(hdd_ctx); + /* is special SAR V1 => SAR V2 logic enabled and applicable? */ if (hdd_ctx->config->enable_sar_conversion && (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, sar_limit_cmd))) diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 1cc0375b7365..ec440b8fbfa1 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -177,6 +177,7 @@ #include "wlan_hdd_sta_info.h" #include "mac_init_api.h" #include "wlan_pkt_capture_ucfg_api.h" +#include #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -7910,6 +7911,8 @@ static int hdd_context_deinit(struct hdd_context *hdd_ctx) void hdd_context_destroy(struct hdd_context *hdd_ctx) { + wlan_hdd_sar_timers_deinit(hdd_ctx); + cds_set_context(QDF_MODULE_ID_HDD, NULL); hdd_exit_netlink_services(hdd_ctx); @@ -10650,6 +10653,8 @@ skip_multicast_logging: cds_set_context(QDF_MODULE_ID_HDD, hdd_ctx); + wlan_hdd_sar_timers_init(hdd_ctx); + hdd_exit(); return hdd_ctx; diff --git a/core/hdd/src/wlan_hdd_sar_limits.c b/core/hdd/src/wlan_hdd_sar_limits.c index bb94ec6b88cd..0e98a1288b74 100644 --- a/core/hdd/src/wlan_hdd_sar_limits.c +++ b/core/hdd/src/wlan_hdd_sar_limits.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -324,3 +324,109 @@ int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy, return errno; } +#ifdef SAR_SAFETY_FEATURE +void hdd_configure_sar_index(struct hdd_context *hdd_ctx, uint32_t sar_index) +{ + struct sar_limit_cmd_params *sar_limit_cmd; + struct sar_limit_cmd_row *row; + QDF_STATUS status; + + sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params)); + if (!sar_limit_cmd) + return; + + if (hdd_ctx->sar_version != SAR_VERSION_2) { + hdd_nofl_debug("FW SAR version: %d", hdd_ctx->sar_version); + return; + } + + /* + * Need two rows to hold the per-chain V2 power index + */ + row = qdf_mem_malloc(2 * sizeof(*row)); + if (!row) + goto config_sar_failed; + + sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_ON_SAR_V2_0; + sar_limit_cmd->commit_limits = 1; + sar_limit_cmd->num_limit_rows = 2; + sar_limit_cmd->sar_limit_row_list = row; + row[0].limit_value = sar_index; + row[1].limit_value = sar_index; + row[0].chain_id = 0; + row[1].chain_id = 1; + row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK; + row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK; + + hdd_nofl_debug("Configure POW_Limit Index: %d for both the chains", + row->limit_value); + + status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_nofl_err("Failed to set sar power limits"); + goto config_sar_failed; + } + + /* + * After SSR, the SAR configuration is lost. As SSR is hidden from + * userland, this command will not come from userspace after a SSR. To + * restore this configuration, save this in hdd context and restore + * after re-init. + */ + hdd_store_sar_config(hdd_ctx, sar_limit_cmd); + return; + +config_sar_failed: + + if (sar_limit_cmd) { + qdf_mem_free(sar_limit_cmd->sar_limit_row_list); + qdf_mem_free(sar_limit_cmd); + } +} + +static void hdd_sar_safety_timer_cb(void *user_data) +{ + struct hdd_context *hdd_ctx = (struct hdd_context *)user_data; + + hdd_nofl_debug("Sar safety timer expires"); + hdd_configure_sar_index(hdd_ctx, hdd_ctx->config->sar_safety_index); +} + +void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx) +{ + if (!hdd_ctx->config->enable_sar_safety) + return; + + if (hdd_ctx->sar_version != SAR_VERSION_2) + return; + + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer)) + qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer); + + qdf_mc_timer_start(&hdd_ctx->sar_safety_timer, + hdd_ctx->config->sar_safety_timeout); +} + +void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx) +{ + if (!hdd_ctx->config->enable_sar_safety) + return; + + qdf_mc_timer_init(&hdd_ctx->sar_safety_timer, QDF_TIMER_TYPE_SW, + hdd_sar_safety_timer_cb, hdd_ctx); +} + +void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx) +{ + if (!hdd_ctx->config->enable_sar_safety) + return; + + if (QDF_TIMER_STATE_RUNNING == + qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer)) + qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer); + + qdf_mc_timer_destroy(&hdd_ctx->sar_safety_timer); +} +#endif + diff --git a/core/hdd/src/wlan_hdd_sar_limits.h b/core/hdd/src/wlan_hdd_sar_limits.h index 2a49a46ef853..9777a1a2c84e 100644 --- a/core/hdd/src/wlan_hdd_sar_limits.h +++ b/core/hdd/src/wlan_hdd_sar_limits.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -26,6 +26,70 @@ */ #ifdef FEATURE_SAR_LIMITS + +#ifdef SAR_SAFETY_FEATURE + +/** + * wlan_hdd_sar_safety_timer_reset() - Reset SAR sefety timer + * @hdd_ctx: Pointer to HDD context + * + * This function checks the state of the sar safety timer, if the + * sar_safety_timer is not runnig, it starts the timer else it stops + * the timer and start the timer again. + * + * Return: None + */ +void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx); + +/** + * wlan_hdd_sar_timers_init() - Initialize SAR timers + * @hdd_ctx: Pointer to HDD context + * + * This function initializes sar timers. + * Return: None + */ +void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx); + +/** + * wlan_hdd_sar_timers_deinit() - De-initialize SAR timers + * @hdd_ctx: Pointer to HDD context + * + * This function de-initializes sar timers. + * Return: None + */ +void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx); + +/** + * hdd_configure_sar_index() - configures SAR index to the FW + * @hdd_ctx: Pointer to HDD context + * @sar_index: sar index which needs to be configured to FW + * + * This function configures SAR power index on both the chains + * for SAR version2 + * + * Return: None + */ +void hdd_configure_sar_index(struct hdd_context *hdd_ctx, uint32_t sar_index); + +#else +static inline void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx) +{ +} + +static inline void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx) +{ +} + +static inline void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx) +{ +} + +static inline void hdd_configure_sar_index(struct hdd_context *hdd_ctx, + uint32_t sar_index) +{ +} +#endif + /** * wlan_hdd_cfg80211_get_sar_power_limits() - Get SAR power limits * @wiphy: Pointer to wireless phy