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