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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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, &param, 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