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