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