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(¶ms);
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