1 /*
2 * Copyright (c) 2011,2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 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 #include <wlan_tgt_def_config.h>
21 #include <hif.h>
22 #include <target_type.h>
23 #include <hif_hw_version.h>
24 #include <wmi_unified_api.h>
25 #include <target_if_spectral.h>
26 #include <wlan_lmac_if_def.h>
27 #include <wlan_osif_priv.h>
28 #include <init_deinit_lmac.h>
29 #include <reg_services_public_struct.h>
30 #include <target_if_spectral_sim.h>
31 #include <target_if.h>
32 #include <qdf_module.h>
33 #include <wlan_reg_services_api.h>
34 #include <wlan_dfs_ucfg_api.h>
35
36 /*
37 * @spectral_ops - Spectral function table, holds the Spectral functions that
38 * depend on whether the architecture is Direct Attach or Offload. This is used
39 * to populate the actual Spectral function table present in the Spectral
40 * module.
41 */
42 struct target_if_spectral_ops spectral_ops;
43 int spectral_debug_level = DEBUG_SPECTRAL;
44 struct spectral_tgt_ops ops_tgt;
45
46 #ifdef SPECTRAL_MODULIZED_ENABLE
47 /**
48 * target_if_spectral_wmi_service_enabled() - API to check whether a
49 * given WMI service is enabled
50 * @psoc: Pointer to psoc
51 * @wmi_handle: WMI handle
52 * @service_id: service id
53 *
54 * Return: true or false
55 */
56 static
target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc * psoc,wmi_unified_t wmi_handle,uint32_t service_id)57 bool target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc *psoc,
58 wmi_unified_t wmi_handle,
59 uint32_t service_id)
60 {
61 struct target_if_psoc_spectral *psoc_spectral;
62
63 if (!psoc) {
64 spectral_err("psoc is null");
65 return false;
66 }
67
68 if (!wmi_handle) {
69 spectral_err("wmi handle is null");
70 return false;
71 }
72
73 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
74 if (!psoc_spectral) {
75 spectral_err("psoc spectral object is null");
76 return false;
77 }
78
79 return psoc_spectral->wmi_ops.wmi_service_enabled(wmi_handle,
80 service_id);
81 }
82 #else
83 /**
84 * target_if_spectral_wmi_service_enabled() - API to check whether a
85 * given WMI service is enabled
86 * @psoc: Pointer to psoc
87 * @wmi_handle: WMI handle
88 * @service_id: service id
89 *
90 * Return: true or false
91 */
92 static
target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc * psoc,wmi_unified_t wmi_handle,uint32_t service_id)93 bool target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc *psoc,
94 wmi_unified_t wmi_handle,
95 uint32_t service_id)
96 {
97 return wmi_service_enabled(wmi_handle, service_id);
98 }
99 #endif /* SPECTRAL_MODULIZED_ENABLE */
100
get_target_if_spectral_handle_from_pdev(struct wlan_objmgr_pdev * pdev)101 struct target_if_spectral *get_target_if_spectral_handle_from_pdev(
102 struct wlan_objmgr_pdev *pdev)
103 {
104 struct target_if_spectral *spectral;
105 struct wlan_objmgr_psoc *psoc;
106 struct wlan_lmac_if_rx_ops *rx_ops;
107
108 if (!pdev) {
109 spectral_err("pdev is null");
110 return NULL;
111 }
112
113 psoc = wlan_pdev_get_psoc(pdev);
114 if (!psoc) {
115 spectral_err("psoc is null");
116 return NULL;
117 }
118
119 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
120 if (!rx_ops) {
121 spectral_err("rx_ops is null");
122 return NULL;
123 }
124
125 spectral = (struct target_if_spectral *)
126 rx_ops->sptrl_rx_ops.sptrlro_get_pdev_target_handle(pdev);
127
128 return spectral;
129 }
130
131 qdf_export_symbol(get_target_if_spectral_handle_from_pdev);
132
133 /**
134 * target_if_spectral_get_normal_mode_cap() - API to get normal
135 * Spectral scan capability of a given pdev
136 * @pdev: pdev handle
137 * @normal_mode_disable: Pointer to caller variable
138 *
139 * API to get normal Spectral scan mode capability a given pdev.
140 * This information is derived from the WMI service
141 * "WMI_SERVICE_SPECTRAL_SCAN_DISABLED".
142 *
143 * Return: QDF_STATUS on success
144 */
145 static QDF_STATUS
target_if_spectral_get_normal_mode_cap(struct wlan_objmgr_pdev * pdev,bool * normal_mode_disable)146 target_if_spectral_get_normal_mode_cap(struct wlan_objmgr_pdev *pdev,
147 bool *normal_mode_disable)
148 {
149 struct wlan_objmgr_psoc *psoc;
150 struct wmi_unified *wmi_handle;
151 struct target_if_psoc_spectral *psoc_spectral;
152
153 if (!pdev) {
154 spectral_err("pdev is null");
155 return QDF_STATUS_E_INVAL;
156 }
157
158 psoc = wlan_pdev_get_psoc(pdev);
159 if (!psoc) {
160 spectral_err("psoc is null");
161 return QDF_STATUS_E_INVAL;
162 }
163
164 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
165 if (!psoc_spectral) {
166 spectral_err("psoc spectral object is null");
167 return QDF_STATUS_E_INVAL;
168 }
169
170 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
171 if (!wmi_handle) {
172 spectral_err("wmi handle is null");
173 return QDF_STATUS_E_INVAL;
174 }
175
176 *normal_mode_disable = target_if_spectral_wmi_service_enabled(psoc,
177 wmi_handle, wmi_service_spectral_scan_disabled);
178
179 return QDF_STATUS_SUCCESS;
180 }
181
182 /**
183 * target_if_spectral_get_agile_mode_cap() - API to check agile
184 * Spectral scan mode capability of a given pdev.
185 * @pdev: pdev handle
186 * @agile_cap: Pointer to caller variable
187 *
188 * API to check agile Spectral scan mode is disabled for a given pdev.
189 * This information is derived from the chain mask table entries.
190 *
191 * Return: QDF_STATUS on success
192 */
193 static QDF_STATUS
target_if_spectral_get_agile_mode_cap(struct wlan_objmgr_pdev * pdev,struct target_if_spectral_agile_mode_cap * agile_cap)194 target_if_spectral_get_agile_mode_cap(
195 struct wlan_objmgr_pdev *pdev,
196 struct target_if_spectral_agile_mode_cap *agile_cap)
197 {
198 struct wlan_objmgr_psoc *psoc;
199 struct target_psoc_info *tgt_psoc_info;
200 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr;
201 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap;
202 uint8_t pdev_id, i;
203 uint32_t table_id;
204 struct wlan_psoc_host_service_ext_param *ext_svc_param;
205 struct wlan_psoc_host_chainmask_table *table;
206 struct wmi_unified *wmi_handle;
207
208 if (!pdev) {
209 spectral_err("pdev is null");
210 return QDF_STATUS_E_INVAL;
211 }
212
213 psoc = wlan_pdev_get_psoc(pdev);
214 if (!psoc) {
215 spectral_err("psoc is null");
216 return QDF_STATUS_E_FAILURE;
217 }
218
219 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
220 if (!wmi_handle) {
221 spectral_err("wmi handle is null");
222 return QDF_STATUS_E_INVAL;
223 }
224
225 /* Agile Spectral is disabled for legacy targets */
226 if (!target_if_spectral_wmi_service_enabled(psoc, wmi_handle,
227 wmi_service_ext_msg)) {
228 agile_cap->agile_spectral_cap = false;
229 agile_cap->agile_spectral_cap_160 = false;
230 agile_cap->agile_spectral_cap_80p80 = false;
231 agile_cap->agile_spectral_cap_320 = false;
232
233 return QDF_STATUS_SUCCESS;
234 }
235
236 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
237 if (!tgt_psoc_info) {
238 spectral_err("target_psoc_info is null");
239 return QDF_STATUS_E_FAILURE;
240 }
241
242 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
243 if (!mac_phy_cap_arr) {
244 spectral_err("mac phy cap array is null");
245 return QDF_STATUS_E_FAILURE;
246 }
247
248 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
249 mac_phy_cap = &mac_phy_cap_arr[pdev_id];
250 table_id = mac_phy_cap->chainmask_table_id;
251 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
252 if (!ext_svc_param) {
253 spectral_err("Extended service ready params null");
254 return QDF_STATUS_E_FAILURE;
255 }
256
257 table = &ext_svc_param->chainmask_table[table_id];
258
259 for (i = 0; i < table->num_valid_chainmasks; i++) {
260 agile_cap->agile_spectral_cap |=
261 table->cap_list[i].supports_aSpectral;
262 agile_cap->agile_spectral_cap_160 |=
263 table->cap_list[i].supports_aSpectral_160;
264 agile_cap->agile_spectral_cap_320 |= 0;
265 }
266
267 agile_cap->agile_spectral_cap_80p80 = agile_cap->agile_spectral_cap_160;
268
269 return QDF_STATUS_SUCCESS;
270 }
271
272 /**
273 * target_if_spectral_init_pdev_feature_cap_per_mode() - API to initialize
274 * Spectral scan pdev feature caps for a given Spectral mode
275 * @pdev: pdev handle
276 * @smode: Spectral scan mode
277 *
278 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE/
279 * QDF_STATUS_E_INVAL on failure
280 */
281 static QDF_STATUS
target_if_spectral_init_pdev_feature_cap_per_mode(struct wlan_objmgr_pdev * pdev,enum spectral_scan_mode smode)282 target_if_spectral_init_pdev_feature_cap_per_mode(struct wlan_objmgr_pdev *pdev,
283 enum spectral_scan_mode smode)
284 {
285 struct wlan_objmgr_psoc *psoc;
286 bool normal_mode_disable;
287 struct target_if_spectral_agile_mode_cap agile_cap = { 0 };
288 QDF_STATUS status;
289
290 if (!pdev) {
291 spectral_err("pdev is null");
292 return QDF_STATUS_E_INVAL;
293 }
294
295 psoc = wlan_pdev_get_psoc(pdev);
296 if (!psoc) {
297 spectral_err("psoc is null");
298 return QDF_STATUS_E_INVAL;
299 }
300
301 switch (smode) {
302 case SPECTRAL_SCAN_MODE_NORMAL:
303 if (target_if_spectral_is_feature_disabled_psoc(psoc)) {
304 wlan_pdev_nif_feat_ext_cap_set(
305 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
306
307 return QDF_STATUS_SUCCESS;
308 }
309
310 status = target_if_spectral_get_normal_mode_cap(
311 pdev, &normal_mode_disable);
312 if (QDF_IS_STATUS_ERROR(status)) {
313 spectral_err("Failed to get normal spectral scan caps");
314 return QDF_STATUS_E_FAILURE;
315 }
316
317 if (normal_mode_disable)
318 wlan_pdev_nif_feat_ext_cap_set(
319 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
320 else
321 wlan_pdev_nif_feat_ext_cap_clear(
322 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
323 break;
324
325 case SPECTRAL_SCAN_MODE_AGILE:
326 if (target_if_spectral_is_feature_disabled_psoc(psoc)) {
327 wlan_pdev_nif_feat_ext_cap_set(
328 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
329 wlan_pdev_nif_feat_ext_cap_set(
330 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
331 wlan_pdev_nif_feat_ext_cap_set(
332 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
333 wlan_pdev_nif_feat_ext_cap_set(
334 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
335
336 return QDF_STATUS_SUCCESS;
337 }
338 status = target_if_spectral_get_agile_mode_cap(
339 pdev, &agile_cap);
340 if (QDF_IS_STATUS_ERROR(status)) {
341 spectral_err("Failed to get agile Spectral capability");
342 return QDF_STATUS_E_FAILURE;
343 }
344
345 if (!agile_cap.agile_spectral_cap)
346 wlan_pdev_nif_feat_ext_cap_set(
347 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
348 else
349 wlan_pdev_nif_feat_ext_cap_clear(
350 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
351
352 if (!agile_cap.agile_spectral_cap_160)
353 wlan_pdev_nif_feat_ext_cap_set(
354 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
355 else
356 wlan_pdev_nif_feat_ext_cap_clear(
357 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
358
359 if (!agile_cap.agile_spectral_cap_80p80)
360 wlan_pdev_nif_feat_ext_cap_set(
361 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
362 else
363 wlan_pdev_nif_feat_ext_cap_clear(
364 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
365
366 if (!agile_cap.agile_spectral_cap_320)
367 wlan_pdev_nif_feat_ext_cap_set(
368 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
369 else
370 wlan_pdev_nif_feat_ext_cap_clear(
371 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
372
373 break;
374
375 default:
376 spectral_err("Invalid Spectral scan mode %d", smode);
377 return QDF_STATUS_E_INVAL;
378 }
379
380 return QDF_STATUS_SUCCESS;
381 }
382
383 /**
384 * target_if_spectral_init_pdev_feature_caps() - API to initialize
385 * Spectral scan pdev feature caps for a given pdev
386 * @pdev: pdev handle
387 *
388 * API initialize normal and agile Spectral scan pdev
389 * feature caps for a given pdev.
390 *
391 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure
392 */
393 static QDF_STATUS
target_if_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev * pdev)394 target_if_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev *pdev)
395 {
396 enum spectral_scan_mode smode;
397
398 if (!pdev) {
399 spectral_err("pdev is NULL!");
400 return QDF_STATUS_E_INVAL;
401 }
402
403 smode = SPECTRAL_SCAN_MODE_NORMAL;
404 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
405 QDF_STATUS status;
406
407 status = target_if_spectral_init_pdev_feature_cap_per_mode(
408 pdev, smode);
409 if (QDF_IS_STATUS_ERROR(status))
410 return QDF_STATUS_E_INVAL;
411 }
412
413 return QDF_STATUS_SUCCESS;
414 }
415
target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev * pdev,void * obj,void * arg)416 static void target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev *pdev,
417 void *obj, void *arg)
418 {
419 struct wlan_objmgr_vdev *vdev = obj;
420 struct wlan_objmgr_vdev **first_vdev = arg;
421
422 if (!(*first_vdev))
423 *first_vdev = vdev;
424 }
425
426 struct wlan_objmgr_vdev *
target_if_spectral_get_vdev(struct target_if_spectral * spectral,enum spectral_scan_mode smode)427 target_if_spectral_get_vdev(struct target_if_spectral *spectral,
428 enum spectral_scan_mode smode)
429 {
430 struct wlan_objmgr_pdev *pdev = NULL;
431 struct wlan_objmgr_vdev *first_vdev = NULL;
432
433 if (!spectral) {
434 spectral_err("spectral variable in null.");
435 return NULL;
436 }
437 pdev = spectral->pdev_obj;
438 if (!pdev) {
439 spectral_err("pdev variable in null.");
440 return NULL;
441 }
442
443 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
444 spectral_err("Invalid Spectral mode %u", smode);
445 return NULL;
446 }
447
448 if (spectral->vdev_id[smode] != WLAN_INVALID_VDEV_ID) {
449 first_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(
450 pdev, spectral->vdev_id[smode],
451 WLAN_SPECTRAL_ID);
452 return first_vdev;
453 }
454
455 if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) !=
456 QDF_STATUS_SUCCESS) {
457 spectral_err("Unable to get pdev reference.");
458 return NULL;
459 }
460
461 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
462 target_if_spectral_get_firstvdev_pdev,
463 &first_vdev, 0, WLAN_SPECTRAL_ID);
464
465 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
466
467 if (!first_vdev)
468 return NULL;
469
470 if (wlan_objmgr_vdev_try_get_ref(first_vdev, WLAN_SPECTRAL_ID) !=
471 QDF_STATUS_SUCCESS)
472 first_vdev = NULL;
473
474 return first_vdev;
475 }
476
477 /**
478 * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure
479 * spectral parameters
480 * @spectral: Pointer to Spectral target_if internal private data
481 * @smode: Spectral scan mode
482 * @param: Pointer to spectral_config giving the Spectral configuration
483 *
484 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
485 */
486 static int
target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral * spectral,enum spectral_scan_mode smode,struct spectral_config * param)487 target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral,
488 enum spectral_scan_mode smode,
489 struct spectral_config *param)
490 {
491 struct vdev_spectral_configure_params sparam;
492 struct wlan_objmgr_psoc *psoc;
493 struct wlan_objmgr_pdev *pdev = NULL;
494 struct wlan_objmgr_vdev *vdev = NULL;
495 struct target_if_psoc_spectral *psoc_spectral;
496
497 if (!spectral || !param || !(spectral->pdev_obj)) {
498 spectral_err("null params: spectral %pK, spectral_config %pK, pdev: %pK.",
499 spectral, param, pdev);
500 return qdf_status_to_os_return(QDF_STATUS_E_NULL_VALUE);
501 }
502
503 pdev = spectral->pdev_obj;
504
505 psoc = wlan_pdev_get_psoc(pdev);
506 if (!psoc) {
507 spectral_err("psoc is null");
508 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
509 }
510
511 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
512 if (!psoc_spectral) {
513 spectral_err("psoc spectral object is null");
514 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
515 }
516
517 vdev = target_if_spectral_get_vdev(spectral, smode);
518 if (!vdev)
519 return QDF_STATUS_E_NOENT;
520
521 qdf_mem_zero(&sparam, sizeof(sparam));
522
523 sparam.vdev_id = wlan_vdev_get_id(vdev);
524 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
525
526 sparam.count = param->ss_count;
527 sparam.period = param->ss_period;
528 sparam.fft_recap = param->ss_recapture;
529 sparam.spectral_pri = param->ss_spectral_pri;
530 sparam.fft_size = param->ss_fft_size;
531 sparam.gc_enable = param->ss_gc_ena;
532 sparam.restart_enable = param->ss_restart_ena;
533 sparam.noise_floor_ref = param->ss_noise_floor_ref;
534 sparam.init_delay = param->ss_init_delay;
535 sparam.nb_tone_thr = param->ss_nb_tone_thr;
536 sparam.str_bin_thr = param->ss_str_bin_thr;
537 sparam.wb_rpt_mode = param->ss_wb_rpt_mode;
538 sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode;
539 sparam.rssi_thr = param->ss_rssi_thr;
540 sparam.pwr_format = param->ss_pwr_format;
541 sparam.rpt_mode = param->ss_rpt_mode;
542 sparam.bin_scale = param->ss_bin_scale;
543 sparam.dbm_adj = param->ss_dbm_adj;
544 sparam.chn_mask = param->ss_chn_mask;
545 sparam.mode = smode;
546 sparam.center_freq1 = param->ss_frequency.cfreq1;
547 sparam.center_freq2 = param->ss_frequency.cfreq2;
548 sparam.chan_width = param->ss_bandwidth;
549
550 return psoc_spectral->wmi_ops.wmi_spectral_configure_cmd_send(
551 GET_WMI_HDL_FROM_PDEV(pdev), &sparam);
552 }
553
554 /**
555 * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to
556 * enable/disable Spectral
557 * @spectral: Pointer to Spectral target_if internal private data
558 * @smode: Spectral scan mode
559 * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is
560 * valid
561 * @is_spectral_active: Value of spectral activate
562 * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid
563 * @is_spectral_enabled: Value of spectral enable
564 *
565 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure
566 */
567 static int
target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral * spectral,enum spectral_scan_mode smode,uint8_t is_spectral_active_valid,uint8_t is_spectral_active,uint8_t is_spectral_enabled_valid,uint8_t is_spectral_enabled)568 target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral,
569 enum spectral_scan_mode smode,
570 uint8_t is_spectral_active_valid,
571 uint8_t is_spectral_active,
572 uint8_t is_spectral_enabled_valid,
573 uint8_t is_spectral_enabled)
574 {
575 struct vdev_spectral_enable_params param;
576 struct wlan_objmgr_psoc *psoc;
577 struct wlan_objmgr_pdev *pdev = NULL;
578 struct wlan_objmgr_vdev *vdev = NULL;
579 struct target_if_psoc_spectral *psoc_spectral;
580
581 if (!spectral) {
582 spectral_err("spectral is null");
583 return qdf_status_to_os_return(QDF_STATUS_E_NULL_VALUE);
584 }
585
586 pdev = spectral->pdev_obj;
587
588 if (!pdev) {
589 spectral_err("pdev is null");
590 return qdf_status_to_os_return(QDF_STATUS_E_NULL_VALUE);
591 }
592
593 psoc = wlan_pdev_get_psoc(pdev);
594 if (!psoc) {
595 spectral_err("psoc is null");
596 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
597 }
598
599 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
600 if (!psoc_spectral) {
601 spectral_err("psoc spectral object is null");
602 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
603 }
604
605 vdev = target_if_spectral_get_vdev(spectral, smode);
606 if (!vdev)
607 return QDF_STATUS_E_NOENT;
608
609 qdf_mem_zero(¶m, sizeof(param));
610
611 param.vdev_id = wlan_vdev_get_id(vdev);
612 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
613
614 param.active_valid = is_spectral_active_valid;
615 param.enabled_valid = is_spectral_enabled_valid;
616 param.active = is_spectral_active;
617 param.enabled = is_spectral_enabled;
618 param.mode = smode;
619
620 return psoc_spectral->wmi_ops.wmi_spectral_enable_cmd_send(
621 GET_WMI_HDL_FROM_PDEV(pdev), ¶m);
622 }
623
624 /**
625 * is_spectral_arch_beryllium() - Check whether the given target Spectral
626 * architecture is Beryllium
627 * @target_tpe: Target type
628 *
629 * Return: true if the spectral architecture is Beryllium, else false
630 */
is_spectral_arch_beryllium(uint32_t target_tpe)631 static inline bool is_spectral_arch_beryllium(uint32_t target_tpe)
632 {
633 if ((target_tpe == TARGET_TYPE_QCN9224) ||
634 (target_tpe == TARGET_TYPE_QCA5332) ||
635 (target_tpe == TARGET_TYPE_QCN6432))
636 return true;
637
638 return false;
639 }
640
641 /*
642 * List of supported sscan BWs. Make sure to maintain the array elements in the
643 * same order of BWs as that of struct spectral_supported_bws bitmap.
644 */
645 static const enum phy_ch_width supported_sscan_bw_list[] = {
646 CH_WIDTH_5MHZ,
647 CH_WIDTH_10MHZ,
648 CH_WIDTH_20MHZ,
649 CH_WIDTH_40MHZ,
650 CH_WIDTH_80MHZ,
651 CH_WIDTH_160MHZ,
652 CH_WIDTH_80P80MHZ,
653 #ifdef WLAN_FEATURE_11BE
654 CH_WIDTH_320MHZ,
655 #endif
656 };
657
658 #define INVALID_SSCAN_BW_POS (-1)
get_supported_sscan_bw_pos(enum phy_ch_width sscan_bw)659 int get_supported_sscan_bw_pos(enum phy_ch_width sscan_bw)
660 {
661 int max_pos, pos;
662
663 max_pos = QDF_ARRAY_SIZE(supported_sscan_bw_list);
664 for (pos = 0; pos < max_pos; pos++) {
665 if (supported_sscan_bw_list[pos] == sscan_bw)
666 return pos;
667 }
668
669 return INVALID_SSCAN_BW_POS;
670 }
671
672 /**
673 * target_if_is_sscan_bw_supported() - Check whether the given sscan_bw is
674 * supported
675 * @spectral: Spectral LMAC object
676 * @smode: Spectral scan mode
677 * @sscan_bw: Spectral scan bandwidth
678 * @op_bw: operating bandwidth
679 * @is_bw_supported: Pointer to the caller variable where this function
680 * populates whether @sscan_bw is supported
681 * @is_80_80_agile: Indicates an 80+80 agile Scan request
682 *
683 * Return: QDF_STATUS of operation
684 */
685 static QDF_STATUS
target_if_is_sscan_bw_supported(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum phy_ch_width sscan_bw,enum phy_ch_width op_bw,bool * is_bw_supported,bool is_80_80_agile)686 target_if_is_sscan_bw_supported(struct target_if_spectral *spectral,
687 enum spectral_scan_mode smode,
688 enum phy_ch_width sscan_bw,
689 enum phy_ch_width op_bw,
690 bool *is_bw_supported,
691 bool is_80_80_agile)
692 {
693 struct spectral_supported_bws *supported_bws;
694
695 *is_bw_supported = false;
696
697 if (op_bw >= CH_WIDTH_INVALID) {
698 spectral_err("Invalid channel width %d", op_bw);
699 return QDF_STATUS_E_INVAL;
700 }
701
702 if ((is_80_80_agile && sscan_bw != CH_WIDTH_80P80MHZ) ||
703 (!is_80_80_agile && sscan_bw == CH_WIDTH_80P80MHZ)) {
704 *is_bw_supported = false;
705 return QDF_STATUS_SUCCESS;
706 }
707
708 /* Get the supported sscan bandwidths for this operating bandwidth */
709 supported_bws = &spectral->supported_bws[smode][op_bw];
710 *is_bw_supported = supported_bws->bandwidths &
711 (1 << get_supported_sscan_bw_pos(sscan_bw));
712
713 return QDF_STATUS_SUCCESS;
714 }
715
716 /**
717 * get_max_sscan_bw() - Get the maximum sscan bandwidth for a given operating
718 * bandwidth
719 * @spectral: Spectral LMAC object
720 * @smode: Spectral scan mode
721 * @op_bw: operating bandwidth
722 *
723 * Return: Maximum sscan bandwidth for @op_bw on success, else CH_WIDTH_INVALID
724 */
725 static enum phy_ch_width
get_max_sscan_bw(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum phy_ch_width op_bw)726 get_max_sscan_bw(struct target_if_spectral *spectral,
727 enum spectral_scan_mode smode,
728 enum phy_ch_width op_bw)
729 {
730 int op_bw_pos, pos;
731 struct spectral_supported_bws *supported_bws;
732
733 supported_bws = &spectral->supported_bws[smode][op_bw];
734 op_bw_pos = get_supported_sscan_bw_pos(op_bw);
735
736 /**
737 * Start with operating bandwidth, and keep reducing the bandwidth until
738 * a supported sscan BW is found.
739 */
740 for (pos = op_bw_pos; pos >= 0; pos--) {
741 if (supported_bws->bandwidths & (1 << pos))
742 return supported_sscan_bw_list[pos];
743 }
744
745 return CH_WIDTH_INVALID;
746 }
747
748 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the
749 * corresponding translation for Agile channel width.
750 * @spectral: pointer to Spectral object
751 * @op_width: operating channel width
752 * @is_80_80_agile: Indicates an 80+80 agile Scan request
753 *
754 * Return: The translated channel width enum.
755 */
756 static enum phy_ch_width
target_if_spectral_find_agile_width(struct target_if_spectral * spectral,enum phy_ch_width op_bw,bool is_80_80_agile)757 target_if_spectral_find_agile_width(struct target_if_spectral *spectral,
758 enum phy_ch_width op_bw,
759 bool is_80_80_agile)
760 {
761 enum phy_ch_width agile_width;
762 struct wlan_objmgr_pdev *pdev;
763 struct wlan_objmgr_psoc *psoc;
764
765 if (!spectral) {
766 spectral_err("Spectral object is null");
767 return CH_WIDTH_INVALID;
768 }
769
770 pdev = spectral->pdev_obj;
771 if (!pdev) {
772 spectral_err("pdev is null");
773 return CH_WIDTH_INVALID;
774 }
775
776 psoc = wlan_pdev_get_psoc(pdev);
777 if (!psoc) {
778 spectral_err("psoc is null");
779 return CH_WIDTH_INVALID;
780 }
781
782 agile_width = get_max_sscan_bw(spectral, SPECTRAL_SCAN_MODE_AGILE,
783 op_bw);
784
785 if (wlan_psoc_nif_fw_ext_cap_get(psoc,
786 WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
787 switch (op_bw) {
788 case CH_WIDTH_80P80MHZ:
789 if (!is_80_80_agile)
790 agile_width = CH_WIDTH_160MHZ;
791 else
792 agile_width = CH_WIDTH_80P80MHZ;
793
794 break;
795
796 case CH_WIDTH_160MHZ:
797 if (is_80_80_agile)
798 agile_width = CH_WIDTH_80P80MHZ;
799 else
800 agile_width = CH_WIDTH_160MHZ;
801
802 break;
803
804 default:
805 break;
806 }
807 }
808
809 return agile_width;
810 }
811
812 /**
813 * get_default_sscan_bw() - Get the default sscan bandwidth for a given
814 * operating bandwidth
815 * @spectral: Spectral LMAC object
816 * @smode: Spectral scan mode
817 * @is_80_80_agile: Indicates an 80+80 agile Scan request
818 *
819 * Return: Default sscan bandwidth for @op_bw on success, else CH_WIDTH_INVALID
820 */
821 static enum phy_ch_width
get_default_sscan_bw(struct target_if_spectral * spectral,enum spectral_scan_mode smode,bool is_80_80_agile)822 get_default_sscan_bw(struct target_if_spectral *spectral,
823 enum spectral_scan_mode smode,
824 bool is_80_80_agile)
825 {
826 struct wlan_objmgr_vdev *vdev;
827 enum phy_ch_width vdev_ch_width, sscan_width;
828
829 vdev = target_if_spectral_get_vdev(spectral, smode);
830 if (!vdev) {
831 spectral_err("vdev is null");
832 return CH_WIDTH_INVALID;
833 }
834
835 vdev_ch_width = target_if_vdev_get_ch_width(vdev);
836 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
837 if (vdev_ch_width >= CH_WIDTH_INVALID) {
838 spectral_err("Invalid vdev channel width %d", vdev_ch_width);
839 return CH_WIDTH_INVALID;
840 }
841
842 switch (smode) {
843 case SPECTRAL_SCAN_MODE_NORMAL:
844 sscan_width = get_max_sscan_bw(spectral, smode, vdev_ch_width);
845 break;
846
847 case SPECTRAL_SCAN_MODE_AGILE:
848 sscan_width = target_if_spectral_find_agile_width(
849 spectral, vdev_ch_width, is_80_80_agile);
850 break;
851
852 default:
853 sscan_width = CH_WIDTH_INVALID;
854 break;
855 }
856
857 return sscan_width;
858 }
859
860 /**
861 * target_if_spectral_info_init_defaults() - Helper function to load defaults
862 * for Spectral information (parameters and state) into cache.
863 * @spectral: Pointer to Spectral target_if internal private data
864 * @smode: Spectral scan mode
865 *
866 * It is assumed that the caller has obtained the requisite lock if applicable.
867 * Note that this is currently treated as a temporary function. Ideally, we
868 * would like to get defaults from the firmware.
869 *
870 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
871 */
872 static QDF_STATUS
target_if_spectral_info_init_defaults(struct target_if_spectral * spectral,enum spectral_scan_mode smode)873 target_if_spectral_info_init_defaults(struct target_if_spectral *spectral,
874 enum spectral_scan_mode smode)
875 {
876 struct target_if_spectral_param_state_info *info;
877 struct wlan_objmgr_vdev *vdev = NULL;
878 enum phy_ch_width sscan_bw;
879
880 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
881 spectral_err("Invalid Spectral mode %u", smode);
882 return QDF_STATUS_E_FAILURE;
883 }
884
885 info = &spectral->param_info[smode];
886
887 /* State */
888 info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT;
889
890 info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT;
891
892 /* Parameters */
893 info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT;
894
895 if (spectral->spectral_gen == SPECTRAL_GEN3)
896 info->osps_cache.osc_params.ss_period =
897 SPECTRAL_SCAN_PERIOD_GEN_III_DEFAULT;
898 else
899 info->osps_cache.osc_params.ss_period =
900 SPECTRAL_SCAN_PERIOD_GEN_II_DEFAULT;
901
902 info->osps_cache.osc_params.ss_recapture =
903 SPECTRAL_FFT_RECAPTURE_DEFAULT;
904 info->osps_cache.osc_params.ss_spectral_pri =
905 SPECTRAL_SCAN_PRIORITY_DEFAULT;
906
907 info->osps_cache.osc_params.ss_fft_size =
908 SPECTRAL_SCAN_FFT_SIZE_DEFAULT;
909
910 info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT;
911
912 info->osps_cache.osc_params.ss_restart_ena =
913 SPECTRAL_SCAN_RESTART_ENA_DEFAULT;
914
915 info->osps_cache.osc_params.ss_noise_floor_ref =
916 SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT;
917
918 info->osps_cache.osc_params.ss_init_delay =
919 SPECTRAL_SCAN_INIT_DELAY_DEFAULT;
920
921 info->osps_cache.osc_params.ss_nb_tone_thr =
922 SPECTRAL_SCAN_NB_TONE_THR_DEFAULT;
923
924 info->osps_cache.osc_params.ss_str_bin_thr =
925 SPECTRAL_SCAN_STR_BIN_THR_DEFAULT;
926
927 info->osps_cache.osc_params.ss_wb_rpt_mode =
928 SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT;
929
930 info->osps_cache.osc_params.ss_rssi_rpt_mode =
931 SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT;
932
933 info->osps_cache.osc_params.ss_rssi_thr =
934 SPECTRAL_SCAN_RSSI_THR_DEFAULT;
935
936 info->osps_cache.osc_params.ss_pwr_format =
937 SPECTRAL_SCAN_PWR_FORMAT_DEFAULT;
938
939 info->osps_cache.osc_params.ss_rpt_mode =
940 SPECTRAL_SCAN_RPT_MODE_DEFAULT;
941
942 info->osps_cache.osc_params.ss_bin_scale =
943 SPECTRAL_SCAN_BIN_SCALE_DEFAULT;
944
945 info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT;
946
947 vdev = target_if_spectral_get_vdev(spectral, smode);
948 if (!vdev)
949 return QDF_STATUS_E_NOENT;
950
951 info->osps_cache.osc_params.ss_chn_mask =
952 wlan_vdev_mlme_get_rxchainmask(vdev);
953 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
954
955 info->osps_cache.osc_params.ss_short_report =
956 SPECTRAL_SCAN_SHORT_REPORT_DEFAULT;
957
958 info->osps_cache.osc_params.ss_fft_period =
959 SPECTRAL_SCAN_FFT_PERIOD_DEFAULT;
960
961 info->osps_cache.osc_params.ss_frequency.cfreq1 =
962 SPECTRAL_SCAN_FREQUENCY_DEFAULT;
963 info->osps_cache.osc_params.ss_frequency.cfreq2 =
964 SPECTRAL_SCAN_FREQUENCY_DEFAULT;
965
966 sscan_bw = get_default_sscan_bw(spectral, smode, false);
967 if (sscan_bw >= CH_WIDTH_INVALID) {
968 spectral_err("Invalid sscan BW %u", sscan_bw);
969 return QDF_STATUS_E_FAILURE;
970 }
971 info->osps_cache.osc_params.ss_bandwidth = sscan_bw;
972
973 /* The cache is now valid */
974 info->osps_cache.osc_is_valid = 1;
975
976 return QDF_STATUS_SUCCESS;
977 }
978
979 /**
980 * target_if_log_read_spectral_active() - Helper function to log whether
981 * spectral is active after reading cache
982 * @function_name: Function name
983 * @output: whether spectral is active or not
984 *
985 * Helper function to log whether spectral is active after reading cache
986 *
987 * Return: none
988 */
989 static void
target_if_log_read_spectral_active(const char * function_name,unsigned char output)990 target_if_log_read_spectral_active(
991 const char *function_name,
992 unsigned char output)
993 {
994 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u",
995 function_name, output);
996 }
997
998 /**
999 * target_if_log_read_spectral_enabled() - Helper function to log whether
1000 * spectral is enabled after reading cache
1001 * @function_name: Function name
1002 * @output: whether spectral is enabled or not
1003 *
1004 * Helper function to log whether spectral is enabled after reading cache
1005 *
1006 * Return: none
1007 */
1008 static void
target_if_log_read_spectral_enabled(const char * function_name,unsigned char output)1009 target_if_log_read_spectral_enabled(
1010 const char *function_name,
1011 unsigned char output)
1012 {
1013 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u",
1014 function_name, output);
1015 }
1016
1017 /**
1018 * target_if_log_read_spectral_params() - log spectral parameters
1019 * @function_name: Function name
1020 * @pparam: Spectral parameters
1021 *
1022 * Helper function to log spectral parameters after reading cache
1023 *
1024 * Return: none
1025 */
1026 static void
target_if_log_read_spectral_params(const char * function_name,struct spectral_config * pparam)1027 target_if_log_read_spectral_params(
1028 const char *function_name,
1029 struct spectral_config *pparam)
1030 {
1031 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Returning following params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency1=%u\nss_frequency2=%u\n",
1032 function_name,
1033 pparam->ss_count,
1034 pparam->ss_period,
1035 pparam->ss_recapture,
1036 pparam->ss_spectral_pri,
1037 pparam->ss_fft_size,
1038 pparam->ss_gc_ena,
1039 pparam->ss_restart_ena,
1040 (int8_t)pparam->ss_noise_floor_ref,
1041 pparam->ss_init_delay,
1042 pparam->ss_nb_tone_thr,
1043 pparam->ss_str_bin_thr,
1044 pparam->ss_wb_rpt_mode,
1045 pparam->ss_rssi_rpt_mode,
1046 (int8_t)pparam->ss_rssi_thr,
1047 pparam->ss_pwr_format,
1048 pparam->ss_rpt_mode,
1049 pparam->ss_bin_scale,
1050 pparam->ss_dbm_adj,
1051 pparam->ss_chn_mask,
1052 pparam->ss_frequency.cfreq1,
1053 pparam->ss_frequency.cfreq2);
1054 }
1055
1056 /**
1057 * target_if_log_read_spectral_active_catch_validate() - Helper function to
1058 * log whether spectral is active after initializing the cache
1059 * @function_name: Function name
1060 * @output: whether spectral is active or not
1061 *
1062 * Helper function to log whether spectral is active after initializing cache
1063 *
1064 * Return: none
1065 */
1066 static void
target_if_log_read_spectral_active_catch_validate(const char * function_name,unsigned char output)1067 target_if_log_read_spectral_active_catch_validate(
1068 const char *function_name,
1069 unsigned char output)
1070 {
1071 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u",
1072 function_name, output);
1073 }
1074
1075 /**
1076 * target_if_log_read_spectral_enabled_catch_validate() - Helper function to
1077 * log whether spectral is enabled after initializing the cache
1078 * @function_name: Function name
1079 * @output: whether spectral is enabled or not
1080 *
1081 * Helper function to log whether spectral is enabled after initializing cache
1082 *
1083 * Return: none
1084 */
1085 static void
target_if_log_read_spectral_enabled_catch_validate(const char * function_name,unsigned char output)1086 target_if_log_read_spectral_enabled_catch_validate(
1087 const char *function_name,
1088 unsigned char output)
1089 {
1090 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n",
1091 function_name, output);
1092 }
1093
1094 /**
1095 * target_if_log_read_spectral_params_catch_validate() - Helper function to
1096 * log spectral parameters after initializing the cache
1097 * @function_name: Function name
1098 * @pparam: Spectral parameters
1099 *
1100 * Helper function to log spectral parameters after initializing the cache
1101 *
1102 * Return: none
1103 */
1104 static void
target_if_log_read_spectral_params_catch_validate(const char * function_name,struct spectral_config * pparam)1105 target_if_log_read_spectral_params_catch_validate(
1106 const char *function_name,
1107 struct spectral_config *pparam)
1108 {
1109 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS on initial cache validation\nReturning following params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u",
1110 function_name,
1111 pparam->ss_count,
1112 pparam->ss_period,
1113 pparam->ss_recapture,
1114 pparam->ss_spectral_pri,
1115 pparam->ss_fft_size,
1116 pparam->ss_gc_ena,
1117 pparam->ss_restart_ena,
1118 (int8_t)pparam->ss_noise_floor_ref,
1119 pparam->ss_init_delay,
1120 pparam->ss_nb_tone_thr,
1121 pparam->ss_str_bin_thr,
1122 pparam->ss_wb_rpt_mode,
1123 pparam->ss_rssi_rpt_mode,
1124 (int8_t)pparam->ss_rssi_thr,
1125 pparam->ss_pwr_format,
1126 pparam->ss_rpt_mode,
1127 pparam->ss_bin_scale,
1128 pparam->ss_dbm_adj, pparam->ss_chn_mask);
1129 }
1130
1131 /**
1132 * target_if_spectral_info_read() - Read spectral information from the cache.
1133 * @spectral: Pointer to Spectral target_if internal private data
1134 * @smode: Spectral scan mode
1135 * @specifier: target_if_spectral_info enumeration specifying which
1136 * information is required
1137 * @output: Void output pointer into which the information will be read
1138 * @output_len: size of object pointed to by output pointer
1139 *
1140 * Read spectral parameters or the desired state information from the cache.
1141 *
1142 * Return: 0 on success, negative error code on failure
1143 */
1144 static int
target_if_spectral_info_read(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum target_if_spectral_info specifier,void * output,int output_len)1145 target_if_spectral_info_read(
1146 struct target_if_spectral *spectral,
1147 enum spectral_scan_mode smode,
1148 enum target_if_spectral_info specifier,
1149 void *output, int output_len)
1150 {
1151 /*
1152 * Note: This function is designed to be able to accommodate
1153 * WMI reads for defaults, non-cacheable information, etc
1154 * if required.
1155 */
1156 struct target_if_spectral_param_state_info *info;
1157 int is_cacheable = 0;
1158 int init_def_retval = 0;
1159
1160 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1161 spectral_err("Invalid Spectral mode %u", smode);
1162 return -EINVAL;
1163 }
1164 info = &spectral->param_info[smode];
1165
1166 if (!output)
1167 return -EINVAL;
1168
1169 switch (specifier) {
1170 case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1171 if (output_len != sizeof(info->osps_cache.osc_spectral_active))
1172 return -EINVAL;
1173 is_cacheable = 1;
1174 break;
1175
1176 case TARGET_IF_SPECTRAL_INFO_ENABLED:
1177 if (output_len != sizeof(info->osps_cache.osc_spectral_enabled))
1178 return -EINVAL;
1179 is_cacheable = 1;
1180 break;
1181
1182 case TARGET_IF_SPECTRAL_INFO_PARAMS:
1183 if (output_len != sizeof(info->osps_cache.osc_params))
1184 return -EINVAL;
1185 is_cacheable = 1;
1186 break;
1187
1188 default:
1189 spectral_err("Unknown target_if_spectral_info specifier");
1190 return -EINVAL;
1191 }
1192
1193 qdf_spin_lock_bh(&info->osps_lock);
1194
1195 if (is_cacheable) {
1196 if (info->osps_cache.osc_is_valid) {
1197 switch (specifier) {
1198 case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1199 qdf_mem_copy(
1200 output,
1201 &info->osps_cache.osc_spectral_active,
1202 sizeof(info->osps_cache.osc_spectral_active));
1203
1204 target_if_log_read_spectral_active(
1205 __func__,
1206 *((unsigned char *)output));
1207 break;
1208
1209 case TARGET_IF_SPECTRAL_INFO_ENABLED:
1210 qdf_mem_copy(
1211 output,
1212 &info->osps_cache.osc_spectral_enabled,
1213 sizeof(
1214 info->osps_cache.osc_spectral_enabled));
1215
1216 target_if_log_read_spectral_enabled(
1217 __func__,
1218 *((unsigned char *)output));
1219 break;
1220
1221 case TARGET_IF_SPECTRAL_INFO_PARAMS:
1222 qdf_mem_copy(
1223 output,
1224 &info->osps_cache.osc_params,
1225 sizeof(info->osps_cache.osc_params));
1226
1227 target_if_log_read_spectral_params(
1228 __func__,
1229 (struct spectral_config *)output);
1230 break;
1231
1232 default:
1233 /* We can't reach this point */
1234 break;
1235 }
1236 qdf_spin_unlock_bh(&info->osps_lock);
1237 return 0;
1238 }
1239 }
1240
1241 /* Cache is invalid */
1242
1243 /*
1244 * If WMI Reads are implemented to fetch defaults/non-cacheable info,
1245 * then the below implementation will change
1246 */
1247 init_def_retval =
1248 target_if_spectral_info_init_defaults(spectral, smode);
1249 if (init_def_retval != QDF_STATUS_SUCCESS) {
1250 qdf_spin_unlock_bh(&info->osps_lock);
1251 if (init_def_retval == QDF_STATUS_E_NOENT)
1252 return -ENOENT;
1253 else
1254 return -EINVAL;
1255 }
1256 /* target_if_spectral_info_init_defaults() has set cache to valid */
1257
1258 switch (specifier) {
1259 case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1260 qdf_mem_copy(output,
1261 &info->osps_cache.osc_spectral_active,
1262 sizeof(info->osps_cache.osc_spectral_active));
1263
1264 target_if_log_read_spectral_active_catch_validate(
1265 __func__,
1266 *((unsigned char *)output));
1267 break;
1268
1269 case TARGET_IF_SPECTRAL_INFO_ENABLED:
1270 qdf_mem_copy(output,
1271 &info->osps_cache.osc_spectral_enabled,
1272 sizeof(info->osps_cache.osc_spectral_enabled));
1273
1274 target_if_log_read_spectral_enabled_catch_validate(
1275 __func__,
1276 *((unsigned char *)output));
1277 break;
1278
1279 case TARGET_IF_SPECTRAL_INFO_PARAMS:
1280 qdf_mem_copy(output,
1281 &info->osps_cache.osc_params,
1282 sizeof(info->osps_cache.osc_params));
1283
1284 target_if_log_read_spectral_params_catch_validate(
1285 __func__,
1286 (struct spectral_config *)output);
1287
1288 break;
1289
1290 default:
1291 /* We can't reach this point */
1292 break;
1293 }
1294
1295 qdf_spin_unlock_bh(&info->osps_lock);
1296
1297 return 0;
1298 }
1299
1300 /**
1301 * target_if_log_write_spectral_active() - Helper function to log inputs and
1302 * return value of call to configure the Spectral 'active' configuration,
1303 * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware
1304 * @function_name: Function name in which this is called
1305 * @pval: whether spectral is active or not
1306 * @ret: return value of the firmware write function
1307 *
1308 * Return: none
1309 */
1310 static void
target_if_log_write_spectral_active(const char * function_name,uint8_t pval,int ret)1311 target_if_log_write_spectral_active(
1312 const char *function_name,
1313 uint8_t pval,
1314 int ret)
1315 {
1316 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d",
1317 function_name, pval, ret);
1318 }
1319
1320 /**
1321 * target_if_log_write_spectral_enabled() - Helper function to log inputs and
1322 * return value of call to configure the Spectral 'enabled' configuration,
1323 * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware
1324 * @function_name: Function name in which this is called
1325 * @pval: whether spectral is enabled or not
1326 * @ret: return value of the firmware write function
1327 *
1328 * Return: none
1329 */
1330 static void
target_if_log_write_spectral_enabled(const char * function_name,uint8_t pval,int ret)1331 target_if_log_write_spectral_enabled(
1332 const char *function_name,
1333 uint8_t pval,
1334 int ret)
1335 {
1336 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d",
1337 function_name, pval, ret);
1338 }
1339
1340 /**
1341 * target_if_log_write_spectral_params() - Helper function to log inputs and
1342 * return value of call to configure Spectral parameters,
1343 * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware
1344 * @param: Spectral parameters
1345 * @function_name: Function name in which this is called
1346 * @ret: return value of the firmware write function
1347 *
1348 * Return: none
1349 */
1350 static void
target_if_log_write_spectral_params(struct spectral_config * param,const char * function_name,int ret)1351 target_if_log_write_spectral_params(
1352 struct spectral_config *param,
1353 const char *function_name,
1354 int ret)
1355 {
1356 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency1=%u\nss_frequency2=%u\nstatus = %d",
1357 function_name,
1358 param->ss_count,
1359 param->ss_period,
1360 param->ss_recapture,
1361 param->ss_spectral_pri,
1362 param->ss_fft_size,
1363 param->ss_gc_ena,
1364 param->ss_restart_ena,
1365 (int8_t)param->ss_noise_floor_ref,
1366 param->ss_init_delay,
1367 param->ss_nb_tone_thr,
1368 param->ss_str_bin_thr,
1369 param->ss_wb_rpt_mode,
1370 param->ss_rssi_rpt_mode,
1371 (int8_t)param->ss_rssi_thr,
1372 param->ss_pwr_format,
1373 param->ss_rpt_mode,
1374 param->ss_bin_scale,
1375 param->ss_dbm_adj,
1376 param->ss_chn_mask,
1377 param->ss_frequency.cfreq1,
1378 param->ss_frequency.cfreq2,
1379 ret);
1380 }
1381
1382 /**
1383 * target_if_spectral_info_write() - Write Spectral information to the
1384 * firmware, and update cache
1385 * @spectral: Pointer to Spectral target_if internal private data
1386 * @smode: Spectral scan mode
1387 * @specifier: target_if_spectral_info enumeration specifying which
1388 * information is involved
1389 * @input: void input pointer containing the information to be written
1390 * @input_len: size of object pointed to by input pointer
1391 *
1392 * Write Spectral parameters or the desired state information to
1393 * the firmware, and update cache
1394 *
1395 * Return: 0 on success, negative error code on failure
1396 */
1397 static int
target_if_spectral_info_write(struct target_if_spectral * spectral,enum spectral_scan_mode smode,enum target_if_spectral_info specifier,void * input,int input_len)1398 target_if_spectral_info_write(
1399 struct target_if_spectral *spectral,
1400 enum spectral_scan_mode smode,
1401 enum target_if_spectral_info specifier,
1402 void *input, int input_len)
1403 {
1404 struct target_if_spectral_param_state_info *info;
1405 int ret;
1406 uint8_t *pval = NULL;
1407 struct spectral_config *param = NULL;
1408
1409 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1410 spectral_err("Invalid Spectral mode %u", smode);
1411 return -EINVAL;
1412 }
1413 info = &spectral->param_info[smode];
1414
1415 if (!input)
1416 return -EINVAL;
1417
1418 switch (specifier) {
1419 case TARGET_IF_SPECTRAL_INFO_ACTIVE:
1420 if (input_len != sizeof(info->osps_cache.osc_spectral_active))
1421 return -EINVAL;
1422
1423 pval = (uint8_t *)input;
1424
1425 qdf_spin_lock_bh(&info->osps_lock);
1426 ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode,
1427 1, *pval, 0, 0);
1428
1429 target_if_log_write_spectral_active(
1430 __func__,
1431 *pval,
1432 ret);
1433
1434 if (ret < 0) {
1435 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
1436 ret);
1437 qdf_spin_unlock_bh(&info->osps_lock);
1438 return ret;
1439 }
1440
1441 info->osps_cache.osc_spectral_active = *pval;
1442
1443 /* The cache is now valid */
1444 info->osps_cache.osc_is_valid = 1;
1445
1446 qdf_spin_unlock_bh(&info->osps_lock);
1447 break;
1448
1449 case TARGET_IF_SPECTRAL_INFO_ENABLED:
1450 if (input_len != sizeof(info->osps_cache.osc_spectral_enabled))
1451 return -EINVAL;
1452
1453 pval = (uint8_t *)input;
1454
1455 qdf_spin_lock_bh(&info->osps_lock);
1456 ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode,
1457 0, 0, 1, *pval);
1458
1459 target_if_log_write_spectral_enabled(
1460 __func__,
1461 *pval,
1462 ret);
1463
1464 if (ret < 0) {
1465 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d",
1466 ret);
1467 qdf_spin_unlock_bh(&info->osps_lock);
1468 return ret;
1469 }
1470
1471 info->osps_cache.osc_spectral_enabled = *pval;
1472
1473 /* The cache is now valid */
1474 info->osps_cache.osc_is_valid = 1;
1475
1476 qdf_spin_unlock_bh(&info->osps_lock);
1477 break;
1478
1479 case TARGET_IF_SPECTRAL_INFO_PARAMS:
1480 if (input_len != sizeof(info->osps_cache.osc_params))
1481 return -EINVAL;
1482
1483 param = (struct spectral_config *)input;
1484
1485 qdf_spin_lock_bh(&info->osps_lock);
1486 ret = target_if_send_vdev_spectral_configure_cmd(spectral,
1487 smode, param);
1488
1489 target_if_log_write_spectral_params(
1490 param,
1491 __func__,
1492 ret);
1493
1494 if (ret < 0) {
1495 spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d",
1496 ret);
1497 qdf_spin_unlock_bh(&info->osps_lock);
1498 return ret;
1499 }
1500
1501 qdf_mem_copy(&info->osps_cache.osc_params,
1502 param, sizeof(info->osps_cache.osc_params));
1503
1504 /* The cache is now valid */
1505 info->osps_cache.osc_is_valid = 1;
1506
1507 qdf_spin_unlock_bh(&info->osps_lock);
1508 break;
1509
1510 default:
1511 spectral_err("Unknown target_if_spectral_info specifier");
1512 return -EINVAL;
1513 }
1514
1515 return 0;
1516 }
1517
1518 /**
1519 * target_if_spectral_get_tsf64() - Function to get the TSF value
1520 * @arg: Pointer to handle for Spectral target_if internal private data
1521 *
1522 * Get the last TSF received in WMI buffer
1523 *
1524 * Return: TSF value
1525 */
1526 static uint64_t
target_if_spectral_get_tsf64(void * arg)1527 target_if_spectral_get_tsf64(void *arg)
1528 {
1529 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1530
1531 return spectral->tsf64;
1532 }
1533
1534 /**
1535 * target_if_spectral_get_capability() - Function to get whether a
1536 * given Spectral hardware capability is available
1537 * @arg: Pointer to handle for Spectral target_if internal private data
1538 * @type: Spectral hardware capability type
1539 *
1540 * Get whether a given Spectral hardware capability is available
1541 *
1542 * Return: True if the capability is available, false if the capability is not
1543 * available
1544 */
1545 uint32_t
target_if_spectral_get_capability(void * arg,enum spectral_capability_type type)1546 target_if_spectral_get_capability(void *arg, enum spectral_capability_type type)
1547 {
1548 int status = STATUS_FAIL;
1549
1550 switch (type) {
1551 case SPECTRAL_CAP_PHYDIAG:
1552 case SPECTRAL_CAP_RADAR:
1553 case SPECTRAL_CAP_SPECTRAL_SCAN:
1554 case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN:
1555 status = STATUS_PASS;
1556 break;
1557 default:
1558 status = STATUS_FAIL;
1559 }
1560 return status;
1561 }
1562
1563 /**
1564 * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start
1565 * @arg: Pointer to handle for Spectral target_if internal private data
1566 * @rxfilter: Rx filter to be used
1567 *
1568 * Note: This is only a placeholder function. It is not currently required since
1569 * FW should be taking care of setting the required filters.
1570 *
1571 * Return: 0
1572 */
1573 uint32_t
target_if_spectral_set_rxfilter(void * arg,int rxfilter)1574 target_if_spectral_set_rxfilter(void *arg, int rxfilter)
1575 {
1576 /*
1577 * Will not be required since enabling of spectral in firmware
1578 * will take care of this
1579 */
1580 return 0;
1581 }
1582
1583 /**
1584 * target_if_spectral_get_rxfilter() - Get the current RX Filter settings
1585 * @arg: Pointer to handle for Spectral target_if internal private data
1586 *
1587 * Note: This is only a placeholder function. It is not currently required since
1588 * FW should be taking care of setting the required filters.
1589 *
1590 * Return: 0
1591 */
1592 uint32_t
target_if_spectral_get_rxfilter(void * arg)1593 target_if_spectral_get_rxfilter(void *arg)
1594 {
1595 /*
1596 * Will not be required since enabling of spectral in firmware
1597 * will take care of this
1598 */
1599 return 0;
1600 }
1601
1602 /**
1603 * target_if_sops_is_spectral_active() - Get whether Spectral is active
1604 * @arg: Pointer to handle for Spectral target_if internal private data
1605 * @smode: Spectral scan mode
1606 *
1607 * Function to check whether Spectral is active
1608 *
1609 * Return: True if Spectral is active, false if Spectral is not active
1610 */
1611 uint32_t
target_if_sops_is_spectral_active(void * arg,enum spectral_scan_mode smode)1612 target_if_sops_is_spectral_active(void *arg, enum spectral_scan_mode smode)
1613 {
1614 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1615 uint8_t val = 0;
1616 int ret;
1617
1618 ret = target_if_spectral_info_read(
1619 spectral,
1620 smode,
1621 TARGET_IF_SPECTRAL_INFO_ACTIVE,
1622 &val, sizeof(val));
1623
1624 if (ret != 0) {
1625 /*
1626 * Could not determine if Spectral is active.
1627 * Return false as a safe value.
1628 * XXX: Consider changing the function prototype
1629 * to be able to indicate failure to fetch value.
1630 */
1631 return 0;
1632 }
1633
1634 return val;
1635 }
1636
1637 /**
1638 * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled
1639 * @arg: Pointer to handle for Spectral target_if internal private data
1640 * @smode: Spectral scan mode
1641 *
1642 * Function to check whether Spectral is enabled
1643 *
1644 * Return: True if Spectral is enabled, false if Spectral is not enabled
1645 */
1646 uint32_t
target_if_sops_is_spectral_enabled(void * arg,enum spectral_scan_mode smode)1647 target_if_sops_is_spectral_enabled(void *arg, enum spectral_scan_mode smode)
1648 {
1649 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1650 uint8_t val = 0;
1651 int ret;
1652
1653 ret = target_if_spectral_info_read(
1654 spectral,
1655 smode,
1656 TARGET_IF_SPECTRAL_INFO_ENABLED,
1657 &val, sizeof(val));
1658
1659 if (ret != 0) {
1660 /*
1661 * Could not determine if Spectral is enabled.
1662 * Return false as a safe value.
1663 * XXX: Consider changing the function prototype
1664 * to be able to indicate failure to fetch value.
1665 */
1666 return 0;
1667 }
1668
1669 return val;
1670 }
1671
1672 /**
1673 * target_if_sops_start_spectral_scan() - Start Spectral scan
1674 * @arg: Pointer to handle for Spectral target_if internal private data
1675 * @smode: Spectral scan mode
1676 * @err: Spectral error code
1677 *
1678 * Function to start spectral scan
1679 *
1680 * Return: 0 on success else failure
1681 */
1682 uint32_t
target_if_sops_start_spectral_scan(void * arg,enum spectral_scan_mode smode,enum spectral_cp_error_code * err)1683 target_if_sops_start_spectral_scan(void *arg, enum spectral_scan_mode smode,
1684 enum spectral_cp_error_code *err)
1685 {
1686 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1687 uint8_t val = 1;
1688 uint8_t enabled = 0;
1689 int ret;
1690
1691 ret = target_if_spectral_info_read(
1692 spectral,
1693 smode,
1694 TARGET_IF_SPECTRAL_INFO_ENABLED,
1695 &enabled, sizeof(enabled));
1696
1697 if (ret != 0) {
1698 /*
1699 * Could not determine if Spectral is enabled. Assume we need
1700 * to enable it
1701 */
1702 enabled = 0;
1703 }
1704
1705 if (!enabled) {
1706 ret = target_if_spectral_info_write(
1707 spectral,
1708 smode,
1709 TARGET_IF_SPECTRAL_INFO_ENABLED,
1710 &val, sizeof(val));
1711
1712 if (ret != 0)
1713 return ret;
1714 }
1715
1716 ret = target_if_spectral_info_write(
1717 spectral,
1718 smode,
1719 TARGET_IF_SPECTRAL_INFO_ACTIVE,
1720 &val, sizeof(val));
1721
1722 if (ret != 0)
1723 return ret;
1724
1725 return 0;
1726 }
1727
1728 /**
1729 * target_if_sops_stop_spectral_scan() - Stop Spectral scan
1730 * @arg: Pointer to handle for Spectral target_if internal private data
1731 * @smode: Spectral scan mode
1732 *
1733 * Function to stop spectral scan
1734 *
1735 * Return: 0 on success else failure
1736 */
1737 uint32_t
target_if_sops_stop_spectral_scan(void * arg,enum spectral_scan_mode smode)1738 target_if_sops_stop_spectral_scan(void *arg, enum spectral_scan_mode smode)
1739 {
1740 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1741 uint8_t val = 0;
1742 int tempret, ret = 0;
1743 uint8_t enabled = 0;
1744
1745 tempret = target_if_spectral_info_read(
1746 spectral,
1747 smode,
1748 TARGET_IF_SPECTRAL_INFO_ENABLED,
1749 &enabled, sizeof(enabled));
1750
1751 if (tempret)
1752 /*
1753 * Could not determine if Spectral is enabled. Assume scan is
1754 * not in progress
1755 */
1756 enabled = 0;
1757
1758 /* if scan is not enabled, no need to send stop to FW */
1759 if (!enabled)
1760 return -EPERM;
1761
1762 tempret = target_if_spectral_info_write(
1763 spectral,
1764 smode,
1765 TARGET_IF_SPECTRAL_INFO_ACTIVE,
1766 &val, sizeof(val));
1767
1768 if (tempret != 0)
1769 ret = tempret;
1770
1771 tempret = target_if_spectral_info_write(
1772 spectral,
1773 smode,
1774 TARGET_IF_SPECTRAL_INFO_ENABLED,
1775 &val, sizeof(val));
1776
1777 if (tempret != 0)
1778 ret = tempret;
1779
1780 if (ret == 0 && smode == SPECTRAL_SCAN_MODE_AGILE) {
1781 struct target_if_spectral_ops *p_sops;
1782 struct spectral_config *sparams;
1783
1784 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
1785 sparams = &spectral->params[smode];
1786 sparams->ss_frequency.cfreq1 = 0;
1787 sparams->ss_frequency.cfreq2 = 0;
1788
1789 p_sops->configure_spectral(spectral, sparams, smode);
1790 }
1791
1792 return ret;
1793 }
1794
1795 /**
1796 * target_if_spectral_get_extension_channel() - Get the Extension channel
1797 * @arg: Pointer to handle for Spectral target_if internal private data
1798 * @smode: Spectral scan mode
1799 *
1800 * Function to get the current Extension channel (in MHz)
1801 *
1802 * Return: Current Extension channel (in MHz) on success, 0 on failure or if
1803 * extension channel is not present.
1804 */
1805 uint32_t
target_if_spectral_get_extension_channel(void * arg,enum spectral_scan_mode smode)1806 target_if_spectral_get_extension_channel(void *arg,
1807 enum spectral_scan_mode smode)
1808 {
1809 /*
1810 * XXX: Once we expand to use cases where Spectral could be activated
1811 * without a channel being set to VDEV, we need to consider returning a
1812 * negative value in case of failure and having all callers handle this.
1813 */
1814
1815 struct target_if_spectral *spectral = NULL;
1816 struct wlan_objmgr_vdev *vdev = NULL;
1817 uint16_t sec20chan_freq = 0;
1818
1819 if (!arg) {
1820 spectral_err("Null argument.");
1821 return 0;
1822 }
1823
1824 spectral = (struct target_if_spectral *)arg;
1825
1826 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1827 spectral_err("Invalid Spectral mode %u", smode);
1828 return 0;
1829 }
1830 vdev = target_if_spectral_get_vdev(spectral, smode);
1831 if (!vdev)
1832 return 0;
1833
1834 if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) {
1835 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1836 return 0;
1837 }
1838
1839 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1840
1841 return sec20chan_freq;
1842 }
1843
1844 /**
1845 * target_if_spectral_get_current_channel() - Get the current channel
1846 * @arg: Pointer to handle for Spectral target_if internal private data
1847 * @smode: Spectral scan mode
1848 *
1849 * Function to get the current channel (in MHz)
1850 *
1851 * Return: Current channel (in MHz) on success, 0 on failure
1852 */
1853 uint32_t
target_if_spectral_get_current_channel(void * arg,enum spectral_scan_mode smode)1854 target_if_spectral_get_current_channel(void *arg, enum spectral_scan_mode smode)
1855 {
1856 /*
1857 * XXX: Once we expand to use cases where Spectral could be activated
1858 * without a channel being set to VDEV, we need to consider returning a
1859 * negative value in case of failure and having all callers handle this.
1860 */
1861
1862 struct target_if_spectral *spectral = NULL;
1863 int16_t chan_freq = 0;
1864 struct wlan_objmgr_vdev *vdev = NULL;
1865
1866 if (!arg) {
1867 spectral_err("Null argument.");
1868 return 0;
1869 }
1870
1871 spectral = (struct target_if_spectral *)arg;
1872
1873 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
1874 spectral_err("Invalid Spectral mode %u", smode);
1875 return 0;
1876 }
1877 vdev = target_if_spectral_get_vdev(spectral, smode);
1878 if (!vdev)
1879 return 0;
1880
1881 chan_freq = target_if_vdev_get_chan_freq(vdev);
1882 if (chan_freq < 0) {
1883 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1884 return 0;
1885 }
1886
1887 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
1888
1889 return chan_freq;
1890 }
1891
1892 /**
1893 * target_if_spectral_reset_hw() - Reset the hardware
1894 * @arg: Pointer to handle for Spectral target_if internal private data
1895 *
1896 * This is only a placeholder since it is not currently required in the offload
1897 * case.
1898 *
1899 * Return: 0
1900 */
1901 uint32_t
target_if_spectral_reset_hw(void * arg)1902 target_if_spectral_reset_hw(void *arg)
1903 {
1904 not_yet_implemented();
1905 return 0;
1906 }
1907
1908 /**
1909 * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from
1910 * Noisefloor history buffer
1911 * @arg: Pointer to handle for Spectral target_if internal private data
1912 * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied
1913 *
1914 * This is only a placeholder since it is not currently required in the offload
1915 * case.
1916 *
1917 * Return: 0
1918 */
1919 uint32_t
target_if_spectral_get_chain_noise_floor(void * arg,int16_t * nf_buf)1920 target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf)
1921 {
1922 not_yet_implemented();
1923 return 0;
1924 }
1925
1926 /**
1927 * target_if_spectral_get_ext_noisefloor() - Get the extension channel
1928 * noisefloor
1929 * @arg: Pointer to handle for Spectral target_if internal private data
1930 *
1931 * This is only a placeholder since it is not currently required in the offload
1932 * case.
1933 *
1934 * Return: 0
1935 */
1936 int8_t
target_if_spectral_get_ext_noisefloor(void * arg)1937 target_if_spectral_get_ext_noisefloor(void *arg)
1938 {
1939 not_yet_implemented();
1940 return 0;
1941 }
1942
1943 /**
1944 * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor
1945 * @arg: Pointer to handle for Spectral target_if internal private data
1946 *
1947 * This is only a placeholder since it is not currently required in the offload
1948 * case.
1949 *
1950 * Return: 0
1951 */
1952 int8_t
target_if_spectral_get_ctl_noisefloor(void * arg)1953 target_if_spectral_get_ctl_noisefloor(void *arg)
1954 {
1955 not_yet_implemented();
1956 return 0;
1957 }
1958
1959 /**
1960 * target_if_spectral_sops_configure_params() - Configure user supplied Spectral
1961 * parameters
1962 * @arg: Pointer to handle for Spectral target_if internal private data
1963 * @params: Spectral parameters
1964 * @smode: Spectral scan mode
1965 *
1966 * Function to configure spectral parameters
1967 *
1968 * Return: 0 on success else failure
1969 */
1970 uint32_t
target_if_spectral_sops_configure_params(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)1971 target_if_spectral_sops_configure_params(
1972 void *arg, struct spectral_config *params,
1973 enum spectral_scan_mode smode)
1974 {
1975 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
1976
1977 return target_if_spectral_info_write(
1978 spectral,
1979 smode,
1980 TARGET_IF_SPECTRAL_INFO_PARAMS,
1981 params, sizeof(*params));
1982 }
1983
1984 /**
1985 * target_if_spectral_sops_get_params() - Get user configured Spectral
1986 * parameters
1987 * @arg: Pointer to handle for Spectral target_if internal private data
1988 * @params: Pointer to buffer into which Spectral parameters should be copied
1989 * @smode: Spectral scan mode
1990 *
1991 * Function to get the configured spectral parameters
1992 *
1993 * Return: 0 on success else failure
1994 */
1995 uint32_t
target_if_spectral_sops_get_params(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)1996 target_if_spectral_sops_get_params(void *arg, struct spectral_config *params,
1997 enum spectral_scan_mode smode)
1998 {
1999 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
2000
2001 return target_if_spectral_info_read(
2002 spectral,
2003 smode,
2004 TARGET_IF_SPECTRAL_INFO_PARAMS,
2005 params, sizeof(*params));
2006 }
2007
2008 /**
2009 * target_if_spectral_get_ent_mask() - Get enterprise mask
2010 * @arg: Pointer to handle for Spectral target_if internal private data
2011 *
2012 * This is only a placeholder since it is not currently required in the offload
2013 * case.
2014 *
2015 * Return: 0
2016 */
2017 static uint32_t
target_if_spectral_get_ent_mask(void * arg)2018 target_if_spectral_get_ent_mask(void *arg)
2019 {
2020 not_yet_implemented();
2021 return 0;
2022 }
2023
2024 /**
2025 * target_if_spectral_get_macaddr() - Get radio MAC address
2026 * @arg: Pointer to handle for Spectral target_if internal private data
2027 * @addr: Pointer to buffer into which MAC address should be copied
2028 *
2029 * Function to get the MAC address of the pdev
2030 *
2031 * Return: 0 on success, -1 on failure
2032 */
2033 static uint32_t
target_if_spectral_get_macaddr(void * arg,char * addr)2034 target_if_spectral_get_macaddr(void *arg, char *addr)
2035 {
2036 uint8_t *myaddr = NULL;
2037 struct target_if_spectral *spectral = (struct target_if_spectral *)arg;
2038 struct wlan_objmgr_pdev *pdev = NULL;
2039
2040 pdev = spectral->pdev_obj;
2041
2042 wlan_pdev_obj_lock(pdev);
2043 myaddr = wlan_pdev_get_hw_macaddr(pdev);
2044 wlan_pdev_obj_unlock(pdev);
2045 qdf_mem_copy(addr, myaddr, QDF_MAC_ADDR_SIZE);
2046
2047 return 0;
2048 }
2049
2050 /**
2051 * target_if_init_spectral_param_min_max_be() - Initialize Spectral parameter
2052 * min and max values for beryllium chipsets
2053 *
2054 * @spectral: Spectral LMAC object
2055 *
2056 * Return: QDF_STATUS of operation
2057 */
2058 static QDF_STATUS
target_if_init_spectral_param_min_max_be(struct target_if_spectral * spectral)2059 target_if_init_spectral_param_min_max_be(struct target_if_spectral *spectral)
2060 {
2061 struct spectral_param_min_max *param_min_max;
2062 enum phy_ch_width op_bw;
2063 QDF_STATUS status;
2064
2065 param_min_max = &spectral->param_min_max;
2066 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3_BE;
2067 param_min_max->scan_count_max = SPECTRAL_PARAM_SCAN_COUNT_MAX_GEN3_BE;
2068
2069 for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) {
2070 bool is_supported;
2071
2072 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj,
2073 op_bw, &is_supported);
2074 if (QDF_IS_STATUS_ERROR(status)) {
2075 spectral_err("Unable to check if ch_width(%d) is supported",
2076 op_bw);
2077 return QDF_STATUS_E_FAILURE;
2078 }
2079
2080 if (!is_supported) {
2081 param_min_max->fft_size_max[op_bw] = INVALID_FFT_SIZE;
2082 continue;
2083 }
2084
2085 switch (op_bw) {
2086 case CH_WIDTH_20MHZ:
2087 param_min_max->fft_size_max[op_bw] =
2088 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE_20MHZ;
2089 break;
2090
2091 case CH_WIDTH_40MHZ:
2092 param_min_max->fft_size_max[op_bw] =
2093 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE_40MHZ;
2094 break;
2095
2096 default:
2097 param_min_max->fft_size_max[op_bw] =
2098 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE;
2099 }
2100 }
2101
2102 return QDF_STATUS_SUCCESS;
2103 }
2104
2105 /**
2106 * target_if_init_spectral_param_min_max() - Initialize Spectral parameter
2107 * min and max values
2108 *
2109 * @spectral: Spectral LMAC object
2110 * @gen: Spectral HW generation
2111 * @target_type: Target type
2112 *
2113 * Initialize Spectral parameter min and max values
2114 *
2115 * Return: QDF_STATUS
2116 */
2117 static QDF_STATUS
target_if_init_spectral_param_min_max(struct target_if_spectral * spectral,enum spectral_gen gen,uint32_t target_type)2118 target_if_init_spectral_param_min_max(
2119 struct target_if_spectral *spectral,
2120 enum spectral_gen gen, uint32_t target_type)
2121 {
2122 struct spectral_param_min_max *param_min_max;
2123
2124 if (!spectral) {
2125 spectral_err("Spectral LMAC object is null");
2126 return QDF_STATUS_E_NULL_VALUE;
2127 }
2128
2129 if (is_spectral_arch_beryllium(target_type))
2130 return target_if_init_spectral_param_min_max_be(spectral);
2131
2132 param_min_max = &spectral->param_min_max;
2133 switch (gen) {
2134 case SPECTRAL_GEN3:
2135 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3;
2136 param_min_max->fft_size_max[CH_WIDTH_20MHZ] =
2137 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2138 param_min_max->scan_count_max =
2139 SPECTRAL_PARAM_SCAN_COUNT_MAX_GEN3;
2140 if (target_type == TARGET_TYPE_QCN9000 ||
2141 target_type == TARGET_TYPE_QCN6122 ||
2142 target_type == TARGET_TYPE_QCN9160 ||
2143 target_type == TARGET_TYPE_QCA5018 ||
2144 target_type == TARGET_TYPE_QCA6490 ||
2145 target_type == TARGET_TYPE_KIWI ||
2146 target_type == TARGET_TYPE_MANGO ||
2147 target_type == TARGET_TYPE_PEACH) {
2148 param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
2149 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2150 param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
2151 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2152 param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
2153 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2154 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
2155 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000;
2156 } else {
2157 param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
2158 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2159 param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
2160 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2161 param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
2162 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2163 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
2164 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT;
2165 }
2166 break;
2167
2168 case SPECTRAL_GEN2:
2169 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2;
2170 param_min_max->fft_size_max[CH_WIDTH_20MHZ] =
2171 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2172 param_min_max->fft_size_max[CH_WIDTH_40MHZ] =
2173 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2174 param_min_max->fft_size_max[CH_WIDTH_80MHZ] =
2175 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2176 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] =
2177 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2178 param_min_max->fft_size_max[CH_WIDTH_160MHZ] =
2179 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2;
2180 break;
2181
2182 default:
2183 spectral_err("Invalid spectral generation %d", gen);
2184 return QDF_STATUS_E_INVAL;
2185 }
2186
2187 return QDF_STATUS_SUCCESS;
2188 }
2189
2190 /**
2191 * target_if_init_spectral_param_properties() - Initialize Spectral parameter
2192 * properties
2193 * @spectral: Pointer to Spectral target_if internal private data
2194 *
2195 * Initialize Spectral parameter properties
2196 *
2197 * Return: QDF_STATUS
2198 */
2199 static QDF_STATUS
target_if_init_spectral_param_properties(struct target_if_spectral * spectral)2200 target_if_init_spectral_param_properties(struct target_if_spectral *spectral)
2201 {
2202 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
2203 int param;
2204
2205 /* Initialize default values for properties.
2206 * Default values are supported for all the parameters for all modes
2207 * and allows different values for each mode for all the parameters .
2208 */
2209 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2210 for (param = 0; param < SPECTRAL_PARAM_MAX; param++) {
2211 spectral->properties[smode][param].supported = true;
2212 spectral->properties[smode][param].common_all_modes =
2213 false;
2214 }
2215 }
2216
2217 /* Once FW advertisement is in place remove this hard coding */
2218 smode = SPECTRAL_SCAN_MODE_NORMAL;
2219 spectral->properties[SPECTRAL_SCAN_MODE_NORMAL]
2220 [SPECTRAL_PARAM_FREQUENCY].supported = false;
2221 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2222 spectral->properties[smode]
2223 [SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true;
2224 spectral->properties[smode]
2225 [SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true;
2226 spectral->properties[smode]
2227 [SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true;
2228 }
2229
2230 return QDF_STATUS_SUCCESS;
2231 }
2232
2233 /* Bandwidth to half bandwidth mapping */
2234 static const enum phy_ch_width half_bw_map[] = {
2235 #ifdef WLAN_FEATURE_11BE
2236 [CH_WIDTH_320MHZ] = CH_WIDTH_160MHZ,
2237 #endif
2238 [CH_WIDTH_80P80MHZ] = CH_WIDTH_80MHZ,
2239 [CH_WIDTH_160MHZ] = CH_WIDTH_80MHZ,
2240 [CH_WIDTH_80MHZ] = CH_WIDTH_40MHZ,
2241 [CH_WIDTH_40MHZ] = CH_WIDTH_20MHZ,
2242 [CH_WIDTH_20MHZ] = CH_WIDTH_10MHZ,
2243 [CH_WIDTH_10MHZ] = CH_WIDTH_5MHZ,
2244 [CH_WIDTH_5MHZ] = CH_WIDTH_INVALID
2245 };
2246
2247 /**
2248 * target_if_get_half_bandwidth() - Get half bandwidth for a given bandwidth
2249 * @bw: bandwidth
2250 *
2251 * Return: Half bandwidth of @bw
2252 */
target_if_get_half_bandwidth(enum phy_ch_width bw)2253 static enum phy_ch_width target_if_get_half_bandwidth(enum phy_ch_width bw)
2254 {
2255 if (bw >= CH_WIDTH_INVALID)
2256 return CH_WIDTH_INVALID;
2257
2258 return half_bw_map[bw];
2259 }
2260
2261 /**
2262 * target_if_populate_supported_sscan_bws_be() - Populate supported spectral
2263 * scan bandwidths for beryllium chipsets
2264 * @spectral: Spectral LMAC object
2265 *
2266 * Return: QDF_STATUS of operation
2267 */
2268 static QDF_STATUS
target_if_populate_supported_sscan_bws_be(struct target_if_spectral * spectral)2269 target_if_populate_supported_sscan_bws_be(struct target_if_spectral *spectral)
2270 {
2271 enum phy_ch_width op_bw;
2272 struct spectral_supported_bws *supported_bws;
2273 QDF_STATUS status;
2274
2275 if (!spectral) {
2276 spectral_err("spectral variable is null");
2277 return QDF_STATUS_E_NULL_VALUE;
2278 }
2279
2280 /* 20MHz */
2281 op_bw = CH_WIDTH_20MHZ;
2282 supported_bws = &spectral->supported_bws
2283 [SPECTRAL_SCAN_MODE_NORMAL][op_bw];
2284 supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw);
2285 spectral->supported_sscan_bw_list
2286 [SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true;
2287 supported_bws = &spectral->supported_bws
2288 [SPECTRAL_SCAN_MODE_AGILE][op_bw];
2289 supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw);
2290 spectral->supported_sscan_bw_list
2291 [SPECTRAL_SCAN_MODE_AGILE][op_bw] = true;
2292
2293 for (op_bw = CH_WIDTH_40MHZ; op_bw < CH_WIDTH_MAX; op_bw++) {
2294 bool is_supported;
2295 enum phy_ch_width half_op_bw;
2296
2297 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj,
2298 op_bw, &is_supported);
2299 if (QDF_IS_STATUS_ERROR(status)) {
2300 spectral_err("Unable to check if ch_width(%d) is supported",
2301 op_bw);
2302 return QDF_STATUS_E_FAILURE;
2303 }
2304
2305 if (!is_supported)
2306 continue;
2307
2308 spectral_debug("Updating supported bw for op_bw: %d", op_bw);
2309 /* Normal mode */
2310 supported_bws = &spectral->supported_bws
2311 [SPECTRAL_SCAN_MODE_NORMAL][op_bw];
2312 supported_bws->bandwidths |=
2313 1 << get_supported_sscan_bw_pos(op_bw);
2314 spectral->supported_sscan_bw_list
2315 [SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true;
2316
2317 /* Agile mode */
2318 supported_bws = &spectral->supported_bws
2319 [SPECTRAL_SCAN_MODE_AGILE][op_bw];
2320 supported_bws->bandwidths |=
2321 1 << get_supported_sscan_bw_pos(op_bw);
2322 spectral->supported_sscan_bw_list
2323 [SPECTRAL_SCAN_MODE_AGILE][op_bw] = true;
2324
2325 half_op_bw = target_if_get_half_bandwidth(op_bw);
2326 if (half_op_bw != CH_WIDTH_INVALID) {
2327 supported_bws->bandwidths |=
2328 1 << get_supported_sscan_bw_pos(half_op_bw);
2329 spectral->supported_sscan_bw_list
2330 [SPECTRAL_SCAN_MODE_AGILE][half_op_bw] = true;
2331 }
2332 }
2333
2334 return QDF_STATUS_SUCCESS;
2335 }
2336
2337 /**
2338 * target_if_populate_supported_sscan_bws() - Populate supported spectral
2339 * scan bandwidths
2340 * @spectral: Spectral LMAC object
2341 * @target_type: Target type
2342 *
2343 * Return: QDF_STATUS of operation
2344 */
2345 static QDF_STATUS
target_if_populate_supported_sscan_bws(struct target_if_spectral * spectral,uint32_t target_type)2346 target_if_populate_supported_sscan_bws(struct target_if_spectral *spectral,
2347 uint32_t target_type)
2348 {
2349 enum spectral_scan_mode smode;
2350 enum phy_ch_width op_bw;
2351 struct spectral_supported_bws *supported_bws;
2352 struct wlan_objmgr_psoc *psoc;
2353 QDF_STATUS status;
2354
2355 if (!spectral) {
2356 spectral_err("spectral is null");
2357 return QDF_STATUS_E_NULL_VALUE;
2358 }
2359
2360 if (is_spectral_arch_beryllium(target_type))
2361 return target_if_populate_supported_sscan_bws_be(spectral);
2362
2363 psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
2364 if (!psoc) {
2365 spectral_err("psoc is null");
2366 return QDF_STATUS_E_NULL_VALUE;
2367 }
2368
2369 for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) {
2370 bool is_supported;
2371
2372 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj,
2373 op_bw, &is_supported);
2374 if (QDF_IS_STATUS_ERROR(status)) {
2375 spectral_err("Unable to check if ch_width(%d) is supported",
2376 op_bw);
2377 return QDF_STATUS_E_FAILURE;
2378 }
2379
2380 if (!is_supported)
2381 continue;
2382
2383 spectral_debug("Updating supported bw for op_bw: %d", op_bw);
2384 smode = SPECTRAL_SCAN_MODE_NORMAL;
2385 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
2386 supported_bws = &spectral->supported_bws[smode][op_bw];
2387
2388 if (is_ch_width_160_or_80p80(op_bw) &&
2389 smode == SPECTRAL_SCAN_MODE_AGILE) {
2390 /**
2391 * If fragmentation is supported, then only 80Hz
2392 * agile width is supported
2393 */
2394 if (spectral->rparams.
2395 fragmentation_160[smode]) {
2396 supported_bws->bandwidths |=
2397 1 << get_supported_sscan_bw_pos(
2398 CH_WIDTH_80MHZ);
2399 spectral->supported_sscan_bw_list
2400 [smode][CH_WIDTH_80MHZ] = true;
2401 }
2402
2403 /**
2404 * If restricted 80p80 is supported, then both
2405 * 160 and 80p80 agile widths are supported for
2406 * 160MHz, and only 160MHz agile width is
2407 * supported for 80p80
2408 */
2409 if (wlan_psoc_nif_fw_ext_cap_get(
2410 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
2411 supported_bws->bandwidths |=
2412 1 << get_supported_sscan_bw_pos(
2413 CH_WIDTH_160MHZ);
2414 spectral->supported_sscan_bw_list
2415 [smode][CH_WIDTH_160MHZ] = true;
2416
2417 if (op_bw == CH_WIDTH_160MHZ) {
2418 supported_bws->bandwidths |=
2419 1 << get_supported_sscan_bw_pos(
2420 CH_WIDTH_80P80MHZ);
2421 spectral->supported_sscan_bw_list
2422 [smode][CH_WIDTH_80P80MHZ] = true;
2423 }
2424 }
2425 } else {
2426 supported_bws->bandwidths |=
2427 1 << get_supported_sscan_bw_pos(
2428 op_bw);
2429 spectral->supported_sscan_bw_list
2430 [smode][op_bw] = true;
2431 }
2432 }
2433 }
2434
2435 return QDF_STATUS_SUCCESS;
2436 }
2437
2438 QDF_STATUS
target_if_init_spectral_capability(struct target_if_spectral * spectral,uint32_t target_type)2439 target_if_init_spectral_capability(struct target_if_spectral *spectral,
2440 uint32_t target_type)
2441 {
2442 struct wlan_objmgr_psoc *psoc;
2443 struct wlan_objmgr_pdev *pdev;
2444 struct wlan_psoc_host_spectral_scaling_params *scaling_params;
2445 uint8_t num_bin_scaling_params, param_idx, pdev_id;
2446 struct target_psoc_info *tgt_psoc_info;
2447 struct wlan_psoc_host_service_ext_param *ext_svc_param;
2448 struct spectral_caps *pcap = &spectral->capability;
2449 QDF_STATUS status;
2450
2451 pdev = spectral->pdev_obj;
2452 psoc = wlan_pdev_get_psoc(pdev);
2453 if (!psoc) {
2454 spectral_err("psoc is null");
2455 return QDF_STATUS_E_FAILURE;
2456 }
2457
2458 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
2459 if (!tgt_psoc_info) {
2460 spectral_err("target_psoc_info is null");
2461 return QDF_STATUS_E_FAILURE;
2462 }
2463
2464 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
2465 num_bin_scaling_params = ext_svc_param->num_bin_scaling_params;
2466 scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info);
2467 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
2468
2469 /* XXX : Workaround: Set Spectral capability */
2470 pcap = &spectral->capability;
2471 pcap->phydiag_cap = 1;
2472 pcap->radar_cap = 1;
2473 pcap->spectral_cap = wlan_pdev_nif_feat_ext_cap_get(
2474 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS);
2475 pcap->advncd_spectral_cap = pcap->spectral_cap;
2476 pcap->hw_gen = spectral->spectral_gen;
2477
2478 pcap->agile_spectral_cap = !wlan_pdev_nif_feat_ext_cap_get(
2479 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS);
2480 pcap->agile_spectral_cap_160 = !wlan_pdev_nif_feat_ext_cap_get(
2481 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS);
2482 pcap->agile_spectral_cap_80p80 = !wlan_pdev_nif_feat_ext_cap_get(
2483 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS);
2484 pcap->agile_spectral_cap_320 = !wlan_pdev_nif_feat_ext_cap_get(
2485 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS);
2486
2487 if (scaling_params) {
2488 for (param_idx = 0; param_idx < num_bin_scaling_params;
2489 param_idx++) {
2490 if (scaling_params[param_idx].pdev_id == pdev_id) {
2491 pcap->is_scaling_params_populated = true;
2492 pcap->formula_id =
2493 scaling_params[param_idx].formula_id;
2494 pcap->low_level_offset =
2495 scaling_params[param_idx].low_level_offset;
2496 pcap->high_level_offset =
2497 scaling_params[param_idx].high_level_offset;
2498 pcap->rssi_thr =
2499 scaling_params[param_idx].rssi_thr;
2500 pcap->default_agc_max_gain =
2501 scaling_params[param_idx].default_agc_max_gain;
2502 break;
2503 }
2504 }
2505 }
2506
2507 pcap->num_detectors_20mhz = 1;
2508 pcap->num_detectors_40mhz = 1;
2509 pcap->num_detectors_80mhz = 1;
2510 if (target_type == TARGET_TYPE_QCN9000 ||
2511 target_type == TARGET_TYPE_QCN6122 ||
2512 target_type == TARGET_TYPE_QCN9160 ||
2513 target_type == TARGET_TYPE_QCA6490 ||
2514 target_type == TARGET_TYPE_KIWI ||
2515 target_type == TARGET_TYPE_MANGO ||
2516 target_type == TARGET_TYPE_PEACH) {
2517 pcap->num_detectors_160mhz = 1;
2518 pcap->num_detectors_80p80mhz = 1;
2519 pcap->num_detectors_320mhz = 0;
2520 } else if (is_spectral_arch_beryllium(target_type)) {
2521 pcap->num_detectors_160mhz = 1;
2522 pcap->num_detectors_80p80mhz = 0;
2523 pcap->num_detectors_320mhz = 1;
2524 } else {
2525 pcap->num_detectors_160mhz = 2;
2526 pcap->num_detectors_80p80mhz = 2;
2527 pcap->num_detectors_320mhz = 0;
2528 }
2529
2530 status = target_if_populate_supported_sscan_bws(spectral, target_type);
2531 if (QDF_IS_STATUS_ERROR(status)) {
2532 spectral_err("Unable to populate supported sscan BWs");
2533 return QDF_STATUS_E_FAILURE;
2534 }
2535
2536 return QDF_STATUS_SUCCESS;
2537 }
2538
2539 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
2540 /**
2541 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
2542 * internal operations with functions related to spectral simulation
2543 * @p_sops: spectral low level ops table
2544 *
2545 * Initialize spectral target_if internal operations with functions
2546 * related to spectral simulation
2547 *
2548 * Return: None
2549 */
2550 static void
target_if_init_spectral_simulation_ops(struct target_if_spectral_ops * p_sops)2551 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
2552 {
2553 /*
2554 * Spectral simulation is currently intended for platform transitions
2555 * where underlying HW support may not be available for some time.
2556 * Hence, we do not currently provide a runtime switch to turn the
2557 * simulation on or off.
2558 * In case of future requirements where runtime switches are required,
2559 * this can be added. But it is suggested to use application layer
2560 * simulation as far as possible in such cases, since the main
2561 * use of record and replay of samples would concern higher
2562 * level sample processing rather than lower level delivery.
2563 */
2564 p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled;
2565 p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active;
2566 p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan;
2567 p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan;
2568 p_sops->configure_spectral =
2569 target_if_spectral_sops_sim_configure_params;
2570 p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params;
2571 }
2572
2573 #else
2574 /**
2575 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if
2576 * internal operations
2577 * @p_sops: spectral low level ops table
2578 *
2579 * Return: None
2580 */
2581 static void
target_if_init_spectral_simulation_ops(struct target_if_spectral_ops * p_sops)2582 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops)
2583 {
2584 p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled;
2585 p_sops->is_spectral_active = target_if_sops_is_spectral_active;
2586 p_sops->start_spectral_scan = target_if_sops_start_spectral_scan;
2587 p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan;
2588 p_sops->configure_spectral = target_if_spectral_sops_configure_params;
2589 p_sops->get_spectral_config = target_if_spectral_sops_get_params;
2590 }
2591 #endif
2592
2593 /**
2594 * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal
2595 * operations common to all Spectral chipset generations
2596 *
2597 * Initializes target_if_spectral_ops common to all chipset generations
2598 *
2599 * Return: None
2600 */
2601 static void
target_if_init_spectral_ops_common(void)2602 target_if_init_spectral_ops_common(void)
2603 {
2604 struct target_if_spectral_ops *p_sops = &spectral_ops;
2605
2606 p_sops->get_tsf64 = target_if_spectral_get_tsf64;
2607 p_sops->get_capability = target_if_spectral_get_capability;
2608 p_sops->set_rxfilter = target_if_spectral_set_rxfilter;
2609 p_sops->get_rxfilter = target_if_spectral_get_rxfilter;
2610
2611 target_if_init_spectral_simulation_ops(p_sops);
2612
2613 p_sops->get_extension_channel =
2614 target_if_spectral_get_extension_channel;
2615 p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor;
2616 p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor;
2617 p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask;
2618 p_sops->get_mac_address = target_if_spectral_get_macaddr;
2619 p_sops->get_current_channel = target_if_spectral_get_current_channel;
2620 p_sops->reset_hw = target_if_spectral_reset_hw;
2621 p_sops->get_chain_noise_floor =
2622 target_if_spectral_get_chain_noise_floor;
2623 }
2624
2625 /**
2626 * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal
2627 * operations specific to Spectral chipset generation 2.
2628 *
2629 * Initializes target_if_spectral_ops specific to Spectral chipset generation 2.
2630 *
2631 * Return: None
2632 */
2633 static void
target_if_init_spectral_ops_gen2(void)2634 target_if_init_spectral_ops_gen2(void)
2635 {
2636 struct target_if_spectral_ops *p_sops = &spectral_ops;
2637
2638 p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2;
2639 }
2640
2641 #ifdef BIG_ENDIAN_HOST
2642 /**
2643 * spectral_is_host_byte_swap_required() - Check if byte swap has to be done
2644 * on the Host
2645 * @pdev: pdev pointer
2646 * @is_swap_required: Pointer to caller variable
2647 *
2648 * Return: QDF_STATUS of operation
2649 */
2650 static QDF_STATUS
spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev * pdev,bool * is_swap_required)2651 spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev *pdev,
2652 bool *is_swap_required)
2653 {
2654 struct wlan_objmgr_psoc *psoc;
2655 struct wmi_unified *wmi_handle;
2656
2657 if (!pdev) {
2658 spectral_err("pdev is null");
2659 return QDF_STATUS_E_INVAL;
2660 }
2661
2662 psoc = wlan_pdev_get_psoc(pdev);
2663 if (!psoc) {
2664 spectral_err("psoc is null");
2665 return QDF_STATUS_E_INVAL;
2666 }
2667
2668 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
2669 if (!wmi_handle) {
2670 spectral_err("wmi handle is null");
2671 return QDF_STATUS_E_INVAL;
2672 }
2673
2674 /**
2675 * If a chipset supports byte-swap inside the target itself, then no
2676 * need to apply byte swap on the Host.
2677 */
2678 *is_swap_required = !target_if_spectral_wmi_service_enabled(
2679 psoc, wmi_handle,
2680 wmi_service_phy_dma_byte_swap_support);
2681
2682 return QDF_STATUS_SUCCESS;
2683 }
2684
2685 /**
2686 * target_if_spectral_init_byte_swap_funcs_gen3() - Initialize byte-swap
2687 * operations for Spectral chipset generation 3.
2688 * @spectral: Spectral LMAC object
2689 * @p_sops: Spectral function pointer table
2690 *
2691 * Return: None
2692 */
2693 static void
target_if_spectral_init_byte_swap_funcs_gen3(struct target_if_spectral * spectral,struct target_if_spectral_ops * p_sops)2694 target_if_spectral_init_byte_swap_funcs_gen3(
2695 struct target_if_spectral *spectral,
2696 struct target_if_spectral_ops *p_sops)
2697 {
2698 bool is_swap_required;
2699 QDF_STATUS status;
2700
2701 if (!spectral) {
2702 spectral_err("spectral variable is null");
2703 return;
2704 }
2705 if (!p_sops) {
2706 spectral_err("spectral ops variable is null");
2707 return;
2708 }
2709 status = spectral_is_host_byte_swap_required(spectral->pdev_obj,
2710 &is_swap_required);
2711 if (QDF_IS_STATUS_ERROR(status)) {
2712 spectral_err("Failed to check whether byte swap is required");
2713 return;
2714 }
2715
2716 if (is_swap_required) {
2717 p_sops->byte_swap_headers =
2718 target_if_byte_swap_spectral_headers_gen3;
2719 p_sops->byte_swap_fft_bins =
2720 target_if_byte_swap_spectral_fft_bins_gen3;
2721 } else {
2722 p_sops->byte_swap_headers = NULL;
2723 p_sops->byte_swap_fft_bins = NULL;
2724 }
2725 }
2726 #else
2727 static void
target_if_spectral_init_byte_swap_funcs_gen3(struct target_if_spectral * spectral,struct target_if_spectral_ops * p_sops)2728 target_if_spectral_init_byte_swap_funcs_gen3(
2729 struct target_if_spectral *spectral,
2730 struct target_if_spectral_ops *p_sops)
2731 {
2732 if (!p_sops) {
2733 spectral_err("spectral ops variable is null");
2734 return;
2735 }
2736
2737 /* Byte-swap is not required for little-endian Hosts */
2738 p_sops->byte_swap_headers = NULL;
2739 p_sops->byte_swap_fft_bins = NULL;
2740 }
2741 #endif /* BIG_ENDIAN_HOST */
2742
2743 /**
2744 * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal
2745 * operations specific to Spectral chipset generation 3.
2746 * @spectral: Spectral LMAC object
2747 *
2748 * Initializes target_if_spectral_ops specific to Spectral chipset generation 3.
2749 *
2750 * Return: None
2751 */
2752 static void
target_if_init_spectral_ops_gen3(struct target_if_spectral * spectral)2753 target_if_init_spectral_ops_gen3(struct target_if_spectral *spectral)
2754 {
2755 struct target_if_spectral_ops *p_sops = &spectral_ops;
2756
2757 p_sops->process_spectral_report =
2758 target_if_spectral_process_report_gen3;
2759
2760 target_if_spectral_init_byte_swap_funcs_gen3(spectral, p_sops);
2761 }
2762
2763 /**
2764 * target_if_init_spectral_ops() - Initialize target_if internal Spectral
2765 * operations.
2766 * @spectral: Pointer to Spectral target_if internal private data
2767 *
2768 * Initializes all function pointers in target_if_spectral_ops for
2769 * all generations
2770 *
2771 * Return: None
2772 */
2773 static void
target_if_init_spectral_ops(struct target_if_spectral * spectral)2774 target_if_init_spectral_ops(struct target_if_spectral *spectral)
2775 {
2776 target_if_init_spectral_ops_common();
2777 if (spectral->spectral_gen == SPECTRAL_GEN2)
2778 target_if_init_spectral_ops_gen2();
2779 else if (spectral->spectral_gen == SPECTRAL_GEN3)
2780 target_if_init_spectral_ops_gen3(spectral);
2781 else
2782 spectral_err("Invalid Spectral generation");
2783 }
2784
2785 /*
2786 * Dummy Functions:
2787 * These functions are initially registered to avoid any crashes due to
2788 * invocation of spectral functions before they are registered.
2789 */
2790
2791 static uint64_t
null_get_tsf64(void * arg)2792 null_get_tsf64(void *arg)
2793 {
2794 spectral_ops_not_registered("get_tsf64");
2795 return 0;
2796 }
2797
2798 static uint32_t
null_get_capability(void * arg,enum spectral_capability_type type)2799 null_get_capability(void *arg, enum spectral_capability_type type)
2800 {
2801 /*
2802 * TODO : We should have conditional compilation to get the capability
2803 * : We have not yet attahced ATH layer here, so there is no
2804 * : way to check the HAL capbalities
2805 */
2806 spectral_ops_not_registered("get_capability");
2807
2808 /* TODO : For the time being, we are returning TRUE */
2809 return true;
2810 }
2811
2812 static uint32_t
null_set_rxfilter(void * arg,int rxfilter)2813 null_set_rxfilter(void *arg, int rxfilter)
2814 {
2815 spectral_ops_not_registered("set_rxfilter");
2816 return 1;
2817 }
2818
2819 static uint32_t
null_get_rxfilter(void * arg)2820 null_get_rxfilter(void *arg)
2821 {
2822 spectral_ops_not_registered("get_rxfilter");
2823 return 0;
2824 }
2825
2826 static uint32_t
null_is_spectral_active(void * arg,enum spectral_scan_mode smode)2827 null_is_spectral_active(void *arg, enum spectral_scan_mode smode)
2828 {
2829 spectral_ops_not_registered("is_spectral_active");
2830 return 1;
2831 }
2832
2833 static uint32_t
null_is_spectral_enabled(void * arg,enum spectral_scan_mode smode)2834 null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode)
2835 {
2836 spectral_ops_not_registered("is_spectral_enabled");
2837 return 1;
2838 }
2839
2840 static uint32_t
null_start_spectral_scan(void * arg,enum spectral_scan_mode smode,enum spectral_cp_error_code * err)2841 null_start_spectral_scan(void *arg, enum spectral_scan_mode smode,
2842 enum spectral_cp_error_code *err)
2843 {
2844 spectral_ops_not_registered("start_spectral_scan");
2845 return 1;
2846 }
2847
2848 static uint32_t
null_stop_spectral_scan(void * arg,enum spectral_scan_mode smode)2849 null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode)
2850 {
2851 spectral_ops_not_registered("stop_spectral_scan");
2852 return 1;
2853 }
2854
2855 static uint32_t
null_get_extension_channel(void * arg,enum spectral_scan_mode smode)2856 null_get_extension_channel(void *arg, enum spectral_scan_mode smode)
2857 {
2858 spectral_ops_not_registered("get_extension_channel");
2859 return 1;
2860 }
2861
2862 static int8_t
null_get_ctl_noisefloor(void * arg)2863 null_get_ctl_noisefloor(void *arg)
2864 {
2865 spectral_ops_not_registered("get_ctl_noisefloor");
2866 return 1;
2867 }
2868
2869 static int8_t
null_get_ext_noisefloor(void * arg)2870 null_get_ext_noisefloor(void *arg)
2871 {
2872 spectral_ops_not_registered("get_ext_noisefloor");
2873 return 0;
2874 }
2875
2876 static uint32_t
null_configure_spectral(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)2877 null_configure_spectral(void *arg, struct spectral_config *params,
2878 enum spectral_scan_mode smode)
2879 {
2880 spectral_ops_not_registered("configure_spectral");
2881 return 0;
2882 }
2883
2884 static uint32_t
null_get_spectral_config(void * arg,struct spectral_config * params,enum spectral_scan_mode smode)2885 null_get_spectral_config(void *arg, struct spectral_config *params,
2886 enum spectral_scan_mode smode)
2887 {
2888 spectral_ops_not_registered("get_spectral_config");
2889 return 0;
2890 }
2891
2892 static uint32_t
null_get_ent_spectral_mask(void * arg)2893 null_get_ent_spectral_mask(void *arg)
2894 {
2895 spectral_ops_not_registered("get_ent_spectral_mask");
2896 return 0;
2897 }
2898
2899 static uint32_t
null_get_mac_address(void * arg,char * addr)2900 null_get_mac_address(void *arg, char *addr)
2901 {
2902 spectral_ops_not_registered("get_mac_address");
2903 return 0;
2904 }
2905
2906 static uint32_t
null_get_current_channel(void * arg,enum spectral_scan_mode smode)2907 null_get_current_channel(void *arg, enum spectral_scan_mode smode)
2908 {
2909 spectral_ops_not_registered("get_current_channel");
2910 return 0;
2911 }
2912
2913 static uint32_t
null_reset_hw(void * arg)2914 null_reset_hw(void *arg)
2915 {
2916 spectral_ops_not_registered("get_current_channel");
2917 return 0;
2918 }
2919
2920 static uint32_t
null_get_chain_noise_floor(void * arg,int16_t * nf_buf)2921 null_get_chain_noise_floor(void *arg, int16_t *nf_buf)
2922 {
2923 spectral_ops_not_registered("get_chain_noise_floor");
2924 return 0;
2925 }
2926
2927 static int
null_spectral_process_phyerr(struct target_if_spectral * spectral,uint8_t * data,uint32_t datalen,struct target_if_spectral_rfqual_info * p_rfqual,struct target_if_spectral_chan_info * p_chaninfo,uint64_t tsf64,struct target_if_spectral_acs_stats * acs_stats)2928 null_spectral_process_phyerr(struct target_if_spectral *spectral,
2929 uint8_t *data,
2930 uint32_t datalen,
2931 struct target_if_spectral_rfqual_info *p_rfqual,
2932 struct target_if_spectral_chan_info *p_chaninfo,
2933 uint64_t tsf64,
2934 struct target_if_spectral_acs_stats *acs_stats)
2935 {
2936 spectral_ops_not_registered("spectral_process_phyerr");
2937 return 0;
2938 }
2939
2940 static int
null_process_spectral_report(struct wlan_objmgr_pdev * pdev,void * payload)2941 null_process_spectral_report(struct wlan_objmgr_pdev *pdev,
2942 void *payload)
2943 {
2944 spectral_ops_not_registered("process_spectral_report");
2945 return 0;
2946 }
2947 /**
2948 * target_if_spectral_init_dummy_function_table() -
2949 * Initialize target_if internal
2950 * Spectral operations to dummy functions
2951 * @ps: Pointer to Spectral target_if internal private data
2952 *
2953 * Initialize all the function pointers in target_if_spectral_ops with
2954 * dummy functions.
2955 *
2956 * Return: None
2957 */
2958 static void
target_if_spectral_init_dummy_function_table(struct target_if_spectral * ps)2959 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps)
2960 {
2961 struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps);
2962
2963 p_sops->get_tsf64 = null_get_tsf64;
2964 p_sops->get_capability = null_get_capability;
2965 p_sops->set_rxfilter = null_set_rxfilter;
2966 p_sops->get_rxfilter = null_get_rxfilter;
2967 p_sops->is_spectral_enabled = null_is_spectral_enabled;
2968 p_sops->is_spectral_active = null_is_spectral_active;
2969 p_sops->start_spectral_scan = null_start_spectral_scan;
2970 p_sops->stop_spectral_scan = null_stop_spectral_scan;
2971 p_sops->get_extension_channel = null_get_extension_channel;
2972 p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor;
2973 p_sops->get_ext_noisefloor = null_get_ext_noisefloor;
2974 p_sops->configure_spectral = null_configure_spectral;
2975 p_sops->get_spectral_config = null_get_spectral_config;
2976 p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask;
2977 p_sops->get_mac_address = null_get_mac_address;
2978 p_sops->get_current_channel = null_get_current_channel;
2979 p_sops->reset_hw = null_reset_hw;
2980 p_sops->get_chain_noise_floor = null_get_chain_noise_floor;
2981 p_sops->spectral_process_phyerr = null_spectral_process_phyerr;
2982 p_sops->process_spectral_report = null_process_spectral_report;
2983 }
2984
2985 /**
2986 * target_if_spectral_register_funcs() - Initialize target_if internal Spectral
2987 * operations
2988 * @spectral: Pointer to Spectral target_if internal private data
2989 * @p: Pointer to Spectral function table
2990 *
2991 * Return: None
2992 */
2993 static void
target_if_spectral_register_funcs(struct target_if_spectral * spectral,struct target_if_spectral_ops * p)2994 target_if_spectral_register_funcs(struct target_if_spectral *spectral,
2995 struct target_if_spectral_ops *p)
2996 {
2997 struct target_if_spectral_ops *p_sops =
2998 GET_TARGET_IF_SPECTRAL_OPS(spectral);
2999
3000 *p_sops = *p;
3001 }
3002
3003 /**
3004 * target_if_spectral_clear_stats() - Clear Spectral stats
3005 * @spectral: Pointer to Spectral target_if internal private data
3006 *
3007 * Function to clear spectral stats
3008 *
3009 * Return: None
3010 */
3011 static void
target_if_spectral_clear_stats(struct target_if_spectral * spectral)3012 target_if_spectral_clear_stats(struct target_if_spectral *spectral)
3013 {
3014 struct target_if_spectral_ops *p_sops =
3015 GET_TARGET_IF_SPECTRAL_OPS(spectral);
3016
3017 qdf_mem_zero(&spectral->spectral_stats,
3018 sizeof(struct target_if_spectral_stats));
3019 spectral->spectral_stats.last_reset_tstamp =
3020 p_sops->get_tsf64(spectral);
3021 }
3022
3023 /**
3024 * target_if_spectral_check_hw_capability() - Check whether HW supports spectral
3025 * @spectral: Pointer to Spectral target_if internal private data
3026 *
3027 * Function to check whether hardware supports spectral
3028 *
3029 * Return: True if HW supports Spectral, false if HW does not support Spectral
3030 */
3031 static int
target_if_spectral_check_hw_capability(struct target_if_spectral * spectral)3032 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral)
3033 {
3034 struct target_if_spectral_ops *p_sops = NULL;
3035 struct spectral_caps *pcap = NULL;
3036 int is_spectral_supported = true;
3037
3038 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3039 pcap = &spectral->capability;
3040
3041 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) {
3042 is_spectral_supported = false;
3043 spectral_info("SPECTRAL : No PHYDIAG support");
3044 return is_spectral_supported;
3045 }
3046 pcap->phydiag_cap = 1;
3047
3048 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) {
3049 is_spectral_supported = false;
3050 spectral_info("SPECTRAL : No RADAR support");
3051 return is_spectral_supported;
3052 }
3053 pcap->radar_cap = 1;
3054
3055 if (p_sops->get_capability(spectral,
3056 SPECTRAL_CAP_SPECTRAL_SCAN) == false) {
3057 is_spectral_supported = false;
3058 spectral_info("SPECTRAL : No SPECTRAL SUPPORT");
3059 return is_spectral_supported;
3060 }
3061 pcap->spectral_cap = 1;
3062
3063 if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN)
3064 == false) {
3065 spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT");
3066 } else {
3067 pcap->advncd_spectral_cap = 1;
3068 }
3069
3070 return is_spectral_supported;
3071 }
3072
3073 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
3074 /**
3075 * target_if_spectral_detach_simulation() - De-initialize Spectral
3076 * Simulation functionality
3077 * @spectral: Pointer to Spectral target_if internal private data
3078 *
3079 * Function to de-initialize Spectral Simulation functionality
3080 *
3081 * Return: None
3082 */
3083 static void
target_if_spectral_detach_simulation(struct target_if_spectral * spectral)3084 target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
3085 {
3086 target_if_spectral_sim_detach(spectral);
3087 }
3088
3089 #else
3090 static void
target_if_spectral_detach_simulation(struct target_if_spectral * spectral)3091 target_if_spectral_detach_simulation(struct target_if_spectral *spectral)
3092 {
3093 }
3094 #endif
3095
3096 /**
3097 * target_if_spectral_detach() - De-initialize target_if Spectral
3098 * @spectral: Pointer to Spectral target_if internal private data
3099 *
3100 * Function to detach target_if spectral
3101 *
3102 * Return: None
3103 */
3104 static void
target_if_spectral_detach(struct target_if_spectral * spectral)3105 target_if_spectral_detach(struct target_if_spectral *spectral)
3106 {
3107 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
3108 spectral_info("spectral detach");
3109
3110 if (spectral) {
3111 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3112 qdf_spinlock_destroy
3113 (&spectral->param_info[smode].osps_lock);
3114
3115 target_if_spectral_detach_simulation(spectral);
3116
3117 qdf_spinlock_destroy(&spectral->spectral_lock);
3118 qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock);
3119
3120 qdf_spinlock_destroy(&spectral->detector_list_lock);
3121 qdf_spinlock_destroy(&spectral->session_report_info_lock);
3122 qdf_spinlock_destroy(&spectral->session_det_map_lock);
3123
3124 qdf_mem_free(spectral);
3125 spectral = NULL;
3126 }
3127 }
3128
3129 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
3130 /**
3131 * target_if_spectral_attach_simulation() - Initialize Spectral Simulation
3132 * functionality
3133 * @spectral: Pointer to Spectral target_if internal private data
3134 *
3135 * Function to initialize spectral simulation functionality
3136 *
3137 * Return: 0 on success, negative error code on failure
3138 */
3139 static int
target_if_spectral_attach_simulation(struct target_if_spectral * spectral)3140 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
3141 {
3142 if (target_if_spectral_sim_attach(spectral)) {
3143 qdf_mem_free(spectral);
3144 return -EPERM;
3145 }
3146 return 0;
3147 }
3148
3149 #else
3150 static int
target_if_spectral_attach_simulation(struct target_if_spectral * spectral)3151 target_if_spectral_attach_simulation(struct target_if_spectral *spectral)
3152 {
3153 return 0;
3154 }
3155 #endif
3156
3157 /**
3158 * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment
3159 * related info
3160 * @swar: Pointer to Spectral FFT bin length adjustment SWAR params
3161 * @rparams: Pointer to Spectral report parameter object
3162 * @target_type: Target type
3163 *
3164 * Function to Initialize parameters related to Spectral FFT bin
3165 * length adjustment SWARs.
3166 *
3167 * Return: void
3168 */
3169 static void
target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar * swar,struct spectral_report_params * rparams,uint32_t target_type)3170 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar,
3171 struct spectral_report_params *rparams,
3172 uint32_t target_type)
3173 {
3174 if (target_type == TARGET_TYPE_QCA8074V2 ||
3175 target_type == TARGET_TYPE_QCA9574 ||
3176 target_type == TARGET_TYPE_QCN9000 ||
3177 target_type == TARGET_TYPE_QCN6122 ||
3178 target_type == TARGET_TYPE_QCN9160 ||
3179 target_type == TARGET_TYPE_QCA5018 ||
3180 target_type == TARGET_TYPE_QCA6750 ||
3181 target_type == TARGET_TYPE_QCA6490 ||
3182 target_type == TARGET_TYPE_KIWI ||
3183 target_type == TARGET_TYPE_MANGO ||
3184 target_type == TARGET_TYPE_PEACH) {
3185 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE;
3186 rparams->hw_fft_bin_width = 2;
3187 } else if (target_type == TARGET_TYPE_QCA8074 ||
3188 target_type == TARGET_TYPE_QCA6018 ||
3189 target_type == TARGET_TYPE_QCA6390) {
3190 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE;
3191 rparams->hw_fft_bin_width = 4;
3192 } else {
3193 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR;
3194 rparams->hw_fft_bin_width = 1;
3195 }
3196
3197 if (target_type == TARGET_TYPE_QCA8074 ||
3198 target_type == TARGET_TYPE_QCA8074V2 ||
3199 target_type == TARGET_TYPE_QCA9574 ||
3200 target_type == TARGET_TYPE_QCA6018 ||
3201 target_type == TARGET_TYPE_QCN6122 ||
3202 target_type == TARGET_TYPE_QCN9160 ||
3203 target_type == TARGET_TYPE_QCN6432 ||
3204 target_type == TARGET_TYPE_QCA5332 ||
3205 target_type == TARGET_TYPE_QCA5018 ||
3206 target_type == TARGET_TYPE_QCN9000 ||
3207 target_type == TARGET_TYPE_QCA6490 ||
3208 target_type == TARGET_TYPE_QCN9224 ||
3209 target_type == TARGET_TYPE_KIWI ||
3210 target_type == TARGET_TYPE_MANGO ||
3211 target_type == TARGET_TYPE_PEACH) {
3212 swar->inband_fftbin_size_adj = 1;
3213 swar->null_fftbin_adj = 1;
3214 } else {
3215 swar->inband_fftbin_size_adj = 0;
3216 swar->null_fftbin_adj = 0;
3217 }
3218
3219 if (target_type == TARGET_TYPE_QCA8074V2)
3220 swar->packmode_fftbin_size_adj = 1;
3221 else
3222 swar->packmode_fftbin_size_adj = 0;
3223 }
3224
3225 /**
3226 * target_if_spectral_report_params_init() - Initialize parameters which
3227 * describes the structure of Spectral reports
3228 *
3229 * @rparams: Pointer to Spectral report parameter object
3230 * @target_type: target type
3231 *
3232 * Function to Initialize parameters related to the structure of Spectral
3233 * reports.
3234 *
3235 * Return: void
3236 */
3237 static void
target_if_spectral_report_params_init(struct spectral_report_params * rparams,uint32_t target_type)3238 target_if_spectral_report_params_init(
3239 struct spectral_report_params *rparams,
3240 uint32_t target_type)
3241 {
3242 enum spectral_scan_mode smode;
3243
3244 /* This entries are currently used by gen3 chipsets only. Hence
3245 * initialization is done for gen3 alone. In future if other generations
3246 * needs to use them they have to add proper initial values.
3247 */
3248 if (target_type == TARGET_TYPE_QCN9000 ||
3249 target_type == TARGET_TYPE_QCN6122 ||
3250 target_type == TARGET_TYPE_QCN9160 ||
3251 target_type == TARGET_TYPE_QCN6432 ||
3252 target_type == TARGET_TYPE_QCA5018 ||
3253 target_type == TARGET_TYPE_QCA6750 ||
3254 target_type == TARGET_TYPE_QCA6490 ||
3255 target_type == TARGET_TYPE_QCA5332 ||
3256 target_type == TARGET_TYPE_QCN9224 ||
3257 target_type == TARGET_TYPE_KIWI ||
3258 target_type == TARGET_TYPE_MANGO ||
3259 target_type == TARGET_TYPE_PEACH) {
3260 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2;
3261 rparams->num_spectral_detectors =
3262 NUM_SPECTRAL_DETECTORS_GEN3_V2;
3263 smode = SPECTRAL_SCAN_MODE_NORMAL;
3264 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3265 rparams->fragmentation_160[smode] = false;
3266 } else {
3267 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1;
3268 rparams->num_spectral_detectors =
3269 NUM_SPECTRAL_DETECTORS_GEN3_V1;
3270 smode = SPECTRAL_SCAN_MODE_NORMAL;
3271 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++)
3272 rparams->fragmentation_160[smode] = true;
3273 }
3274
3275 switch (rparams->version) {
3276 case SPECTRAL_REPORT_FORMAT_VERSION_1:
3277 rparams->ssummary_padding_bytes =
3278 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1;
3279 rparams->fft_report_hdr_len =
3280 FFT_REPORT_HEADER_LENGTH_GEN3_V1;
3281 break;
3282 case SPECTRAL_REPORT_FORMAT_VERSION_2:
3283 rparams->ssummary_padding_bytes =
3284 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2;
3285 rparams->fft_report_hdr_len =
3286 FFT_REPORT_HEADER_LENGTH_GEN3_V2;
3287 break;
3288 }
3289
3290 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] =
3291 SPECTRAL_SCAN_MODE_NORMAL;
3292 if (target_type == TARGET_TYPE_QCN9000 ||
3293 target_type == TARGET_TYPE_QCN6122 ||
3294 target_type == TARGET_TYPE_QCN9224 ||
3295 target_type == TARGET_TYPE_QCN6432 ||
3296 target_type == TARGET_TYPE_QCN9160 ||
3297 target_type == TARGET_TYPE_QCA6490 ||
3298 target_type == TARGET_TYPE_KIWI ||
3299 target_type == TARGET_TYPE_MANGO ||
3300 target_type == TARGET_TYPE_PEACH) {
3301 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
3302 SPECTRAL_SCAN_MODE_AGILE;
3303 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
3304 SPECTRAL_SCAN_MODE_INVALID;
3305 } else if (target_type == TARGET_TYPE_QCA5332) {
3306 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
3307 SPECTRAL_SCAN_MODE_INVALID;
3308 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
3309 SPECTRAL_SCAN_MODE_INVALID;
3310 } else {
3311 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] =
3312 SPECTRAL_SCAN_MODE_NORMAL;
3313 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] =
3314 SPECTRAL_SCAN_MODE_AGILE;
3315 }
3316 }
3317
3318 /**
3319 * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR
3320 * related info
3321 * @twar: Pointer to Spectral timstamp WAR related info
3322 *
3323 * Function to Initialize parameters related to Spectral timestamp WAR
3324 *
3325 * Return: void
3326 */
3327 static void
target_if_spectral_timestamp_war_init(struct spectral_timestamp_war * twar)3328 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar)
3329 {
3330 enum spectral_scan_mode smode;
3331
3332 smode = SPECTRAL_SCAN_MODE_NORMAL;
3333 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
3334 twar->last_fft_timestamp[smode] = 0;
3335 twar->timestamp_war_offset[smode] = 0;
3336 }
3337 twar->target_reset_count = 0;
3338 }
3339
3340 #ifdef OPTIMIZED_SAMP_MESSAGE
3341 /**
3342 * target_if_spectral_is_hw_mode_sbs() - Check if the given pdev is in SBS mode
3343 * @pdev: pdev pointer
3344 * @is_hw_mode_sbs: Pointer to the variable where this function should write
3345 * whether the given pdev is in SBS mode
3346 *
3347 * Return: QDF_STATUS of operation
3348 */
3349 static QDF_STATUS
target_if_spectral_is_hw_mode_sbs(struct wlan_objmgr_pdev * pdev,bool * is_hw_mode_sbs)3350 target_if_spectral_is_hw_mode_sbs(struct wlan_objmgr_pdev *pdev,
3351 bool *is_hw_mode_sbs)
3352 {
3353 struct wlan_objmgr_psoc *psoc;
3354 struct target_psoc_info *tgt_hdl;
3355 enum wmi_host_hw_mode_config_type mode;
3356
3357 if (!is_hw_mode_sbs) {
3358 spectral_err("is_hw_mode_sbs pointer is null.");
3359 return QDF_STATUS_E_NULL_VALUE;
3360 }
3361
3362 psoc = wlan_pdev_get_psoc(pdev);
3363 if (!psoc) {
3364 spectral_err("psoc is null");
3365 return QDF_STATUS_E_NULL_VALUE;
3366 }
3367
3368 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
3369 if (!tgt_hdl) {
3370 spectral_err("target_psoc_info is null");
3371 return QDF_STATUS_E_NULL_VALUE;
3372 }
3373
3374 mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
3375 switch (mode) {
3376 case WMI_HOST_HW_MODE_SBS_PASSIVE:
3377 case WMI_HOST_HW_MODE_SBS:
3378 case WMI_HOST_HW_MODE_DBS_SBS:
3379 case WMI_HOST_HW_MODE_DBS_OR_SBS:
3380 *is_hw_mode_sbs = true;
3381 break;
3382 default:
3383 *is_hw_mode_sbs = false;
3384 break;
3385 }
3386
3387 return QDF_STATUS_SUCCESS;
3388 }
3389
3390 /**
3391 * target_if_get_pdev_mac_phy_caps() - Get the MAC_PHY capabilities of a pdev
3392 * @pdev: pdev pointer
3393 *
3394 * Return: On success, pointer to MAC_PHY capabilities of @pdev.
3395 * On failure, NULL
3396 */
3397 static struct wlan_psoc_host_mac_phy_caps *
target_if_get_pdev_mac_phy_caps(struct wlan_objmgr_pdev * pdev)3398 target_if_get_pdev_mac_phy_caps(struct wlan_objmgr_pdev *pdev)
3399 {
3400 struct wlan_objmgr_psoc *psoc;
3401 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr;
3402 struct target_psoc_info *tgt_psoc_info;
3403 uint8_t pdev_id;
3404
3405 if (!pdev) {
3406 spectral_err("pdev is NULL");
3407 return NULL;
3408 }
3409
3410 psoc = wlan_pdev_get_psoc(pdev);
3411 if (!psoc) {
3412 spectral_err("psoc is null");
3413 return NULL;
3414 }
3415
3416 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
3417 if (!tgt_psoc_info) {
3418 spectral_err("target_psoc_info is null");
3419 return NULL;
3420 }
3421
3422 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
3423 if (!mac_phy_cap_arr) {
3424 spectral_err("mac phy cap array is null");
3425 return NULL;
3426 }
3427
3428 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
3429 return &mac_phy_cap_arr[pdev_id];
3430 }
3431
3432 /**
3433 * struct target_if_sscan_pdev_phy_info - PHY information of the pdev on
3434 * which sscan is done. A pointer to an instance of this structure is passed
3435 * as an argument to the iterator function target_if_find_sscan_pdev_phya1()
3436 * @phy_id: PHY ID of this pdev
3437 * @is_using_phya1: Pointer to the variable where the iterator function should
3438 * populate whether the given pdev is using PHYA1
3439 */
3440 struct target_if_sscan_pdev_phy_info {
3441 uint8_t phy_id;
3442 bool *is_using_phya1;
3443 };
3444
3445 /**
3446 * target_if_find_sscan_pdev_phya1() - This is an iterator function to
3447 * wlan_objmgr_iterate_obj_list(). It checks whether a given sscan_pdev (pdev on
3448 * which sscan is currently issued) is using PHYA1 by comparing against the pdev
3449 * argument given by the wlan_objmgr_iterate_obj_list()
3450 * @psoc: Pointer to psoc
3451 * @object: Pointer to pdev
3452 * @arg: Pointer to target_if_sscan_pdev_phy_info of the sscan_pdev for which
3453 * we want to check if it uses PHYA1
3454 *
3455 * Return: None
3456 */
3457 static void
target_if_find_sscan_pdev_phya1(struct wlan_objmgr_psoc * psoc,void * object,void * arg)3458 target_if_find_sscan_pdev_phya1(struct wlan_objmgr_psoc *psoc,
3459 void *object, void *arg)
3460 {
3461 struct target_if_sscan_pdev_phy_info *sscan_pdev_phy_info = arg;
3462 struct wlan_objmgr_pdev *cur_pdev = object;
3463 struct wlan_psoc_host_mac_phy_caps *cur_mac_phy_caps;
3464
3465 cur_mac_phy_caps = target_if_get_pdev_mac_phy_caps(cur_pdev);
3466 if (!cur_mac_phy_caps) {
3467 spectral_err("Failed to get MAC PHY Capabilities of"
3468 "pdev %pK", cur_pdev);
3469 return;
3470 }
3471
3472 spectral_debug("supported_bands: %0x phy_id: %d",
3473 cur_mac_phy_caps->supported_bands,
3474 cur_mac_phy_caps->phy_id);
3475
3476 /* No need to do anything if the current pdev is same as sscan_pdev */
3477 if (sscan_pdev_phy_info->phy_id == cur_mac_phy_caps->phy_id)
3478 return;
3479
3480 /**
3481 * Compare the phy_id of both the SBS pdevs to figure out if
3482 * the sscan_pdev using PHYA1
3483 */
3484 if (sscan_pdev_phy_info->phy_id > cur_mac_phy_caps->phy_id)
3485 *sscan_pdev_phy_info->is_using_phya1 = true;
3486 else
3487 *sscan_pdev_phy_info->is_using_phya1 = false;
3488 }
3489
3490 /**
3491 * target_if_spectral_detector_list_init() - Initialize Spectral detector list
3492 * based on target type
3493 * @spectral: Pointer to Spectral target_if
3494 *
3495 * Function to initialize Spectral detector list for possible combinations of
3496 * Spectral scan mode and channel width, based on target type.
3497 *
3498 * Return: Success/Failure
3499 */
3500 static QDF_STATUS
target_if_spectral_detector_list_init(struct target_if_spectral * spectral)3501 target_if_spectral_detector_list_init(struct target_if_spectral *spectral)
3502 {
3503 struct sscan_detector_list *det_list;
3504 enum spectral_scan_mode smode;
3505 enum phy_ch_width ch_width;
3506 QDF_STATUS ret;
3507 bool is_hw_mode_sbs = false, is_using_phya1 = false;
3508
3509 if (!spectral) {
3510 spectral_err_rl("Spectral LMAC object is null");
3511 return QDF_STATUS_E_NULL_VALUE;
3512 }
3513
3514 /**
3515 * Special handling is required for SBS mode where the detector
3516 * list should be the following.
3517 * For the pdev that use PHYA0:
3518 * detector 0 for normal mode
3519 * detector 2 for agile mode
3520 * For the pdev that use PHYA1:
3521 * detector 1 for normal mode
3522 * detector 2 for agile mode
3523 *
3524 * There is no direct way of knowing which pdevs are using PHYA0 or
3525 * PHYA1. We need to look at the phy_id of a given pdev and compare
3526 * against other pdevs on the same psoc to figure out whether the given
3527 * pdev is operating using PHYA1.
3528 */
3529
3530 /* First check whether this pdev is in SBS mode */
3531 ret = target_if_spectral_is_hw_mode_sbs(spectral->pdev_obj,
3532 &is_hw_mode_sbs);
3533 if (QDF_IS_STATUS_ERROR(ret)) {
3534 spectral_err("Failed to check whether hw mode is SBS");
3535 return ret;
3536 }
3537
3538 if (is_hw_mode_sbs) {
3539 struct wlan_psoc_host_mac_phy_caps *mac_phy_caps;
3540 struct target_if_sscan_pdev_phy_info pdev_phy_info;
3541
3542 mac_phy_caps =
3543 target_if_get_pdev_mac_phy_caps(spectral->pdev_obj);
3544 if (!mac_phy_caps) {
3545 spectral_err("Failed to get MAC PHY Capabilities of"
3546 "pdev %pK", spectral->pdev_obj);
3547 return QDF_STATUS_E_FAILURE;
3548 }
3549
3550 spectral_debug("bands: %0x phy_id: %d",
3551 mac_phy_caps->supported_bands,
3552 mac_phy_caps->phy_id);
3553
3554 pdev_phy_info.phy_id = mac_phy_caps->phy_id;
3555 pdev_phy_info.is_using_phya1 = &is_using_phya1;
3556
3557 /* Iterate over all pdevs on this psoc */
3558 wlan_objmgr_iterate_obj_list
3559 (wlan_pdev_get_psoc(spectral->pdev_obj),
3560 WLAN_PDEV_OP,
3561 target_if_find_sscan_pdev_phya1,
3562 &pdev_phy_info, 0,
3563 WLAN_SPECTRAL_ID);
3564 }
3565
3566 /**
3567 * We assume there are 2 detectors. The Detector ID coming first will
3568 * always be pri80 detector, and second detector for sec80.
3569 */
3570 ch_width = CH_WIDTH_20MHZ;
3571 for (; ch_width < CH_WIDTH_MAX; ch_width++) {
3572 /* Normal spectral scan */
3573 smode = SPECTRAL_SCAN_MODE_NORMAL;
3574 spectral_debug("is_hw_mode_sbs: %d is_using_phya1:%d",
3575 is_hw_mode_sbs, is_using_phya1);
3576
3577 qdf_spin_lock_bh(&spectral->detector_list_lock);
3578
3579 if (!spectral->supported_sscan_bw_list[smode][ch_width])
3580 goto agile_handling;
3581
3582 det_list = &spectral->detector_list[smode][ch_width];
3583 det_list->num_detectors = 1;
3584
3585 if (is_hw_mode_sbs && is_using_phya1)
3586 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1;
3587 else
3588 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_0;
3589
3590 if (is_ch_width_160_or_80p80(ch_width) &&
3591 spectral->rparams.fragmentation_160[smode]) {
3592 det_list->num_detectors += 1;
3593 det_list->detectors[1] = SPECTRAL_DETECTOR_ID_1;
3594 }
3595
3596 agile_handling:
3597 /* Agile spectral scan */
3598 smode = SPECTRAL_SCAN_MODE_AGILE;
3599 if (!spectral->supported_sscan_bw_list[smode][ch_width]) {
3600 qdf_spin_unlock_bh(&spectral->detector_list_lock);
3601 continue;
3602 }
3603
3604 det_list = &spectral->detector_list[smode][ch_width];
3605 det_list->num_detectors = 1;
3606
3607 if (spectral->rparams.fragmentation_160[smode])
3608 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_2;
3609 else
3610 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1;
3611
3612 qdf_spin_unlock_bh(&spectral->detector_list_lock);
3613 }
3614
3615 return QDF_STATUS_SUCCESS;
3616 }
3617 #else
3618
3619 static QDF_STATUS
target_if_spectral_detector_list_init(struct target_if_spectral * spectral)3620 target_if_spectral_detector_list_init(struct target_if_spectral *spectral)
3621 {
3622 return QDF_STATUS_SUCCESS;
3623 }
3624 #endif /* OPTIMIZED_SAMP_MESSAGE */
3625
3626 /**
3627 * target_if_pdev_spectral_init() - Initialize target_if Spectral
3628 * functionality for the given pdev
3629 * @pdev: Pointer to pdev object
3630 *
3631 * Function to initialize pointer to spectral target_if internal private data
3632 *
3633 * Return: On success, pointer to Spectral target_if internal private data, on
3634 * failure, NULL
3635 */
3636 void *
target_if_pdev_spectral_init(struct wlan_objmgr_pdev * pdev)3637 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev)
3638 {
3639 struct target_if_spectral_ops *p_sops = NULL;
3640 struct target_if_spectral *spectral = NULL;
3641 uint32_t target_type;
3642 uint32_t target_revision;
3643 struct wlan_objmgr_psoc *psoc;
3644 struct wlan_lmac_if_target_tx_ops *tgt_tx_ops;
3645 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL;
3646 QDF_STATUS status;
3647 struct wlan_lmac_if_tx_ops *tx_ops;
3648
3649 if (!pdev) {
3650 spectral_err("SPECTRAL: pdev is NULL!");
3651 return NULL;
3652 }
3653 spectral = (struct target_if_spectral *)qdf_mem_malloc(
3654 sizeof(struct target_if_spectral));
3655 if (!spectral)
3656 return spectral;
3657
3658 qdf_mem_zero(spectral, sizeof(struct target_if_spectral));
3659 /* Store pdev in Spectral */
3660 spectral->pdev_obj = pdev;
3661 spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID;
3662 spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID;
3663
3664 psoc = wlan_pdev_get_psoc(pdev);
3665
3666 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
3667 if (!tx_ops) {
3668 spectral_err("tx_ops is NULL");
3669 qdf_mem_free(spectral);
3670 return NULL;
3671 }
3672
3673 tgt_tx_ops = &tx_ops->target_tx_ops;
3674
3675 if (tgt_tx_ops->tgt_get_tgt_type) {
3676 target_type = tgt_tx_ops->tgt_get_tgt_type(psoc);
3677 } else {
3678 qdf_mem_free(spectral);
3679 return NULL;
3680 }
3681
3682 if (tgt_tx_ops->tgt_get_tgt_revision) {
3683 target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc);
3684 } else {
3685 qdf_mem_free(spectral);
3686 return NULL;
3687 }
3688
3689 /* init the function ptr table */
3690 target_if_spectral_init_dummy_function_table(spectral);
3691
3692 /* get spectral function table */
3693 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
3694 /* TODO : Should this be called here of after ath_attach ? */
3695 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG))
3696 spectral_info("HAL_CAP_PHYDIAG : Capable");
3697
3698 /* TODO: Need to fix the capability check for RADAR */
3699 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR))
3700 spectral_info("HAL_CAP_RADAR : Capable");
3701
3702 /* TODO : Need to fix the capability check for SPECTRAL */
3703 /* TODO : Should this be called here of after ath_attach ? */
3704 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN))
3705 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable");
3706
3707 qdf_spinlock_create(&spectral->spectral_lock);
3708 qdf_spinlock_create(&spectral->noise_pwr_reports_lock);
3709 target_if_spectral_clear_stats(spectral);
3710
3711 if (target_type == TARGET_TYPE_QCA8074 ||
3712 target_type == TARGET_TYPE_QCA8074V2 ||
3713 target_type == TARGET_TYPE_QCA9574 ||
3714 target_type == TARGET_TYPE_QCA5332 ||
3715 target_type == TARGET_TYPE_QCA6018 ||
3716 target_type == TARGET_TYPE_QCA5018 ||
3717 target_type == TARGET_TYPE_QCA6390 ||
3718 target_type == TARGET_TYPE_QCN6122 ||
3719 target_type == TARGET_TYPE_QCN9160 ||
3720 target_type == TARGET_TYPE_QCN6432 ||
3721 target_type == TARGET_TYPE_QCA6490 ||
3722 target_type == TARGET_TYPE_QCN9000 ||
3723 target_type == TARGET_TYPE_QCA6750 ||
3724 target_type == TARGET_TYPE_QCN9224 ||
3725 target_type == TARGET_TYPE_KIWI ||
3726 target_type == TARGET_TYPE_MANGO ||
3727 target_type == TARGET_TYPE_PEACH)
3728 spectral->direct_dma_support = true;
3729
3730 target_if_spectral_report_params_init(&spectral->rparams,
3731 target_type);
3732 target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar,
3733 &spectral->rparams,
3734 target_type);
3735
3736 if ((target_type == TARGET_TYPE_QCA8074) ||
3737 (target_type == TARGET_TYPE_QCA8074V2) ||
3738 (target_type == TARGET_TYPE_QCA9574) ||
3739 (target_type == TARGET_TYPE_QCA6018) ||
3740 (target_type == TARGET_TYPE_QCA5018) ||
3741 (target_type == TARGET_TYPE_QCA5332) ||
3742 (target_type == TARGET_TYPE_QCN6122) ||
3743 (target_type == TARGET_TYPE_QCN9160) ||
3744 (target_type == TARGET_TYPE_QCN6432) ||
3745 (target_type == TARGET_TYPE_QCN9000) ||
3746 (target_type == TARGET_TYPE_QCA6290) ||
3747 (target_type == TARGET_TYPE_QCA6390) ||
3748 (target_type == TARGET_TYPE_QCA6490) ||
3749 (target_type == TARGET_TYPE_QCN9224) ||
3750 (target_type == TARGET_TYPE_QCA6750) ||
3751 (target_type == TARGET_TYPE_KIWI) ||
3752 (target_type == TARGET_TYPE_MANGO) ||
3753 (target_type == TARGET_TYPE_PEACH)) {
3754 spectral->spectral_gen = SPECTRAL_GEN3;
3755 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3;
3756 spectral->tag_sscan_summary_exp =
3757 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3;
3758 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3;
3759 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3;
3760 } else {
3761 spectral->spectral_gen = SPECTRAL_GEN2;
3762 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2;
3763 spectral->tag_sscan_summary_exp =
3764 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2;
3765 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2;
3766 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2);
3767 }
3768
3769 status = target_if_init_spectral_param_min_max(
3770 spectral,
3771 spectral->spectral_gen, target_type);
3772 if (QDF_IS_STATUS_ERROR(status)) {
3773 spectral_err("Failed to initialize parameter min max values");
3774 goto fail;
3775 }
3776
3777 target_if_init_spectral_param_properties(spectral);
3778 /* Init spectral capability */
3779 if (target_if_init_spectral_capability(spectral, target_type) !=
3780 QDF_STATUS_SUCCESS) {
3781 qdf_mem_free(spectral);
3782 return NULL;
3783 }
3784 if (target_if_spectral_attach_simulation(spectral) < 0)
3785 return NULL;
3786
3787 target_if_init_spectral_ops(spectral);
3788 target_if_spectral_timestamp_war_init(&spectral->timestamp_war);
3789
3790 /* Spectral mode specific init */
3791 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) {
3792 spectral->params_valid[smode] = false;
3793 qdf_spinlock_create(&spectral->param_info[smode].osps_lock);
3794 spectral->param_info[smode].osps_cache.osc_is_valid = 0;
3795 }
3796
3797 target_if_spectral_register_funcs(spectral, &spectral_ops);
3798
3799 if (target_if_spectral_check_hw_capability(spectral) == false) {
3800 goto fail;
3801 } else {
3802 /*
3803 * TODO: Once the driver architecture transitions to chipset
3804 * versioning based checks, reflect this here.
3805 */
3806 spectral->is_160_format = false;
3807 spectral->is_lb_edge_extrabins_format = false;
3808 spectral->is_rb_edge_extrabins_format = false;
3809
3810 if (target_type == TARGET_TYPE_QCA9984 ||
3811 target_type == TARGET_TYPE_QCA9888) {
3812 spectral->is_160_format = true;
3813 spectral->is_lb_edge_extrabins_format = true;
3814 spectral->is_rb_edge_extrabins_format = true;
3815 } else if ((target_type == TARGET_TYPE_AR900B) &&
3816 (target_revision == AR900B_REV_2)) {
3817 spectral->is_rb_edge_extrabins_format = true;
3818 }
3819
3820 if (target_type == TARGET_TYPE_QCA9984 ||
3821 target_type == TARGET_TYPE_QCA9888)
3822 spectral->is_sec80_rssi_war_required = true;
3823
3824 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST;
3825
3826 if (spectral->spectral_gen == SPECTRAL_GEN3)
3827 init_160mhz_delivery_state_machine(spectral);
3828 }
3829
3830 qdf_spinlock_create(&spectral->detector_list_lock);
3831 qdf_spinlock_create(&spectral->session_report_info_lock);
3832 qdf_spinlock_create(&spectral->session_det_map_lock);
3833
3834 return spectral;
3835
3836 fail:
3837 target_if_spectral_detach(spectral);
3838 return NULL;
3839 }
3840
3841 /**
3842 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral
3843 * functionality for the given pdev
3844 * @pdev: Pointer to pdev object
3845 *
3846 * Function to de-initialize pointer to spectral target_if internal private data
3847 *
3848 * Return: None
3849 */
3850 void
target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev * pdev)3851 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev)
3852 {
3853 struct target_if_spectral *spectral = NULL;
3854
3855 spectral = get_target_if_spectral_handle_from_pdev(pdev);
3856 if (!spectral) {
3857 spectral_err("SPECTRAL : Module doesn't exist");
3858 return;
3859 }
3860 target_if_spectral_detach(spectral);
3861
3862 return;
3863 }
3864
3865 /**
3866 * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral
3867 * functionality for the given psoc
3868 * @psoc: Pointer to psoc object
3869 *
3870 * Function to de-initialize pointer to psoc spectral target_if internal
3871 * private data
3872 *
3873 * Return: None
3874 */
3875 static void
target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc * psoc)3876 target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc)
3877 {
3878 struct target_if_psoc_spectral *psoc_spectral;
3879
3880 if (!psoc) {
3881 spectral_err("psoc is null");
3882 return;
3883 }
3884
3885 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
3886 if (!psoc_spectral) {
3887 spectral_err("Spectral target_if psoc object is null");
3888 return;
3889 }
3890
3891 qdf_mem_free(psoc_spectral);
3892 }
3893
3894 /**
3895 * target_if_psoc_spectral_init() - Initialize target_if Spectral
3896 * functionality for the given psoc
3897 * @psoc: Pointer to psoc object
3898 *
3899 * Function to initialize pointer to psoc spectral target_if internal
3900 * private data
3901 *
3902 * Return: On success, pointer to Spectral psoc target_if internal
3903 * private data, on failure, NULL
3904 */
3905 static void *
target_if_psoc_spectral_init(struct wlan_objmgr_psoc * psoc)3906 target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc)
3907 {
3908 struct target_if_psoc_spectral *psoc_spectral = NULL;
3909
3910 if (!psoc) {
3911 spectral_err("psoc is null");
3912 goto fail;
3913 }
3914
3915 psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc(
3916 sizeof(struct target_if_psoc_spectral));
3917 if (!psoc_spectral) {
3918 spectral_err("Spectral lmac psoc object allocation failed");
3919 goto fail;
3920 }
3921
3922 psoc_spectral->psoc_obj = psoc;
3923
3924 return psoc_spectral;
3925
3926 fail:
3927 if (psoc_spectral)
3928 target_if_psoc_spectral_deinit(psoc);
3929
3930 return psoc_spectral;
3931 }
3932
3933 /**
3934 * target_if_is_center_freq_of_any_chan() - Check for center frequency
3935 * @pdev: Pointer to pdev object
3936 * @chan_freq: Center frequency of a WLAN channel
3937 * @is_valid: Indicates whether given frequency is valid
3938 *
3939 * Helper routine to check whether given frequency is center frequency
3940 * of a WLAN channel
3941 *
3942 * Return: QDF_STATUS
3943 */
3944 static QDF_STATUS
target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev * pdev,uint32_t chan_freq,bool * is_valid)3945 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev,
3946 uint32_t chan_freq,
3947 bool *is_valid)
3948 {
3949 struct regulatory_channel *cur_chan_list;
3950 int i;
3951
3952 if (!pdev) {
3953 spectral_err("pdev object is null");
3954 return QDF_STATUS_E_FAILURE;
3955 }
3956
3957 if (!is_valid) {
3958 spectral_err("is valid argument is null");
3959 return QDF_STATUS_E_FAILURE;
3960 }
3961
3962 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list));
3963 if (!cur_chan_list)
3964 return QDF_STATUS_E_FAILURE;
3965
3966 if (wlan_reg_get_current_chan_list(
3967 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
3968 spectral_err("Failed to get cur_chan list");
3969 qdf_mem_free(cur_chan_list);
3970 return QDF_STATUS_E_FAILURE;
3971 }
3972
3973 *is_valid = false;
3974 for (i = 0; i < NUM_CHANNELS; i++) {
3975 uint32_t flags;
3976 uint32_t center_freq;
3977
3978 flags = cur_chan_list[i].chan_flags;
3979 center_freq = cur_chan_list[i].center_freq;
3980
3981 if (!(flags & REGULATORY_CHAN_DISABLED) &&
3982 (center_freq == chan_freq)) {
3983 *is_valid = true;
3984 break;
3985 }
3986 }
3987
3988 qdf_mem_free(cur_chan_list);
3989
3990 return QDF_STATUS_SUCCESS;
3991 }
3992
3993 /**
3994 * target_if_calculate_center_freq() - find center frequency of agile span
3995 * @spectral: Pointer to Spectral object
3996 * @ch_width: Channel width array
3997 * @chan_freq: Center frequency of a WLAN channel
3998 * @center_freq: Pointer to center frequency
3999 *
4000 * Helper routine to find the center frequency of the agile span from
4001 * a WLAN channel center frequency
4002 *
4003 * Return: QDF_STATUS
4004 */
4005 static QDF_STATUS
target_if_calculate_center_freq(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,uint16_t chan_freq,uint16_t * center_freq)4006 target_if_calculate_center_freq(struct target_if_spectral *spectral,
4007 enum phy_ch_width *ch_width,
4008 uint16_t chan_freq,
4009 uint16_t *center_freq)
4010 {
4011 enum phy_ch_width agile_ch_width;
4012
4013 if (!spectral) {
4014 spectral_err("spectral target if object is null");
4015 return QDF_STATUS_E_FAILURE;
4016 }
4017
4018 if (!ch_width) {
4019 spectral_err("Channel width array is null");
4020 return QDF_STATUS_E_INVAL;
4021 }
4022 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4023
4024 if (!center_freq) {
4025 spectral_err("center_freq argument is null");
4026 return QDF_STATUS_E_FAILURE;
4027 }
4028
4029 if (agile_ch_width == CH_WIDTH_20MHZ) {
4030 *center_freq = chan_freq;
4031 } else {
4032 uint16_t start_freq;
4033 uint16_t end_freq;
4034 const struct bonded_channel_freq *bonded_chan_ptr = NULL;
4035 enum channel_state state;
4036
4037 state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
4038 (spectral->pdev_obj, chan_freq, agile_ch_width,
4039 &bonded_chan_ptr, REG_CURRENT_PWR_MODE,
4040 NO_SCHANS_PUNC);
4041 if (state == CHANNEL_STATE_DISABLE ||
4042 state == CHANNEL_STATE_INVALID) {
4043 spectral_err("Channel state is disable or invalid");
4044 return QDF_STATUS_E_FAILURE;
4045 }
4046 if (!bonded_chan_ptr) {
4047 spectral_err("Bonded channel is not found");
4048 return QDF_STATUS_E_FAILURE;
4049 }
4050 start_freq = bonded_chan_ptr->start_freq;
4051 end_freq = bonded_chan_ptr->end_freq;
4052 *center_freq = (start_freq + end_freq) >> 1;
4053 }
4054
4055 return QDF_STATUS_SUCCESS;
4056 }
4057
4058 /**
4059 * target_if_validate_center_freq() - validate agile center frequency
4060 * @spectral: Pointer to Spectral object
4061 * @ch_width: Channel width array
4062 * @center_freq: User provided agile span center frequency
4063 * @is_valid: Indicates whether agile span center frequency is valid
4064 *
4065 * Helper routine to validate user provided agile center frequency
4066 *
4067 * Return: QDF_STATUS
4068 */
4069 static QDF_STATUS
target_if_validate_center_freq(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,uint16_t center_freq,bool * is_valid)4070 target_if_validate_center_freq(struct target_if_spectral *spectral,
4071 enum phy_ch_width *ch_width,
4072 uint16_t center_freq,
4073 bool *is_valid)
4074 {
4075 enum phy_ch_width agile_ch_width;
4076 struct wlan_objmgr_pdev *pdev;
4077 QDF_STATUS status;
4078
4079 if (!spectral) {
4080 spectral_err("spectral target if object is null");
4081 return QDF_STATUS_E_FAILURE;
4082 }
4083
4084 if (!ch_width) {
4085 spectral_err("channel width array is null");
4086 return QDF_STATUS_E_INVAL;
4087 }
4088 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4089
4090 if (!is_valid) {
4091 spectral_err("is_valid argument is null");
4092 return QDF_STATUS_E_FAILURE;
4093 }
4094
4095 pdev = spectral->pdev_obj;
4096
4097 if (agile_ch_width == CH_WIDTH_20MHZ) {
4098 status = target_if_is_center_freq_of_any_chan
4099 (pdev, center_freq, is_valid);
4100 if (QDF_IS_STATUS_ERROR(status))
4101 return QDF_STATUS_E_FAILURE;
4102 } else {
4103 uint16_t start_freq;
4104 uint16_t end_freq;
4105 const struct bonded_channel_freq *bonded_chan_ptr = NULL;
4106 bool is_chan;
4107
4108 status = target_if_is_center_freq_of_any_chan
4109 (pdev, center_freq + FREQ_OFFSET_10MHZ,
4110 &is_chan);
4111 if (QDF_IS_STATUS_ERROR(status))
4112 return QDF_STATUS_E_FAILURE;
4113
4114 if (is_chan) {
4115 uint32_t calulated_center_freq;
4116 enum channel_state st;
4117
4118 st =
4119 wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
4120 (pdev, center_freq + FREQ_OFFSET_10MHZ,
4121 agile_ch_width,
4122 &bonded_chan_ptr,
4123 REG_CURRENT_PWR_MODE,
4124 NO_SCHANS_PUNC);
4125 if (st == CHANNEL_STATE_DISABLE ||
4126 st == CHANNEL_STATE_INVALID) {
4127 spectral_err("Channel state disable/invalid");
4128 return QDF_STATUS_E_FAILURE;
4129 }
4130 if (!bonded_chan_ptr) {
4131 spectral_err("Bonded channel is not found");
4132 return QDF_STATUS_E_FAILURE;
4133 }
4134 start_freq = bonded_chan_ptr->start_freq;
4135 end_freq = bonded_chan_ptr->end_freq;
4136 calulated_center_freq = (start_freq + end_freq) >> 1;
4137 *is_valid = (center_freq == calulated_center_freq);
4138 } else {
4139 *is_valid = false;
4140 }
4141 }
4142
4143 return QDF_STATUS_SUCCESS;
4144 }
4145
4146 /**
4147 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to
4148 * check whether agile span overlaps with current operating band.
4149 *
4150 * @spectral: Pointer to Spectral object
4151 * @ch_width: Channel width array
4152 * @center_freq: Agile span center frequency
4153 * @is_overlapping: Indicates whether Agile span overlaps with operating span
4154 *
4155 * Helper routine to check whether agile span overlaps with current
4156 * operating band.
4157 *
4158 * Return: QDF_STATUS
4159 */
4160 static QDF_STATUS
target_if_is_agile_span_overlap_with_operating_span(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,struct spectral_config_frequency * center_freq,bool * is_overlapping)4161 target_if_is_agile_span_overlap_with_operating_span
4162 (struct target_if_spectral *spectral,
4163 enum phy_ch_width *ch_width,
4164 struct spectral_config_frequency *center_freq,
4165 bool *is_overlapping)
4166 {
4167 enum phy_ch_width op_ch_width;
4168 enum phy_ch_width agile_ch_width;
4169 const struct bonded_channel_freq *bonded_chan_ptr = NULL;
4170 struct wlan_objmgr_vdev *vdev;
4171 struct wlan_objmgr_pdev *pdev;
4172 int16_t chan_freq;
4173 uint32_t op_start_freq;
4174 uint32_t op_end_freq;
4175 uint32_t agile_start_freq;
4176 uint32_t agile_end_freq;
4177 uint32_t cfreq2;
4178
4179 if (!spectral) {
4180 spectral_err("spectral object is NULL");
4181 return QDF_STATUS_E_FAILURE;
4182 }
4183
4184 pdev = spectral->pdev_obj;
4185 if (!pdev) {
4186 spectral_err("pdev object is NULL");
4187 return QDF_STATUS_E_FAILURE;
4188 }
4189
4190 if (!ch_width) {
4191 spectral_err("channel width array is null");
4192 return QDF_STATUS_E_FAILURE;
4193 }
4194 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL];
4195 if (op_ch_width == CH_WIDTH_INVALID) {
4196 spectral_err("Invalid channel width");
4197 return QDF_STATUS_E_INVAL;
4198 }
4199 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
4200 if (agile_ch_width == CH_WIDTH_INVALID) {
4201 spectral_err("Invalid channel width");
4202 return QDF_STATUS_E_INVAL;
4203 }
4204
4205 if (!is_overlapping) {
4206 spectral_err("Argument(is_overlapping) is NULL");
4207 return QDF_STATUS_E_FAILURE;
4208 }
4209 *is_overlapping = false;
4210
4211 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE);
4212 if (!vdev) {
4213 spectral_err("vdev is NULL");
4214 return QDF_STATUS_E_FAILURE;
4215 }
4216 chan_freq = target_if_vdev_get_chan_freq(vdev);
4217 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev);
4218 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4219 if (cfreq2 < 0) {
4220 spectral_err("cfreq2 is invalid");
4221 return QDF_STATUS_E_FAILURE;
4222 }
4223
4224 if (op_ch_width == CH_WIDTH_20MHZ) {
4225 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ;
4226 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ;
4227 } else {
4228 enum channel_state state;
4229
4230 state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode
4231 (pdev, chan_freq, op_ch_width, &bonded_chan_ptr,
4232 REG_CURRENT_PWR_MODE, NO_SCHANS_PUNC);
4233 if (state == CHANNEL_STATE_DISABLE ||
4234 state == CHANNEL_STATE_INVALID) {
4235 spectral_err("Channel state is disable or invalid");
4236 return QDF_STATUS_E_FAILURE;
4237 }
4238 if (!bonded_chan_ptr) {
4239 spectral_err("Bonded channel is not found");
4240 return QDF_STATUS_E_FAILURE;
4241 }
4242 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ;
4243 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ;
4244 }
4245
4246 if (agile_ch_width == CH_WIDTH_80P80MHZ) {
4247 agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ;
4248 agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ;
4249 if (agile_end_freq > op_start_freq &&
4250 op_end_freq > agile_start_freq)
4251 *is_overlapping = true;
4252
4253 agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ;
4254 agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ;
4255 if (agile_end_freq > op_start_freq &&
4256 op_end_freq > agile_start_freq)
4257 *is_overlapping = true;
4258 } else {
4259 agile_start_freq = center_freq->cfreq1 -
4260 (wlan_reg_get_bw_value(agile_ch_width) >> 1);
4261 agile_end_freq = center_freq->cfreq1 +
4262 (wlan_reg_get_bw_value(agile_ch_width) >> 1);
4263 if (agile_end_freq > op_start_freq &&
4264 op_end_freq > agile_start_freq)
4265 *is_overlapping = true;
4266 }
4267
4268 if (op_ch_width == CH_WIDTH_80P80MHZ) {
4269 uint32_t sec80_start_feq;
4270 uint32_t sec80_end_freq;
4271
4272 sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ;
4273 sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ;
4274
4275 if (agile_ch_width == CH_WIDTH_80P80MHZ) {
4276 agile_start_freq =
4277 center_freq->cfreq1 - FREQ_OFFSET_40MHZ;
4278 agile_end_freq =
4279 center_freq->cfreq1 + FREQ_OFFSET_40MHZ;
4280 if (agile_end_freq > sec80_start_feq &&
4281 sec80_end_freq > agile_start_freq)
4282 *is_overlapping = true;
4283
4284 agile_start_freq =
4285 center_freq->cfreq2 - FREQ_OFFSET_40MHZ;
4286 agile_end_freq =
4287 center_freq->cfreq2 + FREQ_OFFSET_40MHZ;
4288 if (agile_end_freq > sec80_start_feq &&
4289 sec80_end_freq > agile_start_freq)
4290 *is_overlapping = true;
4291 } else {
4292 agile_start_freq = center_freq->cfreq1 -
4293 (wlan_reg_get_bw_value(agile_ch_width) >> 1);
4294 agile_end_freq = center_freq->cfreq1 +
4295 (wlan_reg_get_bw_value(agile_ch_width) >> 1);
4296 if (agile_end_freq > sec80_start_feq &&
4297 sec80_end_freq > agile_start_freq)
4298 *is_overlapping = true;
4299 }
4300 }
4301
4302 return QDF_STATUS_SUCCESS;
4303 }
4304
4305 /**
4306 * target_if_spectral_populate_chwidth() - Helper routine to
4307 * populate channel width for different Spectral modes
4308 *
4309 * @spectral: Pointer to Spectral object
4310 * @ch_width: Channel width array
4311 * @is_80_80_agile: Indicates whether 80+80 agile scan is requested
4312 *
4313 * Helper routine to populate channel width for different Spectral modes
4314 *
4315 * Return: QDF_STATUS
4316 */
4317 static QDF_STATUS
target_if_spectral_populate_chwidth(struct target_if_spectral * spectral,enum phy_ch_width * ch_width,bool is_80_80_agile)4318 target_if_spectral_populate_chwidth(struct target_if_spectral *spectral,
4319 enum phy_ch_width *ch_width,
4320 bool is_80_80_agile)
4321 {
4322 enum spectral_scan_mode smode;
4323
4324 if (!spectral) {
4325 spectral_err("Spectral variable is null");
4326 return QDF_STATUS_E_NULL_VALUE;
4327 }
4328
4329 smode = SPECTRAL_SCAN_MODE_NORMAL;
4330 for (; smode < SPECTRAL_SCAN_MODE_MAX; ++smode) {
4331 /* If user has configured sscan bandwidth, use it */
4332 if (spectral->sscan_width_configured[smode]) {
4333 ch_width[smode] = spectral->params[smode].ss_bandwidth;
4334 } else {
4335 /* Otherwise, derive the default sscan bandwidth */
4336 ch_width[smode] = get_default_sscan_bw(spectral, smode,
4337 is_80_80_agile);
4338 if (ch_width[smode] >= CH_WIDTH_INVALID) {
4339 spectral_err("Invalid sscan BW %u",
4340 ch_width[smode]);
4341 return QDF_STATUS_E_FAILURE;
4342 }
4343 spectral->params[smode].ss_bandwidth = ch_width[smode];
4344 }
4345 }
4346
4347 return QDF_STATUS_SUCCESS;
4348 }
4349
4350 /**
4351 * target_if_spectral_is_valid_80p80_freq() - API to check whether given
4352 * (cfreq1, cfreq2) pair forms a valid 80+80 combination
4353 * @pdev: pointer to pdev
4354 * @cfreq1: center frequency 1
4355 * @cfreq2: center frequency 2
4356 * @is_valid: Indicates weather the frequency is valid
4357 *
4358 * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80
4359 * combination
4360 *
4361 * Return: QDF_Status
4362 */
4363 static QDF_STATUS
target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev * pdev,uint32_t cfreq1,uint32_t cfreq2,bool * is_valid)4364 target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev,
4365 uint32_t cfreq1, uint32_t cfreq2,
4366 bool *is_valid)
4367 {
4368 struct ch_params ch_params = {0};
4369 enum channel_state chan_state1;
4370 enum channel_state chan_state2;
4371 struct wlan_objmgr_psoc *psoc;
4372 struct ch_params temp_params = {0};
4373
4374 if (!is_valid) {
4375 spectral_err("Argument(is_valid) is null");
4376 return QDF_STATUS_E_NULL_VALUE;
4377 }
4378
4379 if (!pdev) {
4380 spectral_err("pdev is null.");
4381 return QDF_STATUS_E_NULL_VALUE;
4382 }
4383 psoc = wlan_pdev_get_psoc(pdev);
4384 if (!psoc) {
4385 spectral_err("psoc is null.");
4386 return QDF_STATUS_E_NULL_VALUE;
4387 }
4388
4389 /* In restricted 80P80 MHz enabled, only one 80+80 MHz
4390 * channel is supported with cfreq=5690 and cfreq=5775.
4391 */
4392 if (wlan_psoc_nif_fw_ext_cap_get(
4393 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
4394 *is_valid = CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2);
4395 return QDF_STATUS_SUCCESS;
4396 }
4397
4398 ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2);
4399 ch_params.mhz_freq_seg1 = cfreq2;
4400 ch_params.ch_width = CH_WIDTH_80P80MHZ;
4401 wlan_reg_set_channel_params_for_pwrmode(
4402 pdev,
4403 cfreq1 - FREQ_OFFSET_10MHZ,
4404 0,
4405 &ch_params,
4406 REG_CURRENT_PWR_MODE);
4407
4408 if (ch_params.ch_width != CH_WIDTH_80P80MHZ) {
4409 *is_valid = false;
4410 return QDF_STATUS_SUCCESS;
4411 }
4412
4413 if (ch_params.mhz_freq_seg0 != cfreq1 ||
4414 ch_params.mhz_freq_seg1 != cfreq2) {
4415 *is_valid = false;
4416 return QDF_STATUS_SUCCESS;
4417 }
4418
4419 temp_params.ch_width = CH_WIDTH_80MHZ;
4420 chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
4421 pdev,
4422 ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ,
4423 &temp_params,
4424 REG_CURRENT_PWR_MODE);
4425 if ((chan_state1 == CHANNEL_STATE_DISABLE) ||
4426 (chan_state1 == CHANNEL_STATE_INVALID)) {
4427 *is_valid = false;
4428 return QDF_STATUS_SUCCESS;
4429 }
4430
4431 temp_params.ch_width = CH_WIDTH_80MHZ;
4432 chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
4433 pdev,
4434 ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ,
4435 &temp_params,
4436 REG_CURRENT_PWR_MODE);
4437 if ((chan_state2 == CHANNEL_STATE_DISABLE) ||
4438 (chan_state2 == CHANNEL_STATE_INVALID)) {
4439 *is_valid = false;
4440 return QDF_STATUS_SUCCESS;
4441 }
4442
4443 if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <=
4444 FREQ_OFFSET_80MHZ) {
4445 *is_valid = false;
4446 return QDF_STATUS_SUCCESS;
4447 }
4448
4449 *is_valid = true;
4450 return QDF_STATUS_SUCCESS;
4451 }
4452
4453 /**
4454 * _target_if_set_spectral_config() - Set spectral config
4455 * @spectral: Pointer to spectral object
4456 * @param: Spectral parameter id and value
4457 * @smode: Spectral scan mode
4458 * @err: Spectral error code
4459 *
4460 * API to set spectral configurations
4461 *
4462 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4463 */
4464 static QDF_STATUS
_target_if_set_spectral_config(struct target_if_spectral * spectral,const struct spectral_cp_param * param,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)4465 _target_if_set_spectral_config(struct target_if_spectral *spectral,
4466 const struct spectral_cp_param *param,
4467 const enum spectral_scan_mode smode,
4468 enum spectral_cp_error_code *err)
4469 {
4470 struct spectral_config params;
4471 struct target_if_spectral_ops *p_sops;
4472 struct spectral_config *sparams;
4473 QDF_STATUS status;
4474 bool is_overlapping;
4475 uint16_t agile_cfreq;
4476 bool is_valid_chan;
4477 struct spectral_param_min_max *param_min_max;
4478 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX];
4479 enum spectral_scan_mode m;
4480 struct spectral_config_frequency center_freq = {0};
4481 bool is_bw_supported;
4482 struct wlan_objmgr_vdev *vdev;
4483 enum phy_ch_width op_bw;
4484
4485 if (!err) {
4486 spectral_err("Error code argument is null");
4487 return QDF_STATUS_E_NULL_VALUE;
4488 }
4489 *err = SPECTRAL_SCAN_ERR_INVALID;
4490
4491 if (!param) {
4492 spectral_err("Parameter object is null");
4493 return QDF_STATUS_E_FAILURE;
4494 }
4495
4496 if (!spectral) {
4497 spectral_err("spectral object is NULL");
4498 return QDF_STATUS_E_FAILURE;
4499 }
4500 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4501 param_min_max = &spectral->param_min_max;
4502
4503 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4504 spectral_err("Invalid Spectral mode %u", smode);
4505 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4506 return QDF_STATUS_E_FAILURE;
4507 }
4508
4509 sparams = &spectral->params[smode];
4510 m = SPECTRAL_SCAN_MODE_NORMAL;
4511 for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
4512 ch_width[m] = CH_WIDTH_INVALID;
4513
4514 if (!spectral->params_valid[smode]) {
4515 target_if_spectral_info_read(spectral,
4516 smode,
4517 TARGET_IF_SPECTRAL_INFO_PARAMS,
4518 &spectral->params[smode],
4519 sizeof(spectral->params[smode]));
4520 spectral->params_valid[smode] = true;
4521 }
4522
4523 switch (param->id) {
4524 case SPECTRAL_PARAM_FFT_PERIOD:
4525 sparams->ss_fft_period = param->value;
4526 break;
4527 case SPECTRAL_PARAM_SCAN_PERIOD:
4528 sparams->ss_period = param->value;
4529 if (sparams->ss_recapture && ((sparams->ss_period <
4530 SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD) ||
4531 (smode == SPECTRAL_SCAN_MODE_AGILE))) {
4532 sparams->ss_recapture = false;
4533 spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d",
4534 sparams->ss_period, smode);
4535 }
4536 break;
4537 case SPECTRAL_PARAM_FFT_RECAPTURE:
4538 if (param->value) {
4539 if (sparams->ss_period >=
4540 SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD &&
4541 smode == SPECTRAL_SCAN_MODE_NORMAL) {
4542 sparams->ss_recapture = true;
4543 } else {
4544 spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d",
4545 sparams->ss_period, smode);
4546 sparams->ss_recapture = false;
4547 }
4548 } else {
4549 sparams->ss_recapture = false;
4550 }
4551 break;
4552 case SPECTRAL_PARAM_SCAN_COUNT:
4553 if (param->value > param_min_max->scan_count_max) {
4554 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4555 return QDF_STATUS_E_FAILURE;
4556 }
4557 sparams->ss_count = param->value;
4558 break;
4559 case SPECTRAL_PARAM_SHORT_REPORT:
4560 sparams->ss_short_report = (!!param->value) ? true : false;
4561 break;
4562 case SPECTRAL_PARAM_SPECT_PRI:
4563 sparams->ss_spectral_pri = (!!param->value) ? true : false;
4564 break;
4565 case SPECTRAL_PARAM_FFT_SIZE:
4566 status = target_if_spectral_populate_chwidth
4567 (spectral, ch_width, spectral->params
4568 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0);
4569 if (QDF_IS_STATUS_ERROR(status))
4570 return QDF_STATUS_E_FAILURE;
4571 if ((param->value < param_min_max->fft_size_min) ||
4572 (param->value > param_min_max->fft_size_max
4573 [ch_width[smode]])) {
4574 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4575 return QDF_STATUS_E_FAILURE;
4576 }
4577 sparams->ss_fft_size = param->value;
4578 break;
4579 case SPECTRAL_PARAM_GC_ENA:
4580 sparams->ss_gc_ena = !!param->value;
4581 break;
4582 case SPECTRAL_PARAM_RESTART_ENA:
4583 sparams->ss_restart_ena = !!param->value;
4584 break;
4585 case SPECTRAL_PARAM_NOISE_FLOOR_REF:
4586 sparams->ss_noise_floor_ref = param->value;
4587 break;
4588 case SPECTRAL_PARAM_INIT_DELAY:
4589 sparams->ss_init_delay = param->value;
4590 break;
4591 case SPECTRAL_PARAM_NB_TONE_THR:
4592 sparams->ss_nb_tone_thr = param->value;
4593 break;
4594 case SPECTRAL_PARAM_STR_BIN_THR:
4595 sparams->ss_str_bin_thr = param->value;
4596 break;
4597 case SPECTRAL_PARAM_WB_RPT_MODE:
4598 sparams->ss_wb_rpt_mode = !!param->value;
4599 break;
4600 case SPECTRAL_PARAM_RSSI_RPT_MODE:
4601 sparams->ss_rssi_rpt_mode = !!param->value;
4602 break;
4603 case SPECTRAL_PARAM_RSSI_THR:
4604 sparams->ss_rssi_thr = param->value;
4605 break;
4606 case SPECTRAL_PARAM_PWR_FORMAT:
4607 sparams->ss_pwr_format = !!param->value;
4608 break;
4609 case SPECTRAL_PARAM_RPT_MODE:
4610 if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) ||
4611 (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) {
4612 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4613 return QDF_STATUS_E_FAILURE;
4614 }
4615 sparams->ss_rpt_mode = param->value;
4616 break;
4617 case SPECTRAL_PARAM_BIN_SCALE:
4618 sparams->ss_bin_scale = param->value;
4619 break;
4620 case SPECTRAL_PARAM_DBM_ADJ:
4621 sparams->ss_dbm_adj = !!param->value;
4622 break;
4623 case SPECTRAL_PARAM_CHN_MASK:
4624 sparams->ss_chn_mask = param->value;
4625 break;
4626 case SPECTRAL_PARAM_FREQUENCY:
4627 status = target_if_spectral_populate_chwidth(
4628 spectral, ch_width, param->freq.cfreq2 > 0);
4629 if (QDF_IS_STATUS_ERROR(status)) {
4630 spectral_err("Failed to populate channel width");
4631 return QDF_STATUS_E_FAILURE;
4632 }
4633
4634 if (ch_width[smode] != CH_WIDTH_80P80MHZ &&
4635 param->freq.cfreq2) {
4636 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4637 spectral_err("Non zero cfreq2 expected for 80p80 only");
4638 return QDF_STATUS_E_INVAL;
4639 }
4640
4641 if (ch_width[smode] == CH_WIDTH_80P80MHZ &&
4642 !param->freq.cfreq2) {
4643 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4644 spectral_err("Non zero cfreq2 expected for 80p80");
4645 return QDF_STATUS_E_INVAL;
4646 }
4647
4648 status = target_if_is_center_freq_of_any_chan
4649 (spectral->pdev_obj, param->freq.cfreq1,
4650 &is_valid_chan);
4651 if (QDF_IS_STATUS_ERROR(status))
4652 return QDF_STATUS_E_FAILURE;
4653
4654 if (is_valid_chan) {
4655 status = target_if_calculate_center_freq(
4656 spectral, ch_width,
4657 param->freq.cfreq1,
4658 &agile_cfreq);
4659 if (QDF_IS_STATUS_ERROR(status)) {
4660 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4661 return QDF_STATUS_E_FAILURE;
4662 }
4663 } else {
4664 bool is_valid_agile_cfreq;
4665
4666 status = target_if_validate_center_freq
4667 (spectral, ch_width, param->freq.cfreq1,
4668 &is_valid_agile_cfreq);
4669 if (QDF_IS_STATUS_ERROR(status))
4670 return QDF_STATUS_E_FAILURE;
4671
4672 if (!is_valid_agile_cfreq) {
4673 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4674 spectral_err("Invalid agile center frequency");
4675 return QDF_STATUS_E_FAILURE;
4676 }
4677
4678 agile_cfreq = param->freq.cfreq1;
4679 }
4680 center_freq.cfreq1 = agile_cfreq;
4681
4682 if (ch_width[smode] == CH_WIDTH_80P80MHZ) {
4683 status = target_if_is_center_freq_of_any_chan
4684 (spectral->pdev_obj, param->freq.cfreq2,
4685 &is_valid_chan);
4686 if (QDF_IS_STATUS_ERROR(status))
4687 return QDF_STATUS_E_FAILURE;
4688
4689 if (is_valid_chan) {
4690 status = target_if_calculate_center_freq(
4691 spectral, ch_width,
4692 param->freq.cfreq2,
4693 &agile_cfreq);
4694 if (QDF_IS_STATUS_ERROR(status)) {
4695 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4696 return QDF_STATUS_E_FAILURE;
4697 }
4698 } else {
4699 bool is_valid_agile_cfreq;
4700
4701 status = target_if_validate_center_freq
4702 (spectral, ch_width, param->freq.cfreq2,
4703 &is_valid_agile_cfreq);
4704 if (QDF_IS_STATUS_ERROR(status))
4705 return QDF_STATUS_E_FAILURE;
4706
4707 if (!is_valid_agile_cfreq) {
4708 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4709 spectral_err("Invalid agile center frequency");
4710 return QDF_STATUS_E_FAILURE;
4711 }
4712
4713 agile_cfreq = param->freq.cfreq2;
4714 }
4715 center_freq.cfreq2 = agile_cfreq;
4716 }
4717
4718 status = target_if_is_agile_span_overlap_with_operating_span
4719 (spectral, ch_width,
4720 ¢er_freq, &is_overlapping);
4721 if (QDF_IS_STATUS_ERROR(status))
4722 return QDF_STATUS_E_FAILURE;
4723
4724 if (is_overlapping) {
4725 spectral_err("Agile freq %u, %u overlaps with operating span",
4726 center_freq.cfreq1, center_freq.cfreq2);
4727 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4728 return QDF_STATUS_E_FAILURE;
4729 }
4730
4731 if (ch_width[smode] == CH_WIDTH_80P80MHZ) {
4732 bool is_valid_80p80;
4733
4734 status = target_if_spectral_is_valid_80p80_freq(
4735 spectral->pdev_obj,
4736 center_freq.cfreq1,
4737 center_freq.cfreq2,
4738 &is_valid_80p80);
4739
4740 if (QDF_IS_STATUS_ERROR(status))
4741 return status;
4742
4743 if (!is_valid_80p80) {
4744 spectral_err("Agile freq %u, %u is invalid 80+80 combination",
4745 center_freq.cfreq1,
4746 center_freq.cfreq2);
4747 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4748 return QDF_STATUS_E_FAILURE;
4749 }
4750 }
4751
4752 sparams->ss_frequency.cfreq1 = center_freq.cfreq1;
4753 sparams->ss_frequency.cfreq2 = center_freq.cfreq2;
4754
4755 break;
4756
4757 case SPECTRAL_PARAM_CHAN_WIDTH:
4758 if (param->value >= CH_WIDTH_INVALID) {
4759 spectral_err("invalid sscan width: %u", param->value);
4760 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4761 return QDF_STATUS_E_FAILURE;
4762 }
4763
4764 vdev = target_if_spectral_get_vdev(spectral, smode);
4765 if (!vdev) {
4766 spectral_err("vdev is null");
4767 return QDF_STATUS_E_NULL_VALUE;
4768 }
4769 op_bw = target_if_vdev_get_ch_width(vdev);
4770 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
4771
4772 /* Validate the bandwidth */
4773 status = target_if_is_sscan_bw_supported(
4774 spectral, smode,
4775 param->value, op_bw, &is_bw_supported,
4776 spectral->params[SPECTRAL_SCAN_MODE_AGILE].
4777 ss_frequency.cfreq2 > 0);
4778 if (QDF_IS_STATUS_ERROR(status)) {
4779 spectral_err("Unable to check if given sscan_bw is supported");
4780 return QDF_STATUS_E_FAILURE;
4781 }
4782
4783 if (!is_bw_supported) {
4784 spectral_err("sscan bw(%u) is not supported for the current operating width(%u) and sscan mode(%u)",
4785 param->value, op_bw, smode);
4786 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
4787 return QDF_STATUS_E_FAILURE;
4788 }
4789
4790 sparams->ss_bandwidth = param->value;
4791 spectral->sscan_width_configured[smode] = true;
4792
4793 break;
4794 }
4795
4796 p_sops->configure_spectral(spectral, sparams, smode);
4797 /* only to validate the writes */
4798 p_sops->get_spectral_config(spectral, ¶ms, smode);
4799 return QDF_STATUS_SUCCESS;
4800 }
4801
4802 QDF_STATUS
target_if_set_spectral_config(struct wlan_objmgr_pdev * pdev,const struct spectral_cp_param * param,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)4803 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev,
4804 const struct spectral_cp_param *param,
4805 const enum spectral_scan_mode smode,
4806 enum spectral_cp_error_code *err)
4807 {
4808 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL;
4809 struct target_if_spectral *spectral;
4810 QDF_STATUS status;
4811
4812 if (!err) {
4813 spectral_err("Error code argument is null");
4814 return QDF_STATUS_E_NULL_VALUE;
4815 }
4816 *err = SPECTRAL_SCAN_ERR_INVALID;
4817
4818 if (!pdev) {
4819 spectral_err("pdev object is NULL");
4820 return QDF_STATUS_E_FAILURE;
4821 }
4822 spectral = get_target_if_spectral_handle_from_pdev(pdev);
4823 if (!spectral) {
4824 spectral_err("spectral object is NULL");
4825 return QDF_STATUS_E_FAILURE;
4826 }
4827
4828 if (!param) {
4829 spectral_err("parameter object is NULL");
4830 return QDF_STATUS_E_FAILURE;
4831 }
4832
4833 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4834 spectral_err("Invalid Spectral mode %u", smode);
4835 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
4836 return QDF_STATUS_E_FAILURE;
4837 }
4838
4839 if (!spectral->properties[smode][param->id].supported) {
4840 spectral_err("Spectral parameter(%u) unsupported for mode %u",
4841 param->id, smode);
4842 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED;
4843 return QDF_STATUS_E_FAILURE;
4844 }
4845
4846 if (spectral->properties[smode][param->id].common_all_modes) {
4847 spectral_warn("Setting Spectral parameter %u for all modes",
4848 param->id);
4849 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) {
4850 status = _target_if_set_spectral_config
4851 (spectral, param, mode, err);
4852 if (QDF_IS_STATUS_ERROR(status))
4853 return QDF_STATUS_E_FAILURE;
4854 }
4855 return QDF_STATUS_SUCCESS;
4856 }
4857
4858 return _target_if_set_spectral_config(spectral, param, smode, err);
4859 }
4860
4861 /**
4862 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length
4863 * @fft_len: FFT length
4864 *
4865 * API to get fft bin count for a given fft length
4866 *
4867 * Return: FFt bin count
4868 */
4869 static int
target_if_get_fft_bin_count(int fft_len)4870 target_if_get_fft_bin_count(int fft_len)
4871 {
4872 int bin_count = 0;
4873
4874 switch (fft_len) {
4875 case 5:
4876 bin_count = 16;
4877 break;
4878 case 6:
4879 bin_count = 32;
4880 break;
4881 case 7:
4882 bin_count = 64;
4883 break;
4884 case 8:
4885 bin_count = 128;
4886 break;
4887 case 9:
4888 bin_count = 256;
4889 break;
4890 default:
4891 break;
4892 }
4893
4894 return bin_count;
4895 }
4896
4897 /**
4898 * target_if_init_upper_lower_flags() - Initializes control and extension
4899 * segment flags
4900 * @spectral: pointer to target if spectral object
4901 * @smode: Spectral scan mode
4902 *
4903 * API to initialize the control and extension flags with the lower/upper
4904 * segment based on the HT mode
4905 *
4906 * Return: FFt bin count
4907 */
4908 static void
target_if_init_upper_lower_flags(struct target_if_spectral * spectral,enum spectral_scan_mode smode)4909 target_if_init_upper_lower_flags(struct target_if_spectral *spectral,
4910 enum spectral_scan_mode smode)
4911 {
4912 int current_channel = 0;
4913 int ext_channel = 0;
4914 struct target_if_spectral_ops *p_sops =
4915 GET_TARGET_IF_SPECTRAL_OPS(spectral);
4916
4917 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4918 spectral_err("Invalid Spectral mode %u", smode);
4919 return;
4920 }
4921 current_channel = p_sops->get_current_channel(spectral, smode);
4922 ext_channel = p_sops->get_extension_channel(spectral, smode);
4923
4924 if ((current_channel == 0) || (ext_channel == 0))
4925 return;
4926
4927 if (spectral->sc_spectral_20_40_mode) {
4928 /* HT40 mode */
4929 if (ext_channel < current_channel) {
4930 spectral->lower_is_extension = 1;
4931 spectral->upper_is_control = 1;
4932 spectral->lower_is_control = 0;
4933 spectral->upper_is_extension = 0;
4934 } else {
4935 spectral->lower_is_extension = 0;
4936 spectral->upper_is_control = 0;
4937 spectral->lower_is_control = 1;
4938 spectral->upper_is_extension = 1;
4939 }
4940 } else {
4941 /* HT20 mode, lower is always control */
4942 spectral->lower_is_extension = 0;
4943 spectral->upper_is_control = 0;
4944 spectral->lower_is_control = 1;
4945 spectral->upper_is_extension = 0;
4946 }
4947 }
4948
4949 /**
4950 * target_if_get_spectral_config() - Get spectral configuration
4951 * @pdev: Pointer to pdev object
4952 * @param: Pointer to spectral_config structure in which the configuration
4953 * should be returned
4954 * @smode: Spectral scan mode
4955 *
4956 * API to get the current spectral configuration
4957 *
4958 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
4959 */
4960 QDF_STATUS
target_if_get_spectral_config(struct wlan_objmgr_pdev * pdev,struct spectral_config * param,enum spectral_scan_mode smode)4961 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev,
4962 struct spectral_config *param,
4963 enum spectral_scan_mode smode)
4964 {
4965 struct target_if_spectral_ops *p_sops = NULL;
4966 struct target_if_spectral *spectral = NULL;
4967
4968 spectral = get_target_if_spectral_handle_from_pdev(pdev);
4969
4970 if (!spectral) {
4971 spectral_err("SPECTRAL : Module doesn't exist");
4972 return QDF_STATUS_E_FAILURE;
4973 }
4974
4975 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
4976
4977 if (!p_sops) {
4978 spectral_err("p_sops is null");
4979 return QDF_STATUS_E_FAILURE;
4980 }
4981
4982 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
4983 spectral_err("Invalid Spectral mode %u", smode);
4984 return QDF_STATUS_E_FAILURE;
4985 }
4986
4987 qdf_mem_zero(param, sizeof(struct spectral_config));
4988 p_sops->get_spectral_config(spectral, param, smode);
4989
4990 return QDF_STATUS_SUCCESS;
4991 }
4992
4993 #ifdef WLAN_FEATURE_11BE
4994 /**
4995 * target_if_spectral_get_num_detectors_for_higher_bws() - Get number of
4996 * Spectral detectors for higher bandwidths
4997 * @spectral: Pointer to target if Spectral object
4998 * @ch_width: channel width
4999 * @num_detectors: Pointer to the variable to store number of Spectral detectors
5000 *
5001 * API to get number of Spectral detectors used for scan in the given channel
5002 * width.
5003 *
5004 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure
5005 */
5006 static QDF_STATUS
target_if_spectral_get_num_detectors_for_higher_bws(struct target_if_spectral * spectral,enum phy_ch_width ch_width,uint32_t * num_detectors)5007 target_if_spectral_get_num_detectors_for_higher_bws(
5008 struct target_if_spectral *spectral,
5009 enum phy_ch_width ch_width,
5010 uint32_t *num_detectors)
5011 {
5012 switch (ch_width) {
5013 case CH_WIDTH_320MHZ:
5014 *num_detectors = spectral->capability.num_detectors_320mhz;
5015 break;
5016
5017 default:
5018 spectral_err("Unsupported channel width %d", ch_width);
5019 return QDF_STATUS_E_INVAL;
5020 }
5021
5022 return QDF_STATUS_SUCCESS;
5023 }
5024 #else
5025 static QDF_STATUS
target_if_spectral_get_num_detectors_for_higher_bws(struct target_if_spectral * spectral,enum phy_ch_width ch_width,uint32_t * num_detectors)5026 target_if_spectral_get_num_detectors_for_higher_bws(
5027 struct target_if_spectral *spectral,
5028 enum phy_ch_width ch_width,
5029 uint32_t *num_detectors)
5030 {
5031 spectral_err("Unsupported channel width %d", ch_width);
5032 return QDF_STATUS_E_INVAL;
5033 }
5034 #endif
5035
5036 /**
5037 * target_if_spectral_get_num_detectors() - Get number of Spectral detectors
5038 * @spectral: Pointer to target if Spectral object
5039 * @ch_width: channel width
5040 * @num_detectors: Pointer to the variable to store number of Spectral detectors
5041 *
5042 * API to get number of Spectral detectors used for scan in the given channel
5043 * width.
5044 *
5045 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure
5046 */
5047 static QDF_STATUS
target_if_spectral_get_num_detectors(struct target_if_spectral * spectral,enum phy_ch_width ch_width,uint32_t * num_detectors)5048 target_if_spectral_get_num_detectors(struct target_if_spectral *spectral,
5049 enum phy_ch_width ch_width,
5050 uint32_t *num_detectors)
5051 {
5052 if (!spectral) {
5053 spectral_err("target if spectral object is null");
5054 return QDF_STATUS_E_INVAL;
5055 }
5056
5057 if (ch_width >= CH_WIDTH_INVALID) {
5058 spectral_err("Invalid channel width %d", ch_width);
5059 return QDF_STATUS_E_INVAL;
5060 }
5061
5062 if (!num_detectors) {
5063 spectral_err("Invalid argument, number of detectors");
5064 return QDF_STATUS_E_INVAL;
5065 }
5066
5067 switch (ch_width) {
5068 case CH_WIDTH_20MHZ:
5069 *num_detectors = spectral->capability.num_detectors_20mhz;
5070 break;
5071
5072 case CH_WIDTH_40MHZ:
5073 *num_detectors = spectral->capability.num_detectors_40mhz;
5074 break;
5075
5076 case CH_WIDTH_80MHZ:
5077 *num_detectors = spectral->capability.num_detectors_80mhz;
5078 break;
5079
5080 case CH_WIDTH_160MHZ:
5081 *num_detectors = spectral->capability.num_detectors_160mhz;
5082 break;
5083
5084 case CH_WIDTH_80P80MHZ:
5085 *num_detectors = spectral->capability.num_detectors_80p80mhz;
5086 break;
5087
5088 default:
5089 return target_if_spectral_get_num_detectors_for_higher_bws(
5090 spectral, ch_width, num_detectors);
5091 }
5092
5093 return QDF_STATUS_SUCCESS;
5094 }
5095
5096 /**
5097 * target_if_spectral_finite_scan_init() - Initializations required for finite
5098 * Spectral scan
5099 * @spectral: Pointer to target of Spctral object
5100 * @smode: Spectral scan mode
5101 *
5102 * This routine initializes the finite Spectral scan. Finite Spectral scan is
5103 * triggered by configuring a non zero scan count.
5104 *
5105 * Return: QDF_STATUS_SUCCESS on success
5106 */
5107 static QDF_STATUS
target_if_spectral_finite_scan_init(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5108 target_if_spectral_finite_scan_init(struct target_if_spectral *spectral,
5109 enum spectral_scan_mode smode)
5110 {
5111 struct target_if_finite_spectral_scan_params *finite_scan;
5112 enum phy_ch_width ch_width;
5113 uint32_t num_detectors;
5114 QDF_STATUS status;
5115 uint16_t sscan_count;
5116
5117 if (!spectral) {
5118 spectral_err("target if spectral object is null");
5119 return QDF_STATUS_E_INVAL;
5120 }
5121
5122 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5123 spectral_err("Invalid Spectral mode");
5124 return QDF_STATUS_E_INVAL;
5125 }
5126
5127 ch_width = spectral->ch_width[smode];
5128 status = target_if_spectral_get_num_detectors(spectral, ch_width,
5129 &num_detectors);
5130
5131 if (QDF_IS_STATUS_ERROR(status)) {
5132 spectral_err("Failed to get number of detectors");
5133 return QDF_STATUS_E_FAILURE;
5134 }
5135
5136 finite_scan = &spectral->finite_scan[smode];
5137 sscan_count = spectral->params[smode].ss_count;
5138
5139 finite_scan->finite_spectral_scan = true;
5140 finite_scan->num_reports_expected = num_detectors * sscan_count;
5141
5142 return QDF_STATUS_SUCCESS;
5143 }
5144
5145 /**
5146 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral
5147 * parameters
5148 * @spectral: Pointer to Spectral target_if internal private data
5149 * @spectral_params: Pointer to Spectral parameters
5150 * @smode: Spectral scan mode
5151 * @err: Spectral error code
5152 *
5153 * Enable use of desired Spectral parameters by configuring them into HW, and
5154 * starting Spectral scan
5155 *
5156 * Return: 0 on success, 1 on failure
5157 */
5158 int
target_if_spectral_scan_enable_params(struct target_if_spectral * spectral,struct spectral_config * spectral_params,enum spectral_scan_mode smode,enum spectral_cp_error_code * err)5159 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral,
5160 struct spectral_config *spectral_params,
5161 enum spectral_scan_mode smode,
5162 enum spectral_cp_error_code *err)
5163 {
5164 int extension_channel = 0;
5165 int current_channel = 0;
5166 struct target_if_spectral_ops *p_sops = NULL;
5167 QDF_STATUS status;
5168 struct wlan_objmgr_pdev *pdev;
5169 struct wlan_objmgr_psoc *psoc;
5170
5171 if (!spectral) {
5172 spectral_err("Spectral LMAC object is NULL");
5173 return 1;
5174 }
5175
5176 pdev = spectral->pdev_obj;
5177 if (!pdev) {
5178 spectral_err("pdev is null");
5179 return QDF_STATUS_E_INVAL;
5180 }
5181
5182 psoc = wlan_pdev_get_psoc(pdev);
5183 if (!psoc) {
5184 spectral_err("psoc is null");
5185 return QDF_STATUS_E_INVAL;
5186 }
5187
5188 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5189 spectral_err("Invalid Spectral mode %u", smode);
5190 return 1;
5191 }
5192
5193 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
5194
5195 if (!p_sops) {
5196 spectral_err("p_sops is NULL");
5197 return 1;
5198 }
5199
5200 spectral->sc_spectral_noise_pwr_cal =
5201 spectral_params->ss_spectral_pri ? 1 : 0;
5202
5203 /* check if extension channel is present */
5204 extension_channel = p_sops->get_extension_channel(spectral, smode);
5205 current_channel = p_sops->get_current_channel(spectral, smode);
5206
5207 if (spectral->capability.advncd_spectral_cap) {
5208 spectral->lb_edge_extrabins = 0;
5209 spectral->rb_edge_extrabins = 0;
5210
5211 if (spectral->is_lb_edge_extrabins_format &&
5212 spectral->params[smode].ss_rpt_mode == 2) {
5213 spectral->lb_edge_extrabins = 4;
5214 }
5215
5216 if (spectral->is_rb_edge_extrabins_format &&
5217 spectral->params[smode].ss_rpt_mode == 2) {
5218 spectral->rb_edge_extrabins = 4;
5219 }
5220
5221 if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) {
5222 spectral->sc_spectral_20_40_mode = 0;
5223
5224 spectral->spectral_numbins =
5225 target_if_get_fft_bin_count(
5226 spectral->params[smode].ss_fft_size);
5227 spectral->spectral_fft_len =
5228 target_if_get_fft_bin_count(
5229 spectral->params[smode].ss_fft_size);
5230 spectral->spectral_data_len =
5231 target_if_get_fft_bin_count(
5232 spectral->params[smode].ss_fft_size);
5233 /*
5234 * Initialize classifier params to be sent to user
5235 * space classifier
5236 */
5237 spectral->classifier_params.lower_chan_in_mhz =
5238 current_channel;
5239 spectral->classifier_params.upper_chan_in_mhz = 0;
5240
5241 } else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) {
5242 /* TODO : Remove this variable */
5243 spectral->sc_spectral_20_40_mode = 1;
5244 spectral->spectral_numbins =
5245 target_if_get_fft_bin_count(
5246 spectral->params[smode].ss_fft_size);
5247 spectral->spectral_fft_len =
5248 target_if_get_fft_bin_count(
5249 spectral->params[smode].ss_fft_size);
5250 spectral->spectral_data_len =
5251 target_if_get_fft_bin_count(
5252 spectral->params[smode].ss_fft_size);
5253
5254 /*
5255 * Initialize classifier params to be sent to user
5256 * space classifier
5257 */
5258 if (extension_channel < current_channel) {
5259 spectral->classifier_params.lower_chan_in_mhz =
5260 extension_channel;
5261 spectral->classifier_params.upper_chan_in_mhz =
5262 current_channel;
5263 } else {
5264 spectral->classifier_params.lower_chan_in_mhz =
5265 current_channel;
5266 spectral->classifier_params.upper_chan_in_mhz =
5267 extension_channel;
5268 }
5269
5270 } else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) {
5271 /* Set the FFT Size */
5272 /* TODO : Remove this variable */
5273 spectral->sc_spectral_20_40_mode = 0;
5274 spectral->spectral_numbins =
5275 target_if_get_fft_bin_count(
5276 spectral->params[smode].ss_fft_size);
5277 spectral->spectral_fft_len =
5278 target_if_get_fft_bin_count(
5279 spectral->params[smode].ss_fft_size);
5280 spectral->spectral_data_len =
5281 target_if_get_fft_bin_count(
5282 spectral->params[smode].ss_fft_size);
5283
5284 /*
5285 * Initialize classifier params to be sent to user
5286 * space classifier
5287 */
5288 spectral->classifier_params.lower_chan_in_mhz =
5289 current_channel;
5290 spectral->classifier_params.upper_chan_in_mhz = 0;
5291
5292 /*
5293 * Initialize classifier params to be sent to user
5294 * space classifier
5295 */
5296 if (extension_channel < current_channel) {
5297 spectral->classifier_params.lower_chan_in_mhz =
5298 extension_channel;
5299 spectral->classifier_params.upper_chan_in_mhz =
5300 current_channel;
5301 } else {
5302 spectral->classifier_params.lower_chan_in_mhz =
5303 current_channel;
5304 spectral->classifier_params.upper_chan_in_mhz =
5305 extension_channel;
5306 }
5307
5308 } else if (is_ch_width_160_or_80p80(
5309 spectral->ch_width[smode])) {
5310 /* Set the FFT Size */
5311
5312 /* The below applies to both 160 and 80+80 cases */
5313
5314 /* TODO : Remove this variable */
5315 spectral->sc_spectral_20_40_mode = 0;
5316 spectral->spectral_numbins =
5317 target_if_get_fft_bin_count(
5318 spectral->params[smode].ss_fft_size);
5319 spectral->spectral_fft_len =
5320 target_if_get_fft_bin_count(
5321 spectral->params[smode].ss_fft_size);
5322 spectral->spectral_data_len =
5323 target_if_get_fft_bin_count(
5324 spectral->params[smode].ss_fft_size);
5325
5326 /*
5327 * Initialize classifier params to be sent to user
5328 * space classifier
5329 */
5330 spectral->classifier_params.lower_chan_in_mhz =
5331 current_channel;
5332 spectral->classifier_params.upper_chan_in_mhz = 0;
5333
5334 /*
5335 * Initialize classifier params to be sent to user
5336 * space classifier
5337 */
5338 if (extension_channel < current_channel) {
5339 spectral->classifier_params.lower_chan_in_mhz =
5340 extension_channel;
5341 spectral->classifier_params.upper_chan_in_mhz =
5342 current_channel;
5343 } else {
5344 spectral->classifier_params.lower_chan_in_mhz =
5345 current_channel;
5346 spectral->classifier_params.upper_chan_in_mhz =
5347 extension_channel;
5348 }
5349 }
5350
5351 if (spectral->spectral_numbins) {
5352 spectral->spectral_numbins +=
5353 spectral->lb_edge_extrabins;
5354 spectral->spectral_numbins +=
5355 spectral->rb_edge_extrabins;
5356 }
5357
5358 if (spectral->spectral_fft_len) {
5359 spectral->spectral_fft_len +=
5360 spectral->lb_edge_extrabins;
5361 spectral->spectral_fft_len +=
5362 spectral->rb_edge_extrabins;
5363 }
5364
5365 if (spectral->spectral_data_len) {
5366 spectral->spectral_data_len +=
5367 spectral->lb_edge_extrabins;
5368 spectral->spectral_data_len +=
5369 spectral->rb_edge_extrabins;
5370 }
5371 } else {
5372 /*
5373 * The decision to find 20/40 mode is found based on the
5374 * presence of extension channel
5375 * instead of channel width, as the channel width can
5376 * dynamically change
5377 */
5378
5379 if (extension_channel == 0) {
5380 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS;
5381 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX;
5382 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN;
5383 spectral->spectral_data_len =
5384 SPECTRAL_HT20_TOTAL_DATA_LEN;
5385 /* only valid in 20-40 mode */
5386 spectral->spectral_lower_max_index_offset = -1;
5387 /* only valid in 20-40 mode */
5388 spectral->spectral_upper_max_index_offset = -1;
5389 spectral->spectral_max_index_offset =
5390 spectral->spectral_fft_len + 2;
5391 spectral->sc_spectral_20_40_mode = 0;
5392
5393 /*
5394 * Initialize classifier params to be sent to user
5395 * space classifier
5396 */
5397 spectral->classifier_params.lower_chan_in_mhz =
5398 current_channel;
5399 spectral->classifier_params.upper_chan_in_mhz = 0;
5400
5401 } else {
5402 spectral->spectral_numbins =
5403 SPECTRAL_HT40_TOTAL_NUM_BINS;
5404 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN;
5405 spectral->spectral_data_len =
5406 SPECTRAL_HT40_TOTAL_DATA_LEN;
5407 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX;
5408 /* only valid in 20 mode */
5409 spectral->spectral_max_index_offset = -1;
5410 spectral->spectral_lower_max_index_offset =
5411 spectral->spectral_fft_len + 2;
5412 spectral->spectral_upper_max_index_offset =
5413 spectral->spectral_fft_len + 5;
5414 spectral->sc_spectral_20_40_mode = 1;
5415
5416 /*
5417 * Initialize classifier params to be sent to user
5418 * space classifier
5419 */
5420 if (extension_channel < current_channel) {
5421 spectral->classifier_params.lower_chan_in_mhz =
5422 extension_channel;
5423 spectral->classifier_params.upper_chan_in_mhz =
5424 current_channel;
5425 } else {
5426 spectral->classifier_params.lower_chan_in_mhz =
5427 current_channel;
5428 spectral->classifier_params.upper_chan_in_mhz =
5429 extension_channel;
5430 }
5431 }
5432 }
5433
5434 spectral->send_single_packet = 0;
5435 spectral->classifier_params.spectral_20_40_mode =
5436 spectral->sc_spectral_20_40_mode;
5437 spectral->classifier_params.spectral_dc_index =
5438 spectral->spectral_dc_index;
5439 spectral->spectral_sent_msg = 0;
5440 spectral->classify_scan = 0;
5441 spectral->num_spectral_data = 0;
5442
5443 if (!p_sops->is_spectral_active(spectral, smode)) {
5444 p_sops->configure_spectral(spectral, spectral_params, smode);
5445 spectral->rparams.marker[smode].is_valid = false;
5446
5447 if (spectral->params[smode].ss_count) {
5448 status = target_if_spectral_finite_scan_init(spectral,
5449 smode);
5450 if (QDF_IS_STATUS_ERROR(status)) {
5451 spectral_err("Failed to init finite scan");
5452 return 1;
5453 }
5454 }
5455 p_sops->start_spectral_scan(spectral, smode, err);
5456 spectral->timestamp_war.timestamp_war_offset[smode] = 0;
5457 spectral->timestamp_war.last_fft_timestamp[smode] = 0;
5458 }
5459
5460 /* get current spectral configuration */
5461 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode);
5462
5463 target_if_init_upper_lower_flags(spectral, smode);
5464
5465 return 0;
5466 }
5467
5468 /**
5469 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by
5470 * Agile DFS
5471 * @psoc: Pointer to psoc
5472 * @object: Pointer to pdev
5473 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited
5474 *
5475 * This API checks whether Agile DFS is running on any of the pdevs. If so, it
5476 * indicates that Agile Spectral scan is prohibited by Agile DFS.
5477 *
5478 * Return: void
5479 */
5480 static void
target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc * psoc,void * object,void * arg)5481 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc,
5482 void *object, void *arg)
5483 {
5484 bool *is_aspectral_prohibited = arg;
5485 struct wlan_objmgr_pdev *cur_pdev = object;
5486 bool is_agile_precac_enabled_cur_pdev = false;
5487 bool is_agile_rcac_enabled_cur_pdev = false;
5488 QDF_STATUS status;
5489
5490 if (!is_aspectral_prohibited) {
5491 spectral_err("Arg(Indication flag for agile spectral prohibition) is null.");
5492 return;
5493 }
5494
5495 if (*is_aspectral_prohibited)
5496 return;
5497
5498 if (!psoc) {
5499 spectral_err("psoc is null.");
5500 *is_aspectral_prohibited = true;
5501 return;
5502 }
5503
5504 if (!cur_pdev) {
5505 spectral_err("Current pdev is null.");
5506 *is_aspectral_prohibited = true;
5507 return;
5508 }
5509
5510 status = ucfg_dfs_get_agile_precac_enable
5511 (cur_pdev,
5512 &is_agile_precac_enabled_cur_pdev);
5513 if (QDF_IS_STATUS_ERROR(status)) {
5514 spectral_err("Get agile precac failed, prohibiting aSpectral");
5515 *is_aspectral_prohibited = true;
5516 return;
5517 }
5518
5519 status = ucfg_dfs_get_rcac_enable(cur_pdev,
5520 &is_agile_rcac_enabled_cur_pdev);
5521
5522 if (QDF_IS_STATUS_ERROR(status)) {
5523 spectral_err("Get agile RCAC failed, prohibiting aSpectral");
5524 *is_aspectral_prohibited = true;
5525 return;
5526 }
5527
5528 if (is_agile_precac_enabled_cur_pdev) {
5529 spectral_err("aDFS preCAC is in progress on one of the pdevs");
5530 *is_aspectral_prohibited = true;
5531 } else if (is_agile_rcac_enabled_cur_pdev) {
5532 spectral_err("aDFS RCAC is in progress on one of the pdevs");
5533 *is_aspectral_prohibited = true;
5534 }
5535 }
5536
5537 /**
5538 * target_if_get_curr_band() - Get current operating band of pdev
5539 * @pdev: pointer to pdev object
5540 * @vdev_id: id of vdev
5541 *
5542 * API to get current operating band of a given pdev.
5543 *
5544 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure
5545 */
5546 static enum reg_wifi_band
target_if_get_curr_band(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)5547 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
5548 {
5549 struct wlan_objmgr_vdev *vdev;
5550 int16_t chan_freq;
5551 enum reg_wifi_band cur_band;
5552
5553 if (!pdev) {
5554 spectral_err("pdev is NULL");
5555 return REG_BAND_UNKNOWN;
5556 }
5557
5558 if (vdev_id == WLAN_INVALID_VDEV_ID)
5559 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID);
5560 else
5561 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
5562 WLAN_SPECTRAL_ID);
5563 if (!vdev) {
5564 spectral_debug("vdev is NULL");
5565 return REG_BAND_UNKNOWN;
5566 }
5567 chan_freq = target_if_vdev_get_chan_freq(vdev);
5568 cur_band = wlan_reg_freq_to_band(chan_freq);
5569 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5570
5571 return cur_band;
5572 }
5573
5574 /**
5575 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on
5576 * any of the 5G pdevs
5577 * @psoc: Pointer to psoc
5578 * @object: Pointer to pdev
5579 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in
5580 * progress in any 5G pdevs
5581 *
5582 * Return: void
5583 */
5584 static void
target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc * psoc,void * object,void * arg)5585 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc,
5586 void *object, void *arg)
5587 {
5588 enum reg_wifi_band band;
5589 bool *is_agile_scan_inprog_5g_pdev = arg;
5590 struct target_if_spectral *spectral;
5591 struct wlan_objmgr_pdev *cur_pdev = object;
5592 struct target_if_spectral_ops *p_sops;
5593
5594 if (*is_agile_scan_inprog_5g_pdev)
5595 return;
5596
5597 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev);
5598 if (!spectral) {
5599 spectral_err("target if spectral handle is NULL");
5600 return;
5601 }
5602 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
5603
5604 band = target_if_get_curr_band(
5605 cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]);
5606 if (band == REG_BAND_UNKNOWN) {
5607 spectral_debug("Failed to get current band");
5608 return;
5609 }
5610
5611 if (band == REG_BAND_5G &&
5612 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE))
5613 *is_agile_scan_inprog_5g_pdev = true;
5614 }
5615
5616 /**
5617 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported
5618 * for current vdev rx chainmask.
5619 *
5620 * @spectral: Pointer to Spectral object
5621 * @is_supported: Pointer to is_supported
5622 *
5623 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
5624 */
5625 static QDF_STATUS
target_if_is_agile_supported_cur_chmask(struct target_if_spectral * spectral,bool * is_supported)5626 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral,
5627 bool *is_supported)
5628 {
5629 struct wlan_objmgr_vdev *vdev;
5630 uint8_t vdev_rxchainmask;
5631 struct wlan_objmgr_psoc *psoc;
5632 struct wlan_objmgr_pdev *pdev;
5633 struct target_psoc_info *tgt_psoc_info;
5634 struct wlan_psoc_host_service_ext_param *ext_svc_param;
5635 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL;
5636 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL;
5637 struct wlan_psoc_host_chainmask_table *table;
5638 int j;
5639 uint32_t table_id;
5640 enum phy_ch_width ch_width;
5641 uint8_t pdev_id;
5642
5643 if (!spectral) {
5644 spectral_err("spectral target if object is null");
5645 return QDF_STATUS_E_FAILURE;
5646 }
5647
5648 if (!is_supported) {
5649 spectral_err("is supported argument is null");
5650 return QDF_STATUS_E_FAILURE;
5651 }
5652
5653 if (spectral->spectral_gen <= SPECTRAL_GEN2) {
5654 spectral_err("HW Agile mode is not supported up to gen 2");
5655 return QDF_STATUS_E_FAILURE;
5656 }
5657
5658 pdev = spectral->pdev_obj;
5659 if (!pdev) {
5660 spectral_err("pdev is null");
5661 return QDF_STATUS_E_FAILURE;
5662 }
5663
5664 psoc = wlan_pdev_get_psoc(pdev);
5665 if (!psoc) {
5666 spectral_err("psoc is null");
5667 return QDF_STATUS_E_FAILURE;
5668 }
5669
5670 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE);
5671 if (!vdev) {
5672 spectral_err("First vdev is NULL");
5673 return QDF_STATUS_E_FAILURE;
5674 }
5675
5676 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev);
5677 if (!vdev_rxchainmask) {
5678 spectral_err("vdev rx chainmask is zero");
5679 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5680 return QDF_STATUS_E_FAILURE;
5681 }
5682
5683 ch_width = target_if_vdev_get_ch_width(vdev);
5684 if (ch_width == CH_WIDTH_INVALID) {
5685 spectral_err("Invalid channel width");
5686 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5687 return QDF_STATUS_E_FAILURE;
5688 }
5689 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
5690
5691 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
5692 if (!tgt_psoc_info) {
5693 spectral_err("target_psoc_info is null");
5694 return QDF_STATUS_E_FAILURE;
5695 }
5696
5697 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info);
5698 if (!ext_svc_param) {
5699 spectral_err("Extended service ready param null");
5700 return QDF_STATUS_E_FAILURE;
5701 }
5702 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
5703
5704 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info);
5705 if (!mac_phy_cap_arr) {
5706 spectral_err("mac phy cap array is null");
5707 return QDF_STATUS_E_FAILURE;
5708 }
5709
5710 mac_phy_cap = &mac_phy_cap_arr[pdev_id];
5711 if (!mac_phy_cap) {
5712 spectral_err("mac phy cap is null");
5713 return QDF_STATUS_E_FAILURE;
5714 }
5715
5716 table_id = mac_phy_cap->chainmask_table_id;
5717 table = &ext_svc_param->chainmask_table[table_id];
5718 if (!table) {
5719 spectral_err("chainmask table not found");
5720 return QDF_STATUS_E_FAILURE;
5721 }
5722
5723 for (j = 0; j < table->num_valid_chainmasks; j++) {
5724 if (table->cap_list[j].chainmask == vdev_rxchainmask) {
5725 if (ch_width <= CH_WIDTH_80MHZ)
5726 *is_supported =
5727 table->cap_list[j].supports_aSpectral;
5728 else
5729 *is_supported =
5730 table->cap_list[j].supports_aSpectral_160;
5731 break;
5732 }
5733 }
5734
5735 if (j == table->num_valid_chainmasks) {
5736 spectral_err("vdev rx chainmask %u not found in table id = %u",
5737 vdev_rxchainmask, table_id);
5738 return QDF_STATUS_E_FAILURE;
5739 }
5740
5741 return QDF_STATUS_SUCCESS;
5742 }
5743
5744 #define INVALID_SPAN_NUM (-1)
5745 /**
5746 * target_if_spectral_get_num_spans() - Get number of spans for a given sscan_bw
5747 * @pdev: Pointer to pdev object
5748 * @sscan_bw: Spectral scan bandwidth
5749 *
5750 * Return: Number of spans on success, INVALID_SPAN_NUM on failure
5751 */
5752 static int
target_if_spectral_get_num_spans(struct wlan_objmgr_pdev * pdev,enum phy_ch_width sscan_bw)5753 target_if_spectral_get_num_spans(
5754 struct wlan_objmgr_pdev *pdev,
5755 enum phy_ch_width sscan_bw)
5756 {
5757 struct wlan_objmgr_psoc *psoc;
5758 int num_spans;
5759
5760 if (!pdev) {
5761 spectral_err_rl("pdev is null");
5762 return INVALID_SPAN_NUM;
5763 }
5764
5765 psoc = wlan_pdev_get_psoc(pdev);
5766 if (!psoc) {
5767 spectral_err_rl("psoc is null");
5768 return INVALID_SPAN_NUM;
5769 }
5770
5771 if (sscan_bw == CH_WIDTH_80P80MHZ) {
5772 num_spans = 2;
5773 if (wlan_psoc_nif_fw_ext_cap_get(
5774 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT))
5775 /* 5 MHz frequency span in restricted 80p80 case */
5776 num_spans += 1;
5777 } else {
5778 num_spans = 1;
5779 }
5780
5781 return num_spans;
5782 }
5783
5784 #ifdef OPTIMIZED_SAMP_MESSAGE
5785 /**
5786 * target_if_spectral_populate_session_report_info() - Populate per-session
5787 * report level information.
5788 *
5789 * @spectral: Pointer to Spectral object
5790 * @smode: Spectral scan mode
5791 *
5792 * Return: Success/Failure
5793 */
5794 static QDF_STATUS
target_if_spectral_populate_session_report_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5795 target_if_spectral_populate_session_report_info(
5796 struct target_if_spectral *spectral,
5797 enum spectral_scan_mode smode)
5798 {
5799 struct per_session_report_info *rpt_info;
5800
5801 if (!spectral) {
5802 spectral_err_rl("Spectral LMAC object is null");
5803 return QDF_STATUS_E_NULL_VALUE;
5804 }
5805 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5806 spectral_err_rl("Invalid Spectral scan mode");
5807 return QDF_STATUS_E_FAILURE;
5808 }
5809
5810
5811 qdf_spin_lock_bh(&spectral->session_report_info_lock);
5812 /* Fill per-session report information, based on the spectral mode */
5813 rpt_info = &spectral->report_info[smode];
5814
5815 rpt_info->operating_bw = spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL];
5816 rpt_info->sscan_bw = spectral->ch_width[smode];
5817 rpt_info->sscan_cfreq1 = spectral->params[smode].ss_frequency.cfreq1;
5818 rpt_info->sscan_cfreq2 = spectral->params[smode].ss_frequency.cfreq2;
5819 rpt_info->num_spans = target_if_spectral_get_num_spans(
5820 spectral->pdev_obj,
5821 rpt_info->sscan_bw);
5822
5823 if (rpt_info->num_spans == INVALID_SPAN_NUM) {
5824 spectral_err_rl("Invalid number of spans: %u",
5825 rpt_info->num_spans);
5826 return QDF_STATUS_E_INVAL;
5827 }
5828 rpt_info->valid = true;
5829
5830 qdf_spin_unlock_bh(&spectral->session_report_info_lock);
5831
5832 return QDF_STATUS_SUCCESS;
5833 }
5834
5835 /**
5836 * target_if_spectral_populate_session_det_host_info() - Populate per-session
5837 * detector level information that is known to the Host
5838 *
5839 * @spectral: Pointer to Spectral object
5840 * @smode: Spectral scan mode
5841 *
5842 * Return: Success/Failure
5843 */
5844 static QDF_STATUS
target_if_spectral_populate_session_det_host_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5845 target_if_spectral_populate_session_det_host_info(
5846 struct target_if_spectral *spectral,
5847 enum spectral_scan_mode smode)
5848 {
5849 struct per_session_report_info *rpt_info;
5850 struct sscan_detector_list *detector_list;
5851 struct wlan_objmgr_psoc *psoc;
5852 uint16_t dest_det_idx = 0;
5853 uint16_t dest_span_idx = 0;
5854 bool is_sec80 = false;
5855 uint8_t det, dest_det;
5856
5857 if (!spectral) {
5858 spectral_err_rl("Spectral LMAC object is null");
5859 return QDF_STATUS_E_NULL_VALUE;
5860 }
5861 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
5862 spectral_err_rl("Invalid Spectral scan mode");
5863 return QDF_STATUS_E_FAILURE;
5864 }
5865
5866 if (!spectral->pdev_obj) {
5867 spectral_err_rl("Spectral PDEV is null");
5868 return QDF_STATUS_E_NULL_VALUE;
5869 }
5870
5871 psoc = wlan_pdev_get_psoc(spectral->pdev_obj);
5872 if (!psoc) {
5873 spectral_err_rl("psoc is null");
5874 return QDF_STATUS_E_NULL_VALUE;
5875 }
5876
5877 qdf_spin_lock_bh(&spectral->session_report_info_lock);
5878 rpt_info = &spectral->report_info[smode];
5879
5880 qdf_spin_lock_bh(&spectral->detector_list_lock);
5881 /* Fill per-sesion detector-level information */
5882 detector_list = &spectral->detector_list[smode][rpt_info->sscan_bw];
5883
5884 for (det = 0; det < detector_list->num_detectors; det++) {
5885 struct per_session_det_map *det_map;
5886
5887 qdf_spin_lock_bh(&spectral->session_det_map_lock);
5888 det_map = &spectral->det_map[detector_list->detectors[det]];
5889 if (detector_list->num_detectors > 1) {
5890 if (det == 0) {
5891 det_map->buf_type = SPECTRAL_MSG_BUF_NEW;
5892 det_map->send_to_upper_layers = false;
5893 } else if (det == detector_list->num_detectors - 1) {
5894 det_map->buf_type = SPECTRAL_MSG_BUF_SAVED;
5895 det_map->send_to_upper_layers = true;
5896 } else {
5897 /* middle fragments */
5898 det_map->buf_type = SPECTRAL_MSG_BUF_SAVED;
5899 det_map->send_to_upper_layers = false;
5900 }
5901 } else {
5902 det_map->buf_type = SPECTRAL_MSG_BUF_NEW;
5903 det_map->send_to_upper_layers = true;
5904 }
5905
5906 det_map->num_dest_det_info = 1;
5907 if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ &&
5908 wlan_psoc_nif_fw_ext_cap_get(
5909 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) {
5910 /**
5911 * In 165MHz case, 1 Spectral HW detector maps to 3
5912 * detectors in SAMP msg.
5913 */
5914 det_map->num_dest_det_info += 2;
5915 }
5916
5917 for (dest_det = 0; dest_det < det_map->num_dest_det_info;
5918 dest_det++) {
5919 struct per_session_dest_det_info *map_det_info;
5920
5921 map_det_info = &det_map->dest_det_info[dest_det];
5922 map_det_info->freq_span_id = dest_span_idx;
5923 map_det_info->det_id = dest_det_idx;
5924 map_det_info->is_sec80 = is_sec80;
5925 if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ) {
5926 /* Increment span ID for non-contiguous modes */
5927 dest_det_idx = 0;
5928 dest_span_idx++;
5929 } else {
5930 /* Increment detector ID for contiguous modes */
5931 dest_det_idx++;
5932 }
5933 is_sec80 = !is_sec80;
5934 }
5935 det_map->det_map_valid[smode] = true;
5936 qdf_spin_unlock_bh(&spectral->session_det_map_lock);
5937 }
5938 qdf_spin_unlock_bh(&spectral->detector_list_lock);
5939 qdf_spin_unlock_bh(&spectral->session_report_info_lock);
5940
5941 return QDF_STATUS_SUCCESS;
5942 }
5943
5944 #else
5945 static QDF_STATUS
target_if_spectral_populate_session_report_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5946 target_if_spectral_populate_session_report_info(
5947 struct target_if_spectral *spectral,
5948 enum spectral_scan_mode smode)
5949 {
5950 return QDF_STATUS_SUCCESS;
5951 }
5952
5953 static QDF_STATUS
target_if_spectral_populate_session_det_host_info(struct target_if_spectral * spectral,enum spectral_scan_mode smode)5954 target_if_spectral_populate_session_det_host_info(
5955 struct target_if_spectral *spectral,
5956 enum spectral_scan_mode smode)
5957 {
5958 return QDF_STATUS_SUCCESS;
5959 }
5960 #endif /* OPTIMIZED_SAMP_MESSAGE */
5961
5962 QDF_STATUS
spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev * pdev,bool * is_session_info_expected)5963 spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev *pdev,
5964 bool *is_session_info_expected)
5965 {
5966 struct wlan_objmgr_psoc *psoc;
5967 struct wmi_unified *wmi_handle;
5968
5969 if (!pdev) {
5970 spectral_err("pdev is null");
5971 return QDF_STATUS_E_NULL_VALUE;
5972 }
5973
5974 psoc = wlan_pdev_get_psoc(pdev);
5975 if (!psoc) {
5976 spectral_err("psoc is null");
5977 return QDF_STATUS_E_NULL_VALUE;
5978 }
5979
5980 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
5981 if (!wmi_handle) {
5982 spectral_err("wmi handle is null");
5983 return QDF_STATUS_E_NULL_VALUE;
5984 }
5985
5986 *is_session_info_expected = target_if_spectral_wmi_service_enabled(
5987 psoc, wmi_handle,
5988 wmi_service_spectral_session_info_support);
5989
5990 return QDF_STATUS_SUCCESS;
5991 }
5992
5993 QDF_STATUS
target_if_start_spectral_scan(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)5994 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev,
5995 uint8_t vdev_id,
5996 const enum spectral_scan_mode smode,
5997 enum spectral_cp_error_code *err)
5998 {
5999 struct target_if_spectral_ops *p_sops;
6000 struct target_if_spectral *spectral;
6001 struct wlan_objmgr_psoc *psoc;
6002 enum reg_wifi_band band;
6003 QDF_STATUS ret;
6004 bool is_session_info_expected;
6005
6006 if (!err) {
6007 spectral_err("Error code argument is null");
6008 return QDF_STATUS_E_NULL_VALUE;
6009 }
6010 *err = SPECTRAL_SCAN_ERR_INVALID;
6011
6012 if (!pdev) {
6013 spectral_err("pdev object is NUll");
6014 return QDF_STATUS_E_FAILURE;
6015 }
6016
6017 psoc = wlan_pdev_get_psoc(pdev);
6018 if (!psoc) {
6019 spectral_err("psoc is null");
6020 return QDF_STATUS_E_FAILURE;
6021 }
6022
6023 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6024 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6025 spectral_err("Invalid Spectral mode %u", smode);
6026 return QDF_STATUS_E_FAILURE;
6027 }
6028
6029 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6030 if (!spectral) {
6031 spectral_err("Spectral LMAC object is NUll");
6032 return QDF_STATUS_E_FAILURE;
6033 }
6034
6035 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6036 if (!p_sops) {
6037 spectral_err("p_sops is null");
6038 return QDF_STATUS_E_FAILURE;
6039 }
6040
6041 if (p_sops->is_spectral_active(spectral, smode)) {
6042 spectral_err("spectral in progress in current pdev, mode %d",
6043 smode);
6044 return QDF_STATUS_E_FAILURE;
6045 }
6046 spectral->vdev_id[smode] = vdev_id;
6047
6048 if (smode == SPECTRAL_SCAN_MODE_AGILE) {
6049 QDF_STATUS status;
6050 bool is_supported = false;
6051
6052 status = target_if_is_agile_supported_cur_chmask(spectral,
6053 &is_supported);
6054 if (QDF_IS_STATUS_ERROR(status)) {
6055 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6056 return QDF_STATUS_E_FAILURE;
6057 }
6058
6059 if (!is_supported) {
6060 spectral_err("aSpectral unsupported for cur chainmask");
6061 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6062 return QDF_STATUS_E_FAILURE;
6063 }
6064 }
6065
6066 band = target_if_get_curr_band(spectral->pdev_obj, vdev_id);
6067 if (band == REG_BAND_UNKNOWN) {
6068 spectral_err("Failed to get current band");
6069 return QDF_STATUS_E_FAILURE;
6070 }
6071 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) {
6072 struct target_psoc_info *tgt_hdl;
6073 enum wmi_host_hw_mode_config_type mode;
6074 bool is_agile_scan_inprog_5g_pdev;
6075
6076 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
6077 if (!tgt_hdl) {
6078 target_if_err("target_psoc_info is null");
6079 return QDF_STATUS_E_FAILURE;
6080 }
6081
6082 mode = target_psoc_get_preferred_hw_mode(tgt_hdl);
6083 switch (mode) {
6084 case WMI_HOST_HW_MODE_SBS_PASSIVE:
6085 case WMI_HOST_HW_MODE_SBS:
6086 case WMI_HOST_HW_MODE_DBS_SBS:
6087 case WMI_HOST_HW_MODE_DBS_OR_SBS:
6088 is_agile_scan_inprog_5g_pdev = false;
6089 wlan_objmgr_iterate_obj_list
6090 (psoc, WLAN_PDEV_OP,
6091 target_if_is_agile_scan_active_in_5g,
6092 &is_agile_scan_inprog_5g_pdev, 0,
6093 WLAN_SPECTRAL_ID);
6094 break;
6095 default:
6096 is_agile_scan_inprog_5g_pdev = false;
6097 break;
6098 }
6099
6100 if (is_agile_scan_inprog_5g_pdev) {
6101 spectral_err("Agile Scan in progress in one of the SBS 5G pdev");
6102 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6103 return QDF_STATUS_E_FAILURE;
6104 }
6105 }
6106
6107 if (smode == SPECTRAL_SCAN_MODE_AGILE) {
6108 bool is_aspectral_prohibited = false;
6109 QDF_STATUS status;
6110
6111 status = wlan_objmgr_iterate_obj_list
6112 (psoc, WLAN_PDEV_OP,
6113 target_if_is_aspectral_prohibited_by_adfs,
6114 &is_aspectral_prohibited, 0,
6115 WLAN_SPECTRAL_ID);
6116 if (QDF_IS_STATUS_ERROR(status)) {
6117 spectral_err("Failed to iterate over pdevs");
6118 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6119 return QDF_STATUS_E_FAILURE;
6120 }
6121
6122 if (is_aspectral_prohibited) {
6123 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6124 return QDF_STATUS_E_FAILURE;
6125 }
6126 }
6127
6128 if (!spectral->params_valid[smode]) {
6129 target_if_spectral_info_read(spectral,
6130 smode,
6131 TARGET_IF_SPECTRAL_INFO_PARAMS,
6132 &spectral->params[smode],
6133 sizeof(spectral->params[smode]));
6134 spectral->params_valid[smode] = true;
6135 }
6136
6137 qdf_spin_lock_bh(&spectral->spectral_lock);
6138 if (smode == SPECTRAL_SCAN_MODE_AGILE) {
6139 QDF_STATUS status;
6140 bool is_overlapping;
6141 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX];
6142 enum spectral_scan_mode m;
6143 enum phy_ch_width agile_ch_width;
6144
6145 m = SPECTRAL_SCAN_MODE_NORMAL;
6146 for (; m < SPECTRAL_SCAN_MODE_MAX; m++)
6147 ch_width[m] = CH_WIDTH_INVALID;
6148 status = target_if_spectral_populate_chwidth
6149 (spectral, ch_width, spectral->params
6150 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0);
6151 if (QDF_IS_STATUS_ERROR(status)) {
6152 qdf_spin_unlock_bh(&spectral->spectral_lock);
6153 spectral_err("Failed to populate channel width");
6154 return QDF_STATUS_E_FAILURE;
6155 }
6156 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE];
6157
6158 if (!spectral->params[smode].ss_frequency.cfreq1) {
6159 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
6160 qdf_spin_unlock_bh(&spectral->spectral_lock);
6161 spectral_err("Agile Spectral cfreq1 is 0");
6162 return QDF_STATUS_E_FAILURE;
6163 } else if (agile_ch_width == CH_WIDTH_80P80MHZ &&
6164 !spectral->params[smode].ss_frequency.cfreq2) {
6165 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
6166 qdf_spin_unlock_bh(&spectral->spectral_lock);
6167 spectral_err("Agile Spectral cfreq2 is 0");
6168 return QDF_STATUS_E_FAILURE;
6169 }
6170
6171 status = target_if_is_agile_span_overlap_with_operating_span
6172 (spectral, ch_width,
6173 &spectral->params[smode].ss_frequency,
6174 &is_overlapping);
6175 if (QDF_IS_STATUS_ERROR(status)) {
6176 qdf_spin_unlock_bh(&spectral->spectral_lock);
6177 return QDF_STATUS_E_FAILURE;
6178 }
6179
6180 if (is_overlapping) {
6181 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
6182 qdf_spin_unlock_bh(&spectral->spectral_lock);
6183 return QDF_STATUS_E_FAILURE;
6184 }
6185 }
6186
6187 /* Populate detectot list first */
6188 ret = target_if_spectral_detector_list_init(spectral);
6189 if (QDF_IS_STATUS_ERROR(ret)) {
6190 qdf_spin_unlock_bh(&spectral->spectral_lock);
6191 spectral_err("Failed to initialize detector list");
6192 return ret;
6193 }
6194
6195 ret = target_if_spectral_populate_chwidth(
6196 spectral, spectral->ch_width,
6197 spectral->params[SPECTRAL_SCAN_MODE_AGILE].
6198 ss_frequency.cfreq2 > 0);
6199 if (QDF_IS_STATUS_ERROR(ret)) {
6200 qdf_spin_unlock_bh(&spectral->spectral_lock);
6201 spectral_err("Failed to get channel widths");
6202 return ret;
6203 }
6204
6205 ret = spectral_is_session_info_expected_from_target(
6206 spectral->pdev_obj,
6207 &is_session_info_expected);
6208 if (QDF_IS_STATUS_ERROR(ret)) {
6209 qdf_spin_unlock_bh(&spectral->spectral_lock);
6210 spectral_err("Failed to check if session info is expected");
6211 return ret;
6212 }
6213
6214 /* If FW doesn't send session info, populate it */
6215 if (!is_session_info_expected) {
6216 ret = target_if_spectral_populate_session_report_info(spectral,
6217 smode);
6218 if (QDF_IS_STATUS_ERROR(ret)) {
6219 qdf_spin_unlock_bh(&spectral->spectral_lock);
6220 spectral_err("Failed to populate per-session report info");
6221 return QDF_STATUS_E_FAILURE;
6222 }
6223
6224 ret = target_if_spectral_populate_session_det_host_info(
6225 spectral, smode);
6226 if (QDF_IS_STATUS_ERROR(ret)) {
6227 qdf_spin_unlock_bh(&spectral->spectral_lock);
6228 spectral_err("Failed to populate per-session detector info");
6229 return QDF_STATUS_E_FAILURE;
6230 }
6231 }
6232
6233 target_if_spectral_scan_enable_params(spectral,
6234 &spectral->params[smode], smode,
6235 err);
6236
6237 spectral->sscan_width_configured[smode] = false;
6238 qdf_spin_unlock_bh(&spectral->spectral_lock);
6239
6240 return QDF_STATUS_SUCCESS;
6241 }
6242
6243 QDF_STATUS
target_if_stop_spectral_scan(struct wlan_objmgr_pdev * pdev,const enum spectral_scan_mode smode,enum spectral_cp_error_code * err)6244 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev,
6245 const enum spectral_scan_mode smode,
6246 enum spectral_cp_error_code *err)
6247 {
6248 struct target_if_spectral_ops *p_sops;
6249 struct target_if_spectral *spectral;
6250 uint8_t det;
6251
6252 if (!pdev) {
6253 spectral_err("pdev object is NULL");
6254 return QDF_STATUS_E_INVAL;
6255 }
6256
6257 if (target_if_spectral_is_feature_disabled_pdev(pdev)) {
6258 spectral_info("Spectral feature is disabled");
6259 return QDF_STATUS_COMP_DISABLED;
6260 }
6261
6262 if (!err) {
6263 spectral_err("Error code argument is null");
6264 return QDF_STATUS_E_NULL_VALUE;
6265 }
6266 *err = SPECTRAL_SCAN_ERR_INVALID;
6267
6268 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6269 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
6270 spectral_err("Invalid Spectral mode %u", smode);
6271 return QDF_STATUS_E_FAILURE;
6272 }
6273
6274 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6275 if (!spectral) {
6276 spectral_err("Spectral LMAC object is NUll ");
6277 return QDF_STATUS_E_FAILURE;
6278 }
6279 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6280
6281 qdf_spin_lock_bh(&spectral->spectral_lock);
6282 p_sops->stop_spectral_scan(spectral, smode);
6283 if (spectral->classify_scan) {
6284 /* TODO : Check if this logic is necessary */
6285 spectral->detects_control_channel = 0;
6286 spectral->detects_extension_channel = 0;
6287 spectral->detects_above_dc = 0;
6288 spectral->detects_below_dc = 0;
6289 spectral->classify_scan = 0;
6290 }
6291
6292 spectral->send_single_packet = 0;
6293 spectral->sc_spectral_scan = 0;
6294
6295 qdf_spin_lock_bh(&spectral->session_det_map_lock);
6296 for (det = 0; det < MAX_DETECTORS_PER_PDEV; det++)
6297 spectral->det_map[det].det_map_valid[smode] = false;
6298
6299 qdf_spin_unlock_bh(&spectral->session_det_map_lock);
6300
6301 /* Mark report info as invalid */
6302 qdf_spin_lock_bh(&spectral->session_report_info_lock);
6303 spectral->report_info[smode].valid = false;
6304 qdf_spin_unlock_bh(&spectral->session_report_info_lock);
6305
6306 qdf_spin_unlock_bh(&spectral->spectral_lock);
6307
6308 return QDF_STATUS_SUCCESS;
6309 }
6310
6311 /**
6312 * target_if_is_spectral_active() - Get whether Spectral is active
6313 * @pdev: Pointer to pdev object
6314 * @smode: Spectral scan mode
6315 *
6316 * API to get whether Spectral is active
6317 *
6318 * Return: True if Spectral is active, false if Spectral is not active
6319 */
6320 bool
target_if_is_spectral_active(struct wlan_objmgr_pdev * pdev,const enum spectral_scan_mode smode)6321 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev,
6322 const enum spectral_scan_mode smode)
6323 {
6324 struct target_if_spectral *spectral = NULL;
6325 struct target_if_spectral_ops *p_sops = NULL;
6326
6327 if (!pdev) {
6328 spectral_err("pdev is null");
6329 return false;
6330 }
6331
6332 if (target_if_spectral_is_feature_disabled_pdev(pdev)) {
6333 spectral_info("Spectral feature is disabled");
6334 return false;
6335 }
6336
6337 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6338
6339 if (!spectral) {
6340 spectral_err("SPECTRAL : Module doesn't exist");
6341 return false;
6342 }
6343
6344 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6345
6346 if (!p_sops) {
6347 spectral_err("p_sops is null");
6348 return false;
6349 }
6350
6351 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6352 spectral_err("Invalid Spectral mode %u", smode);
6353 return false;
6354 }
6355
6356 return p_sops->is_spectral_active(spectral, smode);
6357 }
6358
6359 /**
6360 * target_if_is_spectral_enabled() - Get whether Spectral is enabled
6361 * @pdev: Pointer to pdev object
6362 * @smode: Spectral scan mode
6363 *
6364 * API to get whether Spectral is enabled
6365 *
6366 * Return: True if Spectral is enabled, false if Spectral is not enabled
6367 */
6368 bool
target_if_is_spectral_enabled(struct wlan_objmgr_pdev * pdev,enum spectral_scan_mode smode)6369 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev,
6370 enum spectral_scan_mode smode)
6371 {
6372 struct target_if_spectral *spectral = NULL;
6373 struct target_if_spectral_ops *p_sops = NULL;
6374
6375 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6376
6377 if (!spectral) {
6378 spectral_err("SPECTRAL : Module doesn't exist");
6379 return false;
6380 }
6381
6382 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6383
6384 if (!p_sops) {
6385 spectral_err("p_sops is null");
6386 return false;
6387 }
6388
6389 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
6390 spectral_err("Invalid Spectral mode %u", smode);
6391 return false;
6392 }
6393
6394 return p_sops->is_spectral_enabled(spectral, smode);
6395 }
6396
6397 #ifdef DIRECT_BUF_RX_DEBUG
6398 /**
6399 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug
6400 * @pdev: Pointer to pdev object
6401 * @enable: Enable/Disable Spectral DMA ring debug
6402 *
6403 * Start/stop Spectral DMA ring debug based on @enable.
6404 * Also save the state for future use.
6405 *
6406 * Return: QDF_STATUS of operation
6407 */
6408 static QDF_STATUS
target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev * pdev,bool enable)6409 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable)
6410 {
6411 struct target_if_spectral *spectral;
6412 struct wlan_lmac_if_tx_ops *tx_ops;
6413 struct wlan_objmgr_psoc *psoc;
6414
6415 if (!pdev)
6416 return QDF_STATUS_E_FAILURE;
6417
6418 psoc = wlan_pdev_get_psoc(pdev);
6419 if (!psoc) {
6420 spectral_err("psoc is null");
6421 return QDF_STATUS_E_INVAL;
6422 }
6423
6424 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
6425 if (!tx_ops) {
6426 spectral_err("tx_ops is NULL");
6427 return QDF_STATUS_E_INVAL;
6428 }
6429
6430 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6431 if (!spectral) {
6432 spectral_err("Spectal LMAC object is NULL");
6433 return QDF_STATUS_E_INVAL;
6434 }
6435
6436 /* Save the state */
6437 spectral->dbr_ring_debug = enable;
6438
6439 if (enable)
6440 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug(
6441 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE);
6442 else
6443 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug(
6444 pdev, 0);
6445
6446 return QDF_STATUS_SUCCESS;
6447 }
6448
6449 /**
6450 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug
6451 * @pdev: Pointer to pdev object
6452 * @enable: Enable/Disable Spectral DMA buffer debug
6453 *
6454 * Start/stop Spectral DMA buffer debug based on @enable.
6455 * Also save the state for future use.
6456 *
6457 * Return: QDF_STATUS of operation
6458 */
6459 static QDF_STATUS
target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev * pdev,bool enable)6460 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable)
6461 {
6462 struct target_if_spectral *spectral;
6463 struct wlan_lmac_if_tx_ops *tx_ops;
6464 struct wlan_objmgr_psoc *psoc;
6465
6466 if (!pdev)
6467 return QDF_STATUS_E_FAILURE;
6468
6469 psoc = wlan_pdev_get_psoc(pdev);
6470 if (!psoc) {
6471 spectral_err("psoc is null");
6472 return QDF_STATUS_E_INVAL;
6473 }
6474
6475 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
6476 if (!tx_ops) {
6477 spectral_err("tx_ops is NULL");
6478 return QDF_STATUS_E_INVAL;
6479 }
6480
6481 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6482 if (!spectral) {
6483 spectral_err("Spectal LMAC object is NULL");
6484 return QDF_STATUS_E_INVAL;
6485 }
6486
6487 /* Save the state */
6488 spectral->dbr_buff_debug = enable;
6489
6490 if (enable)
6491 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning(
6492 pdev, 0, MEM_POISON_SIGNATURE);
6493 else
6494 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning(
6495 pdev, 0);
6496 }
6497
6498 /**
6499 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer
6500 * debug based on the previous state
6501 * @pdev: Pointer to pdev object
6502 *
6503 * Return: QDF_STATUS of operation
6504 */
6505 static QDF_STATUS
target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev * pdev)6506 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev)
6507 {
6508 struct target_if_spectral *spectral;
6509
6510 if (!pdev) {
6511 spectral_err("pdev is NULL!");
6512 return QDF_STATUS_E_FAILURE;
6513 }
6514
6515 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6516 if (!spectral) {
6517 spectral_err("Spectal LMAC object is NULL");
6518 return QDF_STATUS_E_INVAL;
6519 }
6520
6521 if (spectral->dbr_buff_debug)
6522 return target_if_spectral_do_dbr_buff_debug(pdev, true);
6523 else
6524 return target_if_spectral_do_dbr_buff_debug(pdev, false);
6525 }
6526
6527 /**
6528 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring
6529 * debug based on the previous state
6530 * @pdev: Pointer to pdev object
6531 *
6532 * Return: QDF_STATUS of operation
6533 */
6534 static QDF_STATUS
target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev * pdev)6535 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev)
6536 {
6537 struct target_if_spectral *spectral;
6538
6539 if (!pdev) {
6540 spectral_err("pdev is NULL!");
6541 return QDF_STATUS_E_FAILURE;
6542 }
6543
6544 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6545 if (!spectral) {
6546 spectral_err("Spectal LMAC object is NULL");
6547 return QDF_STATUS_E_INVAL;
6548 }
6549
6550 if (spectral->dbr_ring_debug)
6551 return target_if_spectral_do_dbr_ring_debug(pdev, true);
6552 else
6553 return target_if_spectral_do_dbr_ring_debug(pdev, false);
6554 }
6555
6556 /**
6557 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral
6558 * @pdev: Pointer to pdev object
6559 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug
6560 * @debug_value: Value to be set for @dma_debug_type
6561 *
6562 * Set DMA debug for Spectral and start/stop Spectral DMA debug function
6563 * based on @debug_value
6564 *
6565 * Return: QDF_STATUS of operation
6566 */
6567 static QDF_STATUS
target_if_spectral_set_dma_debug(struct wlan_objmgr_pdev * pdev,enum spectral_dma_debug dma_debug_type,bool debug_value)6568 target_if_spectral_set_dma_debug(
6569 struct wlan_objmgr_pdev *pdev,
6570 enum spectral_dma_debug dma_debug_type,
6571 bool debug_value)
6572 {
6573 struct target_if_spectral_ops *p_sops;
6574 struct wlan_objmgr_psoc *psoc;
6575 struct wlan_lmac_if_tx_ops *tx_ops;
6576 struct target_if_spectral *spectral;
6577
6578 if (!pdev)
6579 return QDF_STATUS_E_FAILURE;
6580
6581 psoc = wlan_pdev_get_psoc(pdev);
6582 if (!psoc) {
6583 spectral_err("psoc is null");
6584 return QDF_STATUS_E_INVAL;
6585 }
6586
6587 tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
6588 if (!tx_ops) {
6589 spectral_err("tx_ops is NULL");
6590 return QDF_STATUS_E_FAILURE;
6591 }
6592
6593 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) {
6594 spectral_err("Unable to fetch target type");
6595 return QDF_STATUS_E_FAILURE;
6596 }
6597
6598 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6599 if (!spectral) {
6600 spectral_err("Spectal LMAC object is NULL");
6601 return QDF_STATUS_E_INVAL;
6602 }
6603
6604 if (spectral->direct_dma_support) {
6605 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6606 if (p_sops->is_spectral_active(spectral,
6607 SPECTRAL_SCAN_MODE_NORMAL) ||
6608 p_sops->is_spectral_active(spectral,
6609 SPECTRAL_SCAN_MODE_AGILE)) {
6610 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan");
6611 return QDF_STATUS_E_FAILURE;
6612 }
6613
6614 switch (dma_debug_type) {
6615 case SPECTRAL_DMA_RING_DEBUG:
6616 target_if_spectral_do_dbr_ring_debug(pdev, debug_value);
6617 break;
6618
6619 case SPECTRAL_DMA_BUFFER_DEBUG:
6620 target_if_spectral_do_dbr_buff_debug(pdev, debug_value);
6621 break;
6622
6623 default:
6624 spectral_err("Unsupported DMA debug type : %d",
6625 dma_debug_type);
6626 return QDF_STATUS_E_FAILURE;
6627 }
6628 }
6629 return QDF_STATUS_SUCCESS;
6630 }
6631 #endif /* DIRECT_BUF_RX_DEBUG */
6632
6633 /**
6634 * target_if_spectral_direct_dma_support() - Get Direct-DMA support
6635 * @pdev: Pointer to pdev object
6636 *
6637 * Return: Whether Direct-DMA is supported on this radio
6638 */
6639 static bool
target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev * pdev)6640 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev)
6641 {
6642 struct target_if_spectral *spectral;
6643
6644 if (!pdev) {
6645 spectral_err("pdev is NULL!");
6646 return false;
6647 }
6648
6649 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6650 if (!spectral) {
6651 spectral_err("Spectral LMAC object is NULL");
6652 return false;
6653 }
6654
6655 return spectral->direct_dma_support;
6656 }
6657
6658 /**
6659 * target_if_set_debug_level() - Set debug level for Spectral
6660 * @pdev: Pointer to pdev object
6661 * @debug_level: Debug level
6662 *
6663 * API to set the debug level for Spectral
6664 *
6665 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
6666 */
6667 QDF_STATUS
target_if_set_debug_level(struct wlan_objmgr_pdev * pdev,uint32_t debug_level)6668 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level)
6669 {
6670 spectral_debug_level = (DEBUG_SPECTRAL << debug_level);
6671
6672 return QDF_STATUS_SUCCESS;
6673 }
6674
6675 /**
6676 * target_if_get_debug_level() - Get debug level for Spectral
6677 * @pdev: Pointer to pdev object
6678 *
6679 * API to get the debug level for Spectral
6680 *
6681 * Return: Current debug level
6682 */
6683 uint32_t
target_if_get_debug_level(struct wlan_objmgr_pdev * pdev)6684 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev)
6685 {
6686 return spectral_debug_level;
6687 }
6688
6689 /**
6690 * target_if_get_spectral_capinfo() - Get Spectral capability information
6691 * @pdev: Pointer to pdev object
6692 * @scaps: Buffer into which data should be copied
6693 *
6694 * API to get the spectral capability information
6695 *
6696 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
6697 */
6698 QDF_STATUS
target_if_get_spectral_capinfo(struct wlan_objmgr_pdev * pdev,struct spectral_caps * scaps)6699 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev,
6700 struct spectral_caps *scaps)
6701 {
6702 struct target_if_spectral *spectral = NULL;
6703
6704 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6705 if (!spectral) {
6706 spectral_err("SPECTRAL : Module doesn't exist");
6707 return QDF_STATUS_E_FAILURE;
6708 }
6709
6710 qdf_mem_copy(scaps, &spectral->capability,
6711 sizeof(struct spectral_caps));
6712
6713 return QDF_STATUS_SUCCESS;
6714 }
6715
6716 /**
6717 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics
6718 * @pdev: Pointer to pdev object
6719 * @stats: Buffer into which data should be copied
6720 *
6721 * API to get the spectral diagnostic statistics
6722 *
6723 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
6724 */
6725 QDF_STATUS
target_if_get_spectral_diagstats(struct wlan_objmgr_pdev * pdev,struct spectral_diag_stats * stats)6726 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev,
6727 struct spectral_diag_stats *stats)
6728 {
6729 struct target_if_spectral *spectral = NULL;
6730
6731 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6732 if (!spectral) {
6733 spectral_err("SPECTRAL : Module doesn't exist");
6734 return QDF_STATUS_E_FAILURE;
6735 }
6736
6737 qdf_mem_copy(stats, &spectral->diag_stats,
6738 sizeof(struct spectral_diag_stats));
6739
6740 return QDF_STATUS_SUCCESS;
6741 }
6742
6743 /**
6744 * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations
6745 * @psoc: Pointer to psoc object
6746 * @wmi_ops: Pointer to the structure having Spectral WMI operations
6747 *
6748 * API for registering Spectral WMI operations in
6749 * spectral internal data structure
6750 *
6751 * Return: QDF_STATUS
6752 */
6753 static QDF_STATUS
target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc * psoc,struct spectral_wmi_ops * wmi_ops)6754 target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc,
6755 struct spectral_wmi_ops *wmi_ops)
6756 {
6757 struct target_if_psoc_spectral *psoc_spectral;
6758
6759 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
6760 if (!psoc_spectral) {
6761 spectral_err("Spectral LMAC object is null");
6762 return QDF_STATUS_E_INVAL;
6763 }
6764
6765 psoc_spectral->wmi_ops = *wmi_ops;
6766
6767 return QDF_STATUS_SUCCESS;
6768 }
6769
6770 /**
6771 * target_if_register_spectral_tgt_ops() - Register Spectral target operations
6772 * @psoc: Pointer to psoc object
6773 * @tgt_ops: Pointer to the structure having Spectral target operations
6774 *
6775 * API for registering Spectral target operations in
6776 * spectral internal data structure
6777 *
6778 * Return: QDF_STATUS
6779 */
6780 static QDF_STATUS
target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc * psoc,struct spectral_tgt_ops * tgt_ops)6781 target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc,
6782 struct spectral_tgt_ops *tgt_ops)
6783 {
6784 if (!psoc) {
6785 spectral_err("psoc is null");
6786 return QDF_STATUS_E_INVAL;
6787 }
6788
6789 ops_tgt = *tgt_ops;
6790
6791 return QDF_STATUS_SUCCESS;
6792 }
6793
6794 /**
6795 * target_if_register_netlink_cb() - Register Netlink callbacks
6796 * @pdev: Pointer to pdev object
6797 * @nl_cb: Netlink callbacks to register
6798 *
6799 * Return: void
6800 */
6801 static void
target_if_register_netlink_cb(struct wlan_objmgr_pdev * pdev,struct spectral_nl_cb * nl_cb)6802 target_if_register_netlink_cb(
6803 struct wlan_objmgr_pdev *pdev,
6804 struct spectral_nl_cb *nl_cb)
6805 {
6806 struct target_if_spectral *spectral = NULL;
6807
6808 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6809
6810 if (!spectral) {
6811 spectral_err("SPECTRAL : Module doesn't exist");
6812 return;
6813 }
6814
6815 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb));
6816
6817 if (spectral->use_nl_bcast)
6818 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast;
6819 else
6820 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast;
6821 }
6822
6823 /**
6824 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending
6825 * Netlink messages to the application layer
6826 * @pdev: Pointer to pdev object
6827 *
6828 * Return: true for broadcast, false for unicast
6829 */
6830 static bool
target_if_use_nl_bcast(struct wlan_objmgr_pdev * pdev)6831 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev)
6832 {
6833 struct target_if_spectral *spectral = NULL;
6834
6835 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6836
6837 if (!spectral) {
6838 spectral_err("SPECTRAL : Module doesn't exist");
6839 return false;
6840 }
6841
6842 return spectral->use_nl_bcast;
6843 }
6844
6845 /**
6846 * target_if_deregister_netlink_cb() - De-register Netlink callbacks
6847 * @pdev: Pointer to pdev object
6848 *
6849 * Return: void
6850 */
6851 static void
target_if_deregister_netlink_cb(struct wlan_objmgr_pdev * pdev)6852 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev)
6853 {
6854 struct target_if_spectral *spectral = NULL;
6855
6856 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6857 if (!spectral) {
6858 spectral_err("SPECTRAL : Module doesn't exist");
6859 return;
6860 }
6861
6862 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb));
6863 }
6864
6865 static int
target_if_process_spectral_report(struct wlan_objmgr_pdev * pdev,void * payload)6866 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev,
6867 void *payload)
6868 {
6869 struct target_if_spectral *spectral = NULL;
6870 struct target_if_spectral_ops *p_sops = NULL;
6871
6872 spectral = get_target_if_spectral_handle_from_pdev(pdev);
6873 if (!spectral) {
6874 spectral_err("SPECTRAL : Module doesn't exist");
6875 return -EPERM;
6876 }
6877
6878 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
6879
6880 if (!p_sops) {
6881 spectral_err("p_sops is null");
6882 return -EPERM;
6883 }
6884
6885 return p_sops->process_spectral_report(pdev, payload);
6886 }
6887
6888 #ifdef DIRECT_BUF_RX_DEBUG
6889 static inline void
target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)6890 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
6891 {
6892 if (!tx_ops) {
6893 spectral_err("tx_ops is NULL");
6894 return;
6895 }
6896
6897 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug =
6898 target_if_spectral_set_dma_debug;
6899 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug =
6900 target_if_spectral_check_and_do_dbr_ring_debug;
6901 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug =
6902 target_if_spectral_check_and_do_dbr_buff_debug;
6903 }
6904 #else
6905 static inline void
target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)6906 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
6907 {
6908 }
6909 #endif
6910
6911 #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE)
6912 /**
6913 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
6914 * register WMI event handler
6915 * @psoc: Pointer to psoc object
6916 * @event_id: Event id
6917 * @handler_func: Handler function
6918 * @rx_ctx: Context of WMI event processing
6919 *
6920 * Wrapper function to register WMI event handler
6921 *
6922 * Return: 0 for success else failure
6923 */
6924 static int
target_if_spectral_wmi_unified_register_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id,wmi_unified_event_handler handler_func,uint8_t rx_ctx)6925 target_if_spectral_wmi_unified_register_event_handler(
6926 struct wlan_objmgr_psoc *psoc,
6927 wmi_conv_event_id event_id,
6928 wmi_unified_event_handler handler_func,
6929 uint8_t rx_ctx)
6930 {
6931 wmi_unified_t wmi_handle;
6932 struct target_if_psoc_spectral *psoc_spectral;
6933 QDF_STATUS ret;
6934
6935 if (!psoc) {
6936 spectral_err("psoc is null");
6937 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6938 }
6939
6940 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
6941 if (!wmi_handle) {
6942 spectral_err("WMI handle is null");
6943 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6944 }
6945
6946 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
6947 if (!psoc_spectral) {
6948 spectral_err("spectral object is null");
6949 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
6950 }
6951
6952 ret = psoc_spectral->wmi_ops.wmi_unified_register_event_handler(
6953 wmi_handle, event_id, handler_func, rx_ctx);
6954
6955 return qdf_status_to_os_return(ret);
6956 }
6957
6958 /**
6959 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function
6960 * to unregister WMI event handler
6961 * @psoc: Pointer to psoc object
6962 * @event_id: Event id
6963 *
6964 * Wrapper function to unregister WMI event handler
6965 *
6966 * Return: 0 for success else failure
6967 */
6968 static int
target_if_spectral_wmi_unified_unregister_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id)6969 target_if_spectral_wmi_unified_unregister_event_handler(
6970 struct wlan_objmgr_psoc *psoc,
6971 wmi_conv_event_id event_id)
6972 {
6973 wmi_unified_t wmi_handle;
6974 struct target_if_psoc_spectral *psoc_spectral;
6975 QDF_STATUS ret;
6976
6977 if (!psoc) {
6978 spectral_err("psoc is null");
6979 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6980 }
6981
6982 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
6983 if (!wmi_handle) {
6984 spectral_err("WMI handle is null");
6985 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
6986 }
6987
6988 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
6989 if (!psoc_spectral) {
6990 spectral_err("spectral object is null");
6991 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
6992 }
6993
6994 ret = psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler(
6995 wmi_handle, event_id);
6996
6997 return qdf_status_to_os_return(ret);
6998 }
6999
7000 /**
7001 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper
7002 * function to extract fixed parameters from start scan response event
7003 * @psoc: Pointer to psoc object
7004 * @evt_buf: Event buffer
7005 * @param: Start scan response parameters
7006 *
7007 * Wrapper function to extract fixed parameters from start scan response event
7008 *
7009 * Return: QDF_STATUS
7010 */
7011 static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_startscan_resp_params * param)7012 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7013 struct wlan_objmgr_psoc *psoc,
7014 uint8_t *evt_buf,
7015 struct spectral_startscan_resp_params *param)
7016 {
7017 wmi_unified_t wmi_handle;
7018 struct target_if_psoc_spectral *psoc_spectral;
7019
7020 if (!psoc) {
7021 spectral_err("psoc is null");
7022 return QDF_STATUS_E_INVAL;
7023 }
7024
7025 if (!evt_buf) {
7026 spectral_err("WMI event buffer is null");
7027 return QDF_STATUS_E_INVAL;
7028 }
7029
7030 if (!param) {
7031 spectral_err("Spectral startscan response parameters is null");
7032 return QDF_STATUS_E_INVAL;
7033 }
7034
7035 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7036 if (!wmi_handle) {
7037 spectral_err("WMI handle is null");
7038 return QDF_STATUS_E_INVAL;
7039 }
7040
7041 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7042 if (!psoc_spectral) {
7043 spectral_err("spectral object is null");
7044 return QDF_STATUS_E_FAILURE;
7045 }
7046
7047 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7048 wmi_handle, evt_buf, param);
7049 }
7050
7051 /**
7052 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper
7053 * function to extract start and end indices of primary 80 MHz, 5 MHz and
7054 * secondary 80 MHz FFT bins
7055 * @psoc: Pointer to psoc object
7056 * @evt_buf: Event buffer
7057 * @param: FFT bin start and end indices
7058 *
7059 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz
7060 * and secondary 80 MHz FFT bins
7061 *
7062 * Return: QDF_STATUS
7063 */
7064 static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_bin_markers_160_165mhz * param)7065 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
7066 struct wlan_objmgr_psoc *psoc,
7067 uint8_t *evt_buf,
7068 struct spectral_fft_bin_markers_160_165mhz *param)
7069 {
7070 wmi_unified_t wmi_handle;
7071 struct target_if_psoc_spectral *psoc_spectral;
7072
7073 if (!psoc) {
7074 spectral_err("psoc is null");
7075 return QDF_STATUS_E_INVAL;
7076 }
7077
7078 if (!evt_buf) {
7079 spectral_err("WMI event buffer is null");
7080 return QDF_STATUS_E_INVAL;
7081 }
7082
7083 if (!param) {
7084 spectral_err("Spectral FFT bin markers is null");
7085 return QDF_STATUS_E_INVAL;
7086 }
7087
7088 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7089 if (!wmi_handle) {
7090 spectral_err("WMI handle is null");
7091 return QDF_STATUS_E_INVAL;
7092 }
7093
7094 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7095 if (!psoc_spectral) {
7096 spectral_err("spectral object is null");
7097 return QDF_STATUS_E_FAILURE;
7098 }
7099
7100 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index(
7101 wmi_handle, evt_buf, param);
7102 }
7103
7104 /**
7105 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc
7106 * object from scn handle
7107 * @scn: scn handle
7108 *
7109 * Wrapper function to get psoc object from scn handle
7110 *
7111 * Return: Pointer to psoc object
7112 */
7113 static struct wlan_objmgr_psoc *
target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)7114 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
7115 {
7116 if (!scn) {
7117 spectral_err("scn is null");
7118 return NULL;
7119 }
7120
7121 return ops_tgt.tgt_get_psoc_from_scn_hdl(scn);
7122 }
7123
7124 /**
7125 * target_if_extract_pdev_spectral_session_chan_info() - Wrapper
7126 * function to extract channel information for a spectral scan session
7127 * @psoc: Pointer to psoc object
7128 * @evt_buf: Event buffer
7129 * @chan_info: Spectral session channel information data structure to be filled
7130 * by this API
7131 *
7132 * Return: QDF_STATUS of operation
7133 */
7134 static QDF_STATUS
target_if_extract_pdev_spectral_session_chan_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_chan_info * chan_info)7135 target_if_extract_pdev_spectral_session_chan_info(
7136 struct wlan_objmgr_psoc *psoc,
7137 void *evt_buf,
7138 struct spectral_session_chan_info *chan_info)
7139 {
7140 wmi_unified_t wmi_handle;
7141 struct target_if_psoc_spectral *psoc_spectral;
7142
7143 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7144 if (!wmi_handle) {
7145 spectral_err("WMI handle is null");
7146 return QDF_STATUS_E_NULL_VALUE;
7147 }
7148
7149 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7150 if (!psoc_spectral) {
7151 spectral_err("spectral object is null");
7152 return QDF_STATUS_E_NULL_VALUE;
7153 }
7154
7155 return psoc_spectral->wmi_ops.extract_pdev_spectral_session_chan_info(
7156 wmi_handle, evt_buf, chan_info);
7157 }
7158
7159 /**
7160 * target_if_extract_pdev_spectral_session_detector_info() - Wrapper
7161 * function to extract detector information for a spectral scan session
7162 * @psoc: Pointer to psoc object
7163 * @evt_buf: Event buffer
7164 * @det_info: Spectral session detector information data structure to be filled
7165 * by this API
7166 * @det_info_idx: index in the array of spectral scan detector info TLVs
7167 *
7168 * Return: QDF_STATUS of operation
7169 */
7170 static QDF_STATUS
target_if_extract_pdev_spectral_session_detector_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_det_info * det_info,uint8_t det_info_idx)7171 target_if_extract_pdev_spectral_session_detector_info(
7172 struct wlan_objmgr_psoc *psoc, void *evt_buf,
7173 struct spectral_session_det_info *det_info,
7174 uint8_t det_info_idx)
7175 {
7176 wmi_unified_t wmi_handle;
7177 struct target_if_psoc_spectral *psoc_spectral;
7178
7179 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7180 if (!wmi_handle) {
7181 spectral_err("WMI handle is null");
7182 return QDF_STATUS_E_NULL_VALUE;
7183 }
7184
7185 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7186 if (!psoc_spectral) {
7187 spectral_err("spectral object is null");
7188 return QDF_STATUS_E_NULL_VALUE;
7189 }
7190
7191 return psoc_spectral->wmi_ops.
7192 extract_pdev_spectral_session_detector_info(
7193 wmi_handle, evt_buf, det_info, det_info_idx);
7194 }
7195
7196 /**
7197 * target_if_wmi_extract_spectral_caps_fixed_param() - Wrapper function to
7198 * extract fixed params from Spectral capabilities WMI event
7199 * @psoc: Pointer to psoc object
7200 * @evt_buf: Event buffer
7201 * @param: Spectral capabilities event parameters data structure to be filled
7202 * by this API
7203 *
7204 * Return: QDF_STATUS of operation
7205 */
7206 QDF_STATUS
target_if_wmi_extract_spectral_caps_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_capabilities_event_params * param)7207 target_if_wmi_extract_spectral_caps_fixed_param(
7208 struct wlan_objmgr_psoc *psoc,
7209 uint8_t *evt_buf,
7210 struct spectral_capabilities_event_params *param)
7211 {
7212 struct target_if_psoc_spectral *psoc_spectral;
7213 wmi_unified_t wmi_handle;
7214
7215 if (!psoc) {
7216 spectral_err("psoc is null");
7217 return QDF_STATUS_E_NULL_VALUE;
7218 }
7219
7220 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7221 if (!wmi_handle) {
7222 spectral_err("WMI handle is null");
7223 return QDF_STATUS_E_NULL_VALUE;
7224 }
7225
7226 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7227 if (!psoc_spectral) {
7228 spectral_err("spectral object is null");
7229 return QDF_STATUS_E_FAILURE;
7230 }
7231
7232 return psoc_spectral->wmi_ops.extract_spectral_caps_fixed_param(
7233 wmi_handle, evt_buf, param);
7234 }
7235
7236 /**
7237 * target_if_wmi_extract_spectral_scan_bw_caps() - Wrapper function to
7238 * extract bandwidth capabilities from Spectral capabilities WMI event
7239 * @psoc: Pointer to psoc object
7240 * @evt_buf: Event buffer
7241 * @bw_caps: Data structure to be filled by this API after extraction
7242 *
7243 * Return: QDF_STATUS of operation
7244 */
7245 QDF_STATUS
target_if_wmi_extract_spectral_scan_bw_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_scan_bw_capabilities * bw_caps)7246 target_if_wmi_extract_spectral_scan_bw_caps(
7247 struct wlan_objmgr_psoc *psoc,
7248 uint8_t *evt_buf,
7249 struct spectral_scan_bw_capabilities *bw_caps)
7250 {
7251 struct target_if_psoc_spectral *psoc_spectral;
7252 wmi_unified_t wmi_handle;
7253
7254 if (!psoc) {
7255 spectral_err("psoc is null");
7256 return QDF_STATUS_E_INVAL;
7257 }
7258
7259 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7260 if (!wmi_handle) {
7261 spectral_err("WMI handle is null");
7262 return QDF_STATUS_E_INVAL;
7263 }
7264
7265 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7266 if (!psoc_spectral) {
7267 spectral_err("spectral object is null");
7268 return QDF_STATUS_E_FAILURE;
7269 }
7270
7271 return psoc_spectral->wmi_ops.extract_spectral_scan_bw_caps(
7272 wmi_handle, evt_buf, bw_caps);
7273 }
7274
7275 /**
7276 * target_if_wmi_extract_spectral_fft_size_caps() - Wrapper function to
7277 * extract fft size capabilities from Spectral capabilities WMI event
7278 * @psoc: Pointer to psoc object
7279 * @evt_buf: Event buffer
7280 * @fft_size_caps: Data structure to be filled by this API after extraction
7281 *
7282 * Return: QDF_STATUS of operation
7283 */
7284 QDF_STATUS
target_if_wmi_extract_spectral_fft_size_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_size_capabilities * fft_size_caps)7285 target_if_wmi_extract_spectral_fft_size_caps(
7286 struct wlan_objmgr_psoc *psoc,
7287 uint8_t *evt_buf,
7288 struct spectral_fft_size_capabilities *fft_size_caps)
7289 {
7290 struct target_if_psoc_spectral *psoc_spectral;
7291 wmi_unified_t wmi_handle;
7292
7293 if (!psoc) {
7294 spectral_err("psoc is null");
7295 return QDF_STATUS_E_INVAL;
7296 }
7297
7298 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7299 if (!wmi_handle) {
7300 spectral_err("WMI handle is null");
7301 return QDF_STATUS_E_INVAL;
7302 }
7303
7304 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7305 if (!psoc_spectral) {
7306 spectral_err("spectral object is null");
7307 return QDF_STATUS_E_FAILURE;
7308 }
7309
7310 return psoc_spectral->wmi_ops.extract_spectral_fft_size_caps(
7311 wmi_handle, evt_buf, fft_size_caps);
7312 }
7313 #else
7314 /**
7315 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to
7316 * register WMI event handler
7317 * @psoc: Pointer to psoc object
7318 * @event_id: Event id
7319 * @handler_func: Handler function
7320 * @rx_ctx: Context of WMI event processing
7321 *
7322 * Wrapper function to register WMI event handler
7323 *
7324 * Return: 0 for success else failure
7325 */
7326 static int
target_if_spectral_wmi_unified_register_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id,wmi_unified_event_handler handler_func,uint8_t rx_ctx)7327 target_if_spectral_wmi_unified_register_event_handler(
7328 struct wlan_objmgr_psoc *psoc,
7329 wmi_conv_event_id event_id,
7330 wmi_unified_event_handler handler_func,
7331 uint8_t rx_ctx)
7332 {
7333 wmi_unified_t wmi_handle;
7334 QDF_STATUS ret;
7335
7336 if (!psoc) {
7337 spectral_err("psoc is null");
7338 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7339 }
7340
7341 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7342 if (!wmi_handle) {
7343 spectral_err("WMI handle is null");
7344 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7345 }
7346
7347 ret = wmi_unified_register_event_handler(wmi_handle, event_id,
7348 handler_func, rx_ctx);
7349
7350 return qdf_status_to_os_return(ret);
7351 }
7352
7353 /**
7354 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function
7355 * to unregister WMI event handler
7356 * @psoc: Pointer to psoc object
7357 * @event_id: Event id
7358 *
7359 * Wrapper function to unregister WMI event handler
7360 *
7361 * Return: 0 for success else failure
7362 */
7363 static int
target_if_spectral_wmi_unified_unregister_event_handler(struct wlan_objmgr_psoc * psoc,wmi_conv_event_id event_id)7364 target_if_spectral_wmi_unified_unregister_event_handler(
7365 struct wlan_objmgr_psoc *psoc,
7366 wmi_conv_event_id event_id)
7367 {
7368 wmi_unified_t wmi_handle;
7369 QDF_STATUS ret;
7370
7371 if (!psoc) {
7372 spectral_err("psoc is null");
7373 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7374 }
7375
7376 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7377 if (!wmi_handle) {
7378 spectral_err("WMI handle is null");
7379 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7380 }
7381
7382 ret = wmi_unified_unregister_event_handler(wmi_handle, event_id);
7383
7384 return qdf_status_to_os_return(ret);
7385 }
7386
7387 /**
7388 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper
7389 * function to extract fixed parameters from start scan response event
7390 * @psoc: Pointer to psoc object
7391 * @evt_buf: Event buffer
7392 * @param: Start scan response parameters
7393 *
7394 * Wrapper function to extract fixed parameters from start scan response event
7395 *
7396 * Return: QDF_STATUS
7397 */
7398 static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_startscan_resp_params * param)7399 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7400 struct wlan_objmgr_psoc *psoc,
7401 uint8_t *evt_buf,
7402 struct spectral_startscan_resp_params *param)
7403 {
7404 wmi_unified_t wmi_handle;
7405
7406 if (!psoc) {
7407 spectral_err("psoc is null");
7408 return QDF_STATUS_E_INVAL;
7409 }
7410
7411 if (!evt_buf) {
7412 spectral_err("WMI event buffer is null");
7413 return QDF_STATUS_E_INVAL;
7414 }
7415
7416 if (!param) {
7417 spectral_err("Spectral startscan response parameters is null");
7418 return QDF_STATUS_E_INVAL;
7419 }
7420
7421 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7422 if (!wmi_handle) {
7423 spectral_err("WMI handle is null");
7424 return QDF_STATUS_E_INVAL;
7425 }
7426
7427 return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf,
7428 param);
7429 }
7430
7431 /**
7432 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper
7433 * function to extract start and end indices of primary 80 MHz, 5 MHz and
7434 * secondary 80 MHz FFT bins
7435 * @psoc: Pointer to psoc object
7436 * @evt_buf: Event buffer
7437 * @param: FFT bin start and end indices
7438 *
7439 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz
7440 * and secondary 80 MHz FFT bins
7441 *
7442 * Return: QDF_STATUS
7443 */
7444 static QDF_STATUS
target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_bin_markers_160_165mhz * param)7445 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
7446 struct wlan_objmgr_psoc *psoc,
7447 uint8_t *evt_buf,
7448 struct spectral_fft_bin_markers_160_165mhz *param)
7449 {
7450 wmi_unified_t wmi_handle;
7451
7452 if (!psoc) {
7453 spectral_err("psoc is null");
7454 return QDF_STATUS_E_INVAL;
7455 }
7456
7457 if (!evt_buf) {
7458 spectral_err("WMI event buffer is null");
7459 return QDF_STATUS_E_INVAL;
7460 }
7461
7462 if (!param) {
7463 spectral_err("Spectral FFT bin markers is null");
7464 return QDF_STATUS_E_INVAL;
7465 }
7466
7467 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7468 if (!wmi_handle) {
7469 spectral_err("WMI handle is null");
7470 return QDF_STATUS_E_INVAL;
7471 }
7472
7473 return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param);
7474 }
7475
7476 /**
7477 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc
7478 * object from scn handle
7479 * @scn: scn handle
7480 *
7481 * Wrapper function to get psoc object from scn handle
7482 *
7483 * Return: Pointer to psoc object
7484 */
7485 static struct wlan_objmgr_psoc *
target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)7486 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn)
7487 {
7488 if (!scn) {
7489 spectral_err("scn is null");
7490 return NULL;
7491 }
7492
7493 return target_if_get_psoc_from_scn_hdl(scn);
7494 }
7495
7496 /**
7497 * target_if_extract_pdev_spectral_session_chan_info() - Wrapper
7498 * function to extract channel information for a spectral scan session
7499 * @psoc: Pointer to psoc object
7500 * @evt_buf: Event buffer
7501 * @chan_info: Spectral session channel information data structure to be filled
7502 * by this API
7503 *
7504 * Return: QDF_STATUS of operation
7505 */
7506 static QDF_STATUS
target_if_extract_pdev_spectral_session_chan_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_chan_info * chan_info)7507 target_if_extract_pdev_spectral_session_chan_info(
7508 struct wlan_objmgr_psoc *psoc,
7509 void *evt_buf,
7510 struct spectral_session_chan_info *chan_info)
7511 {
7512 wmi_unified_t wmi_handle;
7513
7514 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7515 if (!wmi_handle) {
7516 spectral_err("WMI handle is null");
7517 return QDF_STATUS_E_NULL_VALUE;
7518 }
7519
7520 return wmi_extract_pdev_spectral_session_chan_info(
7521 wmi_handle, evt_buf, chan_info);
7522 }
7523
7524 /**
7525 * target_if_extract_pdev_spectral_session_detector_info() - Wrapper
7526 * function to extract detector information for a spectral scan session
7527 * @psoc: Pointer to psoc object
7528 * @evt_buf: Event buffer
7529 * @det_info: Spectral session detector information data structure to be filled
7530 * by this API
7531 * @det_info_idx: index in the array of spectral scan detector info TLVs
7532 *
7533 * Return: QDF_STATUS of operation
7534 */
7535 static QDF_STATUS
target_if_extract_pdev_spectral_session_detector_info(struct wlan_objmgr_psoc * psoc,void * evt_buf,struct spectral_session_det_info * det_info,uint8_t det_info_idx)7536 target_if_extract_pdev_spectral_session_detector_info(
7537 struct wlan_objmgr_psoc *psoc, void *evt_buf,
7538 struct spectral_session_det_info *det_info,
7539 uint8_t det_info_idx)
7540 {
7541 wmi_unified_t wmi_handle;
7542
7543 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7544 if (!wmi_handle) {
7545 spectral_err("WMI handle is null");
7546 return QDF_STATUS_E_NULL_VALUE;
7547 }
7548
7549 return wmi_extract_pdev_spectral_session_detector_info(
7550 wmi_handle, evt_buf, det_info, det_info_idx);
7551 }
7552
7553 QDF_STATUS
target_if_wmi_extract_spectral_caps_fixed_param(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_capabilities_event_params * param)7554 target_if_wmi_extract_spectral_caps_fixed_param(
7555 struct wlan_objmgr_psoc *psoc,
7556 uint8_t *evt_buf,
7557 struct spectral_capabilities_event_params *param)
7558 {
7559 wmi_unified_t wmi_handle;
7560
7561 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7562 if (!wmi_handle) {
7563 spectral_err("WMI handle is null");
7564 return QDF_STATUS_E_INVAL;
7565 }
7566
7567 return wmi_extract_spectral_caps_fixed_param(wmi_handle, evt_buf,
7568 param);
7569 }
7570
7571 QDF_STATUS
target_if_wmi_extract_spectral_scan_bw_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_scan_bw_capabilities * bw_caps)7572 target_if_wmi_extract_spectral_scan_bw_caps(
7573 struct wlan_objmgr_psoc *psoc,
7574 uint8_t *evt_buf,
7575 struct spectral_scan_bw_capabilities *bw_caps)
7576 {
7577 wmi_unified_t wmi_handle;
7578
7579 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7580 if (!wmi_handle) {
7581 spectral_err("WMI handle is null");
7582 return QDF_STATUS_E_INVAL;
7583 }
7584
7585 return wmi_extract_spectral_scan_bw_caps(wmi_handle, evt_buf, bw_caps);
7586 }
7587
7588 QDF_STATUS
target_if_wmi_extract_spectral_fft_size_caps(struct wlan_objmgr_psoc * psoc,uint8_t * evt_buf,struct spectral_fft_size_capabilities * fft_size_caps)7589 target_if_wmi_extract_spectral_fft_size_caps(
7590 struct wlan_objmgr_psoc *psoc,
7591 uint8_t *evt_buf,
7592 struct spectral_fft_size_capabilities *fft_size_caps)
7593 {
7594 wmi_unified_t wmi_handle;
7595
7596 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7597 if (!wmi_handle) {
7598 spectral_err("WMI handle is null");
7599 return QDF_STATUS_E_INVAL;
7600 }
7601
7602 return wmi_extract_spectral_fft_size_caps(wmi_handle, evt_buf,
7603 fft_size_caps);
7604 }
7605 #endif
7606
7607 /**
7608 * target_if_update_det_info_in_spectral_session() - Update detector
7609 * information in spectral scan session
7610 * @spectral: Spectral LMAC object
7611 * @det_info: Pointer to spectral session detector information
7612 * @smode: Spectral scan mode
7613 *
7614 * Return: QDF_STATUS of operation
7615 */
7616 static QDF_STATUS
target_if_update_det_info_in_spectral_session(struct target_if_spectral * spectral,const struct spectral_session_det_info * det_info,enum spectral_scan_mode smode)7617 target_if_update_det_info_in_spectral_session(
7618 struct target_if_spectral *spectral,
7619 const struct spectral_session_det_info *det_info,
7620 enum spectral_scan_mode smode)
7621 {
7622 struct per_session_det_map *det_map;
7623 struct per_session_dest_det_info *dest_det_info;
7624
7625 if (!spectral) {
7626 spectral_err_rl("Spectral LMAC object is null");
7627 return QDF_STATUS_E_NULL_VALUE;
7628 }
7629
7630 if (det_info->det_id >= MAX_DETECTORS_PER_PDEV) {
7631 spectral_err_rl("Detector Id: %u exceeding Max detectors.",
7632 det_info->det_id);
7633 return QDF_STATUS_E_INVAL;
7634 }
7635
7636 qdf_spin_lock_bh(&spectral->session_det_map_lock);
7637
7638 det_map = &spectral->det_map[det_info->det_id];
7639 dest_det_info = &det_map->dest_det_info[0];
7640
7641 dest_det_info->start_freq = det_info->start_freq;
7642 dest_det_info->end_freq = det_info->end_freq;
7643
7644 qdf_spin_unlock_bh(&spectral->session_det_map_lock);
7645
7646 /* This detector will be used for this smode throughout this session */
7647 spectral->rparams.detid_mode_table[det_info->det_id] = smode;
7648
7649 return QDF_STATUS_SUCCESS;
7650 }
7651
7652 /**
7653 * target_if_update_chan_info_in_spectral_session() - Update channel information
7654 * in spectral scan session
7655 * @spectral: Spectral LMAC object
7656 * @chan_info: Pointer to spectral session channel information
7657 * @smode: Spectral scan mode
7658 *
7659 * Return: QDF_STATUS of operation
7660 */
7661 static QDF_STATUS
target_if_update_chan_info_in_spectral_session(struct target_if_spectral * spectral,const struct spectral_session_chan_info * chan_info,enum spectral_scan_mode smode)7662 target_if_update_chan_info_in_spectral_session(
7663 struct target_if_spectral *spectral,
7664 const struct spectral_session_chan_info *chan_info,
7665 enum spectral_scan_mode smode)
7666 {
7667 struct per_session_report_info *rpt_info;
7668
7669 if (!spectral) {
7670 spectral_err_rl("Spectral LMAC object is null");
7671 return QDF_STATUS_E_NULL_VALUE;
7672 }
7673
7674 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
7675 spectral_err_rl("Invalid Spectral scan mode :%u", smode);
7676 return QDF_STATUS_E_FAILURE;
7677 }
7678
7679 qdf_spin_lock_bh(&spectral->session_report_info_lock);
7680 rpt_info = &spectral->report_info[smode];
7681
7682 /* Update per-session report info */
7683 rpt_info->pri20_freq = chan_info->operating_pri20_freq;
7684 rpt_info->cfreq1 = chan_info->operating_cfreq1;
7685 rpt_info->cfreq2 = chan_info->operating_cfreq2;
7686 rpt_info->operating_bw = chan_info->operating_bw;
7687 rpt_info->sscan_cfreq1 = chan_info->sscan_cfreq1;
7688 rpt_info->sscan_cfreq2 = chan_info->sscan_cfreq2;
7689 rpt_info->sscan_bw = chan_info->sscan_bw;
7690
7691 /* num_spans depends on sscan_bw, update it */
7692 rpt_info->num_spans = target_if_spectral_get_num_spans(
7693 spectral->pdev_obj,
7694 rpt_info->sscan_bw);
7695 if (rpt_info->num_spans == INVALID_SPAN_NUM) {
7696 spectral_err_rl("Invalid number of spans: %u",
7697 rpt_info->num_spans);
7698 return QDF_STATUS_E_INVAL;
7699 }
7700
7701 rpt_info->valid = true;
7702
7703 qdf_spin_unlock_bh(&spectral->session_report_info_lock);
7704
7705 return QDF_STATUS_SUCCESS;
7706 }
7707
7708 /**
7709 * target_if_spectral_fw_param_event_handler() - WMI event handler to
7710 * process start scan response event
7711 * @scn: Pointer to scn object
7712 * @data_buf: Pointer to event buffer
7713 * @data_len: Length of event buffer
7714 *
7715 * Return: 0 for success, else failure
7716 */
7717 static int
target_if_spectral_fw_param_event_handler(ol_scn_t scn,uint8_t * data_buf,uint32_t data_len)7718 target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf,
7719 uint32_t data_len)
7720 {
7721 QDF_STATUS status;
7722 struct wlan_objmgr_psoc *psoc;
7723 struct wlan_objmgr_pdev *pdev;
7724 struct wmi_unified *wmi_handle;
7725 struct spectral_startscan_resp_params event_params = {0};
7726 struct target_if_psoc_spectral *psoc_spectral;
7727 struct target_if_spectral *spectral;
7728 bool is_session_info_expected;
7729
7730 if (!scn) {
7731 spectral_err("scn handle is null");
7732 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7733 }
7734
7735 if (!data_buf) {
7736 spectral_err("WMI event buffer null");
7737 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7738 }
7739
7740 psoc = target_if_spectral_get_psoc_from_scn_handle(scn);
7741 if (!psoc) {
7742 spectral_err("psoc is null");
7743 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7744 }
7745
7746 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc);
7747 if (!psoc_spectral) {
7748 spectral_err("spectral object is null");
7749 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7750 }
7751
7752 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7753 if (!wmi_handle) {
7754 spectral_err("WMI handle is null");
7755 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7756 }
7757
7758 status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param(
7759 psoc, data_buf, &event_params);
7760 if (QDF_IS_STATUS_ERROR(status)) {
7761 spectral_err("unable to extract sscan fw fixed params");
7762 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7763 }
7764
7765 if (event_params.smode >= SPECTRAL_SCAN_MODE_MAX ||
7766 event_params.smode < SPECTRAL_SCAN_MODE_NORMAL) {
7767 spectral_err("Invalid smode %d", event_params.smode);
7768 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7769 }
7770
7771 pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id,
7772 WLAN_SPECTRAL_ID);
7773 if (!pdev) {
7774 spectral_err("pdev is null");
7775 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7776 }
7777
7778 spectral = get_target_if_spectral_handle_from_pdev(pdev);
7779 if (!spectral) {
7780 spectral_err("spectral object is null");
7781 status = QDF_STATUS_E_FAILURE;
7782 goto release_pdev_ref;
7783 }
7784
7785 if (event_params.num_fft_bin_index == 1) {
7786 status =
7787 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index(
7788 psoc, data_buf,
7789 &spectral->rparams.marker[event_params.smode]);
7790 if (QDF_IS_STATUS_ERROR(status)) {
7791 spectral_err("unable to extract sscan fw fixed params");
7792 goto release_pdev_ref;
7793 }
7794 } else {
7795 spectral->rparams.marker[event_params.smode].is_valid = false;
7796 }
7797
7798 status = spectral_is_session_info_expected_from_target(
7799 pdev, &is_session_info_expected);
7800 if (QDF_IS_STATUS_ERROR(status)) {
7801 spectral_err("Failed to check if session info is expected");
7802 goto release_pdev_ref;
7803 }
7804
7805 if (is_session_info_expected) {
7806 struct spectral_session_chan_info chan_info;
7807 uint8_t det_info_idx = 0;
7808
7809 status = target_if_extract_pdev_spectral_session_chan_info(
7810 psoc, data_buf, &chan_info);
7811 if (QDF_IS_STATUS_ERROR(status)) {
7812 spectral_err("Unable to extract spectral session channel info");
7813 goto release_pdev_ref;
7814 }
7815
7816 status = target_if_update_chan_info_in_spectral_session(
7817 spectral, &chan_info, event_params.smode);
7818 if (QDF_IS_STATUS_ERROR(status)) {
7819 spectral_err("Unable to update channel info");
7820 goto release_pdev_ref;
7821 }
7822
7823 /* FFT bins info depends upon sscan_bw, update it */
7824 status = target_if_populate_fft_bins_info(spectral,
7825 event_params.smode);
7826 if (QDF_IS_STATUS_ERROR(status)) {
7827 spectral_err("Failed to populate FFT bins info");
7828 goto release_pdev_ref;
7829 }
7830
7831 /**
7832 * per-session det info that depends on sscan_bw needs to be
7833 * updated here
7834 */
7835 status = target_if_spectral_populate_session_det_host_info(
7836 spectral, event_params.smode);
7837 if (QDF_IS_STATUS_ERROR(status)) {
7838 spectral_err("Failed to populate per-session det info");
7839 goto release_pdev_ref;
7840 }
7841
7842 for (; det_info_idx < event_params.num_det_info;
7843 ++det_info_idx) {
7844 struct spectral_session_det_info det_info;
7845
7846 status =
7847 target_if_extract_pdev_spectral_session_detector_info
7848 (psoc, data_buf, &det_info, det_info_idx);
7849
7850 if (QDF_IS_STATUS_ERROR(status)) {
7851 spectral_err("Unable to extract spectral session detector info for %u",
7852 det_info_idx);
7853 goto release_pdev_ref;
7854 }
7855
7856 status = target_if_update_det_info_in_spectral_session(
7857 spectral, &det_info,
7858 event_params.smode);
7859 if (QDF_IS_STATUS_ERROR(status)) {
7860 spectral_err("Unable to update detector info");
7861 goto release_pdev_ref;
7862 }
7863 }
7864 }
7865
7866 status = QDF_STATUS_SUCCESS;
7867
7868 release_pdev_ref:
7869 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID);
7870 return qdf_status_to_os_return(status);
7871 }
7872
7873 /**
7874 * target_if_spectral_capabilities_event_handler() - Handler for the Spectral
7875 * Capabilities event
7876 * @scn: Pointer to scn object
7877 * @data_buf: Pointer to event buffer
7878 * @data_len: Length of event buffer
7879 *
7880 * Return: 0 for success, else failure
7881 */
7882 static int
target_if_spectral_capabilities_event_handler(ol_scn_t scn,uint8_t * data_buf,uint32_t data_len)7883 target_if_spectral_capabilities_event_handler(ol_scn_t scn, uint8_t *data_buf,
7884 uint32_t data_len)
7885 {
7886 QDF_STATUS status;
7887 struct wlan_objmgr_psoc *psoc;
7888 struct wmi_unified *wmi_handle;
7889 struct spectral_capabilities_event_params event_params = {0};
7890 struct spectral_scan_bw_capabilities *bw_caps;
7891 struct spectral_fft_size_capabilities *fft_size_caps;
7892
7893 if (!scn) {
7894 spectral_err("scn handle is null");
7895 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7896 }
7897
7898 if (!data_buf) {
7899 spectral_err("WMI event buffer null");
7900 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7901 }
7902
7903 psoc = target_if_spectral_get_psoc_from_scn_handle(scn);
7904 if (!psoc) {
7905 spectral_err("psoc is null");
7906 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7907 }
7908
7909 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc);
7910 if (!wmi_handle) {
7911 spectral_err("WMI handle is null");
7912 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7913 }
7914
7915 status = target_if_wmi_extract_spectral_caps_fixed_param(
7916 psoc, data_buf, &event_params);
7917 if (QDF_IS_STATUS_ERROR(status)) {
7918 spectral_err("Failed to extract fixed parameters");
7919 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
7920 }
7921
7922 /* There should be atleast one capability */
7923 if (!event_params.num_sscan_bw_caps) {
7924 spectral_err("Number of spectral_scan_bw_capabilities is less than one.");
7925 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7926 }
7927
7928 if (!event_params.num_fft_size_caps) {
7929 spectral_err("Number of spectral_scan_fft_size_capabilities is less than one.");
7930 return qdf_status_to_os_return(QDF_STATUS_E_INVAL);
7931 }
7932
7933 bw_caps = qdf_mem_malloc(
7934 sizeof(*bw_caps) * event_params.num_sscan_bw_caps);
7935 if (!bw_caps) {
7936 spectral_err("memory allocation failed");
7937 return qdf_status_to_os_return(QDF_STATUS_E_NOMEM);
7938 }
7939
7940 status = target_if_wmi_extract_spectral_scan_bw_caps(psoc, data_buf,
7941 bw_caps);
7942 if (QDF_IS_STATUS_ERROR(status)) {
7943 spectral_err("Failed to extract BW caps");
7944 status = QDF_STATUS_E_FAILURE;
7945 goto free_bw_caps;
7946 }
7947
7948 fft_size_caps = qdf_mem_malloc(
7949 sizeof(*fft_size_caps) * event_params.num_fft_size_caps);
7950 if (!fft_size_caps) {
7951 spectral_err("memory allocation failed");
7952 status = QDF_STATUS_E_NOMEM;
7953 goto free_bw_caps;
7954 }
7955
7956 status = target_if_wmi_extract_spectral_fft_size_caps(psoc, data_buf,
7957 fft_size_caps);
7958 if (QDF_IS_STATUS_ERROR(status)) {
7959 spectral_err("Failed to extract fft size caps");
7960 status = QDF_STATUS_E_FAILURE;
7961 goto free_fft_size_caps;
7962 }
7963
7964 status = QDF_STATUS_SUCCESS;
7965
7966 free_fft_size_caps:
7967 qdf_mem_free(fft_size_caps);
7968
7969 free_bw_caps:
7970 qdf_mem_free(bw_caps);
7971
7972 return qdf_status_to_os_return(status);
7973 }
7974
7975 static QDF_STATUS
target_if_spectral_register_events(struct wlan_objmgr_psoc * psoc)7976 target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc)
7977 {
7978 int ret;
7979
7980 if (!psoc) {
7981 spectral_err("psoc is null");
7982 return QDF_STATUS_E_INVAL;
7983 }
7984
7985 ret = target_if_spectral_wmi_unified_register_event_handler(
7986 psoc,
7987 wmi_pdev_sscan_fw_param_eventid,
7988 target_if_spectral_fw_param_event_handler,
7989 WMI_RX_UMAC_CTX);
7990
7991 if (ret)
7992 spectral_debug("event handler not supported, ret=%d", ret);
7993
7994 ret = target_if_spectral_wmi_unified_register_event_handler(
7995 psoc,
7996 wmi_spectral_capabilities_eventid,
7997 target_if_spectral_capabilities_event_handler,
7998 WMI_RX_UMAC_CTX);
7999 if (ret)
8000 spectral_debug("event handler not supported, ret=%d", ret);
8001
8002 return QDF_STATUS_SUCCESS;
8003 }
8004
8005 static QDF_STATUS
target_if_spectral_unregister_events(struct wlan_objmgr_psoc * psoc)8006 target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc)
8007 {
8008 int ret;
8009
8010 if (!psoc) {
8011 spectral_err("psoc is null");
8012 return QDF_STATUS_E_INVAL;
8013 }
8014
8015 target_if_spectral_wmi_unified_unregister_event_handler(
8016 psoc, wmi_spectral_capabilities_eventid);
8017
8018 ret = target_if_spectral_wmi_unified_unregister_event_handler(
8019 psoc, wmi_pdev_sscan_fw_param_eventid);
8020
8021 if (ret)
8022 spectral_debug("Unregister WMI event handler failed, ret = %d",
8023 ret);
8024
8025 return QDF_STATUS_SUCCESS;
8026 }
8027
8028 void
target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)8029 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
8030 {
8031 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init =
8032 target_if_pdev_spectral_init;
8033 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit =
8034 target_if_pdev_spectral_deinit;
8035 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init =
8036 target_if_psoc_spectral_init;
8037 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit =
8038 target_if_psoc_spectral_deinit;
8039 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config =
8040 target_if_set_spectral_config;
8041 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config =
8042 target_if_get_spectral_config;
8043 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan =
8044 target_if_start_spectral_scan;
8045 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan =
8046 target_if_stop_spectral_scan;
8047 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active =
8048 target_if_is_spectral_active;
8049 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled =
8050 target_if_is_spectral_enabled;
8051 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level =
8052 target_if_set_debug_level;
8053 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level =
8054 target_if_get_debug_level;
8055 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo =
8056 target_if_get_spectral_capinfo;
8057 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats =
8058 target_if_get_spectral_diagstats;
8059 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops =
8060 target_if_register_spectral_wmi_ops;
8061 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops =
8062 target_if_register_spectral_tgt_ops;
8063 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb =
8064 target_if_register_netlink_cb;
8065 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast =
8066 target_if_use_nl_bcast;
8067 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb =
8068 target_if_deregister_netlink_cb;
8069 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report =
8070 target_if_process_spectral_report;
8071 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support =
8072 target_if_spectral_direct_dma_support;
8073 tx_ops->sptrl_tx_ops.sptrlto_register_events =
8074 target_if_spectral_register_events;
8075 tx_ops->sptrl_tx_ops.sptrlto_unregister_events =
8076 target_if_spectral_unregister_events;
8077 tx_ops->sptrl_tx_ops.sptrlto_init_pdev_feature_caps =
8078 target_if_spectral_init_pdev_feature_caps;
8079
8080 target_if_sptrl_debug_register_tx_ops(tx_ops);
8081 }
8082 qdf_export_symbol(target_if_sptrl_register_tx_ops);
8083
8084 void
target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev * pdev,uint16_t cw_int,uint32_t dcs_enabled)8085 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev,
8086 uint16_t cw_int, uint32_t dcs_enabled)
8087 {
8088 struct spectral_samp_msg *msg = NULL;
8089 struct target_if_spectral_ops *p_sops = NULL;
8090 struct target_if_spectral *spectral = NULL;
8091
8092 spectral = get_target_if_spectral_handle_from_pdev(pdev);
8093
8094 if (!spectral) {
8095 spectral_err("SPECTRAL : Module doesn't exist");
8096 return;
8097 }
8098
8099 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
8100 if (!p_sops) {
8101 spectral_err("p_sops is null");
8102 return;
8103 }
8104
8105 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff(
8106 spectral->pdev_obj,
8107 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION,
8108 SPECTRAL_MSG_BUF_NEW);
8109
8110 if (msg) {
8111 msg->int_type = cw_int ?
8112 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI;
8113 msg->dcs_enabled = dcs_enabled;
8114 msg->signature = SPECTRAL_SIGNATURE;
8115 p_sops->get_mac_address(spectral, msg->macaddr);
8116 if (spectral->send_phy_data
8117 (pdev,
8118 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0)
8119 spectral->spectral_sent_msg++;
8120 }
8121 }
8122 qdf_export_symbol(target_if_spectral_send_intf_found_msg);
8123
8124 QDF_STATUS
target_if_spectral_is_finite_scan(struct target_if_spectral * spectral,enum spectral_scan_mode smode,bool * finite_spectral_scan)8125 target_if_spectral_is_finite_scan(struct target_if_spectral *spectral,
8126 enum spectral_scan_mode smode,
8127 bool *finite_spectral_scan)
8128 {
8129 struct target_if_finite_spectral_scan_params *finite_scan;
8130
8131 if (!spectral) {
8132 spectral_err_rl("target if spectral object is null");
8133 return QDF_STATUS_E_INVAL;
8134 }
8135
8136 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
8137 spectral_err_rl("invalid spectral mode %d", smode);
8138 return QDF_STATUS_E_INVAL;
8139 }
8140
8141 if (!finite_spectral_scan) {
8142 spectral_err_rl("Invalid pointer");
8143 return QDF_STATUS_E_INVAL;
8144 }
8145
8146 finite_scan = &spectral->finite_scan[smode];
8147 *finite_spectral_scan = finite_scan->finite_spectral_scan;
8148
8149 return QDF_STATUS_SUCCESS;
8150 }
8151
8152 QDF_STATUS
target_if_spectral_finite_scan_update(struct target_if_spectral * spectral,enum spectral_scan_mode smode)8153 target_if_spectral_finite_scan_update(struct target_if_spectral *spectral,
8154 enum spectral_scan_mode smode)
8155 {
8156 struct target_if_finite_spectral_scan_params *finite_scan;
8157
8158 if (!spectral) {
8159 spectral_err_rl("target if spectral object is null");
8160 return QDF_STATUS_E_INVAL;
8161 }
8162
8163 if (smode >= SPECTRAL_SCAN_MODE_MAX) {
8164 spectral_err_rl("Invalid Spectral mode");
8165 return QDF_STATUS_E_INVAL;
8166 }
8167
8168 finite_scan = &spectral->finite_scan[smode];
8169
8170 if (!finite_scan->num_reports_expected) {
8171 spectral_err_rl("Error, No reports expected");
8172 return QDF_STATUS_E_FAILURE;
8173 }
8174
8175 finite_scan->num_reports_expected--;
8176 if (!finite_scan->num_reports_expected) {
8177 QDF_STATUS status;
8178 enum spectral_cp_error_code err;
8179
8180 /* received expected number of reports from target, stop scan */
8181 status = target_if_stop_spectral_scan(spectral->pdev_obj, smode,
8182 &err);
8183 if (QDF_IS_STATUS_ERROR(status)) {
8184 spectral_err_rl("Failed to stop finite Spectral scan");
8185 return QDF_STATUS_E_FAILURE;
8186 }
8187 finite_scan->finite_spectral_scan = false;
8188 }
8189
8190 return QDF_STATUS_SUCCESS;
8191 }
8192