Browse Source

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
Ashish Kumar Dhanotiya 5 years ago
parent
commit
97de5e6d0b

+ 3 - 1
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) && \

+ 2 - 0
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)))

+ 5 - 0
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 <wlan_hdd_sar_limits.h>
 
 #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;

+ 107 - 1
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
+

+ 65 - 1
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