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