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