1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-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 <wlan_spectral_utils_api.h> 22 #include <qdf_module.h> 23 #include "../../core/spectral_cmn_api_i.h" 24 #include <wlan_spectral_tgt_api.h> 25 #include <cfg_ucfg_api.h> 26 wlan_spectral_is_mode_disabled_pdev(struct wlan_objmgr_pdev * pdev,enum spectral_scan_mode smode)27 bool wlan_spectral_is_mode_disabled_pdev(struct wlan_objmgr_pdev *pdev, 28 enum spectral_scan_mode smode) 29 { 30 bool spectral_mode_disable; 31 32 if (!pdev) { 33 spectral_err("pdev is NULL!"); 34 return true; 35 } 36 37 switch (smode) { 38 case SPECTRAL_SCAN_MODE_NORMAL: 39 spectral_mode_disable = wlan_pdev_nif_feat_ext_cap_get( 40 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS); 41 break; 42 43 case SPECTRAL_SCAN_MODE_AGILE: 44 spectral_mode_disable = wlan_pdev_nif_feat_ext_cap_get( 45 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS) && 46 wlan_pdev_nif_feat_ext_cap_get( 47 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS) && 48 wlan_pdev_nif_feat_ext_cap_get( 49 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS) && 50 wlan_pdev_nif_feat_ext_cap_get( 51 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS); 52 break; 53 54 default: 55 spectral_err("Invalid Spectral scan mode %d", smode); 56 spectral_mode_disable = true; 57 break; 58 } 59 60 return spectral_mode_disable; 61 } 62 63 bool wlan_spectral_is_feature_disabled_ini(struct wlan_objmgr_psoc * psoc)64 wlan_spectral_is_feature_disabled_ini(struct wlan_objmgr_psoc *psoc) 65 { 66 if (!psoc) { 67 spectral_err("PSOC is NULL!"); 68 return true; 69 } 70 71 return wlan_psoc_nif_feat_cap_get(psoc, 72 WLAN_SOC_F_SPECTRAL_INI_DISABLE); 73 } 74 75 bool wlan_spectral_is_feature_disabled_psoc(struct wlan_objmgr_psoc * psoc)76 wlan_spectral_is_feature_disabled_psoc(struct wlan_objmgr_psoc *psoc) 77 { 78 if (!psoc) { 79 spectral_err("psoc is NULL!"); 80 return true; 81 } 82 83 return wlan_spectral_is_feature_disabled_ini(psoc); 84 } 85 86 bool wlan_spectral_is_feature_disabled_pdev(struct wlan_objmgr_pdev * pdev)87 wlan_spectral_is_feature_disabled_pdev(struct wlan_objmgr_pdev *pdev) 88 { 89 enum spectral_scan_mode smode; 90 91 if (!pdev) { 92 spectral_err("pdev is NULL!"); 93 return true; 94 } 95 96 smode = SPECTRAL_SCAN_MODE_NORMAL; 97 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 98 if (!wlan_spectral_is_mode_disabled_pdev(pdev, smode)) 99 return false; 100 101 return true; 102 } 103 104 QDF_STATUS wlan_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev * pdev)105 wlan_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev *pdev) 106 { 107 return tgt_spectral_init_pdev_feature_caps(pdev); 108 } 109 110 QDF_STATUS wlan_spectral_init_psoc_feature_cap(struct wlan_objmgr_psoc * psoc)111 wlan_spectral_init_psoc_feature_cap(struct wlan_objmgr_psoc *psoc) 112 { 113 if (!psoc) { 114 spectral_err("PSOC is NULL!"); 115 return QDF_STATUS_E_INVAL; 116 } 117 118 if (cfg_get(psoc, CFG_SPECTRAL_DISABLE)) 119 wlan_psoc_nif_feat_cap_set(psoc, 120 WLAN_SOC_F_SPECTRAL_INI_DISABLE); 121 else 122 wlan_psoc_nif_feat_cap_clear(psoc, 123 WLAN_SOC_F_SPECTRAL_INI_DISABLE); 124 125 return QDF_STATUS_SUCCESS; 126 } 127 128 QDF_STATUS wlan_spectral_init(void)129 wlan_spectral_init(void) 130 { 131 if (wlan_objmgr_register_psoc_create_handler( 132 WLAN_UMAC_COMP_SPECTRAL, 133 wlan_spectral_psoc_obj_create_handler, 134 NULL) != 135 QDF_STATUS_SUCCESS) { 136 return QDF_STATUS_E_FAILURE; 137 } 138 if (wlan_objmgr_register_psoc_destroy_handler( 139 WLAN_UMAC_COMP_SPECTRAL, 140 wlan_spectral_psoc_obj_destroy_handler, 141 NULL) != 142 QDF_STATUS_SUCCESS) { 143 return QDF_STATUS_E_FAILURE; 144 } 145 if (wlan_objmgr_register_pdev_create_handler( 146 WLAN_UMAC_COMP_SPECTRAL, 147 wlan_spectral_pdev_obj_create_handler, 148 NULL) != 149 QDF_STATUS_SUCCESS) { 150 return QDF_STATUS_E_FAILURE; 151 } 152 if (wlan_objmgr_register_pdev_destroy_handler( 153 WLAN_UMAC_COMP_SPECTRAL, 154 wlan_spectral_pdev_obj_destroy_handler, 155 NULL) != 156 QDF_STATUS_SUCCESS) { 157 return QDF_STATUS_E_FAILURE; 158 } 159 160 return QDF_STATUS_SUCCESS; 161 } 162 163 QDF_STATUS wlan_spectral_deinit(void)164 wlan_spectral_deinit(void) 165 { 166 if (wlan_objmgr_unregister_psoc_create_handler( 167 WLAN_UMAC_COMP_SPECTRAL, 168 wlan_spectral_psoc_obj_create_handler, 169 NULL) != 170 QDF_STATUS_SUCCESS) { 171 return QDF_STATUS_E_FAILURE; 172 } 173 if (wlan_objmgr_unregister_psoc_destroy_handler( 174 WLAN_UMAC_COMP_SPECTRAL, 175 wlan_spectral_psoc_obj_destroy_handler, 176 NULL) != 177 QDF_STATUS_SUCCESS) { 178 return QDF_STATUS_E_FAILURE; 179 } 180 if (wlan_objmgr_unregister_pdev_create_handler( 181 WLAN_UMAC_COMP_SPECTRAL, 182 wlan_spectral_pdev_obj_create_handler, 183 NULL) != 184 QDF_STATUS_SUCCESS) { 185 return QDF_STATUS_E_FAILURE; 186 } 187 if (wlan_objmgr_unregister_pdev_destroy_handler( 188 WLAN_UMAC_COMP_SPECTRAL, 189 wlan_spectral_pdev_obj_destroy_handler, 190 NULL) != 191 QDF_STATUS_SUCCESS) { 192 return QDF_STATUS_E_FAILURE; 193 } 194 return QDF_STATUS_SUCCESS; 195 } 196 197 QDF_STATUS spectral_register_legacy_cb(struct wlan_objmgr_psoc * psoc,struct spectral_legacy_cbacks * legacy_cbacks)198 spectral_register_legacy_cb(struct wlan_objmgr_psoc *psoc, 199 struct spectral_legacy_cbacks *legacy_cbacks) 200 { 201 struct spectral_context *sc; 202 203 if (!psoc) { 204 spectral_err("psoc is null"); 205 return QDF_STATUS_E_INVAL; 206 } 207 208 if (wlan_spectral_is_feature_disabled_psoc(psoc)) { 209 spectral_info("Spectral feature is disabled"); 210 return QDF_STATUS_COMP_DISABLED; 211 } 212 213 sc = spectral_get_spectral_ctx_from_psoc(psoc); 214 if (!sc) { 215 spectral_err("Invalid Context"); 216 return QDF_STATUS_E_FAILURE; 217 } 218 219 sc->legacy_cbacks.vdev_get_chan_freq = 220 legacy_cbacks->vdev_get_chan_freq; 221 sc->legacy_cbacks.vdev_get_chan_freq_seg2 = 222 legacy_cbacks->vdev_get_chan_freq_seg2; 223 sc->legacy_cbacks.vdev_get_ch_width = legacy_cbacks->vdev_get_ch_width; 224 sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz = 225 legacy_cbacks->vdev_get_sec20chan_freq_mhz; 226 227 return QDF_STATUS_SUCCESS; 228 } 229 qdf_export_symbol(spectral_register_legacy_cb); 230 231 int16_t spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev * vdev)232 spectral_vdev_get_chan_freq(struct wlan_objmgr_vdev *vdev) 233 { 234 struct spectral_context *sc; 235 236 sc = spectral_get_spectral_ctx_from_vdev(vdev); 237 if (!sc) { 238 spectral_err("spectral context is Null"); 239 return -EINVAL; 240 } 241 242 if (!sc->legacy_cbacks.vdev_get_chan_freq) { 243 spectral_err("vdev_get_chan_freq is not supported"); 244 return -ENOTSUPP; 245 } 246 247 return sc->legacy_cbacks.vdev_get_chan_freq(vdev); 248 } 249 250 int16_t spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev * vdev)251 spectral_vdev_get_chan_freq_seg2(struct wlan_objmgr_vdev *vdev) 252 { 253 struct spectral_context *sc; 254 struct wlan_channel *des_chan; 255 256 sc = spectral_get_spectral_ctx_from_vdev(vdev); 257 if (!sc) { 258 spectral_err("spectral context is null"); 259 return -EINVAL; 260 } 261 262 if (!sc->legacy_cbacks.vdev_get_chan_freq_seg2) { 263 des_chan = wlan_vdev_mlme_get_des_chan(vdev); 264 if (des_chan->ch_width == CH_WIDTH_80P80MHZ) 265 return des_chan->ch_freq_seg2; 266 else 267 return 0; 268 } 269 270 return sc->legacy_cbacks.vdev_get_chan_freq_seg2(vdev); 271 } 272 273 enum phy_ch_width spectral_vdev_get_ch_width(struct wlan_objmgr_vdev * vdev)274 spectral_vdev_get_ch_width(struct wlan_objmgr_vdev *vdev) 275 { 276 struct spectral_context *sc; 277 278 sc = spectral_get_spectral_ctx_from_vdev(vdev); 279 if (!sc) { 280 spectral_err("spectral context is Null"); 281 return CH_WIDTH_INVALID; 282 } 283 284 if (!sc->legacy_cbacks.vdev_get_ch_width) { 285 spectral_err("vdev_get_ch_width is not supported"); 286 return -ENOTSUPP; 287 } 288 289 return sc->legacy_cbacks.vdev_get_ch_width(vdev); 290 } 291 292 int spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev * vdev,uint16_t * sec20chan_freq)293 spectral_vdev_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev, 294 uint16_t *sec20chan_freq) 295 { 296 struct spectral_context *sc; 297 298 sc = spectral_get_spectral_ctx_from_vdev(vdev); 299 if (!sc) { 300 spectral_err("spectral context is Null"); 301 return -EINVAL; 302 } 303 304 if (!sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz) { 305 spectral_err("vdev_get_sec20chan_freq_mhz is not supported"); 306 return -ENOTSUPP; 307 } 308 309 return sc->legacy_cbacks.vdev_get_sec20chan_freq_mhz(vdev, 310 sec20chan_freq); 311 } 312 313 void wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)314 wlan_lmac_if_sptrl_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 315 { 316 struct wlan_lmac_if_sptrl_rx_ops *sptrl_rx_ops = &rx_ops->sptrl_rx_ops; 317 318 /* Spectral rx ops */ 319 sptrl_rx_ops->sptrlro_get_pdev_target_handle = 320 tgt_get_pdev_target_handle; 321 sptrl_rx_ops->sptrlro_get_psoc_target_handle = 322 tgt_get_psoc_target_handle; 323 sptrl_rx_ops->sptrlro_vdev_get_chan_freq = spectral_vdev_get_chan_freq; 324 sptrl_rx_ops->sptrlro_vdev_get_chan_freq_seg2 = 325 spectral_vdev_get_chan_freq_seg2; 326 sptrl_rx_ops->sptrlro_vdev_get_ch_width = spectral_vdev_get_ch_width; 327 sptrl_rx_ops->sptrlro_vdev_get_sec20chan_freq_mhz = 328 spectral_vdev_get_sec20chan_freq_mhz; 329 sptrl_rx_ops->sptrlro_spectral_is_feature_disabled_pdev = 330 wlan_spectral_is_feature_disabled_pdev; 331 sptrl_rx_ops->sptrlro_spectral_is_feature_disabled_psoc = 332 wlan_spectral_is_feature_disabled_psoc; 333 } 334 335 QDF_STATUS wlan_register_spectral_wmi_ops(struct wlan_objmgr_psoc * psoc,struct spectral_wmi_ops * wmi_ops)336 wlan_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 337 struct spectral_wmi_ops *wmi_ops) 338 { 339 struct spectral_context *sc; 340 341 if (!psoc) { 342 spectral_err("psoc is NULL!"); 343 return QDF_STATUS_E_INVAL; 344 } 345 346 if (wlan_spectral_is_feature_disabled_psoc(psoc)) { 347 spectral_info("Spectral feature is disabled"); 348 return QDF_STATUS_COMP_DISABLED; 349 } 350 351 sc = spectral_get_spectral_ctx_from_psoc(psoc); 352 if (!sc) { 353 spectral_err("spectral context is NULL!"); 354 return QDF_STATUS_E_FAILURE; 355 } 356 357 return sc->sptrlc_register_spectral_wmi_ops(psoc, wmi_ops); 358 } 359 360 qdf_export_symbol(wlan_register_spectral_wmi_ops); 361 362 QDF_STATUS wlan_register_spectral_tgt_ops(struct wlan_objmgr_psoc * psoc,struct spectral_tgt_ops * tgt_ops)363 wlan_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 364 struct spectral_tgt_ops *tgt_ops) 365 { 366 struct spectral_context *sc; 367 368 if (!psoc) { 369 spectral_err("psoc is NULL!"); 370 return QDF_STATUS_E_INVAL; 371 } 372 373 if (wlan_spectral_is_feature_disabled_psoc(psoc)) { 374 spectral_info("Spectral feature is disabled"); 375 return QDF_STATUS_COMP_DISABLED; 376 } 377 378 sc = spectral_get_spectral_ctx_from_psoc(psoc); 379 if (!sc) { 380 spectral_err("spectral context is NULL!"); 381 return QDF_STATUS_E_FAILURE; 382 } 383 384 return sc->sptrlc_register_spectral_tgt_ops(psoc, tgt_ops); 385 } 386 387 qdf_export_symbol(wlan_register_spectral_tgt_ops); 388 389 /** 390 * wlan_spectral_psoc_target_attach() - Spectral psoc target attach 391 * @psoc: pointer to psoc object 392 * 393 * API to initialize Spectral psoc target object 394 * 395 * Return: QDF_STATUS_SUCCESS upon successful registration, 396 * QDF_STATUS_E_FAILURE upon failure 397 */ 398 static QDF_STATUS wlan_spectral_psoc_target_attach(struct wlan_objmgr_psoc * psoc)399 wlan_spectral_psoc_target_attach(struct wlan_objmgr_psoc *psoc) 400 { 401 struct spectral_context *sc = NULL; 402 403 if (!psoc) { 404 spectral_err("psoc is null"); 405 return QDF_STATUS_E_FAILURE; 406 } 407 408 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 409 WLAN_UMAC_COMP_SPECTRAL); 410 if (!sc) { 411 spectral_err("Spectral context is null"); 412 return QDF_STATUS_E_NOMEM; 413 } 414 415 if (sc->sptrlc_psoc_spectral_init) { 416 void *target_handle; 417 418 target_handle = sc->sptrlc_psoc_spectral_init(psoc); 419 if (!target_handle) { 420 spectral_err("Spectral psoc lmac object is NULL!"); 421 return QDF_STATUS_E_FAILURE; 422 } 423 sc->psoc_target_handle = target_handle; 424 } 425 426 return QDF_STATUS_SUCCESS; 427 } 428 429 /** 430 * wlan_spectral_psoc_target_detach() - Spectral psoc target detach 431 * @psoc: pointer to psoc object 432 * 433 * API to destroy Spectral psoc target object 434 * 435 * Return: QDF_STATUS_SUCCESS upon successful registration, 436 * QDF_STATUS_E_FAILURE upon failure 437 */ 438 static QDF_STATUS wlan_spectral_psoc_target_detach(struct wlan_objmgr_psoc * psoc)439 wlan_spectral_psoc_target_detach(struct wlan_objmgr_psoc *psoc) 440 { 441 struct spectral_context *sc = NULL; 442 443 if (!psoc) { 444 spectral_err("psoc is null"); 445 return QDF_STATUS_E_FAILURE; 446 } 447 448 sc = wlan_objmgr_psoc_get_comp_private_obj(psoc, 449 WLAN_UMAC_COMP_SPECTRAL); 450 if (!sc) { 451 spectral_err("Spectral context is null"); 452 return QDF_STATUS_E_INVAL; 453 } 454 455 if (sc->sptrlc_psoc_spectral_deinit) 456 sc->sptrlc_psoc_spectral_deinit(psoc); 457 sc->psoc_target_handle = NULL; 458 459 return QDF_STATUS_SUCCESS; 460 } 461 462 #ifdef DIRECT_BUF_RX_ENABLE spectral_dbr_event_handler(struct wlan_objmgr_pdev * pdev,struct direct_buf_rx_data * payload)463 bool spectral_dbr_event_handler(struct wlan_objmgr_pdev *pdev, 464 struct direct_buf_rx_data *payload) 465 { 466 struct spectral_context *sc; 467 468 if (!pdev) { 469 spectral_err("PDEV is NULL!"); 470 return -EINVAL; 471 } 472 sc = spectral_get_spectral_ctx_from_pdev(pdev); 473 if (!sc) { 474 spectral_err("spectral context is NULL!"); 475 return -EINVAL; 476 } 477 478 sc->sptrlc_process_spectral_report(pdev, payload); 479 480 return true; 481 } 482 #endif 483 spectral_pdev_open(struct wlan_objmgr_pdev * pdev)484 QDF_STATUS spectral_pdev_open(struct wlan_objmgr_pdev *pdev) 485 { 486 struct wlan_objmgr_psoc *psoc; 487 QDF_STATUS status; 488 489 psoc = wlan_pdev_get_psoc(pdev); 490 491 if (wlan_spectral_is_feature_disabled_pdev(pdev)) { 492 spectral_info("Spectral feature is disabled"); 493 return QDF_STATUS_COMP_DISABLED; 494 } 495 496 if (cfg_get(psoc, CFG_SPECTRAL_POISON_BUFS)) 497 tgt_set_spectral_dma_debug(pdev, SPECTRAL_DMA_BUFFER_DEBUG, 1); 498 499 status = spectral_register_dbr(pdev); 500 return status; 501 } 502 spectral_register_dbr(struct wlan_objmgr_pdev * pdev)503 QDF_STATUS spectral_register_dbr(struct wlan_objmgr_pdev *pdev) 504 { 505 if (wlan_spectral_is_feature_disabled_pdev(pdev)) { 506 spectral_info("spectral feature is disabled"); 507 return QDF_STATUS_COMP_DISABLED; 508 } 509 510 return tgt_spectral_register_to_dbr(pdev); 511 } 512 513 qdf_export_symbol(spectral_register_dbr); 514 spectral_unregister_dbr(struct wlan_objmgr_pdev * pdev)515 QDF_STATUS spectral_unregister_dbr(struct wlan_objmgr_pdev *pdev) 516 { 517 QDF_STATUS status; 518 519 if (wlan_spectral_is_feature_disabled_pdev(pdev)) { 520 spectral_info("spectral feature is disabled"); 521 return QDF_STATUS_COMP_DISABLED; 522 } 523 status = tgt_spectral_unregister_to_dbr(pdev); 524 525 return status; 526 } 527 528 qdf_export_symbol(spectral_unregister_dbr); 529 wlan_spectral_psoc_open(struct wlan_objmgr_psoc * psoc)530 QDF_STATUS wlan_spectral_psoc_open(struct wlan_objmgr_psoc *psoc) 531 { 532 if (!psoc) { 533 spectral_err("psoc is null"); 534 return QDF_STATUS_E_INVAL; 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 return wlan_spectral_psoc_target_attach(psoc); 543 } 544 wlan_spectral_psoc_close(struct wlan_objmgr_psoc * psoc)545 QDF_STATUS wlan_spectral_psoc_close(struct wlan_objmgr_psoc *psoc) 546 { 547 if (!psoc) { 548 spectral_err("psoc is null"); 549 return QDF_STATUS_E_INVAL; 550 } 551 552 if (wlan_spectral_is_feature_disabled_psoc(psoc)) { 553 spectral_info("Spectral feature is disabled"); 554 return QDF_STATUS_COMP_DISABLED; 555 } 556 557 return wlan_spectral_psoc_target_detach(psoc); 558 } 559 wlan_spectral_psoc_enable(struct wlan_objmgr_psoc * psoc)560 QDF_STATUS wlan_spectral_psoc_enable(struct wlan_objmgr_psoc *psoc) 561 { 562 if (!psoc) { 563 spectral_err("psoc is null"); 564 return QDF_STATUS_E_INVAL; 565 } 566 567 if (wlan_spectral_is_feature_disabled_psoc(psoc)) { 568 spectral_info("Spectral feature is disabled"); 569 return QDF_STATUS_COMP_DISABLED; 570 } 571 572 return tgt_spectral_register_events(psoc); 573 } 574 wlan_spectral_psoc_disable(struct wlan_objmgr_psoc * psoc)575 QDF_STATUS wlan_spectral_psoc_disable(struct wlan_objmgr_psoc *psoc) 576 { 577 if (!psoc) { 578 spectral_err("psoc is null"); 579 return QDF_STATUS_E_INVAL; 580 } 581 582 if (wlan_spectral_is_feature_disabled_psoc(psoc)) { 583 spectral_info("Spectral feature is disabled"); 584 return QDF_STATUS_COMP_DISABLED; 585 } 586 587 return tgt_spectral_unregister_events(psoc); 588 } 589 590 struct wlan_lmac_if_sptrl_tx_ops * wlan_spectral_pdev_get_lmac_if_txops(struct wlan_objmgr_pdev * pdev)591 wlan_spectral_pdev_get_lmac_if_txops(struct wlan_objmgr_pdev *pdev) 592 { 593 struct wlan_objmgr_psoc *psoc; 594 struct wlan_lmac_if_tx_ops *tx_ops; 595 596 if (!pdev) { 597 spectral_err("pdev is NULL!"); 598 return NULL; 599 } 600 601 psoc = wlan_pdev_get_psoc(pdev); 602 if (!psoc) { 603 spectral_err("psoc is NULL!"); 604 return NULL; 605 } 606 607 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 608 if (!tx_ops) { 609 spectral_err("tx_ops is NULL"); 610 return NULL; 611 } 612 613 return &tx_ops->sptrl_tx_ops; 614 } 615