1 /*
2 * Copyright (c) 2011,2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 *
6 * Permission to use, copy, modify, and/or distribute this software for
7 * any purpose with or without fee is hereby granted, provided that the
8 * above copyright notice and this permission notice appear in all
9 * copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18 * PERFORMANCE OF THIS SOFTWARE.
19 */
20
21 #include "spectral_cmn_api_i.h"
22 #include "spectral_ol_api_i.h"
23 #include <qdf_mem.h>
24 #include <qdf_types.h>
25 #include <wlan_spectral_public_structs.h>
26 #include <wlan_cfg80211_spectral.h>
27 #include <cfg_ucfg_api.h>
28
29 /**
30 * spectral_get_vdev() - Get pointer to vdev to be used for Spectral
31 * operations
32 * @pdev: Pointer to pdev
33 * @vdev_id: vdev_id
34 *
35 * Spectral operates on pdev. However, in order to retrieve some WLAN
36 * properties, a vdev is required. To facilitate this, the function returns the
37 * first vdev in our pdev. The caller should release the reference to the vdev
38 * once it is done using it. Additionally, the caller should ensure it has a
39 * reference to the pdev at the time of calling this function, and should
40 * release the pdev reference either after this function returns or at a later
41 * time when the caller is done using pdev.
42 * TODO:
43 * - If the framework later provides an API to obtain the first active
44 * vdev, then it would be preferable to use this API.
45 * - Use a common get_vdev() handler for core and target_if using Rx ops. This
46 * is deferred till details emerge on framework providing API to get first
47 * active vdev.
48 *
49 * Return: Pointer to vdev on success, NULL on failure
50 */
51 static struct wlan_objmgr_vdev*
spectral_get_vdev(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)52 spectral_get_vdev(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
53 {
54 struct wlan_objmgr_vdev *vdev = NULL;
55
56 if (!pdev) {
57 spectral_err("pdev is null");
58 return NULL;
59 }
60
61 if (vdev_id == WLAN_INVALID_VDEV_ID)
62 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID);
63 else
64 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
65 WLAN_SPECTRAL_ID);
66 if (!vdev) {
67 spectral_warn("Unable to get first vdev of pdev");
68 return NULL;
69 }
70
71 return vdev;
72 }
73
74 #ifdef SPECTRAL_MODULIZED_ENABLE
75 /**
76 * spectral_register_cfg80211_handlers() - Register spectral cfg80211 handlers
77 * @pdev: Pointer to pdev
78 *
79 * Register spectral cfg80211 handlers
80 * Handlers can be different depending on whether spectral modulized or not
81 *
82 * Return: None
83 */
84 static void
spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev * pdev)85 spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
86 {
87 struct spectral_cfg80211_vendor_cmd_handlers handlers = {0};
88
89 handlers.wlan_cfg80211_spectral_scan_start =
90 wlan_cfg80211_spectral_scan_config_and_start;
91 handlers.wlan_cfg80211_spectral_scan_stop =
92 wlan_cfg80211_spectral_scan_stop;
93 handlers.wlan_cfg80211_spectral_scan_get_config =
94 wlan_cfg80211_spectral_scan_get_config;
95 handlers.wlan_cfg80211_spectral_scan_get_diag_stats =
96 wlan_cfg80211_spectral_scan_get_diag_stats;
97 handlers.wlan_cfg80211_spectral_scan_get_cap =
98 wlan_cfg80211_spectral_scan_get_cap;
99 handlers.wlan_cfg80211_spectral_scan_get_status =
100 wlan_cfg80211_spectral_scan_get_status;
101
102 wlan_cfg80211_register_spectral_cmd_handler(pdev, &handlers);
103 }
104 #else
105 static void
spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev * pdev)106 spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
107 {
108 }
109 #endif
110
111 QDF_STATUS
spectral_control_cmn(struct wlan_objmgr_pdev * pdev,struct spectral_cp_request * sscan_req)112 spectral_control_cmn(struct wlan_objmgr_pdev *pdev,
113 struct spectral_cp_request *sscan_req)
114 {
115 QDF_STATUS status = QDF_STATUS_E_FAILURE;
116 int temp_debug;
117 struct spectral_config sp_out;
118 struct spectral_config *sp_in;
119 struct spectral_config *spectralparams;
120 struct spectral_context *sc;
121 struct wlan_objmgr_vdev *vdev = NULL;
122 uint8_t vdev_rxchainmask = 0;
123 enum spectral_scan_mode smode = sscan_req->ss_mode;
124 enum spectral_cp_error_code *err;
125 QDF_STATUS ret;
126 struct spectral_cp_param param;
127
128 if (!pdev) {
129 spectral_err("PDEV is NULL!");
130 goto bad;
131 }
132 sc = spectral_get_spectral_ctx_from_pdev(pdev);
133 if (!sc) {
134 spectral_err("Spectral context is NULL!");
135 goto bad;
136 }
137
138 switch (sscan_req->req_id) {
139 case SPECTRAL_SET_CONFIG:
140 err = &sscan_req->config_req.sscan_err_code;
141 sp_in = &sscan_req->config_req.sscan_config;
142 if (sp_in->ss_count != SPECTRAL_PHYERR_PARAM_NOVAL) {
143 param.id = SPECTRAL_PARAM_SCAN_COUNT;
144 param.value = sp_in->ss_count;
145 ret = sc->sptrlc_set_spectral_config
146 (pdev, ¶m, smode, err);
147 if (QDF_IS_STATUS_ERROR(ret))
148 goto bad;
149 }
150
151 if (sp_in->ss_fft_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
152 param.id = SPECTRAL_PARAM_FFT_PERIOD;
153 param.value = sp_in->ss_fft_period;
154 ret = sc->sptrlc_set_spectral_config
155 (pdev, ¶m, smode, err);
156 if (QDF_IS_STATUS_ERROR(ret))
157 goto bad;
158 }
159
160 if (sp_in->ss_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
161 param.id = SPECTRAL_PARAM_SCAN_PERIOD;
162 param.value = sp_in->ss_period;
163 ret = sc->sptrlc_set_spectral_config
164 (pdev, ¶m, smode, err);
165 if (QDF_IS_STATUS_ERROR(ret))
166 goto bad;
167 }
168
169 if (sp_in->ss_recapture != SPECTRAL_PHYERR_PARAM_NOVAL) {
170 param.id = SPECTRAL_PARAM_FFT_RECAPTURE;
171 param.value = sp_in->ss_recapture;
172 ret = sc->sptrlc_set_spectral_config
173 (pdev, ¶m, smode, err);
174 if (QDF_IS_STATUS_ERROR(ret))
175 goto bad;
176 }
177
178 if (sp_in->ss_short_report != SPECTRAL_PHYERR_PARAM_NOVAL) {
179 param.id = SPECTRAL_PARAM_SHORT_REPORT;
180 param.value = (uint32_t)sp_in->ss_short_report ? 1 : 0;
181 ret = sc->sptrlc_set_spectral_config
182 (pdev, ¶m, smode, err);
183 if (QDF_IS_STATUS_ERROR(ret))
184 goto bad;
185 }
186
187 if (sp_in->ss_spectral_pri != SPECTRAL_PHYERR_PARAM_NOVAL) {
188 param.id = SPECTRAL_PARAM_SPECT_PRI;
189 param.value = (uint32_t)sp_in->ss_spectral_pri;
190 ret = sc->sptrlc_set_spectral_config
191 (pdev, ¶m, smode, err);
192 if (QDF_IS_STATUS_ERROR(ret))
193 goto bad;
194 }
195
196 if (sp_in->ss_fft_size != SPECTRAL_PHYERR_PARAM_NOVAL) {
197 param.id = SPECTRAL_PARAM_FFT_SIZE;
198 param.value = sp_in->ss_fft_size;
199 ret = sc->sptrlc_set_spectral_config
200 (pdev, ¶m, smode, err);
201 if (QDF_IS_STATUS_ERROR(ret))
202 goto bad;
203 }
204
205 if (sp_in->ss_gc_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
206 param.id = SPECTRAL_PARAM_GC_ENA;
207 param.value = sp_in->ss_gc_ena;
208 ret = sc->sptrlc_set_spectral_config
209 (pdev, ¶m, smode, err);
210 if (QDF_IS_STATUS_ERROR(ret))
211 goto bad;
212 }
213
214 if (sp_in->ss_restart_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
215 param.id = SPECTRAL_PARAM_RESTART_ENA;
216 param.value = sp_in->ss_restart_ena;
217 ret = sc->sptrlc_set_spectral_config
218 (pdev, ¶m, smode, err);
219 if (QDF_IS_STATUS_ERROR(ret))
220 goto bad;
221 }
222
223 if (sp_in->ss_noise_floor_ref != SPECTRAL_PHYERR_PARAM_NOVAL) {
224 param.id = SPECTRAL_PARAM_NOISE_FLOOR_REF;
225 param.value = sp_in->ss_noise_floor_ref;
226 ret = sc->sptrlc_set_spectral_config
227 (pdev, ¶m, smode, err);
228 if (QDF_IS_STATUS_ERROR(ret))
229 goto bad;
230 }
231
232 if (sp_in->ss_init_delay != SPECTRAL_PHYERR_PARAM_NOVAL) {
233 param.id = SPECTRAL_PARAM_INIT_DELAY;
234 param.value = sp_in->ss_init_delay;
235 ret = sc->sptrlc_set_spectral_config
236 (pdev, ¶m, smode, err);
237 if (QDF_IS_STATUS_ERROR(ret))
238 goto bad;
239 }
240
241 if (sp_in->ss_nb_tone_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
242 param.id = SPECTRAL_PARAM_NB_TONE_THR;
243 param.value = sp_in->ss_nb_tone_thr;
244 ret = sc->sptrlc_set_spectral_config
245 (pdev, ¶m, smode, err);
246 if (QDF_IS_STATUS_ERROR(ret))
247 goto bad;
248 }
249
250 if (sp_in->ss_str_bin_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
251 param.id = SPECTRAL_PARAM_STR_BIN_THR;
252 param.value = sp_in->ss_str_bin_thr;
253 ret = sc->sptrlc_set_spectral_config
254 (pdev, ¶m, smode, err);
255 if (QDF_IS_STATUS_ERROR(ret))
256 goto bad;
257 }
258
259 if (sp_in->ss_wb_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
260 param.id = SPECTRAL_PARAM_WB_RPT_MODE;
261 param.value = sp_in->ss_wb_rpt_mode;
262 ret = sc->sptrlc_set_spectral_config
263 (pdev, ¶m, smode, err);
264 if (QDF_IS_STATUS_ERROR(ret))
265 goto bad;
266 }
267
268 if (sp_in->ss_rssi_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
269 param.id = SPECTRAL_PARAM_RSSI_RPT_MODE;
270 param.value = sp_in->ss_rssi_rpt_mode;
271 ret = sc->sptrlc_set_spectral_config
272 (pdev, ¶m, smode, err);
273 if (QDF_IS_STATUS_ERROR(ret))
274 goto bad;
275 }
276
277 if (sp_in->ss_rssi_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
278 param.id = SPECTRAL_PARAM_RSSI_THR;
279 param.value = sp_in->ss_rssi_thr;
280 ret = sc->sptrlc_set_spectral_config
281 (pdev, ¶m, smode, err);
282 if (QDF_IS_STATUS_ERROR(ret))
283 goto bad;
284 }
285
286 if (sp_in->ss_pwr_format != SPECTRAL_PHYERR_PARAM_NOVAL) {
287 param.id = SPECTRAL_PARAM_PWR_FORMAT;
288 param.value = sp_in->ss_pwr_format;
289 ret = sc->sptrlc_set_spectral_config
290 (pdev, ¶m, smode, err);
291 if (QDF_IS_STATUS_ERROR(ret))
292 goto bad;
293 }
294
295 if (sp_in->ss_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
296 param.id = SPECTRAL_PARAM_RPT_MODE;
297 param.value = sp_in->ss_rpt_mode;
298 ret = sc->sptrlc_set_spectral_config
299 (pdev, ¶m, smode, err);
300 if (QDF_IS_STATUS_ERROR(ret))
301 goto bad;
302 }
303
304 if (sp_in->ss_bin_scale != SPECTRAL_PHYERR_PARAM_NOVAL) {
305 param.id = SPECTRAL_PARAM_BIN_SCALE;
306 param.value = sp_in->ss_bin_scale;
307 ret = sc->sptrlc_set_spectral_config
308 (pdev, ¶m, smode, err);
309 if (QDF_IS_STATUS_ERROR(ret))
310 goto bad;
311 }
312
313 if (sp_in->ss_dbm_adj != SPECTRAL_PHYERR_PARAM_NOVAL) {
314 param.id = SPECTRAL_PARAM_DBM_ADJ;
315 param.value = sp_in->ss_dbm_adj;
316 ret = sc->sptrlc_set_spectral_config
317 (pdev, ¶m, smode, err);
318 if (QDF_IS_STATUS_ERROR(ret))
319 goto bad;
320 }
321
322 if (sp_in->ss_chn_mask != SPECTRAL_PHYERR_PARAM_NOVAL) {
323 /*
324 * Check if any of the inactive Rx antenna
325 * chains is set active in spectral chainmask
326 */
327 vdev = spectral_get_vdev(pdev, sscan_req->vdev_id);
328 if (!vdev)
329 goto bad;
330
331 vdev_rxchainmask =
332 wlan_vdev_mlme_get_rxchainmask(vdev);
333 wlan_objmgr_vdev_release_ref(vdev,
334 WLAN_SPECTRAL_ID);
335
336 if (!(sp_in->ss_chn_mask & vdev_rxchainmask)) {
337 spectral_err("Invalid Spectral Chainmask - Inactive Rx antenna chain cannot be an active spectral chain");
338 goto bad;
339 } else {
340 param.id = SPECTRAL_PARAM_CHN_MASK;
341 param.value = sp_in->ss_chn_mask;
342 ret = sc->sptrlc_set_spectral_config
343 (pdev, ¶m, smode, err);
344 if (QDF_IS_STATUS_ERROR(ret))
345 goto bad;
346 }
347 }
348
349 if (sp_in->ss_frequency.cfreq1 != SPECTRAL_PHYERR_PARAM_NOVAL) {
350 param.id = SPECTRAL_PARAM_FREQUENCY;
351 param.freq.cfreq1 = sp_in->ss_frequency.cfreq1;
352 param.freq.cfreq2 = sp_in->ss_frequency.cfreq2;
353 ret = sc->sptrlc_set_spectral_config
354 (pdev, ¶m, smode, err);
355 if (QDF_IS_STATUS_ERROR(ret))
356 goto bad;
357 }
358
359 if (sp_in->ss_bandwidth != SPECTRAL_PHYERR_PARAM_NOVAL) {
360 param.id = SPECTRAL_PARAM_CHAN_WIDTH;
361 param.value = sp_in->ss_bandwidth;
362 ret = sc->sptrlc_set_spectral_config
363 (pdev, ¶m, smode, err);
364 if (QDF_IS_STATUS_ERROR(ret))
365 goto bad;
366 }
367
368 break;
369
370 case SPECTRAL_GET_CONFIG:
371 sc->sptrlc_get_spectral_config(pdev, &sp_out, smode);
372 spectralparams = &sscan_req->config_req.sscan_config;
373 spectralparams->ss_fft_period = sp_out.ss_fft_period;
374 spectralparams->ss_period = sp_out.ss_period;
375 spectralparams->ss_recapture = sp_out.ss_recapture;
376 spectralparams->ss_count = sp_out.ss_count;
377 spectralparams->ss_short_report =
378 sp_out.ss_short_report;
379 spectralparams->ss_spectral_pri =
380 sp_out.ss_spectral_pri;
381 spectralparams->ss_fft_size = sp_out.ss_fft_size;
382 spectralparams->ss_gc_ena = sp_out.ss_gc_ena;
383 spectralparams->ss_restart_ena = sp_out.ss_restart_ena;
384 spectralparams->ss_noise_floor_ref =
385 sp_out.ss_noise_floor_ref;
386 spectralparams->ss_init_delay = sp_out.ss_init_delay;
387 spectralparams->ss_nb_tone_thr = sp_out.ss_nb_tone_thr;
388 spectralparams->ss_str_bin_thr = sp_out.ss_str_bin_thr;
389 spectralparams->ss_wb_rpt_mode = sp_out.ss_wb_rpt_mode;
390 spectralparams->ss_rssi_rpt_mode =
391 sp_out.ss_rssi_rpt_mode;
392 spectralparams->ss_rssi_thr = sp_out.ss_rssi_thr;
393 spectralparams->ss_pwr_format = sp_out.ss_pwr_format;
394 spectralparams->ss_rpt_mode = sp_out.ss_rpt_mode;
395 spectralparams->ss_bin_scale = sp_out.ss_bin_scale;
396 spectralparams->ss_dbm_adj = sp_out.ss_dbm_adj;
397 spectralparams->ss_chn_mask = sp_out.ss_chn_mask;
398 spectralparams->ss_frequency = sp_out.ss_frequency;
399 spectralparams->ss_bandwidth = sp_out.ss_bandwidth;
400 break;
401
402 case SPECTRAL_IS_ACTIVE:
403 sscan_req->status_req.is_active =
404 sc->sptrlc_is_spectral_active(pdev,
405 smode);
406 break;
407
408 case SPECTRAL_IS_ENABLED:
409 sscan_req->status_req.is_enabled =
410 sc->sptrlc_is_spectral_enabled(pdev,
411 smode);
412 break;
413
414 case SPECTRAL_SET_DEBUG_LEVEL:
415 temp_debug = sscan_req->debug_req.spectral_dbg_level;
416 sc->sptrlc_set_debug_level(pdev, temp_debug);
417 break;
418
419 case SPECTRAL_GET_DEBUG_LEVEL:
420 sscan_req->debug_req.spectral_dbg_level =
421 sc->sptrlc_get_debug_level(pdev);
422 break;
423
424 case SPECTRAL_ACTIVATE_SCAN:
425 err = &sscan_req->action_req.sscan_err_code;
426 ret = sc->sptrlc_start_spectral_scan(pdev, sscan_req->vdev_id,
427 smode, err);
428 if (QDF_IS_STATUS_ERROR(ret))
429 goto bad;
430 break;
431
432 case SPECTRAL_STOP_SCAN:
433 err = &sscan_req->action_req.sscan_err_code;
434 ret = sc->sptrlc_stop_spectral_scan(pdev, smode, err);
435 if (QDF_IS_STATUS_ERROR(ret))
436 goto bad;
437 break;
438
439 case SPECTRAL_GET_CAPABILITY_INFO:
440 {
441 struct spectral_caps *caps;
442
443 caps = &sscan_req->caps_req.sscan_caps;
444 ret = sc->sptrlc_get_spectral_capinfo(pdev, caps);
445 if (QDF_IS_STATUS_ERROR(ret))
446 goto bad;
447 }
448 break;
449
450 case SPECTRAL_GET_DIAG_STATS:
451 {
452 struct spectral_diag_stats *diag;
453
454 diag = &sscan_req->diag_req.sscan_diag;
455 ret = sc->sptrlc_get_spectral_diagstats(pdev, diag);
456 if (QDF_IS_STATUS_ERROR(ret))
457 goto bad;
458 }
459 break;
460
461 case SPECTRAL_GET_CHAN_WIDTH:
462 {
463 uint32_t chan_width;
464
465 vdev = spectral_get_vdev(pdev, sscan_req->vdev_id);
466 if (!vdev)
467 goto bad;
468
469 chan_width = spectral_vdev_get_ch_width(vdev);
470 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
471
472 sscan_req->chan_width_req.chan_width =
473 (uint32_t)chan_width;
474 }
475 break;
476
477 case SPECTRAL_SET_DMA_DEBUG:
478 if (sc->sptrlc_set_dma_debug)
479 sc->sptrlc_set_dma_debug(
480 pdev,
481 sscan_req->dma_debug_req.dma_debug_type,
482 sscan_req->dma_debug_req.dma_debug_enable);
483 break;
484
485 default:
486 goto bad;
487 break;
488 }
489
490 status = QDF_STATUS_SUCCESS;
491 bad:
492 return status;
493 }
494
495 /**
496 * spectral_ctx_deinit() - De-initialize function pointers from spectral context
497 * @sc: Reference to spectral_context object
498 *
499 * Return: None
500 */
501 static void
spectral_ctx_deinit(struct spectral_context * sc)502 spectral_ctx_deinit(struct spectral_context *sc)
503 {
504 if (sc) {
505 sc->sptrlc_ucfg_phyerr_config = NULL;
506 sc->sptrlc_pdev_spectral_init = NULL;
507 sc->sptrlc_pdev_spectral_deinit = NULL;
508 sc->sptrlc_psoc_spectral_init = NULL;
509 sc->sptrlc_psoc_spectral_deinit = NULL;
510 sc->sptrlc_set_spectral_config = NULL;
511 sc->sptrlc_get_spectral_config = NULL;
512 sc->sptrlc_start_spectral_scan = NULL;
513 sc->sptrlc_stop_spectral_scan = NULL;
514 sc->sptrlc_is_spectral_active = NULL;
515 sc->sptrlc_is_spectral_enabled = NULL;
516 sc->sptrlc_set_debug_level = NULL;
517 sc->sptrlc_get_debug_level = NULL;
518 sc->sptrlc_get_spectral_capinfo = NULL;
519 sc->sptrlc_get_spectral_diagstats = NULL;
520 }
521 }
522
523 QDF_STATUS
wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc * psoc,void * arg)524 wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
525 {
526 struct spectral_context *sc = NULL;
527 QDF_STATUS status;
528
529 if (!psoc) {
530 spectral_err("PSOC is NULL");
531 return QDF_STATUS_E_FAILURE;
532 }
533
534 status = wlan_spectral_init_psoc_feature_cap(psoc);
535 if (QDF_IS_STATUS_ERROR(status)) {
536 spectral_err("Failed to initialize spectral pdev feature caps");
537 return QDF_STATUS_E_FAILURE;
538 }
539
540 if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
541 spectral_info("Spectral feature is disabled");
542 return QDF_STATUS_COMP_DISABLED;
543 }
544
545 sc = (struct spectral_context *)
546 qdf_mem_malloc(sizeof(struct spectral_context));
547 if (!sc)
548 return QDF_STATUS_E_NOMEM;
549
550 qdf_mem_zero(sc, sizeof(struct spectral_context));
551 sc->psoc_obj = psoc;
552 if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_OL)
553 spectral_ctx_init_ol(sc);
554 wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_SPECTRAL,
555 (void *)sc, QDF_STATUS_SUCCESS);
556
557 return QDF_STATUS_SUCCESS;
558 }
559
560 QDF_STATUS
wlan_spectral_psoc_obj_destroy_handler(struct wlan_objmgr_psoc * psoc,void * arg)561 wlan_spectral_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc,
562 void *arg)
563 {
564 struct spectral_context *sc = NULL;
565
566 if (!psoc) {
567 spectral_err("PSOC is NULL");
568 return QDF_STATUS_E_FAILURE;
569 }
570
571 if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
572 spectral_info("Spectral feature is disabled");
573 return QDF_STATUS_COMP_DISABLED;
574 }
575
576 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
577 WLAN_UMAC_COMP_SPECTRAL);
578 if (sc) {
579 wlan_objmgr_psoc_component_obj_detach(psoc,
580 WLAN_UMAC_COMP_SPECTRAL,
581 (void *)sc);
582 /* Deinitilise function pointers from spectral context */
583 spectral_ctx_deinit(sc);
584 qdf_mem_free(sc);
585 }
586
587 return QDF_STATUS_SUCCESS;
588 }
589
590 QDF_STATUS
wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev * pdev,void * arg)591 wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
592 {
593 struct pdev_spectral *ps = NULL;
594 struct spectral_context *sc = NULL;
595 void *target_handle = NULL;
596 QDF_STATUS status;
597
598 if (!pdev) {
599 spectral_err("PDEV is NULL");
600 return QDF_STATUS_E_FAILURE;
601 }
602
603 status = wlan_spectral_init_pdev_feature_caps(pdev);
604 if (QDF_IS_STATUS_ERROR(status)) {
605 spectral_err("Failed to initialize spectral pdev feature caps");
606 return QDF_STATUS_E_FAILURE;
607 }
608
609 if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
610 spectral_info("Spectral feature is disabled");
611 return QDF_STATUS_COMP_DISABLED;
612 }
613
614 ps = (struct pdev_spectral *)
615 qdf_mem_malloc(sizeof(struct pdev_spectral));
616 if (!ps)
617 return QDF_STATUS_E_NOMEM;
618
619 sc = spectral_get_spectral_ctx_from_pdev(pdev);
620 if (!sc) {
621 spectral_err("Spectral context is NULL!");
622 goto cleanup;
623 }
624
625 qdf_mem_zero(ps, sizeof(struct pdev_spectral));
626 ps->psptrl_pdev = pdev;
627
628 spectral_register_cfg80211_handlers(pdev);
629 if (sc->sptrlc_pdev_spectral_init) {
630 target_handle = sc->sptrlc_pdev_spectral_init(pdev);
631 if (!target_handle) {
632 spectral_err("Spectral lmac object is NULL!");
633 goto cleanup;
634 }
635 ps->psptrl_target_handle = target_handle;
636 }
637 wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_SPECTRAL,
638 (void *)ps, QDF_STATUS_SUCCESS);
639
640 return QDF_STATUS_SUCCESS;
641 cleanup:
642 qdf_mem_free(ps);
643 return QDF_STATUS_E_FAILURE;
644 }
645
646 QDF_STATUS
wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev * pdev,void * arg)647 wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
648 void *arg)
649 {
650 struct pdev_spectral *ps = NULL;
651 struct spectral_context *sc = NULL;
652
653 if (!pdev) {
654 spectral_err("PDEV is NULL");
655 return QDF_STATUS_E_FAILURE;
656 }
657
658 if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
659 spectral_info("Spectral feature is disabled");
660 return QDF_STATUS_COMP_DISABLED;
661 }
662
663 sc = spectral_get_spectral_ctx_from_pdev(pdev);
664 if (!sc) {
665 spectral_err("Spectral context is NULL!");
666 return QDF_STATUS_E_FAILURE;
667 }
668 ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
669 WLAN_UMAC_COMP_SPECTRAL);
670 if (ps) {
671 if (sc->sptrlc_pdev_spectral_deinit)
672 sc->sptrlc_pdev_spectral_deinit(pdev);
673 ps->psptrl_target_handle = NULL;
674 wlan_objmgr_pdev_component_obj_detach(pdev,
675 WLAN_UMAC_COMP_SPECTRAL,
676 (void *)ps);
677 qdf_mem_free(ps);
678 }
679
680 return QDF_STATUS_SUCCESS;
681 }
682