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