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