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