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