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