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