From 97de5e6d0becafc9cd2e8cae47e6e3b97c54617f Mon Sep 17 00:00:00 2001 From: Ashish Kumar Dhanotiya Date: Fri, 17 Jan 2020 21:15:26 +0530 Subject: [PATCH] qcacld-3.0: Add SAR safety Timer Add SAR safety timer to the driver. This timer starts when first QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command is recived. This timer gets reset on every sar set vendor command. When this timer expires, configure sar safety index to the FW and restart the timer. Change-Id: I0536ab88baf962e1bc2aef39478380534e0e1401 CRs-Fixed: 2615442 --- core/hdd/inc/wlan_hdd_main.h | 4 +- core/hdd/src/wlan_hdd_cfg80211.c | 2 + core/hdd/src/wlan_hdd_main.c | 5 ++ core/hdd/src/wlan_hdd_sar_limits.c | 108 ++++++++++++++++++++++++++++- core/hdd/src/wlan_hdd_sar_limits.h | 66 +++++++++++++++++- 5 files changed, 182 insertions(+), 3 deletions(-) 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