1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_hdd_vendor_sar_limits.c
22  *
23  * WLAN SAR limits functions
24  *
25  */
26 
27 #include "osif_sync.h"
28 #include <wlan_hdd_includes.h>
29 #include <linux/netdevice.h>
30 #include <linux/skbuff.h>
31 #include <linux/etherdevice.h>
32 #include <linux/if_ether.h>
33 #include <wlan_osif_request_manager.h>
34 #include <wlan_hdd_sar_limits.h>
35 
36 #define WLAN_WAIT_TIME_SAR 5000
37 /**
38  * struct hdd_sar_context - hdd sar context
39  * @event: sar limit event
40  */
41 struct hdd_sar_context {
42 	struct sar_limit_event event;
43 };
44 
hdd_sar_wmi_to_nl_enable(uint32_t wmi_value)45 static u32 hdd_sar_wmi_to_nl_enable(uint32_t wmi_value)
46 {
47 	switch (wmi_value) {
48 	default:
49 	case WMI_SAR_FEATURE_OFF:
50 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
51 	case WMI_SAR_FEATURE_ON_SET_0:
52 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
53 	case WMI_SAR_FEATURE_ON_SET_1:
54 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
55 	case WMI_SAR_FEATURE_ON_SET_2:
56 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
57 	case WMI_SAR_FEATURE_ON_SET_3:
58 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
59 	case WMI_SAR_FEATURE_ON_SET_4:
60 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
61 	case WMI_SAR_FEATURE_ON_USER_DEFINED:
62 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER;
63 	case WMI_SAR_FEATURE_ON_SAR_V2_0:
64 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
65 	}
66 }
67 
hdd_sar_wmi_to_nl_band(uint32_t wmi_value)68 static u32 hdd_sar_wmi_to_nl_band(uint32_t wmi_value)
69 {
70 	switch (wmi_value) {
71 	default:
72 	case WMI_SAR_2G_ID:
73 		return HDD_NL80211_BAND_2GHZ;
74 	case WMI_SAR_5G_ID:
75 		return HDD_NL80211_BAND_5GHZ;
76 	}
77 }
78 
hdd_sar_wmi_to_nl_modulation(uint32_t wmi_value)79 static u32 hdd_sar_wmi_to_nl_modulation(uint32_t wmi_value)
80 {
81 	switch (wmi_value) {
82 	default:
83 	case WMI_SAR_MOD_CCK:
84 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK;
85 	case WMI_SAR_MOD_OFDM:
86 		return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM;
87 	}
88 }
89 
90 /**
91  * hdd_sar_cb () - sar response message handler
92  * @cookie: hdd request cookie
93  * @event: sar response event
94  *
95  * Return: none
96  */
hdd_sar_cb(void * cookie,struct sar_limit_event * event)97 static void hdd_sar_cb(void *cookie,
98 		       struct sar_limit_event *event)
99 {
100 	struct osif_request *request;
101 	struct hdd_sar_context *context;
102 
103 	hdd_enter();
104 
105 	if (!event) {
106 		hdd_err("response is NULL");
107 		return;
108 	}
109 
110 	request = osif_request_get(cookie);
111 	if (!request) {
112 		hdd_debug("Obsolete request");
113 		return;
114 	}
115 
116 	context = osif_request_priv(request);
117 	context->event = *event;
118 	osif_request_complete(request);
119 	osif_request_put(request);
120 
121 	hdd_exit();
122 }
123 
hdd_sar_get_response_len(const struct sar_limit_event * event)124 static uint32_t hdd_sar_get_response_len(const struct sar_limit_event *event)
125 {
126 	uint32_t len;
127 	uint32_t row_len;
128 
129 	len = NLMSG_HDRLEN;
130 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE */
131 	len += NLA_HDRLEN + sizeof(u32);
132 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS */
133 	len += NLA_HDRLEN + sizeof(u32);
134 
135 	/* nest */
136 	row_len = NLA_HDRLEN;
137 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND */
138 	row_len += NLA_HDRLEN + sizeof(u32);
139 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN */
140 	row_len += NLA_HDRLEN + sizeof(u32);
141 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION */
142 	row_len += NLA_HDRLEN + sizeof(u32);
143 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT */
144 	row_len += NLA_HDRLEN + sizeof(u32);
145 
146 	/* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC */
147 	len += NLA_HDRLEN + (row_len * event->num_limit_rows);
148 
149 	return len;
150 }
151 
hdd_sar_fill_response(struct sk_buff * skb,const struct sar_limit_event * event)152 static int hdd_sar_fill_response(struct sk_buff *skb,
153 				 const struct sar_limit_event *event)
154 {
155 	int errno;
156 	u32 value;
157 	u32 attr;
158 	struct nlattr *nla_spec_attr;
159 	struct nlattr *nla_row_attr;
160 	uint32_t row;
161 	const struct sar_limit_event_row *event_row;
162 
163 	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE;
164 	value = hdd_sar_wmi_to_nl_enable(event->sar_enable);
165 	errno = nla_put_u32(skb, attr, value);
166 	if (errno)
167 		return errno;
168 
169 	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS;
170 	value = event->num_limit_rows;
171 	errno = nla_put_u32(skb, attr, value);
172 	if (errno)
173 		return errno;
174 
175 	attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC;
176 	nla_spec_attr = nla_nest_start(skb, attr);
177 	if (!nla_spec_attr)
178 		return -EINVAL;
179 
180 	for (row = 0, event_row = event->sar_limit_row;
181 	     row < event->num_limit_rows;
182 	     row++, event_row++) {
183 		nla_row_attr = nla_nest_start(skb, attr);
184 		if (!nla_row_attr)
185 			return -EINVAL;
186 
187 		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND;
188 		value = hdd_sar_wmi_to_nl_band(event_row->band_id);
189 		errno = nla_put_u32(skb, attr, value);
190 		if (errno)
191 			return errno;
192 
193 		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN;
194 		value = event_row->chain_id;
195 		errno = nla_put_u32(skb, attr, value);
196 		if (errno)
197 			return errno;
198 
199 		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION;
200 		value = hdd_sar_wmi_to_nl_modulation(event_row->mod_id);
201 		errno = nla_put_u32(skb, attr, value);
202 		if (errno)
203 			return errno;
204 
205 		attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT;
206 		value = event_row->limit_value;
207 		errno = nla_put_u32(skb, attr, value);
208 		if (errno)
209 			return errno;
210 
211 		nla_nest_end(skb, nla_row_attr);
212 	}
213 	nla_nest_end(skb, nla_spec_attr);
214 
215 	return 0;
216 }
217 
hdd_sar_send_response(struct wiphy * wiphy,const struct sar_limit_event * event)218 static int hdd_sar_send_response(struct wiphy *wiphy,
219 				 const struct sar_limit_event *event)
220 {
221 	uint32_t len;
222 	struct sk_buff *skb;
223 	int errno;
224 
225 	len = hdd_sar_get_response_len(event);
226 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
227 	if (!skb) {
228 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
229 		return -ENOMEM;
230 	}
231 
232 	errno = hdd_sar_fill_response(skb, event);
233 	if (errno) {
234 		wlan_cfg80211_vendor_free_skb(skb);
235 		return errno;
236 	}
237 
238 	return wlan_cfg80211_vendor_cmd_reply(skb);
239 }
240 
241 /**
242  * __wlan_hdd_get_sar_power_limits() - Get SAR power limits
243  * @wiphy: Pointer to wireless phy
244  * @wdev: Pointer to wireless device
245  * @data: Pointer to data
246  * @data_len: Length of @data
247  *
248  * This function is used to retrieve Specific Absorption Rate limit specs.
249  *
250  * Return: 0 on success, negative errno on failure
251  */
__wlan_hdd_get_sar_power_limits(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)252 static int __wlan_hdd_get_sar_power_limits(struct wiphy *wiphy,
253 					   struct wireless_dev *wdev,
254 					   const void *data, int data_len)
255 {
256 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
257 	struct osif_request *request;
258 	struct hdd_sar_context *context;
259 	mac_handle_t mac_handle;
260 	void *cookie;
261 	QDF_STATUS status;
262 	int ret;
263 	static const struct osif_request_params params = {
264 		.priv_size = sizeof(*context),
265 		.timeout_ms = WLAN_WAIT_TIME_SAR,
266 	};
267 
268 	hdd_enter();
269 
270 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
271 		hdd_err("Command not allowed in FTM mode");
272 		return -EPERM;
273 	}
274 
275 	if (wlan_hdd_validate_context(hdd_ctx))
276 		return -EINVAL;
277 
278 	request = osif_request_alloc(&params);
279 	if (!request) {
280 		hdd_err("Request allocation failure");
281 		return -ENOMEM;
282 	}
283 
284 	cookie = osif_request_cookie(request);
285 
286 	mac_handle = hdd_ctx->mac_handle;
287 	status = sme_get_sar_power_limits(mac_handle, hdd_sar_cb, cookie);
288 	if (!QDF_IS_STATUS_SUCCESS(status)) {
289 		hdd_err("Unable to post sar message");
290 		ret = -EINVAL;
291 		goto cleanup;
292 	}
293 
294 	ret = osif_request_wait_for_response(request);
295 	if (ret) {
296 		hdd_err("Target response timed out");
297 		goto cleanup;
298 	}
299 
300 	context = osif_request_priv(request);
301 	ret = hdd_sar_send_response(wiphy, &context->event);
302 
303 cleanup:
304 	osif_request_put(request);
305 
306 	return ret;
307 }
308 
309 /**
310  * hdd_to_nl_sar_version - Map SAR version enum from hdd to nl
311  * @hdd_sar_version: Current SAR version stored in hdd_ctx
312  *
313  * This function is used to map SAR version enum stored in hdd_ctx to
314  * nl
315  *
316  * Return - NL SAR version
317  */
hdd_to_nl_sar_version(enum sar_version hdd_sar_version)318 static u32 hdd_to_nl_sar_version(enum sar_version hdd_sar_version)
319 {
320 	switch (hdd_sar_version) {
321 	case (SAR_VERSION_1):
322 		return QCA_WLAN_VENDOR_SAR_VERSION_1;
323 	case (SAR_VERSION_2):
324 		return QCA_WLAN_VENDOR_SAR_VERSION_2;
325 	case (SAR_VERSION_3):
326 		return QCA_WLAN_VENDOR_SAR_VERSION_3;
327 	case (SAR_VERSION_4):
328 		return QCA_WLAN_VENDOR_SAR_VERSION_4;
329 	case (SAR_VERSION_5):
330 		return QCA_WLAN_VENDOR_SAR_VERSION_5;
331 	case (SAR_VERSION_6):
332 		return QCA_WLAN_VENDOR_SAR_VERSION_1;
333 	default:
334 		hdd_err("Unexpected SAR version received :%u, sending default to userspace",
335 			hdd_sar_version);
336 		return QCA_WLAN_VENDOR_SAR_VERSION_1;
337 	}
338 }
339 
340 /**
341  * hdd_sar_fill_capability_response - Fill SAR capability
342  * @skb: Pointer to socket buffer
343  * @hdd_ctx: pointer to hdd context
344  *
345  * This function fills SAR Capability in the socket buffer
346  *
347  * Return - 0 on success, negative errno on failure
348  */
hdd_sar_fill_capability_response(struct sk_buff * skb,struct hdd_context * hdd_ctx)349 static int hdd_sar_fill_capability_response(struct sk_buff *skb,
350 					    struct hdd_context *hdd_ctx)
351 {
352 	int errno;
353 	u32 attr;
354 	u32 value;
355 
356 	attr = QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION;
357 	value = hdd_to_nl_sar_version(hdd_ctx->sar_version);
358 
359 	hdd_debug("Sending SAR Version = %u to userspace, fw_sar_version: %d",
360 		  value, hdd_ctx->sar_version);
361 
362 	errno = nla_put_u32(skb, attr, value);
363 
364 	return errno;
365 }
366 
367 /**
368  * hdd_sar_send_capability_response - Send SAR capability response
369  * @wiphy: Pointer to wireless phy
370  * @hdd_ctx: Pointer to hdd context
371  *
372  * This function sends SAR capability.
373  */
hdd_sar_send_capability_response(struct wiphy * wiphy,struct hdd_context * hdd_ctx)374 static int hdd_sar_send_capability_response(struct wiphy *wiphy,
375 					    struct hdd_context *hdd_ctx)
376 {
377 	uint32_t len;
378 	struct sk_buff *skb;
379 	int errno;
380 
381 	len = NLMSG_HDRLEN;
382 	/* QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION */
383 	len += NLA_HDRLEN + sizeof(u32);
384 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
385 	if (!skb) {
386 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
387 		return -ENOMEM;
388 	}
389 
390 	errno = hdd_sar_fill_capability_response(skb, hdd_ctx);
391 	if (errno) {
392 		wlan_cfg80211_vendor_free_skb(skb);
393 		return errno;
394 	}
395 
396 	return wlan_cfg80211_vendor_cmd_reply(skb);
397 }
398 
399 /**
400  * __wlan_hdd_get_sar_capability - Get SAR Capabilities
401  * @wiphy: Pointer to wireless phy
402  * @wdev: Pointer to wireless device
403  * @data: Pointer to data
404  * @data_len: Length of @data
405  *
406  * This function is used to retrieve SAR Version .
407  *
408  * Return: 0 on success, negative errno on failure
409  */
410 
__wlan_hdd_get_sar_capability(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)411 static int __wlan_hdd_get_sar_capability(struct wiphy *wiphy,
412 					 struct wireless_dev *wdev,
413 					 const void *data,
414 					 int data_len)
415 {
416 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
417 	int ret;
418 
419 	hdd_enter();
420 
421 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE ||
422 	    hdd_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
423 		hdd_err("Command not allowed in FTM/MONITOR mode");
424 		return -EPERM;
425 	}
426 
427 	if (wlan_hdd_validate_context(hdd_ctx))
428 		return -EINVAL;
429 
430 	ret = hdd_sar_send_capability_response(wiphy, hdd_ctx);
431 
432 	return ret;
433 }
434 
435 #define SAR_LIMITS_SAR_ENABLE QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE
436 #define SAR_LIMITS_NUM_SPECS QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS
437 #define SAR_LIMITS_SPEC QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC
438 #define SAR_LIMITS_SPEC_BAND QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND
439 #define SAR_LIMITS_SPEC_CHAIN QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN
440 #define SAR_LIMITS_SPEC_MODULATION \
441 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION
442 #define SAR_LIMITS_SPEC_POWER_LIMIT \
443 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT
444 #define SAR_LIMITS_SPEC_POWER_LIMIT_INDEX \
445 	QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
446 #define SAR_LIMITS_MAX QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX
447 
448 const struct nla_policy
449 wlan_hdd_sar_limits_policy[SAR_LIMITS_MAX + 1] = {
450 	[SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
451 	[SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
452 	[SAR_LIMITS_SPEC] = {.type = NLA_NESTED},
453 	[SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
454 	[SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
455 	[SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
456 	[SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
457 	[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX] = {.type = NLA_U32},
458 };
459 
hdd_store_sar_config(struct hdd_context * hdd_ctx,struct sar_limit_cmd_params * sar_limit_cmd)460 void hdd_store_sar_config(struct hdd_context *hdd_ctx,
461 			  struct sar_limit_cmd_params *sar_limit_cmd)
462 {
463 	/* Free the previously stored sar_limit_cmd */
464 	wlan_hdd_free_sar_config(hdd_ctx);
465 
466 	hdd_ctx->sar_cmd_params = sar_limit_cmd;
467 }
468 
wlan_hdd_free_sar_config(struct hdd_context * hdd_ctx)469 void wlan_hdd_free_sar_config(struct hdd_context *hdd_ctx)
470 {
471 	struct sar_limit_cmd_params *sar_limit_cmd;
472 
473 	if (!hdd_ctx->sar_cmd_params)
474 		return;
475 
476 	sar_limit_cmd = hdd_ctx->sar_cmd_params;
477 	hdd_ctx->sar_cmd_params = NULL;
478 	qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
479 	qdf_mem_free(sar_limit_cmd);
480 }
481 
482 /**
483  * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
484  * @nl80211_value:    Vendor command attribute value
485  * @wmi_value:        Pointer to return converted WMI return value
486  *
487  * Convert NL80211 vendor command value for SAR limit set to WMI value
488  * Return: 0 on success, -1 on invalid value
489  */
wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,u32 * wmi_value)490 static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
491 						   u32 *wmi_value)
492 {
493 	int ret = 0;
494 
495 	switch (nl80211_value) {
496 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
497 		*wmi_value = WMI_SAR_FEATURE_OFF;
498 		break;
499 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
500 		*wmi_value = WMI_SAR_FEATURE_ON_SET_0;
501 		break;
502 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
503 		*wmi_value = WMI_SAR_FEATURE_ON_SET_1;
504 		break;
505 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
506 		*wmi_value = WMI_SAR_FEATURE_ON_SET_2;
507 		break;
508 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
509 		*wmi_value = WMI_SAR_FEATURE_ON_SET_3;
510 		break;
511 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
512 		*wmi_value = WMI_SAR_FEATURE_ON_SET_4;
513 		break;
514 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
515 		*wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
516 		break;
517 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0:
518 		*wmi_value = WMI_SAR_FEATURE_ON_SAR_V2_0;
519 		break;
520 
521 	default:
522 		ret = -1;
523 	}
524 	return ret;
525 }
526 
527 #ifdef WLAN_FEATURE_SARV1_TO_SARV2
528 /**
529  * hdd_convert_sarv1_to_sarv2() - convert SAR V1 BDF reference to SAR V2
530  * @hdd_ctx: The HDD global context
531  * @tb: The parsed array of netlink attributes
532  * @sar_limit_cmd: The WMI command to be filled
533  *
534  * This feature/function is designed to solve the following problem:
535  * 1) Userspace application was written to use SARv1 BDF entries
536  * 2) Product is configured with SAR V2 BDF entries
537  *
538  * So if this feature is enabled, and if the firmware is configured
539  * with SAR V2 support, and if the incoming request is to enable a SAR
540  * V1 BDF entry, then the WMI command is generated to actually
541  * configure a SAR V2 BDF entry.
542  *
543  * Return: true if conversion was performed and @sar_limit_cmd is
544  * ready to be sent to firmware. Otherwise false in which case the
545  * normal parsing logic should be applied.
546  */
547 
548 static bool
hdd_convert_sarv1_to_sarv2(struct hdd_context * hdd_ctx,struct nlattr * tb[],struct sar_limit_cmd_params * sar_limit_cmd)549 hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
550 			   struct nlattr *tb[],
551 			   struct sar_limit_cmd_params *sar_limit_cmd)
552 {
553 	struct nlattr *attr;
554 	uint32_t bdf_index, set;
555 	struct sar_limit_cmd_row *row;
556 
557 	hdd_enter();
558 	if (hdd_ctx->sar_version == SAR_VERSION_1) {
559 		hdd_debug("SAR version: %d", hdd_ctx->sar_version);
560 		return false;
561 	}
562 
563 	attr = tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE];
564 	if (!attr)
565 		return false;
566 
567 	bdf_index = nla_get_u32(attr);
568 
569 	if ((bdf_index >= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0) &&
570 	    (bdf_index <= QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4)) {
571 		set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0;
572 	} else if (bdf_index == QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE) {
573 		set = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
574 		bdf_index = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
575 	} else {
576 		return false;
577 	}
578 
579 	/* Need two rows to hold the per-chain V2 power index
580 	 * To disable SARv2 limit, send chain, num_limits_row and
581 	 * power limit set to 0 (except power index 0xff)
582 	 */
583 	row = qdf_mem_malloc(2 * sizeof(*row));
584 	if (!row)
585 		return false;
586 
587 	if (wlan_hdd_cfg80211_sar_convert_limit_set(
588 		set, &sar_limit_cmd->sar_enable)) {
589 		hdd_err("Failed to convert SAR limit to WMI value");
590 		return false;
591 	}
592 
593 	sar_limit_cmd->commit_limits = 1;
594 	sar_limit_cmd->num_limit_rows = 2;
595 	sar_limit_cmd->sar_limit_row_list = row;
596 	row[0].limit_value = bdf_index;
597 	row[1].limit_value = row[0].limit_value;
598 	row[0].chain_id = 0;
599 	row[1].chain_id = 1;
600 	row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
601 	row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
602 
603 	hdd_exit();
604 	return true;
605 }
606 
607 #else /* WLAN_FEATURE_SARV1_TO_SARV2 */
608 static bool
hdd_convert_sarv1_to_sarv2(struct hdd_context * hdd_ctx,struct nlattr * tb[],struct sar_limit_cmd_params * sar_limit_cmd)609 hdd_convert_sarv1_to_sarv2(struct hdd_context *hdd_ctx,
610 			   struct nlattr *tb[],
611 			   struct sar_limit_cmd_params *sar_limit_cmd)
612 {
613 	return false;
614 }
615 
616 #endif /* WLAN_FEATURE_SARV1_TO_SARV2 */
617 
618 /**
619  * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
620  * @nl80211_value:    Vendor command attribute value
621  * @wmi_value:        Pointer to return converted WMI return value
622  *
623  * Convert NL80211 vendor command value for SAR BAND to WMI value
624  * Return: 0 on success, -1 on invalid value
625  */
wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value,u32 * wmi_value)626 static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
627 {
628 	int ret = 0;
629 
630 	switch (nl80211_value) {
631 	case HDD_NL80211_BAND_2GHZ:
632 		*wmi_value = WMI_SAR_2G_ID;
633 		break;
634 	case HDD_NL80211_BAND_5GHZ:
635 		*wmi_value = WMI_SAR_5G_ID;
636 		break;
637 	default:
638 		ret = -1;
639 	}
640 	return ret;
641 }
642 
643 /**
644  * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
645  * @nl80211_value:    Vendor command attribute value
646  * @wmi_value:        Pointer to return converted WMI return value
647  *
648  * Convert NL80211 vendor command value for SAR Modulation to WMI value
649  * Return: 0 on success, -1 on invalid value
650  */
wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,u32 * wmi_value)651 static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
652 						    u32 *wmi_value)
653 {
654 	int ret = 0;
655 
656 	switch (nl80211_value) {
657 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
658 		*wmi_value = WMI_SAR_MOD_CCK;
659 		break;
660 	case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
661 		*wmi_value = WMI_SAR_MOD_OFDM;
662 		break;
663 	default:
664 		ret = -1;
665 	}
666 	return ret;
667 }
668 
669 /**
670  * hdd_extract_sar_nested_attrs() - Extract nested SAR attribute
671  * @spec: nested nla attribute
672  * @row: output to hold extract nested attribute
673  *
674  * This function extracts nested SAR attribute one at a time which means
675  * for each nested attribute this has to be invoked from
676  * __wlan_hdd_set_sar_power_limits().
677  *
678  * Return: On success - 0
679  *         On Failure - Negative value
680  */
hdd_extract_sar_nested_attrs(struct nlattr * spec[],struct sar_limit_cmd_row * row)681 static int hdd_extract_sar_nested_attrs(struct nlattr *spec[],
682 					struct sar_limit_cmd_row *row)
683 {
684 	uint32_t limit;
685 	uint32_t band;
686 	uint32_t modulation;
687 	int ret;
688 
689 	row->validity_bitmap = 0;
690 
691 	if (spec[SAR_LIMITS_SPEC_POWER_LIMIT]) {
692 		limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT]);
693 		row->limit_value = limit;
694 	} else if (spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]) {
695 		limit = nla_get_u32(spec[SAR_LIMITS_SPEC_POWER_LIMIT_INDEX]);
696 		row->limit_value = limit;
697 	} else {
698 		hdd_err("SAR Spec does not have power limit or index value");
699 		return -EINVAL;
700 	}
701 
702 	if (spec[SAR_LIMITS_SPEC_BAND]) {
703 		band = nla_get_u32(spec[SAR_LIMITS_SPEC_BAND]);
704 		ret = wlan_hdd_cfg80211_sar_convert_band(band, &row->band_id);
705 		if (ret) {
706 			hdd_err("Invalid SAR Band attr");
707 			return ret;
708 		}
709 
710 		row->validity_bitmap |= WMI_SAR_BAND_ID_VALID_MASK;
711 	}
712 
713 	if (spec[SAR_LIMITS_SPEC_CHAIN]) {
714 		row->chain_id = nla_get_u32(spec[SAR_LIMITS_SPEC_CHAIN]);
715 		row->validity_bitmap |= WMI_SAR_CHAIN_ID_VALID_MASK;
716 	}
717 
718 	if (spec[SAR_LIMITS_SPEC_MODULATION]) {
719 		modulation = nla_get_u32(spec[SAR_LIMITS_SPEC_MODULATION]);
720 		ret = wlan_hdd_cfg80211_sar_convert_modulation(modulation,
721 							       &row->mod_id);
722 		if (ret) {
723 			hdd_err("Invalid SAR Modulation attr");
724 			return ret;
725 		}
726 
727 		row->validity_bitmap |= WMI_SAR_MOD_ID_VALID_MASK;
728 	}
729 
730 	return 0;
731 }
732 
733 /**
734  * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
735  * @wiphy: Pointer to wireless phy
736  * @wdev: Pointer to wireless device
737  * @data: Pointer to data
738  * @data_len: Length of @data
739  *
740  * This function is used to setup Specific Absorption Rate limit specs.
741  *
742  * Return: 0 on success, negative errno on failure
743  */
__wlan_hdd_set_sar_power_limits(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)744 static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
745 					   struct wireless_dev *wdev,
746 					   const void *data, int data_len)
747 {
748 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
749 	struct nlattr *spec[SAR_LIMITS_MAX + 1];
750 	struct nlattr *tb[SAR_LIMITS_MAX + 1];
751 	struct nlattr *spec_list;
752 	struct sar_limit_cmd_params *sar_limit_cmd;
753 	int ret = -EINVAL, i = 0, rem = 0;
754 	QDF_STATUS status;
755 	uint32_t num_limit_rows = 0;
756 	struct sar_limit_cmd_row *row;
757 	uint32_t sar_enable;
758 
759 	hdd_enter();
760 
761 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
762 		hdd_err("Command not allowed in FTM mode");
763 		return -EPERM;
764 	}
765 
766 	if (wlan_hdd_validate_context(hdd_ctx))
767 		return -EINVAL;
768 
769 	if (wlan_cfg80211_nla_parse(tb, SAR_LIMITS_MAX, data, data_len,
770 				    wlan_hdd_sar_limits_policy)) {
771 		hdd_err("Invalid SAR attributes");
772 		return -EINVAL;
773 	}
774 
775 	if (tb[SAR_LIMITS_SAR_ENABLE]) {
776 		sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
777 
778 		if ((sar_enable >=
779 			QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 &&
780 		     sar_enable <=
781 			QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4) &&
782 		     hdd_ctx->sar_version != SAR_VERSION_1 &&
783 		     !hdd_ctx->config->enable_sar_conversion) {
784 			hdd_err("SARV1 to SARV2 is disabled from ini");
785 			return -EINVAL;
786 		} else if (sar_enable ==
787 				QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 &&
788 				hdd_ctx->sar_version == SAR_VERSION_1) {
789 			hdd_err("FW expects SARV1 given command is SARV2");
790 			return -EINVAL;
791 		}
792 	}
793 
794 	sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params));
795 	if (!sar_limit_cmd)
796 		return -ENOMEM;
797 
798 	wlan_hdd_sar_timers_reset(hdd_ctx);
799 
800 	/* is special SAR V1 => SAR V2 logic enabled and applicable? */
801 	if (hdd_ctx->config->enable_sar_conversion &&
802 	    (hdd_convert_sarv1_to_sarv2(hdd_ctx, tb, sar_limit_cmd)))
803 		goto send_sar_limits;
804 
805 	/* Vendor command manadates all SAR Specs in single call */
806 	sar_limit_cmd->commit_limits = 1;
807 	sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
808 	if (tb[SAR_LIMITS_SAR_ENABLE]) {
809 		uint32_t *sar_ptr = &sar_limit_cmd->sar_enable;
810 
811 		sar_enable = nla_get_u32(tb[SAR_LIMITS_SAR_ENABLE]);
812 		ret = wlan_hdd_cfg80211_sar_convert_limit_set(sar_enable,
813 							      sar_ptr);
814 		if (ret) {
815 			hdd_err("Invalid SAR Enable attr");
816 			goto fail;
817 		}
818 	}
819 
820 	hdd_debug("attr sar sar_enable %d", sar_limit_cmd->sar_enable);
821 
822 	if (tb[SAR_LIMITS_NUM_SPECS]) {
823 		num_limit_rows = nla_get_u32(tb[SAR_LIMITS_NUM_SPECS]);
824 		hdd_debug("attr sar num_limit_rows %u", num_limit_rows);
825 	}
826 
827 	if (num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
828 		hdd_err("SAR Spec list exceed supported size");
829 		goto fail;
830 	}
831 
832 	if (num_limit_rows == 0)
833 		goto send_sar_limits;
834 
835 	row = qdf_mem_malloc(sizeof(*row) * num_limit_rows);
836 	if (!row)
837 		goto fail;
838 
839 	sar_limit_cmd->num_limit_rows = num_limit_rows;
840 	sar_limit_cmd->sar_limit_row_list = row;
841 
842 	if (!tb[SAR_LIMITS_SPEC]) {
843 		hdd_err("Invalid SAR specification list");
844 		goto fail;
845 	}
846 
847 	nla_for_each_nested(spec_list, tb[SAR_LIMITS_SPEC], rem) {
848 		if (i == num_limit_rows) {
849 			hdd_warn("SAR Cmd has excess SPECs in list");
850 			break;
851 		}
852 
853 		if (wlan_cfg80211_nla_parse(spec,
854 					    SAR_LIMITS_MAX,
855 					    nla_data(spec_list),
856 					    nla_len(spec_list),
857 					    wlan_hdd_sar_limits_policy)) {
858 			hdd_err("nla_parse failed for SAR Spec list");
859 			goto fail;
860 		}
861 
862 		ret = hdd_extract_sar_nested_attrs(spec, row);
863 		if (ret) {
864 			hdd_err("Failed to extract SAR nested attrs");
865 			goto fail;
866 		}
867 
868 		hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
869 			  i, row->band_id, row->chain_id, row->mod_id,
870 			  row->limit_value, row->validity_bitmap);
871 
872 		i++;
873 		row++;
874 	}
875 
876 	if (i < sar_limit_cmd->num_limit_rows) {
877 		hdd_warn("SAR Cmd has less SPECs in list");
878 		sar_limit_cmd->num_limit_rows = i;
879 	}
880 
881 send_sar_limits:
882 	status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd);
883 	if (QDF_IS_STATUS_ERROR(status)) {
884 		hdd_err("Failed to set sar power limits");
885 		goto fail;
886 	}
887 
888 	/* After SSR, the SAR configuration is lost. As SSR is hidden from
889 	 * userland, this command will not come from userspace after a SSR. To
890 	 * restore this configuration, save this in hdd context and restore
891 	 * after re-init.
892 	 */
893 	hdd_store_sar_config(hdd_ctx, sar_limit_cmd);
894 	return 0;
895 
896 fail:
897 	if (sar_limit_cmd) {
898 		qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
899 		qdf_mem_free(sar_limit_cmd);
900 	}
901 
902 	return ret;
903 }
904 
905 #undef SAR_LIMITS_SAR_ENABLE
906 #undef SAR_LIMITS_NUM_SPECS
907 #undef SAR_LIMITS_SPEC
908 #undef SAR_LIMITS_SPEC_BAND
909 #undef SAR_LIMITS_SPEC_CHAIN
910 #undef SAR_LIMITS_SPEC_MODULATION
911 #undef SAR_LIMITS_SPEC_POWER_LIMIT
912 #undef SAR_LIMITS_SPEC_POWER_LIMIT_INDEX
913 #undef SAR_LIMITS_MAX
914 
wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)915 int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
916 					   struct wireless_dev *wdev,
917 					   const void *data,
918 					   int data_len)
919 {
920 	struct osif_psoc_sync *psoc_sync;
921 	int errno;
922 
923 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
924 	if (errno)
925 		return errno;
926 
927 	errno = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data, data_len);
928 
929 	osif_psoc_sync_op_stop(psoc_sync);
930 
931 	return errno;
932 }
933 
wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)934 int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy,
935 					   struct wireless_dev *wdev,
936 					   const void *data,
937 					   int data_len)
938 {
939 	struct osif_psoc_sync *psoc_sync;
940 	int errno;
941 
942 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
943 	if (errno)
944 		return errno;
945 
946 	errno = __wlan_hdd_get_sar_power_limits(wiphy, wdev, data, data_len);
947 
948 	osif_psoc_sync_op_stop(psoc_sync);
949 
950 	return errno;
951 }
952 
953 /**
954  * wlan_hdd_cfg80211_get_sar_capability() - Get SAR capability
955  * @wiphy: Pointer to wireless phy
956  * @wdev: Pointer to wireless device
957  * @data: Pointer to data
958  * @data_len: Length of @data
959  *
960  * Wrapper function of __wlan_hdd_get_sar_capability()
961  *
962  * Return: 0 on success, negative errno on failure
963  */
964 
wlan_hdd_cfg80211_get_sar_capability(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)965 int wlan_hdd_cfg80211_get_sar_capability(struct wiphy *wiphy,
966 					 struct wireless_dev *wdev,
967 					 const void *data,
968 					 int data_len)
969 {
970 	struct osif_psoc_sync *psoc_sync;
971 	int errno;
972 
973 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
974 	if (errno)
975 		return errno;
976 
977 	errno = __wlan_hdd_get_sar_capability(wiphy, wdev, data, data_len);
978 
979 	osif_psoc_sync_op_stop(psoc_sync);
980 
981 	return errno;
982 }
983 
984 #ifdef SAR_SAFETY_FEATURE
hdd_disable_sar(struct hdd_context * hdd_ctx)985 void hdd_disable_sar(struct hdd_context *hdd_ctx)
986 {
987 	struct sar_limit_cmd_params *sar_limit_cmd;
988 	struct sar_limit_cmd_row *row;
989 	QDF_STATUS status;
990 
991 	if (hdd_ctx->sar_version == SAR_VERSION_1) {
992 		hdd_nofl_debug("FW SAR version: %d", hdd_ctx->sar_version);
993 		return;
994 	}
995 
996 	sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params));
997 	if (!sar_limit_cmd)
998 		return;
999 
1000 	/*
1001 	 * Need two rows to hold the per-chain V2 power index
1002 	 */
1003 	row = qdf_mem_malloc(2 * sizeof(*row));
1004 	if (!row)
1005 		goto config_sar_failed;
1006 
1007 	sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_OFF;
1008 	sar_limit_cmd->commit_limits = 1;
1009 	sar_limit_cmd->num_limit_rows = 2;
1010 	sar_limit_cmd->sar_limit_row_list = row;
1011 	row[0].limit_value = 0;
1012 	row[1].limit_value = 0;
1013 	row[0].chain_id = 0;
1014 	row[1].chain_id = 1;
1015 	row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
1016 	row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
1017 
1018 	hdd_nofl_debug("Disable the SAR limit index for both the chains");
1019 
1020 	status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd);
1021 	if (QDF_IS_STATUS_ERROR(status)) {
1022 		hdd_nofl_err("Failed to set sar power limits");
1023 		goto config_sar_failed;
1024 	}
1025 
1026 	/* After SSR, the SAR configuration is lost. As SSR is hidden from
1027 	 * userland, this command will not come from userspace after a SSR. To
1028 	 * restore this configuration, save this in hdd context and restore
1029 	 * after re-init.
1030 	 */
1031 	hdd_store_sar_config(hdd_ctx, sar_limit_cmd);
1032 	return;
1033 
1034 config_sar_failed:
1035 
1036 	if (sar_limit_cmd) {
1037 		qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
1038 		qdf_mem_free(sar_limit_cmd);
1039 	}
1040 }
1041 
hdd_configure_sar_index(struct hdd_context * hdd_ctx,uint32_t sar_index)1042 void hdd_configure_sar_index(struct hdd_context *hdd_ctx, uint32_t sar_index)
1043 {
1044 	struct sar_limit_cmd_params *sar_limit_cmd;
1045 	struct sar_limit_cmd_row *row;
1046 	QDF_STATUS status;
1047 
1048 	if (hdd_ctx->sar_version == SAR_VERSION_1) {
1049 		hdd_nofl_debug("FW SAR version: %d", hdd_ctx->sar_version);
1050 		return;
1051 	}
1052 
1053 	sar_limit_cmd = qdf_mem_malloc(sizeof(struct sar_limit_cmd_params));
1054 	if (!sar_limit_cmd)
1055 		return;
1056 
1057 	/*
1058 	 * Need two rows to hold the per-chain V2 power index
1059 	 */
1060 	row = qdf_mem_malloc(2 * sizeof(*row));
1061 	if (!row)
1062 		goto config_sar_failed;
1063 
1064 	sar_limit_cmd->sar_enable = WMI_SAR_FEATURE_ON_SAR_V2_0;
1065 	sar_limit_cmd->commit_limits = 1;
1066 	sar_limit_cmd->num_limit_rows = 2;
1067 	sar_limit_cmd->sar_limit_row_list = row;
1068 	row[0].limit_value = sar_index;
1069 	row[1].limit_value = sar_index;
1070 	row[0].chain_id = 0;
1071 	row[1].chain_id = 1;
1072 	row[0].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
1073 	row[1].validity_bitmap = WMI_SAR_CHAIN_ID_VALID_MASK;
1074 
1075 	hdd_nofl_debug("Configure POW_Limit Index: %d for both the chains",
1076 		       row->limit_value);
1077 
1078 	status = sme_set_sar_power_limits(hdd_ctx->mac_handle, sar_limit_cmd);
1079 	if (QDF_IS_STATUS_ERROR(status)) {
1080 		hdd_nofl_err("Failed to set sar power limits");
1081 		goto config_sar_failed;
1082 	}
1083 
1084 	/*
1085 	 * After SSR, the SAR configuration is lost. As SSR is hidden from
1086 	 * userland, this command will not come from userspace after a SSR. To
1087 	 * restore this configuration, save this in hdd context and restore
1088 	 * after re-init.
1089 	 */
1090 	hdd_store_sar_config(hdd_ctx, sar_limit_cmd);
1091 	return;
1092 
1093 config_sar_failed:
1094 
1095 	if (sar_limit_cmd) {
1096 		qdf_mem_free(sar_limit_cmd->sar_limit_row_list);
1097 		qdf_mem_free(sar_limit_cmd);
1098 	}
1099 }
1100 
hdd_configure_sar_sleep_index(struct hdd_context * hdd_ctx)1101 void hdd_configure_sar_sleep_index(struct hdd_context *hdd_ctx)
1102 {
1103 	if (!(hdd_ctx->config->enable_sar_safety & SAR_SAFETY_ENABLED_TIMER))
1104 		return;
1105 
1106 	if (hdd_ctx->config->config_sar_safety_sleep_index) {
1107 		hdd_nofl_debug("Configure SAR sleep index %d",
1108 			       hdd_ctx->config->sar_safety_sleep_index);
1109 		hdd_configure_sar_index(
1110 				hdd_ctx,
1111 				hdd_ctx->config->sar_safety_sleep_index);
1112 	} else {
1113 		hdd_nofl_debug("Disable SAR");
1114 		hdd_disable_sar(hdd_ctx);
1115 	}
1116 }
1117 
hdd_configure_sar_resume_index(struct hdd_context * hdd_ctx)1118 void hdd_configure_sar_resume_index(struct hdd_context *hdd_ctx)
1119 {
1120 	if (!(hdd_ctx->config->enable_sar_safety & SAR_SAFETY_ENABLED_TIMER))
1121 		return;
1122 
1123 	hdd_nofl_debug("Configure SAR safety index %d on wlan resume",
1124 		       hdd_ctx->config->sar_safety_index);
1125 	hdd_configure_sar_index(hdd_ctx,
1126 				hdd_ctx->config->sar_safety_index);
1127 }
1128 
hdd_send_sar_unsolicited_event(struct hdd_context * hdd_ctx)1129 static void hdd_send_sar_unsolicited_event(struct hdd_context *hdd_ctx)
1130 {
1131 	struct sk_buff *vendor_event;
1132 	uint32_t len;
1133 
1134 	if (!hdd_ctx) {
1135 		hdd_err_rl("hdd context is null");
1136 		return;
1137 	}
1138 
1139 	len = NLMSG_HDRLEN;
1140 	vendor_event =
1141 		wlan_cfg80211_vendor_event_alloc(
1142 			hdd_ctx->wiphy, NULL, len,
1143 			QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_INDEX,
1144 			GFP_KERNEL);
1145 
1146 	if (!vendor_event) {
1147 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1148 		return;
1149 	}
1150 
1151 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1152 }
1153 
hdd_sar_unsolicited_work_cb(void * user_data)1154 static void hdd_sar_unsolicited_work_cb(void *user_data)
1155 {
1156 	struct hdd_context *hdd_ctx = (struct hdd_context *)user_data;
1157 	uint8_t i = 0;
1158 	QDF_STATUS status;
1159 	int errno;
1160 	struct osif_psoc_sync *psoc_sync;
1161 
1162 	hdd_nofl_debug("Sar unsolicited timer expired");
1163 
1164 	errno = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
1165 
1166 	if (errno == -EAGAIN) {
1167 		hdd_nofl_debug("rescheduling sar unsolicited work");
1168 		status = qdf_delayed_work_create(&hdd_ctx->sar_safety_unsolicited_work,
1169 						 hdd_sar_unsolicited_work_cb,
1170 						 hdd_ctx);
1171 		if (QDF_IS_STATUS_ERROR(status))
1172 			hdd_err("failed to create sar safety unsolicited work");
1173 		return;
1174 	} else if (errno) {
1175 		hdd_err("cannot handle sar unsolicited work");
1176 		return;
1177 	}
1178 
1179 	qdf_atomic_set(&hdd_ctx->sar_safety_req_resp_event_in_progress, 1);
1180 
1181 	for (i = 0; i < hdd_ctx->config->sar_safety_req_resp_retry; i++) {
1182 		qdf_event_reset(&hdd_ctx->sar_safety_req_resp_event);
1183 		hdd_send_sar_unsolicited_event(hdd_ctx);
1184 		status = qdf_wait_for_event_completion(
1185 				&hdd_ctx->sar_safety_req_resp_event,
1186 				hdd_ctx->config->sar_safety_req_resp_timeout);
1187 		if (QDF_IS_STATUS_SUCCESS(status))
1188 			break;
1189 	}
1190 	qdf_atomic_set(&hdd_ctx->sar_safety_req_resp_event_in_progress, 0);
1191 
1192 	if (i >= hdd_ctx->config->sar_safety_req_resp_retry)
1193 		hdd_configure_sar_index(hdd_ctx,
1194 					hdd_ctx->config->sar_safety_index);
1195 
1196 	osif_psoc_sync_op_stop(psoc_sync);
1197 }
1198 
hdd_sar_safety_timer_cb(void * user_data)1199 static void hdd_sar_safety_timer_cb(void *user_data)
1200 {
1201 	struct hdd_context *hdd_ctx = (struct hdd_context *)user_data;
1202 
1203 	hdd_nofl_debug("Sar safety timer expires");
1204 	hdd_configure_sar_index(hdd_ctx, hdd_ctx->config->sar_safety_index);
1205 }
1206 
wlan_hdd_sar_unsolicited_timer_start(struct hdd_context * hdd_ctx)1207 void wlan_hdd_sar_unsolicited_timer_start(struct hdd_context *hdd_ctx)
1208 {
1209 	if (!(hdd_ctx->config->enable_sar_safety & SAR_SAFETY_ENABLED_TIMER))
1210 		return;
1211 
1212 	if (qdf_atomic_read(
1213 			&hdd_ctx->sar_safety_req_resp_event_in_progress) > 0)
1214 		return;
1215 
1216 	qdf_delayed_work_start(&hdd_ctx->sar_safety_unsolicited_work,
1217 			       hdd_ctx->config->sar_safety_unsolicited_timeout);
1218 
1219 	hdd_nofl_debug("sar safety unsolicited work started");
1220 }
1221 
wlan_hdd_sar_timers_reset(struct hdd_context * hdd_ctx)1222 void wlan_hdd_sar_timers_reset(struct hdd_context *hdd_ctx)
1223 {
1224 	QDF_STATUS status;
1225 
1226 	if (!(hdd_ctx->config->enable_sar_safety & SAR_SAFETY_ENABLED_TIMER))
1227 		return;
1228 
1229 	if (hdd_ctx->sar_version == SAR_VERSION_1)
1230 		return;
1231 
1232 	if (QDF_TIMER_STATE_RUNNING ==
1233 		qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer)) {
1234 		status = qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer);
1235 		if (QDF_IS_STATUS_SUCCESS(status))
1236 			hdd_nofl_debug("sar safety timer stopped");
1237 	}
1238 
1239 	status = qdf_mc_timer_start(&hdd_ctx->sar_safety_timer,
1240 				    hdd_ctx->config->sar_safety_timeout);
1241 	if (QDF_IS_STATUS_SUCCESS(status))
1242 		hdd_nofl_debug("sar safety timer started");
1243 
1244 	qdf_event_set(&hdd_ctx->sar_safety_req_resp_event);
1245 
1246 	qdf_delayed_work_stop_sync(&hdd_ctx->sar_safety_unsolicited_work);
1247 	hdd_nofl_debug("sar safety unsolicited work stopped");
1248 
1249 }
1250 
wlan_hdd_sar_timers_init(struct hdd_context * hdd_ctx)1251 void wlan_hdd_sar_timers_init(struct hdd_context *hdd_ctx)
1252 {
1253 	QDF_STATUS status;
1254 
1255 	if (!(hdd_ctx->config->enable_sar_safety & SAR_SAFETY_ENABLED_TIMER))
1256 		return;
1257 
1258 	hdd_enter();
1259 
1260 	qdf_mc_timer_init(&hdd_ctx->sar_safety_timer, QDF_TIMER_TYPE_SW,
1261 			  hdd_sar_safety_timer_cb, hdd_ctx);
1262 
1263 	status = qdf_delayed_work_create(&hdd_ctx->sar_safety_unsolicited_work,
1264 					 hdd_sar_unsolicited_work_cb,
1265 					 hdd_ctx);
1266 
1267 	if (QDF_IS_STATUS_ERROR(status)) {
1268 		hdd_err("failed to create sar safety unsolicited work");
1269 		goto hdd_exit;
1270 	}
1271 
1272 	qdf_atomic_init(&hdd_ctx->sar_safety_req_resp_event_in_progress);
1273 	qdf_event_create(&hdd_ctx->sar_safety_req_resp_event);
1274 
1275 hdd_exit:
1276 	hdd_exit();
1277 }
1278 
wlan_hdd_sar_timers_deinit(struct hdd_context * hdd_ctx)1279 void wlan_hdd_sar_timers_deinit(struct hdd_context *hdd_ctx)
1280 {
1281 	if (!(hdd_ctx->config->enable_sar_safety & SAR_SAFETY_ENABLED_TIMER))
1282 		return;
1283 
1284 	hdd_enter();
1285 
1286 	if (QDF_TIMER_STATE_RUNNING ==
1287 		qdf_mc_timer_get_current_state(&hdd_ctx->sar_safety_timer))
1288 		qdf_mc_timer_stop(&hdd_ctx->sar_safety_timer);
1289 
1290 	qdf_mc_timer_destroy(&hdd_ctx->sar_safety_timer);
1291 
1292 	qdf_delayed_work_destroy(&hdd_ctx->sar_safety_unsolicited_work);
1293 
1294 	qdf_event_destroy(&hdd_ctx->sar_safety_req_resp_event);
1295 
1296 	hdd_exit();
1297 }
1298 #endif
1299 
1300