xref: /wlan-dirver/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c (revision d0c05845839e5f2ba5a8dcebe0cd3e4cd4e8dfcf)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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: defines driver functions interfacing with linux kernel
22  */
23 
24 #include <qdf_list.h>
25 #include <qdf_status.h>
26 #include <linux/wireless.h>
27 #include <linux/netdevice.h>
28 #include <net/cfg80211.h>
29 #include <wlan_cfg80211.h>
30 #include <wlan_osif_priv.h>
31 #include <qdf_mem.h>
32 #include <wlan_spectral_ucfg_api.h>
33 #include <wlan_cfg80211_spectral.h>
34 #include <spectral_ioctl.h>
35 #include <wlan_objmgr_vdev_obj.h>
36 #include "wlan_osif_features.h"
37 
38 const struct nla_policy spectral_scan_policy[
39 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = {
40 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = {
41 							.type = NLA_U32},
42 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = {
43 							.type = NLA_U32},
44 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = {
45 							.type = NLA_U32},
46 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = {
47 							.type = NLA_U32},
48 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = {
49 							.type = NLA_U32},
50 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = {
51 							.type = NLA_U32},
52 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = {
53 							.type = NLA_U32},
54 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = {
55 							.type = NLA_U32},
56 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = {
57 							.type = NLA_U32},
58 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = {
59 							.type = NLA_U32},
60 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = {
61 							.type = NLA_U32},
62 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = {
63 							.type = NLA_U32},
64 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = {
65 							.type = NLA_U32},
66 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = {
67 							.type = NLA_U32},
68 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = {
69 							.type = NLA_U32},
70 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = {
71 							.type = NLA_U32},
72 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = {
73 							.type = NLA_U32},
74 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = {
75 							.type = NLA_U32},
76 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = {
77 							.type = NLA_U32},
78 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = {
79 							.type = NLA_U64},
80 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = {
81 							.type = NLA_U32},
82 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = {
83 							.type = NLA_U32},
84 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = {
85 							.type = NLA_U32},
86 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY] = {
87 							.type = NLA_U32},
88 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2] = {
89 							.type = NLA_U32},
90 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE] = {
91 							.type = NLA_U32},
92 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG] = {
93 							.type = NLA_U8},
94 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG] = {
95 							.type = NLA_U8},
96 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH] = {
97 							.type = NLA_U8},
98 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE] = {
99 							.type = NLA_U32},
100 };
101 
102 const struct nla_policy spectral_scan_get_status_policy[
103 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX + 1] = {
104 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED] = {
105 							.type = NLA_FLAG },
106 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE] = {
107 							.type = NLA_FLAG },
108 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE] = { .type = NLA_U32 },
109 };
110 
111 static void wlan_spectral_intit_config(struct spectral_config *config_req)
112 {
113 	config_req->ss_period =          SPECTRAL_PHYERR_PARAM_NOVAL;
114 	config_req->ss_recapture =       SPECTRAL_PHYERR_PARAM_NOVAL;
115 	config_req->ss_count =           SPECTRAL_PHYERR_PARAM_NOVAL;
116 	config_req->ss_fft_period =      SPECTRAL_PHYERR_PARAM_NOVAL;
117 	config_req->ss_short_report =    SPECTRAL_PHYERR_PARAM_NOVAL;
118 	config_req->ss_spectral_pri =    SPECTRAL_PHYERR_PARAM_NOVAL;
119 	config_req->ss_fft_size =        SPECTRAL_PHYERR_PARAM_NOVAL;
120 	config_req->ss_gc_ena =          SPECTRAL_PHYERR_PARAM_NOVAL;
121 	config_req->ss_restart_ena =     SPECTRAL_PHYERR_PARAM_NOVAL;
122 	config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL;
123 	config_req->ss_init_delay =      SPECTRAL_PHYERR_PARAM_NOVAL;
124 	config_req->ss_nb_tone_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
125 	config_req->ss_str_bin_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
126 	config_req->ss_wb_rpt_mode =     SPECTRAL_PHYERR_PARAM_NOVAL;
127 	config_req->ss_rssi_rpt_mode =   SPECTRAL_PHYERR_PARAM_NOVAL;
128 	config_req->ss_rssi_thr =        SPECTRAL_PHYERR_PARAM_NOVAL;
129 	config_req->ss_pwr_format =      SPECTRAL_PHYERR_PARAM_NOVAL;
130 	config_req->ss_rpt_mode =        SPECTRAL_PHYERR_PARAM_NOVAL;
131 	config_req->ss_bin_scale =       SPECTRAL_PHYERR_PARAM_NOVAL;
132 	config_req->ss_dbm_adj =         SPECTRAL_PHYERR_PARAM_NOVAL;
133 	config_req->ss_chn_mask =        SPECTRAL_PHYERR_PARAM_NOVAL;
134 	config_req->ss_frequency.cfreq1 = SPECTRAL_PHYERR_PARAM_NOVAL;
135 	config_req->ss_frequency.cfreq2 = SPECTRAL_PHYERR_PARAM_NOVAL;
136 	config_req->ss_bandwidth = SPECTRAL_PHYERR_PARAM_NOVAL;
137 }
138 
139 /**
140  * convert_spectral_mode_nl_to_internal() - Get Spectral mode
141  * @nl_spectral_mode: Spectral mode in vendor attribute
142  * @mode: Converted Spectral mode
143  *
144  * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE
145  */
146 static QDF_STATUS
147 convert_spectral_mode_nl_to_internal
148 		(enum qca_wlan_vendor_spectral_scan_mode nl_spectral_mode,
149 		 enum spectral_scan_mode *mode)
150 {
151 	switch (nl_spectral_mode) {
152 	case QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL:
153 		*mode = SPECTRAL_SCAN_MODE_NORMAL;
154 		break;
155 
156 	case QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE:
157 		*mode = SPECTRAL_SCAN_MODE_AGILE;
158 		break;
159 
160 	default:
161 		osif_err("Invalid spectral mode %u", nl_spectral_mode);
162 		return QDF_STATUS_E_FAILURE;
163 	}
164 
165 	return QDF_STATUS_SUCCESS;
166 }
167 
168 /**
169  * convert_spectral_err_code_internal_to_nl() - Get Spectral error code
170  * @spectral_err_code: Spectral error code used internally
171  * @nl_err_code: Spectral error code for cfg80211
172  *
173  * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE
174  */
175 static QDF_STATUS
176 convert_spectral_err_code_internal_to_nl
177 		(enum spectral_cp_error_code spectral_err_code,
178 		 enum qca_wlan_vendor_spectral_scan_error_code *nl_err_code)
179 {
180 	switch (spectral_err_code) {
181 	case SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED:
182 		*nl_err_code =
183 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED;
184 		break;
185 
186 	case SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED:
187 		*nl_err_code =
188 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
189 		break;
190 
191 	case SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE:
192 		*nl_err_code =
193 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
194 		break;
195 
196 	case SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED:
197 		*nl_err_code =
198 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
199 		break;
200 
201 	default:
202 		osif_err("Invalid spectral error code %u", spectral_err_code);
203 		return QDF_STATUS_E_FAILURE;
204 	}
205 
206 	return QDF_STATUS_SUCCESS;
207 }
208 
209 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
210 int
211 wlan_spectral_get_nl80211_chwidth(uint8_t phy_chwidth)
212 {
213 	switch ((enum phy_ch_width)phy_chwidth) {
214 	case CH_WIDTH_5MHZ:
215 		return NL80211_CHAN_WIDTH_5;
216 	case CH_WIDTH_10MHZ:
217 		return NL80211_CHAN_WIDTH_10;
218 	case CH_WIDTH_20MHZ:
219 		return NL80211_CHAN_WIDTH_20;
220 	case CH_WIDTH_40MHZ:
221 		return NL80211_CHAN_WIDTH_40;
222 	case CH_WIDTH_80MHZ:
223 		return NL80211_CHAN_WIDTH_80;
224 	case CH_WIDTH_160MHZ:
225 		return NL80211_CHAN_WIDTH_160;
226 	case CH_WIDTH_80P80MHZ:
227 		return NL80211_CHAN_WIDTH_80P80;
228 	case CH_WIDTH_320MHZ:
229 	case CH_WIDTH_MAX:
230 		return NL80211_CHAN_WIDTH_320;
231 	case CH_WIDTH_INVALID:
232 	default:
233 		osif_err("Invalid spectral channel width %u", phy_chwidth);
234 		return -EINVAL;
235 	}
236 }
237 
238 uint8_t
239 wlan_spectral_get_phy_ch_width(uint8_t nl_chwidth)
240 {
241 	switch ((enum nl80211_chan_width)nl_chwidth) {
242 	case NL80211_CHAN_WIDTH_5:
243 		return CH_WIDTH_5MHZ;
244 	case NL80211_CHAN_WIDTH_10:
245 		return CH_WIDTH_10MHZ;
246 	case NL80211_CHAN_WIDTH_20:
247 		return CH_WIDTH_20MHZ;
248 	case NL80211_CHAN_WIDTH_40:
249 		return CH_WIDTH_40MHZ;
250 	case NL80211_CHAN_WIDTH_80:
251 		return CH_WIDTH_80MHZ;
252 	case NL80211_CHAN_WIDTH_160:
253 		return CH_WIDTH_160MHZ;
254 	case NL80211_CHAN_WIDTH_80P80:
255 		return CH_WIDTH_80P80MHZ;
256 	case NL80211_CHAN_WIDTH_320:
257 		return CH_WIDTH_320MHZ;
258 	default:
259 		osif_err("Invalid nl80211 channel width %u", nl_chwidth);
260 		return CH_WIDTH_INVALID;
261 	}
262 }
263 #else
264 int
265 wlan_spectral_get_nl80211_chwidth(uint8_t phy_chwidth)
266 {
267 	switch ((enum phy_ch_width)phy_chwidth) {
268 	case CH_WIDTH_5MHZ:
269 		return NL80211_CHAN_WIDTH_5;
270 	case CH_WIDTH_10MHZ:
271 		return NL80211_CHAN_WIDTH_10;
272 	case CH_WIDTH_20MHZ:
273 		return NL80211_CHAN_WIDTH_20;
274 	case CH_WIDTH_40MHZ:
275 		return NL80211_CHAN_WIDTH_40;
276 	case CH_WIDTH_80MHZ:
277 		return NL80211_CHAN_WIDTH_80;
278 	case CH_WIDTH_160MHZ:
279 	case CH_WIDTH_MAX:
280 		return NL80211_CHAN_WIDTH_160;
281 	case CH_WIDTH_80P80MHZ:
282 		return NL80211_CHAN_WIDTH_80P80;
283 	case CH_WIDTH_INVALID:
284 	default:
285 		osif_err("Invalid spectral channel width %u", phy_chwidth);
286 		return -EINVAL;
287 	}
288 }
289 
290 uint8_t
291 wlan_spectral_get_phy_ch_width(uint8_t nl_chwidth)
292 {
293 	switch ((enum nl80211_chan_width)nl_chwidth) {
294 	case NL80211_CHAN_WIDTH_5:
295 		return CH_WIDTH_5MHZ;
296 	case NL80211_CHAN_WIDTH_10:
297 		return CH_WIDTH_10MHZ;
298 	case NL80211_CHAN_WIDTH_20:
299 		return CH_WIDTH_20MHZ;
300 	case NL80211_CHAN_WIDTH_40:
301 		return CH_WIDTH_40MHZ;
302 	case NL80211_CHAN_WIDTH_80:
303 		return CH_WIDTH_80MHZ;
304 	case NL80211_CHAN_WIDTH_160:
305 		return CH_WIDTH_160MHZ;
306 	case NL80211_CHAN_WIDTH_80P80:
307 		return CH_WIDTH_80P80MHZ;
308 	default:
309 		osif_err("Invalid nl80211 channel width %u", nl_chwidth);
310 		return CH_WIDTH_INVALID;
311 	}
312 }
313 #endif /* WLAN_FEATURE_11BE */
314 
315 #ifdef DIRECT_BUF_RX_DEBUG
316 QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
317 	struct wlan_objmgr_pdev *pdev,
318 	struct wlan_objmgr_vdev *vdev,
319 	struct nlattr **tb,
320 	enum spectral_scan_mode sscan_mode)
321 {
322 	struct spectral_cp_request sscan_req;
323 	uint8_t dma_debug_enable;
324 	QDF_STATUS status;
325 
326 	if (!tb || !pdev)
327 		return QDF_STATUS_E_FAILURE;
328 
329 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]) {
330 		dma_debug_enable = nla_get_u8(tb[
331 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]);
332 		sscan_req.ss_mode = sscan_mode;
333 		sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable;
334 		sscan_req.dma_debug_req.dma_debug_type =
335 				SPECTRAL_DMA_RING_DEBUG;
336 		sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG;
337 		status = ucfg_spectral_control(pdev, &sscan_req);
338 		if (status != QDF_STATUS_SUCCESS) {
339 			osif_err("Could not configure dma ring debug");
340 			return QDF_STATUS_E_FAILURE;
341 		}
342 	}
343 
344 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]) {
345 		dma_debug_enable = nla_get_u8(tb[
346 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]);
347 		sscan_req.ss_mode = sscan_mode;
348 		sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable;
349 		sscan_req.dma_debug_req.dma_debug_type =
350 				SPECTRAL_DMA_BUFFER_DEBUG;
351 		sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG;
352 		return ucfg_spectral_control(pdev, &sscan_req);
353 	}
354 
355 	return QDF_STATUS_SUCCESS;
356 }
357 #else
358 QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
359 	struct wlan_objmgr_pdev *pdev,
360 	struct wlan_objmgr_vdev *vdev,
361 	struct nlattr **tb,
362 	enum spectral_scan_mode sscan_mode)
363 {
364 	return QDF_STATUS_SUCCESS;
365 }
366 #endif /* DIRECT_BUF_RX_DEBUG */
367 
368 int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
369 						 struct wlan_objmgr_pdev *pdev,
370 						 struct wlan_objmgr_vdev *vdev,
371 						 const void *data,
372 						 int data_len)
373 {
374 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
375 	struct spectral_config config_req;
376 	QDF_STATUS status;
377 	uint64_t cookie;
378 	struct sk_buff *skb;
379 	uint32_t spectral_dbg_level;
380 	uint32_t scan_req_type = 0;
381 	struct spectral_cp_request sscan_req;
382 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
383 	uint16_t skb_len;
384 
385 	if (wlan_cfg80211_nla_parse(
386 			tb,
387 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
388 			data,
389 			data_len,
390 			spectral_scan_policy)) {
391 		osif_err("Invalid Spectral Scan config ATTR");
392 		return -EINVAL;
393 	}
394 
395 	wlan_spectral_intit_config(&config_req);
396 
397 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT])
398 		config_req.ss_count = nla_get_u32(tb
399 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]);
400 
401 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD])
402 		config_req.ss_period = nla_get_u32(tb
403 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]);
404 
405 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE])
406 		config_req.ss_recapture = nla_get_u32(tb
407 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE]);
408 
409 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY])
410 		config_req.ss_spectral_pri = nla_get_u32(tb
411 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]);
412 
413 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE])
414 		config_req.ss_fft_size = nla_get_u32(tb
415 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]);
416 
417 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA])
418 		config_req.ss_gc_ena = nla_get_u32(tb
419 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]);
420 
421 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA])
422 		config_req.ss_restart_ena = nla_get_u32(tb
423 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]);
424 
425 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF])
426 		config_req.ss_noise_floor_ref = nla_get_u32(tb
427 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]);
428 
429 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY])
430 		config_req.ss_init_delay = nla_get_u32(tb
431 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]);
432 
433 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR])
434 		config_req.ss_nb_tone_thr = nla_get_u32(tb
435 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]);
436 
437 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR])
438 		config_req.ss_str_bin_thr = nla_get_u32(tb
439 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]);
440 
441 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE])
442 		config_req.ss_wb_rpt_mode = nla_get_u32(tb
443 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]);
444 
445 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE])
446 		config_req.ss_rssi_rpt_mode = nla_get_u32(tb
447 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]);
448 
449 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR])
450 		config_req.ss_rssi_thr = nla_get_u32(tb
451 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]);
452 
453 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT])
454 		config_req.ss_pwr_format = nla_get_u32(tb
455 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]);
456 
457 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE])
458 		config_req.ss_rpt_mode = nla_get_u32(tb
459 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]);
460 
461 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE])
462 		config_req.ss_bin_scale = nla_get_u32(tb
463 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]);
464 
465 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ])
466 		config_req.ss_dbm_adj = nla_get_u32(tb
467 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]);
468 
469 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK])
470 		config_req.ss_chn_mask = nla_get_u32(tb
471 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]);
472 
473 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD])
474 		config_req.ss_fft_period = nla_get_u32(tb
475 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]);
476 
477 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT])
478 		config_req.ss_short_report = nla_get_u32(tb
479 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]);
480 
481 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY])
482 		config_req.ss_frequency.cfreq1 = nla_get_u32(tb
483 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY]);
484 
485 	config_req.ss_frequency.cfreq2 = 0;
486 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2])
487 		config_req.ss_frequency.cfreq2 = nla_get_u32(tb
488 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2]);
489 
490 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH]) {
491 		uint8_t sscan_bw_nl;
492 
493 		sscan_bw_nl = nla_get_u8(
494 		   tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH]);
495 
496 		/* Convert to phy_ch_width format */
497 		config_req.ss_bandwidth =
498 			wlan_spectral_get_phy_ch_width(sscan_bw_nl);
499 	}
500 
501 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) {
502 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
503 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode);
504 
505 		if (QDF_IS_STATUS_ERROR(status))
506 			return -EINVAL;
507 	}
508 
509 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) {
510 		spectral_dbg_level = nla_get_u32(tb
511 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]);
512 		sscan_req.ss_mode = sscan_mode;
513 		sscan_req.debug_req.spectral_dbg_level = spectral_dbg_level;
514 		sscan_req.req_id = SPECTRAL_SET_DEBUG_LEVEL;
515 		status = ucfg_spectral_control(pdev, &sscan_req);
516 		if (QDF_IS_STATUS_ERROR(status))
517 			return -EINVAL;
518 	}
519 
520 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE])
521 		scan_req_type = nla_get_u32(tb
522 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]);
523 
524 	skb_len = NLMSG_HDRLEN;
525 	/* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE */
526 	skb_len += NLA_HDRLEN + sizeof(u32);
527 	/* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE */
528 	skb_len += NLA_HDRLEN + sizeof(u64);
529 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
530 
531 	if (!skb) {
532 		osif_err(" reply skb alloc failed");
533 		return -ENOMEM;
534 	}
535 
536 	status = wlan_cfg80211_spectral_scan_dma_debug_config(
537 			pdev, vdev, tb, sscan_mode);
538 	if (QDF_IS_STATUS_ERROR(status)) {
539 		status = QDF_STATUS_E_INVAL;
540 		goto free_skb_return_os_status;
541 	}
542 
543 	if (vdev)
544 		sscan_req.vdev_id = wlan_vdev_get_id(vdev);
545 	else
546 		sscan_req.vdev_id = WLAN_INVALID_VDEV_ID;
547 
548 	if (CONFIG_REQUESTED(scan_req_type)) {
549 		sscan_req.ss_mode = sscan_mode;
550 		sscan_req.req_id = SPECTRAL_SET_CONFIG;
551 		qdf_mem_copy(&sscan_req.config_req.sscan_config, &config_req,
552 			     qdf_min(sizeof(sscan_req.config_req.sscan_config),
553 				     sizeof(config_req)));
554 		status = ucfg_spectral_control(pdev, &sscan_req);
555 		if (QDF_IS_STATUS_ERROR(status)) {
556 			enum qca_wlan_vendor_spectral_scan_error_code
557 							spectral_nl_err_code;
558 
559 			/* No error reasons populated, just return error */
560 			if (sscan_req.config_req.sscan_err_code ==
561 					SPECTRAL_SCAN_ERR_INVALID)
562 				goto free_skb_return_os_status;
563 
564 			status = convert_spectral_err_code_internal_to_nl
565 					(sscan_req.config_req.sscan_err_code,
566 					 &spectral_nl_err_code);
567 			if (QDF_IS_STATUS_ERROR(status)) {
568 				status = QDF_STATUS_E_INVAL;
569 				goto free_skb_return_os_status;
570 			}
571 
572 			if (nla_put_u32
573 			    (skb,
574 			     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
575 			     spectral_nl_err_code)) {
576 				status = QDF_STATUS_E_INVAL;
577 				goto free_skb_return_os_status;
578 			}
579 		}
580 	}
581 
582 	if (SCAN_REQUESTED(scan_req_type)) {
583 		sscan_req.ss_mode = sscan_mode;
584 		sscan_req.req_id = SPECTRAL_ACTIVATE_SCAN;
585 		status = ucfg_spectral_control(pdev, &sscan_req);
586 		if (QDF_IS_STATUS_ERROR(status)) {
587 			enum qca_wlan_vendor_spectral_scan_error_code
588 							spectral_nl_err_code;
589 
590 			/* No error reasons populated, just return error */
591 			if (sscan_req.action_req.sscan_err_code ==
592 					SPECTRAL_SCAN_ERR_INVALID)
593 				goto free_skb_return_os_status;
594 
595 			status = convert_spectral_err_code_internal_to_nl
596 					(sscan_req.action_req.sscan_err_code,
597 					 &spectral_nl_err_code);
598 			if (QDF_IS_STATUS_ERROR(status)) {
599 				status = QDF_STATUS_E_INVAL;
600 				goto free_skb_return_os_status;
601 			}
602 
603 			if (nla_put_u32
604 			    (skb,
605 			     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
606 			     spectral_nl_err_code)) {
607 				status = QDF_STATUS_E_INVAL;
608 				goto free_skb_return_os_status;
609 			}
610 		}
611 	}
612 
613 	cookie = 0;
614 	if (wlan_cfg80211_nla_put_u64(skb,
615 				      QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE,
616 				      cookie)) {
617 		status = QDF_STATUS_E_INVAL;
618 		goto free_skb_return_os_status;
619 	}
620 
621 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
622 	return 0;
623 free_skb_return_os_status:
624 	wlan_cfg80211_vendor_free_skb(skb);
625 	return qdf_status_to_os_return(status);
626 }
627 
628 int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
629 				     struct wlan_objmgr_pdev *pdev,
630 				     struct wlan_objmgr_vdev *vdev,
631 				     const void *data,
632 				     int data_len)
633 {
634 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
635 	QDF_STATUS status;
636 	struct spectral_cp_request sscan_req;
637 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
638 	struct sk_buff *skb;
639 
640 	if (wlan_cfg80211_nla_parse(
641 			tb,
642 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
643 			data,
644 			data_len,
645 			spectral_scan_policy)) {
646 		osif_err("Invalid Spectral Scan stop ATTR");
647 		return -EINVAL;
648 	}
649 
650 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) {
651 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
652 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode);
653 
654 		if (QDF_IS_STATUS_ERROR(status))
655 			return -EINVAL;
656 	}
657 
658 	sscan_req.ss_mode = sscan_mode;
659 	sscan_req.req_id = SPECTRAL_STOP_SCAN;
660 	status = ucfg_spectral_control(pdev, &sscan_req);
661 	if (QDF_IS_STATUS_ERROR(status)) {
662 		enum qca_wlan_vendor_spectral_scan_error_code
663 						spectral_nl_err_code;
664 
665 		/* No error reasons populated, just return error */
666 		if (sscan_req.action_req.sscan_err_code ==
667 				SPECTRAL_SCAN_ERR_INVALID)
668 			return qdf_status_to_os_return(status);
669 
670 		status = convert_spectral_err_code_internal_to_nl
671 				(sscan_req.action_req.sscan_err_code,
672 				 &spectral_nl_err_code);
673 		if (QDF_IS_STATUS_ERROR(status))
674 			return -EINVAL;
675 
676 		skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
677 				NLMSG_HDRLEN + sizeof(u32) + NLA_HDRLEN);
678 
679 		if (!skb) {
680 			osif_err(" reply skb alloc failed");
681 			return -ENOMEM;
682 		}
683 
684 		if (nla_put_u32
685 		    (skb,
686 		     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
687 		     spectral_nl_err_code)) {
688 			wlan_cfg80211_vendor_free_skb(skb);
689 			return -EINVAL;
690 		}
691 		wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
692 	}
693 
694 	return 0;
695 }
696 
697 int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy,
698 					   struct wlan_objmgr_pdev *pdev,
699 					   struct wlan_objmgr_vdev *vdev,
700 					   const void *data,
701 					   int data_len)
702 {
703 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
704 	struct spectral_config *sconfig;
705 	uint32_t spectral_dbg_level;
706 	struct sk_buff *skb;
707 	struct spectral_cp_request sscan_req;
708 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
709 	QDF_STATUS status;
710 	int sscan_bw_nl;
711 
712 	if (wlan_cfg80211_nla_parse(
713 			tb,
714 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
715 			data,
716 			data_len,
717 			spectral_scan_policy)) {
718 		osif_err("Invalid Spectral Scan config ATTR");
719 		return -EINVAL;
720 	}
721 
722 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) {
723 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
724 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode);
725 
726 		if (QDF_IS_STATUS_ERROR(status))
727 			return -EINVAL;
728 	}
729 
730 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
731 		(sizeof(u32) +
732 		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX +
733 		NLMSG_HDRLEN);
734 	if (!skb) {
735 		osif_err(" reply skb alloc failed");
736 		return -ENOMEM;
737 	}
738 
739 	sscan_req.ss_mode = sscan_mode;
740 	sscan_req.req_id = SPECTRAL_GET_CONFIG;
741 	status = ucfg_spectral_control(pdev, &sscan_req);
742 	sconfig = &sscan_req.config_req.sscan_config;
743 
744 	/* Convert to sscan_bw to NL8021 format */
745 	sscan_bw_nl = wlan_spectral_get_nl80211_chwidth(sconfig->ss_bandwidth);
746 	if (sscan_bw_nl == -EINVAL)
747 		goto fail;
748 
749 	if (nla_put_u32(skb,
750 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT,
751 			sconfig->ss_count) ||
752 	    nla_put_u32(skb,
753 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD,
754 			sconfig->ss_period) ||
755 	    nla_put_u32(skb,
756 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY,
757 			sconfig->ss_spectral_pri) ||
758 	    nla_put_u32(skb,
759 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE,
760 			sconfig->ss_fft_size) ||
761 	    nla_put_u32(skb,
762 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA,
763 			sconfig->ss_gc_ena) ||
764 	    nla_put_u32(skb,
765 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA,
766 			sconfig->ss_restart_ena) ||
767 	    nla_put_u32(
768 		skb,
769 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF,
770 		sconfig->ss_noise_floor_ref) ||
771 	    nla_put_u32(skb,
772 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY,
773 			sconfig->ss_init_delay) ||
774 	    nla_put_u32(skb,
775 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR,
776 			sconfig->ss_nb_tone_thr) ||
777 	    nla_put_u32(skb,
778 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR,
779 			sconfig->ss_str_bin_thr) ||
780 	    nla_put_u32(skb,
781 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE,
782 			sconfig->ss_wb_rpt_mode) ||
783 	    nla_put_u32(skb,
784 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE,
785 			sconfig->ss_rssi_rpt_mode) ||
786 	    nla_put_u32(skb,
787 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR,
788 			sconfig->ss_rssi_thr) ||
789 	    nla_put_u32(skb,
790 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT,
791 			sconfig->ss_pwr_format) ||
792 	    nla_put_u32(skb,
793 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE,
794 			sconfig->ss_rpt_mode) ||
795 	    nla_put_u32(skb,
796 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE,
797 			sconfig->ss_bin_scale) ||
798 	    nla_put_u32(skb,
799 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ,
800 			sconfig->ss_dbm_adj) ||
801 	    nla_put_u32(skb,
802 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK,
803 			sconfig->ss_chn_mask) ||
804 	    nla_put_u32(skb,
805 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD,
806 			sconfig->ss_fft_period) ||
807 	    nla_put_u32(skb,
808 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT,
809 			sconfig->ss_short_report) ||
810 	    nla_put_u32(skb,
811 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY,
812 			sconfig->ss_frequency.cfreq1) ||
813 	    nla_put_u32(skb,
814 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2,
815 			sconfig->ss_frequency.cfreq2) ||
816 	    nla_put_u8(skb,
817 		       QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH,
818 		       sscan_bw_nl) ||
819 	    nla_put_u32(skb,
820 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE,
821 			sconfig->ss_recapture))
822 
823 		goto fail;
824 
825 	sscan_req.ss_mode = sscan_mode;
826 	sscan_req.req_id = SPECTRAL_GET_DEBUG_LEVEL;
827 	status = ucfg_spectral_control(pdev, &sscan_req);
828 	spectral_dbg_level = sscan_req.debug_req.spectral_dbg_level;
829 	if (nla_put_u32(skb,
830 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL,
831 			spectral_dbg_level))
832 		goto fail;
833 
834 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
835 	return 0;
836 fail:
837 	wlan_cfg80211_vendor_free_skb(skb);
838 	return -EINVAL;
839 }
840 
841 int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy,
842 					struct wlan_objmgr_pdev *pdev,
843 					struct wlan_objmgr_vdev *vdev,
844 					const void *data,
845 					int data_len)
846 {
847 	struct spectral_caps *scaps;
848 	struct sk_buff *skb;
849 	struct spectral_cp_request sscan_req;
850 	QDF_STATUS status;
851 
852 	sscan_req.req_id = SPECTRAL_GET_CAPABILITY_INFO;
853 	status = ucfg_spectral_control(pdev, &sscan_req);
854 	scaps = &sscan_req.caps_req.sscan_caps;
855 
856 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
857 		(sizeof(u32) +
858 		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX +
859 		NLMSG_HDRLEN);
860 	if (!skb) {
861 		osif_err(" reply skb alloc failed");
862 		return -ENOMEM;
863 	}
864 
865 	if (scaps->phydiag_cap)
866 		if (nla_put_flag(
867 			skb,
868 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG))
869 			goto fail;
870 
871 	if (scaps->radar_cap)
872 		if (nla_put_flag(skb,
873 				 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR))
874 			goto fail;
875 
876 	if (scaps->spectral_cap)
877 		if (nla_put_flag(
878 			skb,
879 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL))
880 			goto fail;
881 
882 	if (scaps->advncd_spectral_cap)
883 		if (nla_put_flag(
884 		skb,
885 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL))
886 			goto fail;
887 
888 	if (nla_put_u32(skb,
889 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN,
890 			scaps->hw_gen))
891 		goto fail;
892 
893 	if (scaps->is_scaling_params_populated) {
894 		if (nla_put_u16(
895 			skb,
896 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID,
897 			scaps->formula_id))
898 			goto fail;
899 
900 		if (nla_put_u16(
901 			skb,
902 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_LOW_LEVEL_OFFSET,
903 			scaps->low_level_offset))
904 			goto fail;
905 
906 		if (nla_put_u16(
907 		       skb,
908 		       QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HIGH_LEVEL_OFFSET,
909 		       scaps->high_level_offset))
910 			goto fail;
911 
912 		if (nla_put_u16(
913 			skb,
914 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RSSI_THR,
915 			scaps->rssi_thr))
916 			goto fail;
917 
918 		if (nla_put_u8(
919 		    skb,
920 		    QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN,
921 		    scaps->default_agc_max_gain))
922 			goto fail;
923 	}
924 
925 	if (scaps->agile_spectral_cap) {
926 		int ret;
927 
928 		ret = nla_put_flag
929 			(skb,
930 			 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL);
931 		if (ret)
932 			goto fail;
933 	}
934 
935 	if (scaps->agile_spectral_cap_160) {
936 		int ret;
937 
938 		ret = nla_put_flag
939 		    (skb,
940 		     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_160);
941 		if (ret)
942 			goto fail;
943 	}
944 	if (scaps->agile_spectral_cap_80p80) {
945 		int ret;
946 
947 		ret = nla_put_flag
948 		  (skb,
949 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80);
950 		if (ret)
951 			goto fail;
952 	}
953 	if (scaps->agile_spectral_cap_320) {
954 		int ret;
955 
956 		ret = nla_put_flag
957 		  (skb,
958 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320);
959 		if (ret)
960 			goto fail;
961 	}
962 
963 
964 	if (nla_put_u32(
965 		skb,
966 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_20_MHZ,
967 		scaps->num_detectors_20mhz))
968 		goto fail;
969 
970 	if (nla_put_u32(
971 		skb,
972 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_40_MHZ,
973 		scaps->num_detectors_40mhz))
974 		goto fail;
975 
976 	if (nla_put_u32(
977 		skb,
978 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80_MHZ,
979 		scaps->num_detectors_80mhz))
980 		goto fail;
981 
982 	if (nla_put_u32(
983 		skb,
984 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_160_MHZ,
985 		scaps->num_detectors_160mhz))
986 		goto fail;
987 
988 	if (nla_put_u32(
989 		skb,
990 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ,
991 		scaps->num_detectors_80p80mhz))
992 		goto fail;
993 
994 	if (nla_put_u32(
995 		skb,
996 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ,
997 		scaps->num_detectors_320mhz))
998 		goto fail;
999 
1000 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
1001 
1002 	return 0;
1003 
1004 fail:
1005 	wlan_cfg80211_vendor_free_skb(skb);
1006 	return -EINVAL;
1007 }
1008 
1009 int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy,
1010 					       struct wlan_objmgr_pdev *pdev,
1011 					       struct wlan_objmgr_vdev *vdev,
1012 					       const void *data,
1013 					       int data_len)
1014 {
1015 	struct spectral_diag_stats *spetcral_diag;
1016 	struct sk_buff *skb;
1017 	struct spectral_cp_request sscan_req;
1018 	QDF_STATUS status;
1019 
1020 	sscan_req.req_id = SPECTRAL_GET_DIAG_STATS;
1021 	status = ucfg_spectral_control(pdev, &sscan_req);
1022 	spetcral_diag = &sscan_req.diag_req.sscan_diag;
1023 
1024 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1025 		(sizeof(u64) + NLA_HDRLEN) *
1026 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX +
1027 		NLMSG_HDRLEN);
1028 	if (!skb) {
1029 		osif_err(" reply skb alloc failed");
1030 		return -ENOMEM;
1031 	}
1032 
1033 	if (wlan_cfg80211_nla_put_u64(
1034 		skb,
1035 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH,
1036 		spetcral_diag->spectral_mismatch) ||
1037 	    wlan_cfg80211_nla_put_u64(
1038 		skb,
1039 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN,
1040 		spetcral_diag->spectral_sec80_sfft_insufflen) ||
1041 	    wlan_cfg80211_nla_put_u64(
1042 		skb,
1043 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT,
1044 		spetcral_diag->spectral_no_sec80_sfft) ||
1045 	    wlan_cfg80211_nla_put_u64(
1046 		skb,
1047 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH,
1048 		spetcral_diag->spectral_vhtseg1id_mismatch) ||
1049 	    wlan_cfg80211_nla_put_u64(
1050 		skb,
1051 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH,
1052 		spetcral_diag->spectral_vhtseg2id_mismatch)) {
1053 		wlan_cfg80211_vendor_free_skb(skb);
1054 		return -EINVAL;
1055 	}
1056 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
1057 
1058 	return 0;
1059 }
1060 
1061 int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
1062 					   struct wlan_objmgr_pdev *pdev,
1063 					   struct wlan_objmgr_vdev *vdev,
1064 					   const void *data,
1065 					   int data_len)
1066 {
1067 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX + 1];
1068 	struct spectral_scan_state sscan_state = { 0 };
1069 	struct sk_buff *skb;
1070 	struct spectral_cp_request sscan_req;
1071 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
1072 	QDF_STATUS status;
1073 
1074 	if (wlan_cfg80211_nla_parse(
1075 			tb,
1076 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX,
1077 			data,
1078 			data_len,
1079 			spectral_scan_get_status_policy)) {
1080 		osif_err("Invalid Spectral Scan config ATTR");
1081 		return -EINVAL;
1082 	}
1083 
1084 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE]) {
1085 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
1086 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE]), &sscan_mode);
1087 
1088 		if (QDF_IS_STATUS_ERROR(status))
1089 			return -EINVAL;
1090 	}
1091 
1092 	/* Sending a request and extracting response from it has to be atomic */
1093 	sscan_req.ss_mode = sscan_mode;
1094 	sscan_req.req_id = SPECTRAL_IS_ACTIVE;
1095 	status = ucfg_spectral_control(pdev, &sscan_req);
1096 	sscan_state.is_active = sscan_req.status_req.is_active;
1097 
1098 	sscan_req.ss_mode = sscan_mode;
1099 	sscan_req.req_id = SPECTRAL_IS_ENABLED;
1100 	status = ucfg_spectral_control(pdev, &sscan_req);
1101 	sscan_state.is_enabled = sscan_req.status_req.is_enabled;
1102 
1103 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1104 		2 * (sizeof(u32) + NLA_HDRLEN) + NLMSG_HDRLEN);
1105 	if (!skb) {
1106 		osif_err(" reply skb alloc failed");
1107 		return -ENOMEM;
1108 	}
1109 
1110 	if (sscan_state.is_enabled)
1111 		if (nla_put_flag(
1112 			skb,
1113 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED))
1114 			goto fail;
1115 
1116 	if (sscan_state.is_active)
1117 		if (nla_put_flag(
1118 			skb,
1119 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE))
1120 			goto fail;
1121 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
1122 
1123 	return 0;
1124 fail:
1125 	wlan_cfg80211_vendor_free_skb(skb);
1126 	return -EINVAL;
1127 }
1128