1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 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_spectral_scan.c
22 *
23 * WLAN Host Device Driver Spectral Scan Implementation
24 */
25
26 #include <linux/version.h>
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <net/cfg80211.h>
30 #include "osif_sync.h"
31 #include "wlan_hdd_includes.h"
32 #include "cds_api.h"
33 #include "ani_global.h"
34 #include "wlan_cfg80211_spectral.h"
35 #include "wlan_hdd_spectralscan.h"
36 #include <wlan_spectral_ucfg_api.h>
37 #include "wma.h"
38 #include "wlan_hdd_object_manager.h"
39 #ifdef CNSS_GENL
40 #ifdef CONFIG_CNSS_OUT_OF_TREE
41 #include "cnss_nl.h"
42 #else
43 #include <net/cnss_nl.h>
44 #endif
45 #endif
46
47 /**
48 * __wlan_hdd_cfg80211_spectral_scan_start() - start spectral scan
49 * @wiphy: WIPHY structure pointer
50 * @wdev: Wireless device structure pointer
51 * @data: Pointer to the data received
52 * @data_len: Length of the data received
53 *
54 * This function starts spectral scan
55 *
56 * Return: 0 on success and errno on failure
57 */
__wlan_hdd_cfg80211_spectral_scan_start(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)58 static int __wlan_hdd_cfg80211_spectral_scan_start(struct wiphy *wiphy,
59 struct wireless_dev *wdev,
60 const void *data,
61 int data_len)
62 {
63 int ret;
64 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
65 struct net_device *dev = wdev->netdev;
66 struct hdd_adapter *adapter;
67 struct wlan_objmgr_vdev *vdev;
68
69 hdd_enter();
70
71 ret = wlan_hdd_validate_context(hdd_ctx);
72 if (ret)
73 return ret;
74
75 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
76 hdd_err("Command not allowed in FTM mode");
77 return -EPERM;
78 }
79
80 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
81 ret = hdd_validate_adapter(adapter);
82 if (ret)
83 return ret;
84
85 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
86 WLAN_OSIF_SPECTRAL_ID);
87 if (!vdev) {
88 hdd_err("can't get vdev");
89 return -EINVAL;
90 }
91 wlan_spectral_update_rx_chainmask(adapter->deflink);
92 ret = wlan_cfg80211_spectral_scan_config_and_start(wiphy, hdd_ctx->pdev,
93 vdev, data,
94 data_len);
95 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
96 hdd_exit();
97
98 return ret;
99 }
100
101 /**
102 * __wlan_hdd_cfg80211_spectral_scan_stop() - stop spectral scan
103 * @wiphy: WIPHY structure pointer
104 * @wdev: Wireless device structure pointer
105 * @data: Pointer to the data received
106 * @data_len: Length of the data received
107 *
108 * This function stops spectral scan
109 *
110 * Return: 0 on success and errno on failure
111 */
__wlan_hdd_cfg80211_spectral_scan_stop(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)112 static int __wlan_hdd_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
113 struct wireless_dev *wdev,
114 const void *data,
115 int data_len)
116 {
117 int ret;
118 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
119 struct net_device *dev = wdev->netdev;
120 struct hdd_adapter *adapter;
121 struct wlan_objmgr_vdev *vdev;
122
123 hdd_enter();
124
125 ret = wlan_hdd_validate_context(hdd_ctx);
126 if (ret)
127 return ret;
128
129 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
130 hdd_err("Command not allowed in FTM mode");
131 return -EPERM;
132 }
133
134 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
135 ret = hdd_validate_adapter(adapter);
136 if (ret)
137 return ret;
138
139 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
140 WLAN_OSIF_SPECTRAL_ID);
141 if (!vdev) {
142 hdd_err("can't get vdev");
143 return -EINVAL;
144 }
145 ret = wlan_cfg80211_spectral_scan_stop(wiphy, hdd_ctx->pdev,
146 vdev, data, data_len);
147 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
148 hdd_exit();
149
150 return ret;
151 }
152
153 /**
154 * __wlan_hdd_cfg80211_spectral_scan_get_config() - spectral scan get config
155 * @wiphy: WIPHY structure pointer
156 * @wdev: Wireless device structure pointer
157 * @data: Pointer to the data received
158 * @data_len: Length of the data received
159 *
160 * This function to get the spectral scan configuration
161 *
162 * Return: 0 on success and errno on failure
163 */
__wlan_hdd_cfg80211_spectral_scan_get_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)164 static int __wlan_hdd_cfg80211_spectral_scan_get_config(
165 struct wiphy *wiphy,
166 struct wireless_dev *wdev,
167 const void *data,
168 int data_len)
169 {
170 int ret;
171 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
172 struct net_device *dev = wdev->netdev;
173 struct hdd_adapter *adapter;
174 struct wlan_objmgr_vdev *vdev;
175
176 hdd_enter();
177
178 ret = wlan_hdd_validate_context(hdd_ctx);
179 if (ret)
180 return ret;
181
182 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
183 hdd_err("Command not allowed in FTM mode");
184 return -EPERM;
185 }
186
187 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
188 ret = hdd_validate_adapter(adapter);
189 if (ret)
190 return ret;
191
192 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
193 WLAN_OSIF_SPECTRAL_ID);
194 if (!vdev) {
195 hdd_err("can't get vdev");
196 return -EINVAL;
197 }
198 ret = wlan_cfg80211_spectral_scan_get_config(wiphy, hdd_ctx->pdev,
199 vdev, data, data_len);
200 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
201 hdd_exit();
202
203 return ret;
204 }
205
206 /**
207 * __wlan_hdd_cfg80211_spectral_scan_get_diag_stats() - get diag stats
208 * @wiphy: WIPHY structure pointer
209 * @wdev: Wireless device structure pointer
210 * @data: Pointer to the data received
211 * @data_len: Length of the data received
212 *
213 * This function gets the spectral scan diag stats
214 *
215 * Return: 0 on success and errno on failure
216 */
__wlan_hdd_cfg80211_spectral_scan_get_diag_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)217 static int __wlan_hdd_cfg80211_spectral_scan_get_diag_stats(
218 struct wiphy *wiphy,
219 struct wireless_dev *wdev,
220 const void *data,
221 int data_len)
222 {
223 int ret;
224 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
225 struct net_device *dev = wdev->netdev;
226 struct hdd_adapter *adapter;
227 struct wlan_objmgr_vdev *vdev;
228
229 hdd_enter();
230
231 ret = wlan_hdd_validate_context(hdd_ctx);
232 if (ret)
233 return ret;
234
235 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
236 hdd_err("Command not allowed in FTM mode");
237 return -EPERM;
238 }
239
240 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
241 ret = hdd_validate_adapter(adapter);
242 if (ret)
243 return ret;
244
245 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
246 WLAN_OSIF_SPECTRAL_ID);
247 if (!vdev) {
248 hdd_err("can't get vdev");
249 return -EINVAL;
250 }
251 ret = wlan_cfg80211_spectral_scan_get_diag_stats(
252 wiphy, hdd_ctx->pdev,
253 vdev, data, data_len);
254 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
255 hdd_exit();
256
257 return ret;
258 }
259
260 /**
261 * __wlan_hdd_cfg80211_spectral_scan_get_cap_info() - get spectral caps
262 * @wiphy: WIPHY structure pointer
263 * @wdev: Wireless device structure pointer
264 * @data: Pointer to the data received
265 * @data_len: Length of the data received
266 *
267 * This function gets spectral scan configured capabilities
268 *
269 * Return: 0 on success and errno on failure
270 */
__wlan_hdd_cfg80211_spectral_scan_get_cap_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)271 static int __wlan_hdd_cfg80211_spectral_scan_get_cap_info(
272 struct wiphy *wiphy,
273 struct wireless_dev *wdev,
274 const void *data,
275 int data_len)
276 {
277 int ret;
278 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
279 struct net_device *dev = wdev->netdev;
280 struct hdd_adapter *adapter;
281 struct wlan_objmgr_vdev *vdev;
282
283 hdd_enter();
284
285 ret = wlan_hdd_validate_context(hdd_ctx);
286 if (ret)
287 return ret;
288
289 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
290 hdd_err("Command not allowed in FTM mode");
291 return -EPERM;
292 }
293
294 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
295 ret = hdd_validate_adapter(adapter);
296 if (ret)
297 return ret;
298
299 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
300 WLAN_OSIF_SPECTRAL_ID);
301 if (!vdev) {
302 hdd_err("can't get vdev");
303 return -EINVAL;
304 }
305 ret = wlan_cfg80211_spectral_scan_get_cap(wiphy, hdd_ctx->pdev,
306 vdev, data, data_len);
307 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
308 hdd_exit();
309
310 return ret;
311 }
312
313 /*
314 * __wlan_hdd_cfg80211_spectral_scan_get_status() - get spectral scan
315 * status
316 * @wiphy: WIPHY structure pointer
317 * @wdev: Wireless device structure pointer
318 * @data: Pointer to the data received
319 * @data_len: Length of the data received
320 *
321 * This function gets current status of spectral scan
322 *
323 * Return: 0 on success and errno on failure
324 */
__wlan_hdd_cfg80211_spectral_scan_get_status(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)325 static int __wlan_hdd_cfg80211_spectral_scan_get_status(
326 struct wiphy *wiphy,
327 struct wireless_dev *wdev,
328 const void *data,
329 int data_len)
330 {
331 int ret;
332 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
333 struct net_device *dev = wdev->netdev;
334 struct hdd_adapter *adapter;
335 struct wlan_objmgr_vdev *vdev;
336
337 hdd_enter();
338
339 ret = wlan_hdd_validate_context(hdd_ctx);
340 if (ret)
341 return ret;
342
343 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
344 hdd_err("Command not allowed in FTM mode");
345 return -EPERM;
346 }
347
348 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
349 ret = hdd_validate_adapter(adapter);
350 if (ret)
351 return ret;
352
353 vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
354 WLAN_OSIF_SPECTRAL_ID);
355 if (!vdev) {
356 hdd_err("can't get vdev");
357 return -EINVAL;
358 }
359 ret = wlan_cfg80211_spectral_scan_get_status(wiphy, hdd_ctx->pdev,
360 vdev, data, data_len);
361 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
362 hdd_exit();
363
364 return ret;
365 }
366
wlan_hdd_cfg80211_spectral_scan_start(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)367 int wlan_hdd_cfg80211_spectral_scan_start(struct wiphy *wiphy,
368 struct wireless_dev *wdev,
369 const void *data,
370 int data_len)
371 {
372 struct osif_psoc_sync *psoc_sync;
373 int errno;
374
375 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
376 if (errno)
377 return errno;
378
379 errno = __wlan_hdd_cfg80211_spectral_scan_start(wiphy, wdev,
380 data, data_len);
381
382 osif_psoc_sync_op_stop(psoc_sync);
383
384 return errno;
385 }
386
wlan_hdd_cfg80211_spectral_scan_stop(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)387 int wlan_hdd_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
388 struct wireless_dev *wdev,
389 const void *data,
390 int data_len)
391 {
392 struct osif_psoc_sync *psoc_sync;
393 int errno;
394
395 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
396 if (errno)
397 return errno;
398
399 errno = __wlan_hdd_cfg80211_spectral_scan_stop(wiphy, wdev,
400 data, data_len);
401
402 osif_psoc_sync_op_stop(psoc_sync);
403
404 return errno;
405 }
406
wlan_hdd_cfg80211_spectral_scan_get_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)407 int wlan_hdd_cfg80211_spectral_scan_get_config(struct wiphy *wiphy,
408 struct wireless_dev *wdev,
409 const void *data,
410 int data_len)
411 {
412 struct osif_psoc_sync *psoc_sync;
413 int errno;
414
415 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
416 if (errno)
417 return errno;
418
419 errno = __wlan_hdd_cfg80211_spectral_scan_get_config(wiphy, wdev,
420 data, data_len);
421
422 osif_psoc_sync_op_stop(psoc_sync);
423
424 return errno;
425 }
426
wlan_hdd_cfg80211_spectral_scan_get_diag_stats(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)427 int wlan_hdd_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy,
428 struct wireless_dev *wdev,
429 const void *data,
430 int data_len)
431 {
432 struct osif_psoc_sync *psoc_sync;
433 int errno;
434
435 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
436 if (errno)
437 return errno;
438
439 errno = __wlan_hdd_cfg80211_spectral_scan_get_diag_stats(wiphy, wdev,
440 data,
441 data_len);
442
443 osif_psoc_sync_op_stop(psoc_sync);
444
445 return errno;
446 }
447
wlan_hdd_cfg80211_spectral_scan_get_cap_info(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)448 int wlan_hdd_cfg80211_spectral_scan_get_cap_info(struct wiphy *wiphy,
449 struct wireless_dev *wdev,
450 const void *data,
451 int data_len)
452 {
453 struct osif_psoc_sync *psoc_sync;
454 int errno;
455
456 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
457 if (errno)
458 return errno;
459
460 errno = __wlan_hdd_cfg80211_spectral_scan_get_cap_info(wiphy, wdev,
461 data, data_len);
462
463 osif_psoc_sync_op_stop(psoc_sync);
464
465 return errno;
466 }
467
wlan_hdd_cfg80211_spectral_scan_get_status(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)468 int wlan_hdd_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
469 struct wireless_dev *wdev,
470 const void *data,
471 int data_len)
472 {
473 struct osif_psoc_sync *psoc_sync;
474 int errno;
475
476 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
477 if (errno)
478 return errno;
479
480 errno = __wlan_hdd_cfg80211_spectral_scan_get_status(wiphy, wdev,
481 data, data_len);
482
483 osif_psoc_sync_op_stop(psoc_sync);
484
485 return errno;
486 }
487
hdd_spectral_register_to_dbr(struct hdd_context * hdd_ctx)488 void hdd_spectral_register_to_dbr(struct hdd_context *hdd_ctx)
489 {
490 ucfg_spectral_register_to_dbr(hdd_ctx->pdev);
491 }
492
493 #if defined(CNSS_GENL) && defined(WLAN_CONV_SPECTRAL_ENABLE)
send_spectral_scan_reg_rsp_msg(struct hdd_context * hdd_ctx)494 static void send_spectral_scan_reg_rsp_msg(struct hdd_context *hdd_ctx)
495 {
496 struct sk_buff *skb;
497 struct nlmsghdr *nlh;
498 struct spectral_scan_msg_v *rsp_msg;
499 int err;
500
501 skb = alloc_skb(NLMSG_SPACE(sizeof(struct spectral_scan_msg_v)),
502 GFP_KERNEL);
503 if (!skb) {
504 hdd_err("Skb allocation failed");
505 return;
506 }
507
508 nlh = (struct nlmsghdr *)skb->data;
509 nlh->nlmsg_pid = 0;
510 nlh->nlmsg_flags = 0;
511 nlh->nlmsg_seq = 0;
512 nlh->nlmsg_type = WLAN_NL_MSG_SPECTRAL_SCAN;
513
514 rsp_msg = NLMSG_DATA(nlh);
515 rsp_msg->msg_type = SPECTRAL_SCAN_REGISTER_RSP;
516 rsp_msg->pid = hdd_ctx->sscan_pid;
517 ucfg_spectral_get_version(hdd_ctx->pdev, &rsp_msg->version,
518 &rsp_msg->sub_version);
519
520 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct spectral_scan_msg_v));
521 skb_put(skb, NLMSG_SPACE(sizeof(struct spectral_scan_msg_v)));
522
523 hdd_info("sending App Reg Response to process pid %d",
524 hdd_ctx->sscan_pid);
525
526 err = nl_srv_ucast(skb, hdd_ctx->sscan_pid, MSG_DONTWAIT,
527 WLAN_NL_MSG_SPECTRAL_SCAN, CLD80211_MCGRP_OEM_MSGS);
528
529 if (err < 0)
530 hdd_err("SPECTRAL: failed to send to spectral scan reg"
531 " response");
532 }
533
534 /**
535 * __spectral_scan_msg_handler() - API to handle spectral scan command
536 * @data: Data received
537 * @data_len: length of the data received
538 * @ctx: Pointer to stored context
539 * @pid: Process ID
540 *
541 * API to handle spectral scan commands from user space
542 *
543 * Return: None
544 */
__spectral_scan_msg_handler(const void * data,int data_len,void * ctx,int pid)545 static void __spectral_scan_msg_handler(const void *data, int data_len,
546 void *ctx, int pid)
547 {
548 struct spectral_scan_msg *ss_msg = NULL;
549 struct nlattr *tb[CLD80211_ATTR_MAX + 1];
550 struct hdd_context *hdd_ctx;
551 int ret;
552
553 hdd_ctx = (struct hdd_context *)cds_get_context(QDF_MODULE_ID_HDD);
554 ret = wlan_hdd_validate_context(hdd_ctx);
555 if (ret)
556 return;
557
558 /*
559 * audit note: it is ok to pass a NULL policy here since only
560 * one attribute is parsed and it is explicitly validated
561 */
562 if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX, data,
563 data_len, NULL)) {
564 hdd_err("nla parse fails");
565 return;
566 }
567
568 if (!tb[CLD80211_ATTR_DATA]) {
569 hdd_err("attr VENDOR_DATA fails");
570 return;
571 }
572
573 if (nla_len(tb[CLD80211_ATTR_DATA]) < sizeof(*ss_msg)) {
574 hdd_err_rl("Invalid length for ATTR_DATA");
575 return;
576 }
577
578 ss_msg = (struct spectral_scan_msg *)nla_data(tb[CLD80211_ATTR_DATA]);
579
580 if (!ss_msg) {
581 hdd_err("data NULL");
582 return;
583 }
584
585 switch (ss_msg->msg_type) {
586 case SPECTRAL_SCAN_REGISTER_REQ:
587 hdd_ctx->sscan_pid = ss_msg->pid;
588 hdd_debug("spectral scan application registered, pid=%d",
589 hdd_ctx->sscan_pid);
590 send_spectral_scan_reg_rsp_msg(hdd_ctx);
591 ucfg_spectral_scan_set_ppid(hdd_ctx->pdev,
592 hdd_ctx->sscan_pid);
593 break;
594 default:
595 hdd_warn("invalid message type %d", ss_msg->msg_type);
596 break;
597 }
598 }
599
spectral_scan_msg_handler(const void * data,int data_len,void * ctx,int pid)600 static void spectral_scan_msg_handler(const void *data, int data_len,
601 void *ctx, int pid)
602 {
603 struct device *dev = ctx;
604 struct osif_psoc_sync *psoc_sync;
605
606 if (osif_psoc_sync_op_start(dev, &psoc_sync))
607 return;
608
609 __spectral_scan_msg_handler(data, data_len, ctx, pid);
610
611 osif_psoc_sync_op_stop(psoc_sync);
612 }
613
spectral_scan_activate_service(struct hdd_context * hdd_ctx)614 void spectral_scan_activate_service(struct hdd_context *hdd_ctx)
615 {
616 register_cld_cmd_cb(WLAN_NL_MSG_SPECTRAL_SCAN,
617 spectral_scan_msg_handler, hdd_ctx->parent_dev);
618 }
619
spectral_scan_deactivate_service(void)620 void spectral_scan_deactivate_service(void)
621 {
622 deregister_cld_cmd_cb(WLAN_NL_MSG_SPECTRAL_SCAN);
623 }
624
625 QDF_STATUS
wlan_spectral_update_rx_chainmask(struct wlan_hdd_link_info * link_info)626 wlan_spectral_update_rx_chainmask(struct wlan_hdd_link_info *link_info)
627 {
628 uint32_t chainmask_2g = 0;
629 uint32_t chainmask_5g = 0;
630 uint32_t chainmask;
631 qdf_freq_t home_chan_freq;
632 uint8_t pdev_id;
633 struct wlan_objmgr_vdev *vdev;
634 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
635
636 home_chan_freq = hdd_get_link_info_home_channel(link_info);
637 pdev_id = wlan_objmgr_pdev_get_pdev_id(hdd_ctx->pdev);
638 wma_get_rx_chainmask(pdev_id, &chainmask_2g, &chainmask_5g);
639 chainmask = chainmask_5g;
640
641 if (wlan_reg_is_24ghz_ch_freq(home_chan_freq))
642 chainmask = chainmask_2g;
643
644 hdd_debug("chan freq %d chainmask %d", home_chan_freq, chainmask);
645 vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_SPECTRAL_ID);
646 if (!vdev)
647 return QDF_STATUS_E_FAILURE;
648
649 wlan_vdev_mlme_set_rxchainmask(vdev, chainmask);
650 hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_SPECTRAL_ID);
651
652 return QDF_STATUS_SUCCESS;
653 }
654 #endif
655