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