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