xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c (revision 87a8e4458319c60b618522e263ed900e36aab528)
1 /*
2  * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: defines driver functions interfacing with linux kernel
21  */
22 
23 #include <qdf_list.h>
24 #include <qdf_status.h>
25 #include <linux/wireless.h>
26 #include <linux/netdevice.h>
27 #include <net/cfg80211.h>
28 #include <wlan_cfg80211.h>
29 #include <wlan_osif_priv.h>
30 #include <qdf_mem.h>
31 #include <wlan_spectral_ucfg_api.h>
32 #include <wlan_cfg80211_spectral.h>
33 #include <spectral_ioctl.h>
34 #include "qal_devcfg.h"
35 
36 static const struct nla_policy spectral_scan_policy[
37 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = {
38 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = {
39 							.type = NLA_U32},
40 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = {
41 							.type = NLA_U32},
42 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = {
43 							.type = NLA_U32},
44 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = {
45 							.type = NLA_U32},
46 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = {
47 							.type = NLA_U32},
48 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = {
49 							.type = NLA_U32},
50 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = {
51 							.type = NLA_U32},
52 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = {
53 							.type = NLA_U32},
54 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = {
55 							.type = NLA_U32},
56 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = {
57 							.type = NLA_U32},
58 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = {
59 							.type = NLA_U32},
60 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = {
61 							.type = NLA_U32},
62 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = {
63 							.type = NLA_U32},
64 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = {
65 							.type = NLA_U32},
66 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = {
67 							.type = NLA_U32},
68 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = {
69 							.type = NLA_U32},
70 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = {
71 							.type = NLA_U32},
72 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = {
73 							.type = NLA_U32},
74 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = {
75 							.type = NLA_U32},
76 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = {
77 							.type = NLA_U64},
78 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = {
79 							.type = NLA_U32},
80 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = {
81 							.type = NLA_U32},
82 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = {
83 							.type = NLA_U32},
84 };
85 
86 static void wlan_spectral_intit_config(struct spectral_config *config_req)
87 {
88 	config_req->ss_period =          SPECTRAL_PHYERR_PARAM_NOVAL;
89 	config_req->ss_count =           SPECTRAL_PHYERR_PARAM_NOVAL;
90 	config_req->ss_fft_period =      SPECTRAL_PHYERR_PARAM_NOVAL;
91 	config_req->ss_short_report =    SPECTRAL_PHYERR_PARAM_NOVAL;
92 	config_req->ss_spectral_pri =    SPECTRAL_PHYERR_PARAM_NOVAL;
93 	config_req->ss_fft_size =        SPECTRAL_PHYERR_PARAM_NOVAL;
94 	config_req->ss_gc_ena =          SPECTRAL_PHYERR_PARAM_NOVAL;
95 	config_req->ss_restart_ena =     SPECTRAL_PHYERR_PARAM_NOVAL;
96 	config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL;
97 	config_req->ss_init_delay =      SPECTRAL_PHYERR_PARAM_NOVAL;
98 	config_req->ss_nb_tone_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
99 	config_req->ss_str_bin_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
100 	config_req->ss_wb_rpt_mode =     SPECTRAL_PHYERR_PARAM_NOVAL;
101 	config_req->ss_rssi_rpt_mode =   SPECTRAL_PHYERR_PARAM_NOVAL;
102 	config_req->ss_rssi_thr =        SPECTRAL_PHYERR_PARAM_NOVAL;
103 	config_req->ss_pwr_format =      SPECTRAL_PHYERR_PARAM_NOVAL;
104 	config_req->ss_rpt_mode =        SPECTRAL_PHYERR_PARAM_NOVAL;
105 	config_req->ss_bin_scale =       SPECTRAL_PHYERR_PARAM_NOVAL;
106 	config_req->ss_dbm_adj =         SPECTRAL_PHYERR_PARAM_NOVAL;
107 	config_req->ss_chn_mask =        SPECTRAL_PHYERR_PARAM_NOVAL;
108 }
109 
110 static int wlan_spectral_set_config(struct wlan_objmgr_pdev *pdev,
111 				    struct spectral_config *config_req)
112 {
113 	int status;
114 
115 	status = ucfg_spectral_control(pdev,
116 				       SPECTRAL_SET_CONFIG,
117 				       config_req,
118 				       sizeof(struct spectral_config),
119 				       NULL,
120 				       NULL);
121 	if (status < 0)
122 		return -EINVAL;
123 
124 	return 0;
125 }
126 
127 static int wlan_spectral_set_debug_level(struct wlan_objmgr_pdev *pdev,
128 					 uint32_t spectral_dbg_level)
129 {
130 	int status;
131 
132 	status = ucfg_spectral_control(pdev,
133 				       SPECTRAL_SET_DEBUG_LEVEL,
134 				       &spectral_dbg_level,
135 				       sizeof(uint32_t),
136 				       NULL,
137 				       NULL);
138 	if (status < 0)
139 		return -EINVAL;
140 
141 	return 0;
142 }
143 
144 static int wlan_spectral_get_debug_level(struct wlan_objmgr_pdev *pdev,
145 					 uint32_t *spectral_dbg_level)
146 {
147 	int status;
148 	uint32_t outsize;
149 
150 	outsize = sizeof(uint32_t);
151 	status = ucfg_spectral_control(pdev,
152 				       SPECTRAL_GET_DEBUG_LEVEL,
153 				       NULL,
154 				       0,
155 				       spectral_dbg_level,
156 				       &outsize);
157 	if (status < 0)
158 		return -EINVAL;
159 
160 	return 0;
161 }
162 
163 static int wlan_spectral_get_config(struct wlan_objmgr_pdev *pdev,
164 				    struct spectral_config *config_req)
165 {
166 	int status;
167 	uint32_t outsize;
168 
169 	outsize = sizeof(struct spectral_config);
170 	status = ucfg_spectral_control(pdev,
171 				       SPECTRAL_GET_CONFIG,
172 				       NULL,
173 				       0,
174 				       config_req,
175 				       &outsize);
176 	if (status < 0)
177 		return -EINVAL;
178 
179 	return 0;
180 }
181 
182 static int wlan_spectral_get_cap(struct wlan_objmgr_pdev *pdev,
183 				 struct spectral_caps *spectral_cap)
184 {
185 	int status;
186 	uint32_t outsize;
187 
188 	outsize = sizeof(struct spectral_caps);
189 	status = ucfg_spectral_control(pdev,
190 				       SPECTRAL_GET_CAPABILITY_INFO,
191 				       NULL,
192 				       0,
193 				       spectral_cap,
194 				       &outsize);
195 	if (status < 0)
196 		return -EINVAL;
197 
198 	return 0;
199 }
200 
201 static int wlan_spectral_get_diag_stats(
202 		struct wlan_objmgr_pdev *pdev,
203 		struct spectral_diag_stats *spectral_diag)
204 {
205 	int status;
206 	uint32_t outsize;
207 
208 	outsize = sizeof(struct spectral_diag_stats);
209 	status = ucfg_spectral_control(pdev,
210 				       SPECTRAL_GET_DIAG_STATS,
211 				       NULL,
212 				       0,
213 				       spectral_diag,
214 				       &outsize);
215 	if (status < 0)
216 		return -EINVAL;
217 
218 	return 0;
219 }
220 
221 static int wlan_spectral_scan_get_status(
222 		struct wlan_objmgr_pdev *pdev,
223 		struct spectral_scan_state *sscan_state)
224 {
225 	uint32_t is_active;
226 	uint32_t is_enabled;
227 	int status;
228 	uint32_t outsize;
229 
230 	outsize = sizeof(uint32_t);
231 	status = ucfg_spectral_control(pdev,
232 				       SPECTRAL_IS_ACTIVE,
233 				       NULL,
234 				       0,
235 				       &is_active,
236 				       &outsize);
237 	if (status < 0)
238 		return -EINVAL;
239 
240 	sscan_state->is_active = is_active;
241 
242 	outsize = sizeof(uint32_t);
243 	status = ucfg_spectral_control(pdev,
244 				       SPECTRAL_IS_ENABLED,
245 				       NULL,
246 				       0,
247 				       &is_enabled,
248 				       &outsize);
249 	if (status < 0)
250 		return -EINVAL;
251 
252 	sscan_state->is_enabled = is_enabled;
253 
254 	return 0;
255 }
256 
257 static int wlan_start_spectral_scan(struct wlan_objmgr_pdev *pdev)
258 {
259 	int status;
260 
261 	status = ucfg_spectral_control(pdev,
262 				       SPECTRAL_ACTIVATE_SCAN,
263 				       NULL,
264 				       0,
265 				       NULL,
266 				       NULL);
267 	if (status < 0)
268 		return -EINVAL;
269 
270 	return 0;
271 }
272 
273 static int wlan_stop_spectral_scan(struct wlan_objmgr_pdev *pdev)
274 {
275 	int status;
276 
277 	status = ucfg_spectral_control(pdev,
278 				       SPECTRAL_STOP_SCAN,
279 				       NULL,
280 				       0,
281 				       NULL,
282 				       NULL);
283 	if (status < 0)
284 		return -EINVAL;
285 
286 	return 0;
287 }
288 
289 int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
290 						 struct wlan_objmgr_pdev *pdev,
291 						 const void *data,
292 						 int data_len)
293 {
294 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
295 	struct spectral_config config_req;
296 	QDF_STATUS status;
297 	uint64_t cookie;
298 	struct sk_buff *skb;
299 	uint32_t spectral_dbg_level;
300 	uint32_t scan_req_type = 0;
301 
302 	if (wlan_cfg80211_nla_parse(
303 			tb,
304 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
305 			data,
306 			data_len,
307 			spectral_scan_policy)) {
308 		qdf_print("Invalid Spectral Scan config ATTR");
309 		return -EINVAL;
310 	}
311 
312 	wlan_spectral_intit_config(&config_req);
313 
314 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT])
315 		config_req.ss_count = nla_get_u32(tb
316 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]);
317 
318 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD])
319 		config_req.ss_period = nla_get_u32(tb
320 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]);
321 
322 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY])
323 		config_req.ss_spectral_pri = nla_get_u32(tb
324 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]);
325 
326 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE])
327 		config_req.ss_fft_size = nla_get_u32(tb
328 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]);
329 
330 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA])
331 		config_req.ss_gc_ena = nla_get_u32(tb
332 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]);
333 
334 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA])
335 		config_req.ss_restart_ena = nla_get_u32(tb
336 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]);
337 
338 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF])
339 		config_req.ss_noise_floor_ref = nla_get_u32(tb
340 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]);
341 
342 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY])
343 		config_req.ss_init_delay = nla_get_u32(tb
344 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]);
345 
346 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR])
347 		config_req.ss_nb_tone_thr = nla_get_u32(tb
348 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]);
349 
350 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR])
351 		config_req.ss_str_bin_thr = nla_get_u32(tb
352 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]);
353 
354 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE])
355 		config_req.ss_wb_rpt_mode = nla_get_u32(tb
356 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]);
357 
358 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE])
359 		config_req.ss_rssi_rpt_mode = nla_get_u32(tb
360 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]);
361 
362 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR])
363 		config_req.ss_rssi_thr = nla_get_u32(tb
364 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]);
365 
366 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT])
367 		config_req.ss_pwr_format = nla_get_u32(tb
368 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]);
369 
370 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE])
371 		config_req.ss_rpt_mode = nla_get_u32(tb
372 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]);
373 
374 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE])
375 		config_req.ss_bin_scale = nla_get_u32(tb
376 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]);
377 
378 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ])
379 		config_req.ss_dbm_adj = nla_get_u32(tb
380 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]);
381 
382 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK])
383 		config_req.ss_chn_mask = nla_get_u32(tb
384 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]);
385 
386 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD])
387 		config_req.ss_fft_period = nla_get_u32(tb
388 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]);
389 
390 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT])
391 		config_req.ss_short_report = nla_get_u32(tb
392 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]);
393 
394 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) {
395 		spectral_dbg_level = nla_get_u32(tb
396 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]);
397 		status = wlan_spectral_set_debug_level(pdev,
398 						       spectral_dbg_level);
399 		if (QDF_STATUS_SUCCESS != status)
400 			return -EINVAL;
401 	}
402 
403 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE])
404 		scan_req_type = nla_get_u32(tb
405 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]);
406 
407 	if (CONFIG_REQUESTED(scan_req_type)) {
408 		status = wlan_spectral_set_config(pdev, &config_req);
409 		if (QDF_STATUS_SUCCESS != status)
410 			return -EINVAL;
411 	}
412 
413 	if (SCAN_REQUESTED(scan_req_type)) {
414 		status = wlan_start_spectral_scan(pdev);
415 		if (QDF_STATUS_SUCCESS != status)
416 			return -EINVAL;
417 	}
418 
419 	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u64) +
420 		NLA_HDRLEN + NLMSG_HDRLEN);
421 	if (!skb) {
422 		qdf_print(" reply skb alloc failed");
423 		return -ENOMEM;
424 	}
425 
426 	cookie = 0;
427 	if (wlan_cfg80211_nla_put_u64(skb,
428 				      QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE,
429 				      cookie)) {
430 		kfree_skb(skb);
431 		return -EINVAL;
432 	}
433 
434 	qal_devcfg_send_response((qdf_nbuf_t)skb);
435 
436 	return 0;
437 }
438 
439 int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
440 				     struct wlan_objmgr_pdev *pdev,
441 				     const void *data,
442 				     int data_len)
443 {
444 	QDF_STATUS status;
445 
446 	status = wlan_stop_spectral_scan(pdev);
447 	if (QDF_STATUS_SUCCESS != status)
448 		return -EINVAL;
449 	return 0;
450 }
451 
452 int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy,
453 					   struct wlan_objmgr_pdev *pdev,
454 					   const void *data,
455 					   int data_len)
456 {
457 	struct spectral_config config_buf;
458 	uint32_t spectral_dbg_level;
459 	struct sk_buff *skb;
460 
461 	wlan_spectral_get_config(pdev, &config_buf);
462 	wlan_spectral_get_debug_level(pdev, &spectral_dbg_level);
463 
464 	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (21 * sizeof(u32)) +
465 		NLA_HDRLEN + NLMSG_HDRLEN);
466 	if (!skb) {
467 		qdf_print(" reply skb alloc failed");
468 		return -ENOMEM;
469 	}
470 
471 	if (nla_put_u32(skb,
472 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT,
473 			config_buf.ss_count) ||
474 	    nla_put_u32(skb,
475 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD,
476 			config_buf.ss_period) ||
477 	    nla_put_u32(skb,
478 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY,
479 			config_buf.ss_spectral_pri) ||
480 	    nla_put_u32(skb,
481 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE,
482 			config_buf.ss_fft_size) ||
483 	    nla_put_u32(skb,
484 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA,
485 			config_buf.ss_gc_ena) ||
486 	    nla_put_u32(skb,
487 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA,
488 			config_buf.ss_restart_ena) ||
489 	    nla_put_u32(
490 		skb,
491 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF,
492 		config_buf.ss_noise_floor_ref) ||
493 	    nla_put_u32(skb,
494 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY,
495 			config_buf.ss_init_delay) ||
496 	    nla_put_u32(skb,
497 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR,
498 			config_buf.ss_nb_tone_thr) ||
499 	    nla_put_u32(skb,
500 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR,
501 			config_buf.ss_str_bin_thr) ||
502 	    nla_put_u32(skb,
503 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE,
504 			config_buf.ss_wb_rpt_mode) ||
505 	    nla_put_u32(skb,
506 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE,
507 			config_buf.ss_rssi_rpt_mode) ||
508 	    nla_put_u32(skb,
509 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR,
510 			config_buf.ss_rssi_thr) ||
511 	    nla_put_u32(skb,
512 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT,
513 			config_buf.ss_pwr_format) ||
514 	    nla_put_u32(skb,
515 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE,
516 			config_buf.ss_rpt_mode) ||
517 	    nla_put_u32(skb,
518 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE,
519 			config_buf.ss_bin_scale) ||
520 	    nla_put_u32(skb,
521 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ,
522 			config_buf.ss_dbm_adj) ||
523 	    nla_put_u32(skb,
524 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK,
525 			config_buf.ss_chn_mask) ||
526 	    nla_put_u32(skb,
527 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD,
528 			config_buf.ss_fft_period) ||
529 	    nla_put_u32(skb,
530 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT,
531 			config_buf.ss_short_report) ||
532 	    nla_put_u32(skb,
533 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL,
534 			spectral_dbg_level)) {
535 		kfree_skb(skb);
536 		return -EINVAL;
537 	}
538 	qal_devcfg_send_response((qdf_nbuf_t)skb);
539 
540 	return 0;
541 }
542 
543 int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy,
544 					struct wlan_objmgr_pdev *pdev,
545 					const void *data,
546 					int data_len)
547 {
548 	struct spectral_caps spectral_cap;
549 	struct sk_buff *skb;
550 
551 	wlan_spectral_get_cap(pdev, &spectral_cap);
552 
553 	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 5 * sizeof(u32) +
554 		NLA_HDRLEN + NLMSG_HDRLEN);
555 	if (!skb) {
556 		qdf_print(" reply skb alloc failed");
557 		return -ENOMEM;
558 	}
559 
560 	if (spectral_cap.phydiag_cap)
561 		if (nla_put_flag(
562 			skb,
563 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG))
564 			goto fail;
565 
566 	if (spectral_cap.radar_cap)
567 		if (nla_put_flag(skb,
568 				 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR))
569 			goto fail;
570 
571 	if (spectral_cap.spectral_cap)
572 		if (nla_put_flag(
573 			skb,
574 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL))
575 			goto fail;
576 
577 	if (spectral_cap.advncd_spectral_cap)
578 		if (nla_put_flag(
579 		skb,
580 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL))
581 			goto fail;
582 
583 	if (nla_put_u32(skb,
584 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN,
585 			spectral_cap.hw_gen))
586 		goto fail;
587 
588 	qal_devcfg_send_response((qdf_nbuf_t)skb);
589 
590 	return 0;
591 
592 fail:
593 	kfree_skb(skb);
594 	return -EINVAL;
595 }
596 
597 int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy,
598 					       struct wlan_objmgr_pdev *pdev,
599 					       const void *data,
600 					       int data_len)
601 {
602 	struct spectral_diag_stats spetcral_diag;
603 	struct sk_buff *skb;
604 
605 	wlan_spectral_get_diag_stats(pdev, &spetcral_diag);
606 
607 	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 5 * sizeof(u64) +
608 		NLA_HDRLEN + NLMSG_HDRLEN);
609 	if (!skb) {
610 		qdf_print(" reply skb alloc failed");
611 		return -ENOMEM;
612 	}
613 
614 	if (wlan_cfg80211_nla_put_u64(
615 		skb,
616 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH,
617 		spetcral_diag.spectral_mismatch) ||
618 	    wlan_cfg80211_nla_put_u64(
619 		skb,
620 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN,
621 		spetcral_diag.spectral_sec80_sfft_insufflen) ||
622 	    wlan_cfg80211_nla_put_u64(
623 		skb,
624 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT,
625 		spetcral_diag.spectral_no_sec80_sfft) ||
626 	    wlan_cfg80211_nla_put_u64(
627 		skb,
628 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH,
629 		spetcral_diag.spectral_vhtseg1id_mismatch) ||
630 	    wlan_cfg80211_nla_put_u64(
631 		skb,
632 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH,
633 		spetcral_diag.spectral_vhtseg2id_mismatch)) {
634 		kfree_skb(skb);
635 		return -EINVAL;
636 	}
637 	qal_devcfg_send_response((qdf_nbuf_t)skb);
638 
639 	return 0;
640 }
641 
642 int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
643 					   struct wlan_objmgr_pdev *pdev,
644 					   const void *data,
645 					   int data_len)
646 {
647 	struct spectral_scan_state sscan_state = { 0 };
648 	struct sk_buff *skb;
649 
650 	skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 2 * sizeof(u32) +
651 		NLA_HDRLEN + NLMSG_HDRLEN);
652 	if (!skb) {
653 		qdf_print(" reply skb alloc failed");
654 		return -ENOMEM;
655 	}
656 
657 	wlan_spectral_scan_get_status(pdev, &sscan_state);
658 
659 	if (sscan_state.is_enabled)
660 		if (nla_put_flag(
661 			skb,
662 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED))
663 			goto fail;
664 
665 	if (sscan_state.is_active)
666 		if (nla_put_flag(
667 			skb,
668 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE))
669 			goto fail;
670 	qal_devcfg_send_response((qdf_nbuf_t)skb);
671 	return 0;
672 
673 fail:
674 	kfree_skb(skb);
675 	return -EINVAL;
676 }
677