1 /* 2 * Copyright (c) 2011,2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 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_tgt_def_config.h> 21 #include <hif.h> 22 #include <target_type.h> 23 #include <hif_hw_version.h> 24 #include <wmi_unified_api.h> 25 #include <target_if_spectral.h> 26 #include <wlan_lmac_if_def.h> 27 #include <wlan_osif_priv.h> 28 #include <init_deinit_lmac.h> 29 #include <reg_services_public_struct.h> 30 #include <target_if_spectral_sim.h> 31 #include <target_if.h> 32 #include <qdf_module.h> 33 #include <wlan_reg_services_api.h> 34 #include <wlan_dfs_ucfg_api.h> 35 36 /** 37 * @spectral_ops - Spectral function table, holds the Spectral functions that 38 * depend on whether the architecture is Direct Attach or Offload. This is used 39 * to populate the actual Spectral function table present in the Spectral 40 * module. 41 */ 42 struct target_if_spectral_ops spectral_ops; 43 int spectral_debug_level = DEBUG_SPECTRAL; 44 struct spectral_tgt_ops ops_tgt; 45 46 #ifdef SPECTRAL_MODULIZED_ENABLE 47 /** 48 * target_if_spectral_wmi_service_enabled() - API to check whether a 49 * given WMI service is enabled 50 * @psoc: Pointer to psoc 51 * @wmi_handle: WMI handle 52 * @service_id: service id 53 * 54 * Return: true or false 55 */ 56 static 57 bool target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc *psoc, 58 wmi_unified_t wmi_handle, 59 uint32_t service_id) 60 { 61 struct target_if_psoc_spectral *psoc_spectral; 62 63 if (!psoc) { 64 spectral_err("psoc is null"); 65 return false; 66 } 67 68 if (!wmi_handle) { 69 spectral_err("wmi handle is null"); 70 return false; 71 } 72 73 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 74 if (!psoc_spectral) { 75 spectral_err("psoc spectral object is null"); 76 return false; 77 } 78 79 return psoc_spectral->wmi_ops.wmi_service_enabled(wmi_handle, 80 service_id); 81 } 82 #else 83 /** 84 * target_if_spectral_wmi_service_enabled() - API to check whether a 85 * given WMI service is enabled 86 * @psoc: Pointer to psoc 87 * @wmi_handle: WMI handle 88 * @service_id: service id 89 * 90 * Return: true or false 91 */ 92 static 93 bool target_if_spectral_wmi_service_enabled(struct wlan_objmgr_psoc *psoc, 94 wmi_unified_t wmi_handle, 95 uint32_t service_id) 96 { 97 return wmi_service_enabled(wmi_handle, service_id); 98 } 99 #endif /* SPECTRAL_MODULIZED_ENABLE */ 100 101 struct target_if_spectral *get_target_if_spectral_handle_from_pdev( 102 struct wlan_objmgr_pdev *pdev) 103 { 104 struct target_if_spectral *spectral; 105 struct wlan_objmgr_psoc *psoc; 106 struct wlan_lmac_if_rx_ops *rx_ops; 107 108 if (!pdev) { 109 spectral_err("pdev is null"); 110 return NULL; 111 } 112 113 psoc = wlan_pdev_get_psoc(pdev); 114 if (!psoc) { 115 spectral_err("psoc is null"); 116 return NULL; 117 } 118 119 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 120 if (!rx_ops) { 121 spectral_err("rx_ops is null"); 122 return NULL; 123 } 124 125 spectral = (struct target_if_spectral *) 126 rx_ops->sptrl_rx_ops.sptrlro_get_pdev_target_handle(pdev); 127 128 return spectral; 129 } 130 131 qdf_export_symbol(get_target_if_spectral_handle_from_pdev); 132 133 /** 134 * target_if_spectral_get_normal_mode_cap() - API to get normal 135 * Spectral scan capability of a given pdev 136 * @pdev: pdev handle 137 * @normal_mode_disable: Pointer to caller variable 138 * 139 * API to get normal Spectral scan mode capability a given pdev. 140 * This information is derived from the WMI service 141 * "WMI_SERVICE_SPECTRAL_SCAN_DISABLED". 142 * 143 * Return: QDF_STATUS on success 144 */ 145 static QDF_STATUS 146 target_if_spectral_get_normal_mode_cap(struct wlan_objmgr_pdev *pdev, 147 bool *normal_mode_disable) 148 { 149 struct wlan_objmgr_psoc *psoc; 150 struct wmi_unified *wmi_handle; 151 struct target_if_psoc_spectral *psoc_spectral; 152 153 if (!pdev) { 154 spectral_err("pdev is null"); 155 return QDF_STATUS_E_INVAL; 156 } 157 158 psoc = wlan_pdev_get_psoc(pdev); 159 if (!psoc) { 160 spectral_err("psoc is null"); 161 return QDF_STATUS_E_INVAL; 162 } 163 164 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 165 if (!psoc_spectral) { 166 spectral_err("psoc spectral object is null"); 167 return QDF_STATUS_E_INVAL; 168 } 169 170 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 171 if (!wmi_handle) { 172 spectral_err("wmi handle is null"); 173 return QDF_STATUS_E_INVAL; 174 } 175 176 *normal_mode_disable = target_if_spectral_wmi_service_enabled(psoc, 177 wmi_handle, wmi_service_spectral_scan_disabled); 178 179 return QDF_STATUS_SUCCESS; 180 } 181 182 /** 183 * target_if_spectral_get_agile_mode_cap() - API to check agile 184 * Spectral scan mode capability of a given pdev. 185 * @pdev: pdev handle 186 * @agile_cap: Pointer to caller variable 187 * 188 * API to check agile Spectral scan mode is disabled for a given pdev. 189 * This information is derived from the chain mask table entries. 190 * 191 * Return: QDF_STATUS on success 192 */ 193 static QDF_STATUS 194 target_if_spectral_get_agile_mode_cap( 195 struct wlan_objmgr_pdev *pdev, 196 struct target_if_spectral_agile_mode_cap *agile_cap) 197 { 198 struct wlan_objmgr_psoc *psoc; 199 struct target_psoc_info *tgt_psoc_info; 200 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr; 201 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap; 202 uint8_t pdev_id, i; 203 uint32_t table_id; 204 struct wlan_psoc_host_service_ext_param *ext_svc_param; 205 struct wlan_psoc_host_chainmask_table *table; 206 struct wmi_unified *wmi_handle; 207 208 if (!pdev) { 209 spectral_err("pdev is null"); 210 return QDF_STATUS_E_INVAL; 211 } 212 213 psoc = wlan_pdev_get_psoc(pdev); 214 if (!psoc) { 215 spectral_err("psoc is null"); 216 return QDF_STATUS_E_FAILURE; 217 } 218 219 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 220 if (!wmi_handle) { 221 spectral_err("wmi handle is null"); 222 return QDF_STATUS_E_INVAL; 223 } 224 225 /* Agile Spectral is disabled for legacy targets */ 226 if (!target_if_spectral_wmi_service_enabled(psoc, wmi_handle, 227 wmi_service_ext_msg)) { 228 agile_cap->agile_spectral_cap = false; 229 agile_cap->agile_spectral_cap_160 = false; 230 agile_cap->agile_spectral_cap_80p80 = false; 231 agile_cap->agile_spectral_cap_320 = false; 232 233 return QDF_STATUS_SUCCESS; 234 } 235 236 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 237 if (!tgt_psoc_info) { 238 spectral_err("target_psoc_info is null"); 239 return QDF_STATUS_E_FAILURE; 240 } 241 242 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 243 if (!mac_phy_cap_arr) { 244 spectral_err("mac phy cap array is null"); 245 return QDF_STATUS_E_FAILURE; 246 } 247 248 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 249 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 250 table_id = mac_phy_cap->chainmask_table_id; 251 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 252 if (!ext_svc_param) { 253 spectral_err("Extended service ready params null"); 254 return QDF_STATUS_E_FAILURE; 255 } 256 257 table = &ext_svc_param->chainmask_table[table_id]; 258 259 for (i = 0; i < table->num_valid_chainmasks; i++) { 260 agile_cap->agile_spectral_cap |= 261 table->cap_list[i].supports_aSpectral; 262 agile_cap->agile_spectral_cap_160 |= 263 table->cap_list[i].supports_aSpectral_160; 264 agile_cap->agile_spectral_cap_320 |= 0; 265 } 266 267 agile_cap->agile_spectral_cap_80p80 = agile_cap->agile_spectral_cap_160; 268 269 return QDF_STATUS_SUCCESS; 270 } 271 272 /** 273 * target_if_spectral_init_pdev_feature_cap_per_mode() - API to initialize 274 * Spectral scan pdev feature caps for a given Spectral mode 275 * @pdev: pdev handle 276 * @smode: Spectral scan mode 277 * 278 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE/ 279 * QDF_STATUS_E_INVAL on failure 280 */ 281 static QDF_STATUS 282 target_if_spectral_init_pdev_feature_cap_per_mode(struct wlan_objmgr_pdev *pdev, 283 enum spectral_scan_mode smode) 284 { 285 struct wlan_objmgr_psoc *psoc; 286 bool normal_mode_disable; 287 struct target_if_spectral_agile_mode_cap agile_cap = { 0 }; 288 QDF_STATUS status; 289 290 if (!pdev) { 291 spectral_err("pdev is null"); 292 return QDF_STATUS_E_INVAL; 293 } 294 295 psoc = wlan_pdev_get_psoc(pdev); 296 if (!psoc) { 297 spectral_err("psoc is null"); 298 return QDF_STATUS_E_INVAL; 299 } 300 301 switch (smode) { 302 case SPECTRAL_SCAN_MODE_NORMAL: 303 if (target_if_spectral_is_feature_disabled_psoc(psoc)) { 304 wlan_pdev_nif_feat_ext_cap_set( 305 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS); 306 307 return QDF_STATUS_SUCCESS; 308 } 309 310 status = target_if_spectral_get_normal_mode_cap( 311 pdev, &normal_mode_disable); 312 if (QDF_IS_STATUS_ERROR(status)) { 313 spectral_err("Failed to get normal spectral scan caps"); 314 return QDF_STATUS_E_FAILURE; 315 } 316 317 if (normal_mode_disable) 318 wlan_pdev_nif_feat_ext_cap_set( 319 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS); 320 else 321 wlan_pdev_nif_feat_ext_cap_clear( 322 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS); 323 break; 324 325 case SPECTRAL_SCAN_MODE_AGILE: 326 if (target_if_spectral_is_feature_disabled_psoc(psoc)) { 327 wlan_pdev_nif_feat_ext_cap_set( 328 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS); 329 wlan_pdev_nif_feat_ext_cap_set( 330 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS); 331 wlan_pdev_nif_feat_ext_cap_set( 332 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS); 333 wlan_pdev_nif_feat_ext_cap_set( 334 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS); 335 336 return QDF_STATUS_SUCCESS; 337 } 338 status = target_if_spectral_get_agile_mode_cap( 339 pdev, &agile_cap); 340 if (QDF_IS_STATUS_ERROR(status)) { 341 spectral_err("Failed to get agile Spectral capability"); 342 return QDF_STATUS_E_FAILURE; 343 } 344 345 if (!agile_cap.agile_spectral_cap) 346 wlan_pdev_nif_feat_ext_cap_set( 347 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS); 348 else 349 wlan_pdev_nif_feat_ext_cap_clear( 350 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS); 351 352 if (!agile_cap.agile_spectral_cap_160) 353 wlan_pdev_nif_feat_ext_cap_set( 354 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS); 355 else 356 wlan_pdev_nif_feat_ext_cap_clear( 357 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS); 358 359 if (!agile_cap.agile_spectral_cap_80p80) 360 wlan_pdev_nif_feat_ext_cap_set( 361 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS); 362 else 363 wlan_pdev_nif_feat_ext_cap_clear( 364 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS); 365 366 if (!agile_cap.agile_spectral_cap_320) 367 wlan_pdev_nif_feat_ext_cap_set( 368 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS); 369 else 370 wlan_pdev_nif_feat_ext_cap_clear( 371 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS); 372 373 break; 374 375 default: 376 spectral_err("Invalid Spectral scan mode %d", smode); 377 return QDF_STATUS_E_INVAL; 378 } 379 380 return QDF_STATUS_SUCCESS; 381 } 382 383 /** 384 * target_if_spectral_init_pdev_feature_caps() - API to initialize 385 * Spectral scan pdev feature caps for a given pdev 386 * @pdev: pdev handle 387 * 388 * API initialize normal and agile Spectral scan pdev 389 * feature caps for a given pdev. 390 * 391 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure 392 */ 393 static QDF_STATUS 394 target_if_spectral_init_pdev_feature_caps(struct wlan_objmgr_pdev *pdev) 395 { 396 enum spectral_scan_mode smode; 397 398 if (!pdev) { 399 spectral_err("pdev is NULL!"); 400 return QDF_STATUS_E_INVAL; 401 } 402 403 smode = SPECTRAL_SCAN_MODE_NORMAL; 404 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 405 QDF_STATUS status; 406 407 status = target_if_spectral_init_pdev_feature_cap_per_mode( 408 pdev, smode); 409 if (QDF_IS_STATUS_ERROR(status)) 410 return QDF_STATUS_E_INVAL; 411 } 412 413 return QDF_STATUS_SUCCESS; 414 } 415 416 static void target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev *pdev, 417 void *obj, void *arg) 418 { 419 struct wlan_objmgr_vdev *vdev = obj; 420 struct wlan_objmgr_vdev **first_vdev = arg; 421 422 if (!(*first_vdev)) 423 *first_vdev = vdev; 424 } 425 426 struct wlan_objmgr_vdev * 427 target_if_spectral_get_vdev(struct target_if_spectral *spectral, 428 enum spectral_scan_mode smode) 429 { 430 struct wlan_objmgr_pdev *pdev = NULL; 431 struct wlan_objmgr_vdev *first_vdev = NULL; 432 433 qdf_assert_always(spectral); 434 pdev = spectral->pdev_obj; 435 qdf_assert_always(pdev); 436 437 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 438 spectral_err("Invalid Spectral mode %u", smode); 439 return NULL; 440 } 441 442 if (spectral->vdev_id[smode] != WLAN_INVALID_VDEV_ID) { 443 first_vdev = wlan_objmgr_get_vdev_by_id_from_pdev( 444 pdev, spectral->vdev_id[smode], 445 WLAN_SPECTRAL_ID); 446 return first_vdev; 447 } 448 449 if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) != 450 QDF_STATUS_SUCCESS) { 451 spectral_err("Unable to get pdev reference."); 452 return NULL; 453 } 454 455 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 456 target_if_spectral_get_firstvdev_pdev, 457 &first_vdev, 0, WLAN_SPECTRAL_ID); 458 459 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 460 461 if (!first_vdev) 462 return NULL; 463 464 if (wlan_objmgr_vdev_try_get_ref(first_vdev, WLAN_SPECTRAL_ID) != 465 QDF_STATUS_SUCCESS) 466 first_vdev = NULL; 467 468 return first_vdev; 469 } 470 471 /** 472 * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure 473 * spectral parameters 474 * @spectral: Pointer to Spectral target_if internal private data 475 * @smode: Spectral scan mode 476 * @param: Pointer to spectral_config giving the Spectral configuration 477 * 478 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 479 */ 480 static int 481 target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, 482 enum spectral_scan_mode smode, 483 struct spectral_config *param) 484 { 485 struct vdev_spectral_configure_params sparam; 486 struct wlan_objmgr_psoc *psoc; 487 struct wlan_objmgr_pdev *pdev = NULL; 488 struct wlan_objmgr_vdev *vdev = NULL; 489 struct target_if_psoc_spectral *psoc_spectral; 490 491 qdf_assert_always(spectral); 492 qdf_assert_always(param); 493 494 pdev = spectral->pdev_obj; 495 496 qdf_assert_always(pdev); 497 498 psoc = wlan_pdev_get_psoc(pdev); 499 if (!psoc) { 500 spectral_err("psoc is null"); 501 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 502 } 503 504 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 505 if (!psoc_spectral) { 506 spectral_err("psoc spectral object is null"); 507 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 508 } 509 510 vdev = target_if_spectral_get_vdev(spectral, smode); 511 if (!vdev) 512 return QDF_STATUS_E_NOENT; 513 514 qdf_mem_zero(&sparam, sizeof(sparam)); 515 516 sparam.vdev_id = wlan_vdev_get_id(vdev); 517 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 518 519 sparam.count = param->ss_count; 520 sparam.period = param->ss_period; 521 sparam.fft_recap = param->ss_recapture; 522 sparam.spectral_pri = param->ss_spectral_pri; 523 sparam.fft_size = param->ss_fft_size; 524 sparam.gc_enable = param->ss_gc_ena; 525 sparam.restart_enable = param->ss_restart_ena; 526 sparam.noise_floor_ref = param->ss_noise_floor_ref; 527 sparam.init_delay = param->ss_init_delay; 528 sparam.nb_tone_thr = param->ss_nb_tone_thr; 529 sparam.str_bin_thr = param->ss_str_bin_thr; 530 sparam.wb_rpt_mode = param->ss_wb_rpt_mode; 531 sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode; 532 sparam.rssi_thr = param->ss_rssi_thr; 533 sparam.pwr_format = param->ss_pwr_format; 534 sparam.rpt_mode = param->ss_rpt_mode; 535 sparam.bin_scale = param->ss_bin_scale; 536 sparam.dbm_adj = param->ss_dbm_adj; 537 sparam.chn_mask = param->ss_chn_mask; 538 sparam.mode = smode; 539 sparam.center_freq1 = param->ss_frequency.cfreq1; 540 sparam.center_freq2 = param->ss_frequency.cfreq2; 541 sparam.chan_width = param->ss_bandwidth; 542 543 return psoc_spectral->wmi_ops.wmi_spectral_configure_cmd_send( 544 GET_WMI_HDL_FROM_PDEV(pdev), &sparam); 545 } 546 547 /** 548 * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to 549 * enable/disable Spectral 550 * @spectral: Pointer to Spectral target_if internal private data 551 * @smode: Spectral scan mode 552 * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is 553 * valid 554 * @is_spectral_active: Value of spectral activate 555 * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid 556 * @is_spectral_enabled: Value of spectral enable 557 * 558 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 559 */ 560 static int 561 target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral, 562 enum spectral_scan_mode smode, 563 uint8_t is_spectral_active_valid, 564 uint8_t is_spectral_active, 565 uint8_t is_spectral_enabled_valid, 566 uint8_t is_spectral_enabled) 567 { 568 struct vdev_spectral_enable_params param; 569 struct wlan_objmgr_psoc *psoc; 570 struct wlan_objmgr_pdev *pdev = NULL; 571 struct wlan_objmgr_vdev *vdev = NULL; 572 struct target_if_psoc_spectral *psoc_spectral; 573 574 qdf_assert_always(spectral); 575 576 pdev = spectral->pdev_obj; 577 578 qdf_assert_always(pdev); 579 580 psoc = wlan_pdev_get_psoc(pdev); 581 if (!psoc) { 582 spectral_err("psoc is null"); 583 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 584 } 585 586 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 587 if (!psoc_spectral) { 588 spectral_err("psoc spectral object is null"); 589 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 590 } 591 592 vdev = target_if_spectral_get_vdev(spectral, smode); 593 if (!vdev) 594 return QDF_STATUS_E_NOENT; 595 596 qdf_mem_zero(¶m, sizeof(param)); 597 598 param.vdev_id = wlan_vdev_get_id(vdev); 599 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 600 601 param.active_valid = is_spectral_active_valid; 602 param.enabled_valid = is_spectral_enabled_valid; 603 param.active = is_spectral_active; 604 param.enabled = is_spectral_enabled; 605 param.mode = smode; 606 607 return psoc_spectral->wmi_ops.wmi_spectral_enable_cmd_send( 608 GET_WMI_HDL_FROM_PDEV(pdev), ¶m); 609 } 610 611 /** 612 * is_spectral_arch_beryllium() - Check whether the given target Spectral 613 * architecture is Beryllium 614 * @target_tpe: Target type 615 * 616 * Return: true if the spectral architecture is Beryllium, else false 617 */ 618 static inline bool is_spectral_arch_beryllium(uint32_t target_tpe) 619 { 620 if ((target_tpe == TARGET_TYPE_QCN9224) || 621 (target_tpe == TARGET_TYPE_QCA5332)) 622 return true; 623 624 return false; 625 } 626 627 /** 628 * List of supported sscan BWs. Make sure to maintain the array elements in the 629 * same order of BWs as that of struct spectral_supported_bws bitmap. 630 */ 631 static const enum phy_ch_width supported_sscan_bw_list[] = { 632 CH_WIDTH_5MHZ, 633 CH_WIDTH_10MHZ, 634 CH_WIDTH_20MHZ, 635 CH_WIDTH_40MHZ, 636 CH_WIDTH_80MHZ, 637 CH_WIDTH_160MHZ, 638 CH_WIDTH_80P80MHZ, 639 #ifdef WLAN_FEATURE_11BE 640 CH_WIDTH_320MHZ, 641 #endif 642 }; 643 644 #define INVALID_SSCAN_BW_POS (-1) 645 int get_supported_sscan_bw_pos(enum phy_ch_width sscan_bw) 646 { 647 int max_pos, pos; 648 649 max_pos = QDF_ARRAY_SIZE(supported_sscan_bw_list); 650 for (pos = 0; pos < max_pos; pos++) { 651 if (supported_sscan_bw_list[pos] == sscan_bw) 652 return pos; 653 } 654 655 return INVALID_SSCAN_BW_POS; 656 } 657 658 /** 659 * target_if_is_sscan_bw_supported() - Check whether the given sscan_bw is 660 * supported 661 * @spectral: Spectral LMAC object 662 * @smode: Spectral scan mode 663 * @sscan_bw: Spectral scan bandwidth 664 * @op_bw: operating bandwidth 665 * @is_bw_supported: Pointer to the caller variable where this function 666 * populates whether @sscan_bw is supported 667 * @is_80_80_agile: Indicates an 80+80 agile Scan request 668 * 669 * Return: QDF_STATUS of operation 670 */ 671 static QDF_STATUS 672 target_if_is_sscan_bw_supported(struct target_if_spectral *spectral, 673 enum spectral_scan_mode smode, 674 enum phy_ch_width sscan_bw, 675 enum phy_ch_width op_bw, 676 bool *is_bw_supported, 677 bool is_80_80_agile) 678 { 679 struct spectral_supported_bws *supported_bws; 680 681 *is_bw_supported = false; 682 683 if (op_bw >= CH_WIDTH_INVALID) { 684 spectral_err("Invalid channel width %d", op_bw); 685 return QDF_STATUS_E_INVAL; 686 } 687 688 if ((is_80_80_agile && sscan_bw != CH_WIDTH_80P80MHZ) || 689 (!is_80_80_agile && sscan_bw == CH_WIDTH_80P80MHZ)) { 690 *is_bw_supported = false; 691 return QDF_STATUS_SUCCESS; 692 } 693 694 /* Get the supported sscan bandwidths for this operating bandwidth */ 695 supported_bws = &spectral->supported_bws[smode][op_bw]; 696 *is_bw_supported = supported_bws->bandwidths & 697 (1 << get_supported_sscan_bw_pos(sscan_bw)); 698 699 return QDF_STATUS_SUCCESS; 700 } 701 702 /** 703 * get_max_sscan_bw() - Get the maximum sscan bandwidth for a given operating 704 * bandwidth 705 * @spectral: Spectral LMAC object 706 * @smode: Spectral scan mode 707 * @op_bw: operating bandwidth 708 * 709 * Return: Maximum sscan bandwidth for @op_bw on success, else CH_WIDTH_INVALID 710 */ 711 static enum phy_ch_width 712 get_max_sscan_bw(struct target_if_spectral *spectral, 713 enum spectral_scan_mode smode, 714 enum phy_ch_width op_bw) 715 { 716 int op_bw_pos, pos; 717 struct spectral_supported_bws *supported_bws; 718 719 supported_bws = &spectral->supported_bws[smode][op_bw]; 720 op_bw_pos = get_supported_sscan_bw_pos(op_bw); 721 722 /** 723 * Start with operating bandwidth, and keep reducing the bandwidth until 724 * a supported sscan BW is found. 725 */ 726 for (pos = op_bw_pos; pos >= 0; pos--) { 727 if (supported_bws->bandwidths & (1 << pos)) 728 return supported_sscan_bw_list[pos]; 729 } 730 731 return CH_WIDTH_INVALID; 732 } 733 734 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the 735 * corresponding translation for Agile channel width. 736 * @spectral: pointer to Spectral object 737 * @op_width: operating channel width 738 * @is_80_80_agile: Indicates an 80+80 agile Scan request 739 * 740 * Return: The translated channel width enum. 741 */ 742 static enum phy_ch_width 743 target_if_spectral_find_agile_width(struct target_if_spectral *spectral, 744 enum phy_ch_width op_bw, 745 bool is_80_80_agile) 746 { 747 enum phy_ch_width agile_width; 748 struct wlan_objmgr_pdev *pdev; 749 struct wlan_objmgr_psoc *psoc; 750 751 if (!spectral) { 752 spectral_err("Spectral object is null"); 753 return CH_WIDTH_INVALID; 754 } 755 756 pdev = spectral->pdev_obj; 757 if (!pdev) { 758 spectral_err("pdev is null"); 759 return CH_WIDTH_INVALID; 760 } 761 762 psoc = wlan_pdev_get_psoc(pdev); 763 if (!psoc) { 764 spectral_err("psoc is null"); 765 return CH_WIDTH_INVALID; 766 } 767 768 agile_width = get_max_sscan_bw(spectral, SPECTRAL_SCAN_MODE_AGILE, 769 op_bw); 770 771 if (wlan_psoc_nif_fw_ext_cap_get(psoc, 772 WLAN_SOC_RESTRICTED_80P80_SUPPORT)) { 773 switch (op_bw) { 774 case CH_WIDTH_80P80MHZ: 775 if (!is_80_80_agile) 776 agile_width = CH_WIDTH_160MHZ; 777 else 778 agile_width = CH_WIDTH_80P80MHZ; 779 780 break; 781 782 case CH_WIDTH_160MHZ: 783 if (is_80_80_agile) 784 agile_width = CH_WIDTH_80P80MHZ; 785 else 786 agile_width = CH_WIDTH_160MHZ; 787 788 break; 789 790 default: 791 break; 792 } 793 } 794 795 return agile_width; 796 } 797 798 /** 799 * get_default_sscan_bw() - Get the default sscan bandwidth for a given 800 * operating bandwidth 801 * @spectral: Spectral LMAC object 802 * @smode: Spectral scan mode 803 * @is_80_80_agile: Indicates an 80+80 agile Scan request 804 * 805 * Return: Default sscan bandwidth for @op_bw on success, else CH_WIDTH_INVALID 806 */ 807 static enum phy_ch_width 808 get_default_sscan_bw(struct target_if_spectral *spectral, 809 enum spectral_scan_mode smode, 810 bool is_80_80_agile) 811 { 812 struct wlan_objmgr_vdev *vdev; 813 enum phy_ch_width vdev_ch_width, sscan_width; 814 815 vdev = target_if_spectral_get_vdev(spectral, smode); 816 if (!vdev) { 817 spectral_err("vdev is null"); 818 return CH_WIDTH_INVALID; 819 } 820 821 vdev_ch_width = target_if_vdev_get_ch_width(vdev); 822 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 823 if (vdev_ch_width >= CH_WIDTH_INVALID) { 824 spectral_err("Invalid vdev channel width %d", vdev_ch_width); 825 return CH_WIDTH_INVALID; 826 } 827 828 switch (smode) { 829 case SPECTRAL_SCAN_MODE_NORMAL: 830 sscan_width = get_max_sscan_bw(spectral, smode, vdev_ch_width); 831 break; 832 833 case SPECTRAL_SCAN_MODE_AGILE: 834 sscan_width = target_if_spectral_find_agile_width( 835 spectral, vdev_ch_width, is_80_80_agile); 836 break; 837 838 default: 839 sscan_width = CH_WIDTH_INVALID; 840 break; 841 } 842 843 return sscan_width; 844 } 845 846 /** 847 * target_if_spectral_info_init_defaults() - Helper function to load defaults 848 * for Spectral information (parameters and state) into cache. 849 * @spectral: Pointer to Spectral target_if internal private data 850 * @smode: Spectral scan mode 851 * 852 * It is assumed that the caller has obtained the requisite lock if applicable. 853 * Note that this is currently treated as a temporary function. Ideally, we 854 * would like to get defaults from the firmware. 855 * 856 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 857 */ 858 static QDF_STATUS 859 target_if_spectral_info_init_defaults(struct target_if_spectral *spectral, 860 enum spectral_scan_mode smode) 861 { 862 struct target_if_spectral_param_state_info *info; 863 struct wlan_objmgr_vdev *vdev = NULL; 864 enum phy_ch_width sscan_bw; 865 866 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 867 spectral_err("Invalid Spectral mode %u", smode); 868 return QDF_STATUS_E_FAILURE; 869 } 870 871 info = &spectral->param_info[smode]; 872 873 /* State */ 874 info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT; 875 876 info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT; 877 878 /* Parameters */ 879 info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT; 880 881 if (spectral->spectral_gen == SPECTRAL_GEN3) 882 info->osps_cache.osc_params.ss_period = 883 SPECTRAL_SCAN_PERIOD_GEN_III_DEFAULT; 884 else 885 info->osps_cache.osc_params.ss_period = 886 SPECTRAL_SCAN_PERIOD_GEN_II_DEFAULT; 887 888 info->osps_cache.osc_params.ss_recapture = 889 SPECTRAL_FFT_RECAPTURE_DEFAULT; 890 info->osps_cache.osc_params.ss_spectral_pri = 891 SPECTRAL_SCAN_PRIORITY_DEFAULT; 892 893 info->osps_cache.osc_params.ss_fft_size = 894 SPECTRAL_SCAN_FFT_SIZE_DEFAULT; 895 896 info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT; 897 898 info->osps_cache.osc_params.ss_restart_ena = 899 SPECTRAL_SCAN_RESTART_ENA_DEFAULT; 900 901 info->osps_cache.osc_params.ss_noise_floor_ref = 902 SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT; 903 904 info->osps_cache.osc_params.ss_init_delay = 905 SPECTRAL_SCAN_INIT_DELAY_DEFAULT; 906 907 info->osps_cache.osc_params.ss_nb_tone_thr = 908 SPECTRAL_SCAN_NB_TONE_THR_DEFAULT; 909 910 info->osps_cache.osc_params.ss_str_bin_thr = 911 SPECTRAL_SCAN_STR_BIN_THR_DEFAULT; 912 913 info->osps_cache.osc_params.ss_wb_rpt_mode = 914 SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT; 915 916 info->osps_cache.osc_params.ss_rssi_rpt_mode = 917 SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT; 918 919 info->osps_cache.osc_params.ss_rssi_thr = 920 SPECTRAL_SCAN_RSSI_THR_DEFAULT; 921 922 info->osps_cache.osc_params.ss_pwr_format = 923 SPECTRAL_SCAN_PWR_FORMAT_DEFAULT; 924 925 info->osps_cache.osc_params.ss_rpt_mode = 926 SPECTRAL_SCAN_RPT_MODE_DEFAULT; 927 928 info->osps_cache.osc_params.ss_bin_scale = 929 SPECTRAL_SCAN_BIN_SCALE_DEFAULT; 930 931 info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT; 932 933 vdev = target_if_spectral_get_vdev(spectral, smode); 934 if (!vdev) 935 return QDF_STATUS_E_NOENT; 936 937 info->osps_cache.osc_params.ss_chn_mask = 938 wlan_vdev_mlme_get_rxchainmask(vdev); 939 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 940 941 info->osps_cache.osc_params.ss_short_report = 942 SPECTRAL_SCAN_SHORT_REPORT_DEFAULT; 943 944 info->osps_cache.osc_params.ss_fft_period = 945 SPECTRAL_SCAN_FFT_PERIOD_DEFAULT; 946 947 info->osps_cache.osc_params.ss_frequency.cfreq1 = 948 SPECTRAL_SCAN_FREQUENCY_DEFAULT; 949 info->osps_cache.osc_params.ss_frequency.cfreq2 = 950 SPECTRAL_SCAN_FREQUENCY_DEFAULT; 951 952 sscan_bw = get_default_sscan_bw(spectral, smode, false); 953 if (sscan_bw >= CH_WIDTH_INVALID) { 954 spectral_err("Invalid sscan BW %u", sscan_bw); 955 return QDF_STATUS_E_FAILURE; 956 } 957 info->osps_cache.osc_params.ss_bandwidth = sscan_bw; 958 959 /* The cache is now valid */ 960 info->osps_cache.osc_is_valid = 1; 961 962 return QDF_STATUS_SUCCESS; 963 } 964 965 /** 966 * target_if_log_read_spectral_active() - Helper function to log whether 967 * spectral is active after reading cache 968 * @function_name: Function name 969 * @output: whether spectral is active or not 970 * 971 * Helper function to log whether spectral is active after reading cache 972 * 973 * Return: none 974 */ 975 static void 976 target_if_log_read_spectral_active( 977 const char *function_name, 978 unsigned char output) 979 { 980 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u", 981 function_name, output); 982 } 983 984 /** 985 * target_if_log_read_spectral_enabled() - Helper function to log whether 986 * spectral is enabled after reading cache 987 * @function_name: Function name 988 * @output: whether spectral is enabled or not 989 * 990 * Helper function to log whether spectral is enabled after reading cache 991 * 992 * Return: none 993 */ 994 static void 995 target_if_log_read_spectral_enabled( 996 const char *function_name, 997 unsigned char output) 998 { 999 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u", 1000 function_name, output); 1001 } 1002 1003 /** 1004 * target_if_log_read_spectral_enabled() - Helper function to log spectral 1005 * parameters after reading cache 1006 * @function_name: Function name 1007 * @pparam: Spectral parameters 1008 * 1009 * Helper function to log spectral parameters after reading cache 1010 * 1011 * Return: none 1012 */ 1013 static void 1014 target_if_log_read_spectral_params( 1015 const char *function_name, 1016 struct spectral_config *pparam) 1017 { 1018 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Returning following params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency1=%u\nss_frequency2=%u\n", 1019 function_name, 1020 pparam->ss_count, 1021 pparam->ss_period, 1022 pparam->ss_recapture, 1023 pparam->ss_spectral_pri, 1024 pparam->ss_fft_size, 1025 pparam->ss_gc_ena, 1026 pparam->ss_restart_ena, 1027 (int8_t)pparam->ss_noise_floor_ref, 1028 pparam->ss_init_delay, 1029 pparam->ss_nb_tone_thr, 1030 pparam->ss_str_bin_thr, 1031 pparam->ss_wb_rpt_mode, 1032 pparam->ss_rssi_rpt_mode, 1033 (int8_t)pparam->ss_rssi_thr, 1034 pparam->ss_pwr_format, 1035 pparam->ss_rpt_mode, 1036 pparam->ss_bin_scale, 1037 pparam->ss_dbm_adj, 1038 pparam->ss_chn_mask, 1039 pparam->ss_frequency.cfreq1, 1040 pparam->ss_frequency.cfreq2); 1041 } 1042 1043 /** 1044 * target_if_log_read_spectral_active_catch_validate() - Helper function to 1045 * log whether spectral is active after initializing the cache 1046 * @function_name: Function name 1047 * @output: whether spectral is active or not 1048 * 1049 * Helper function to log whether spectral is active after initializing cache 1050 * 1051 * Return: none 1052 */ 1053 static void 1054 target_if_log_read_spectral_active_catch_validate( 1055 const char *function_name, 1056 unsigned char output) 1057 { 1058 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u", 1059 function_name, output); 1060 } 1061 1062 /** 1063 * target_if_log_read_spectral_enabled_catch_validate() - Helper function to 1064 * log whether spectral is enabled after initializing the cache 1065 * @function_name: Function name 1066 * @output: whether spectral is enabled or not 1067 * 1068 * Helper function to log whether spectral is enabled after initializing cache 1069 * 1070 * Return: none 1071 */ 1072 static void 1073 target_if_log_read_spectral_enabled_catch_validate( 1074 const char *function_name, 1075 unsigned char output) 1076 { 1077 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n", 1078 function_name, output); 1079 } 1080 1081 /** 1082 * target_if_log_read_spectral_params_catch_validate() - Helper function to 1083 * log spectral parameters after initializing the cache 1084 * @function_name: Function name 1085 * @pparam: Spectral parameters 1086 * 1087 * Helper function to log spectral parameters after initializing the cache 1088 * 1089 * Return: none 1090 */ 1091 static void 1092 target_if_log_read_spectral_params_catch_validate( 1093 const char *function_name, 1094 struct spectral_config *pparam) 1095 { 1096 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS on initial cache validation\nReturning following params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u", 1097 function_name, 1098 pparam->ss_count, 1099 pparam->ss_period, 1100 pparam->ss_recapture, 1101 pparam->ss_spectral_pri, 1102 pparam->ss_fft_size, 1103 pparam->ss_gc_ena, 1104 pparam->ss_restart_ena, 1105 (int8_t)pparam->ss_noise_floor_ref, 1106 pparam->ss_init_delay, 1107 pparam->ss_nb_tone_thr, 1108 pparam->ss_str_bin_thr, 1109 pparam->ss_wb_rpt_mode, 1110 pparam->ss_rssi_rpt_mode, 1111 (int8_t)pparam->ss_rssi_thr, 1112 pparam->ss_pwr_format, 1113 pparam->ss_rpt_mode, 1114 pparam->ss_bin_scale, 1115 pparam->ss_dbm_adj, pparam->ss_chn_mask); 1116 } 1117 1118 /** 1119 * target_if_spectral_info_read() - Read spectral information from the cache. 1120 * @spectral: Pointer to Spectral target_if internal private data 1121 * @smode: Spectral scan mode 1122 * @specifier: target_if_spectral_info enumeration specifying which 1123 * information is required 1124 * @output: Void output pointer into which the information will be read 1125 * @output_len: size of object pointed to by output pointer 1126 * 1127 * Read spectral parameters or the desired state information from the cache. 1128 * 1129 * Return: 0 on success, negative error code on failure 1130 */ 1131 static int 1132 target_if_spectral_info_read( 1133 struct target_if_spectral *spectral, 1134 enum spectral_scan_mode smode, 1135 enum target_if_spectral_info specifier, 1136 void *output, int output_len) 1137 { 1138 /* 1139 * Note: This function is designed to be able to accommodate 1140 * WMI reads for defaults, non-cacheable information, etc 1141 * if required. 1142 */ 1143 struct target_if_spectral_param_state_info *info; 1144 int is_cacheable = 0; 1145 int init_def_retval = 0; 1146 1147 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 1148 spectral_err("Invalid Spectral mode %u", smode); 1149 return -EINVAL; 1150 } 1151 info = &spectral->param_info[smode]; 1152 1153 if (!output) 1154 return -EINVAL; 1155 1156 switch (specifier) { 1157 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 1158 if (output_len != sizeof(info->osps_cache.osc_spectral_active)) 1159 return -EINVAL; 1160 is_cacheable = 1; 1161 break; 1162 1163 case TARGET_IF_SPECTRAL_INFO_ENABLED: 1164 if (output_len != sizeof(info->osps_cache.osc_spectral_enabled)) 1165 return -EINVAL; 1166 is_cacheable = 1; 1167 break; 1168 1169 case TARGET_IF_SPECTRAL_INFO_PARAMS: 1170 if (output_len != sizeof(info->osps_cache.osc_params)) 1171 return -EINVAL; 1172 is_cacheable = 1; 1173 break; 1174 1175 default: 1176 spectral_err("Unknown target_if_spectral_info specifier"); 1177 return -EINVAL; 1178 } 1179 1180 qdf_spin_lock_bh(&info->osps_lock); 1181 1182 if (is_cacheable) { 1183 if (info->osps_cache.osc_is_valid) { 1184 switch (specifier) { 1185 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 1186 qdf_mem_copy( 1187 output, 1188 &info->osps_cache.osc_spectral_active, 1189 sizeof(info->osps_cache.osc_spectral_active)); 1190 1191 target_if_log_read_spectral_active( 1192 __func__, 1193 *((unsigned char *)output)); 1194 break; 1195 1196 case TARGET_IF_SPECTRAL_INFO_ENABLED: 1197 qdf_mem_copy( 1198 output, 1199 &info->osps_cache.osc_spectral_enabled, 1200 sizeof( 1201 info->osps_cache.osc_spectral_enabled)); 1202 1203 target_if_log_read_spectral_enabled( 1204 __func__, 1205 *((unsigned char *)output)); 1206 break; 1207 1208 case TARGET_IF_SPECTRAL_INFO_PARAMS: 1209 qdf_mem_copy( 1210 output, 1211 &info->osps_cache.osc_params, 1212 sizeof(info->osps_cache.osc_params)); 1213 1214 target_if_log_read_spectral_params( 1215 __func__, 1216 (struct spectral_config *)output); 1217 break; 1218 1219 default: 1220 /* We can't reach this point */ 1221 break; 1222 } 1223 qdf_spin_unlock_bh(&info->osps_lock); 1224 return 0; 1225 } 1226 } 1227 1228 /* Cache is invalid */ 1229 1230 /* 1231 * If WMI Reads are implemented to fetch defaults/non-cacheable info, 1232 * then the below implementation will change 1233 */ 1234 init_def_retval = 1235 target_if_spectral_info_init_defaults(spectral, smode); 1236 if (init_def_retval != QDF_STATUS_SUCCESS) { 1237 qdf_spin_unlock_bh(&info->osps_lock); 1238 if (init_def_retval == QDF_STATUS_E_NOENT) 1239 return -ENOENT; 1240 else 1241 return -EINVAL; 1242 } 1243 /* target_if_spectral_info_init_defaults() has set cache to valid */ 1244 1245 switch (specifier) { 1246 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 1247 qdf_mem_copy(output, 1248 &info->osps_cache.osc_spectral_active, 1249 sizeof(info->osps_cache.osc_spectral_active)); 1250 1251 target_if_log_read_spectral_active_catch_validate( 1252 __func__, 1253 *((unsigned char *)output)); 1254 break; 1255 1256 case TARGET_IF_SPECTRAL_INFO_ENABLED: 1257 qdf_mem_copy(output, 1258 &info->osps_cache.osc_spectral_enabled, 1259 sizeof(info->osps_cache.osc_spectral_enabled)); 1260 1261 target_if_log_read_spectral_enabled_catch_validate( 1262 __func__, 1263 *((unsigned char *)output)); 1264 break; 1265 1266 case TARGET_IF_SPECTRAL_INFO_PARAMS: 1267 qdf_mem_copy(output, 1268 &info->osps_cache.osc_params, 1269 sizeof(info->osps_cache.osc_params)); 1270 1271 target_if_log_read_spectral_params_catch_validate( 1272 __func__, 1273 (struct spectral_config *)output); 1274 1275 break; 1276 1277 default: 1278 /* We can't reach this point */ 1279 break; 1280 } 1281 1282 qdf_spin_unlock_bh(&info->osps_lock); 1283 1284 return 0; 1285 } 1286 1287 /** 1288 * target_if_log_write_spectral_active() - Helper function to log inputs and 1289 * return value of call to configure the Spectral 'active' configuration, 1290 * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware 1291 * @function_name: Function name in which this is called 1292 * @pval: whether spectral is active or not 1293 * @ret: return value of the firmware write function 1294 * 1295 * Return: none 1296 */ 1297 static void 1298 target_if_log_write_spectral_active( 1299 const char *function_name, 1300 uint8_t pval, 1301 int ret) 1302 { 1303 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d", 1304 function_name, pval, ret); 1305 } 1306 1307 /** 1308 * target_if_log_write_spectral_enabled() - Helper function to log inputs and 1309 * return value of call to configure the Spectral 'enabled' configuration, 1310 * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware 1311 * @function_name: Function name in which this is called 1312 * @pval: whether spectral is enabled or not 1313 * @ret: return value of the firmware write function 1314 * 1315 * Return: none 1316 */ 1317 static void 1318 target_if_log_write_spectral_enabled( 1319 const char *function_name, 1320 uint8_t pval, 1321 int ret) 1322 { 1323 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d", 1324 function_name, pval, ret); 1325 } 1326 1327 /** 1328 * target_if_log_write_spectral_params() - Helper function to log inputs and 1329 * return value of call to configure Spectral parameters, 1330 * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware 1331 * @param: Spectral parameters 1332 * @function_name: Function name in which this is called 1333 * @ret: return value of the firmware write function 1334 * 1335 * Return: none 1336 */ 1337 static void 1338 target_if_log_write_spectral_params( 1339 struct spectral_config *param, 1340 const char *function_name, 1341 int ret) 1342 { 1343 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_PARAMS. Params:\nss_count = %u\nss_period = %u\nss_recapture = %u\nss_spectral_pri = %u\nss_fft_size = %u\nss_gc_ena = %u\nss_restart_ena = %u\nss_noise_floor_ref = %d\nss_init_delay = %u\nss_nb_tone_thr = %u\nss_str_bin_thr = %u\nss_wb_rpt_mode = %u\nss_rssi_rpt_mode = %u\nss_rssi_thr = %d\nss_pwr_format = %u\nss_rpt_mode = %u\nss_bin_scale = %u\nss_dbm_adj = %u\nss_chn_mask = %u\nss_frequency1=%u\nss_frequency2=%u\nstatus = %d", 1344 function_name, 1345 param->ss_count, 1346 param->ss_period, 1347 param->ss_recapture, 1348 param->ss_spectral_pri, 1349 param->ss_fft_size, 1350 param->ss_gc_ena, 1351 param->ss_restart_ena, 1352 (int8_t)param->ss_noise_floor_ref, 1353 param->ss_init_delay, 1354 param->ss_nb_tone_thr, 1355 param->ss_str_bin_thr, 1356 param->ss_wb_rpt_mode, 1357 param->ss_rssi_rpt_mode, 1358 (int8_t)param->ss_rssi_thr, 1359 param->ss_pwr_format, 1360 param->ss_rpt_mode, 1361 param->ss_bin_scale, 1362 param->ss_dbm_adj, 1363 param->ss_chn_mask, 1364 param->ss_frequency.cfreq1, 1365 param->ss_frequency.cfreq2, 1366 ret); 1367 } 1368 1369 /** 1370 * target_if_spectral_info_write() - Write Spectral information to the 1371 * firmware, and update cache 1372 * @spectral: Pointer to Spectral target_if internal private data 1373 * @smode: Spectral scan mode 1374 * @specifier: target_if_spectral_info enumeration specifying which 1375 * information is involved 1376 * @input: void input pointer containing the information to be written 1377 * @input_len: size of object pointed to by input pointer 1378 * 1379 * Write Spectral parameters or the desired state information to 1380 * the firmware, and update cache 1381 * 1382 * Return: 0 on success, negative error code on failure 1383 */ 1384 static int 1385 target_if_spectral_info_write( 1386 struct target_if_spectral *spectral, 1387 enum spectral_scan_mode smode, 1388 enum target_if_spectral_info specifier, 1389 void *input, int input_len) 1390 { 1391 struct target_if_spectral_param_state_info *info; 1392 int ret; 1393 uint8_t *pval = NULL; 1394 struct spectral_config *param = NULL; 1395 1396 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 1397 spectral_err("Invalid Spectral mode %u", smode); 1398 return -EINVAL; 1399 } 1400 info = &spectral->param_info[smode]; 1401 1402 if (!input) 1403 return -EINVAL; 1404 1405 switch (specifier) { 1406 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 1407 if (input_len != sizeof(info->osps_cache.osc_spectral_active)) 1408 return -EINVAL; 1409 1410 pval = (uint8_t *)input; 1411 1412 qdf_spin_lock_bh(&info->osps_lock); 1413 ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode, 1414 1, *pval, 0, 0); 1415 1416 target_if_log_write_spectral_active( 1417 __func__, 1418 *pval, 1419 ret); 1420 1421 if (ret < 0) { 1422 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d", 1423 ret); 1424 qdf_spin_unlock_bh(&info->osps_lock); 1425 return ret; 1426 } 1427 1428 info->osps_cache.osc_spectral_active = *pval; 1429 1430 /* The cache is now valid */ 1431 info->osps_cache.osc_is_valid = 1; 1432 1433 qdf_spin_unlock_bh(&info->osps_lock); 1434 break; 1435 1436 case TARGET_IF_SPECTRAL_INFO_ENABLED: 1437 if (input_len != sizeof(info->osps_cache.osc_spectral_enabled)) 1438 return -EINVAL; 1439 1440 pval = (uint8_t *)input; 1441 1442 qdf_spin_lock_bh(&info->osps_lock); 1443 ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode, 1444 0, 0, 1, *pval); 1445 1446 target_if_log_write_spectral_enabled( 1447 __func__, 1448 *pval, 1449 ret); 1450 1451 if (ret < 0) { 1452 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d", 1453 ret); 1454 qdf_spin_unlock_bh(&info->osps_lock); 1455 return ret; 1456 } 1457 1458 info->osps_cache.osc_spectral_enabled = *pval; 1459 1460 /* The cache is now valid */ 1461 info->osps_cache.osc_is_valid = 1; 1462 1463 qdf_spin_unlock_bh(&info->osps_lock); 1464 break; 1465 1466 case TARGET_IF_SPECTRAL_INFO_PARAMS: 1467 if (input_len != sizeof(info->osps_cache.osc_params)) 1468 return -EINVAL; 1469 1470 param = (struct spectral_config *)input; 1471 1472 qdf_spin_lock_bh(&info->osps_lock); 1473 ret = target_if_send_vdev_spectral_configure_cmd(spectral, 1474 smode, param); 1475 1476 target_if_log_write_spectral_params( 1477 param, 1478 __func__, 1479 ret); 1480 1481 if (ret < 0) { 1482 spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d", 1483 ret); 1484 qdf_spin_unlock_bh(&info->osps_lock); 1485 return ret; 1486 } 1487 1488 qdf_mem_copy(&info->osps_cache.osc_params, 1489 param, sizeof(info->osps_cache.osc_params)); 1490 1491 /* The cache is now valid */ 1492 info->osps_cache.osc_is_valid = 1; 1493 1494 qdf_spin_unlock_bh(&info->osps_lock); 1495 break; 1496 1497 default: 1498 spectral_err("Unknown target_if_spectral_info specifier"); 1499 return -EINVAL; 1500 } 1501 1502 return 0; 1503 } 1504 1505 /** 1506 * target_if_spectral_get_tsf64() - Function to get the TSF value 1507 * @arg: Pointer to handle for Spectral target_if internal private data 1508 * 1509 * Get the last TSF received in WMI buffer 1510 * 1511 * Return: TSF value 1512 */ 1513 static uint64_t 1514 target_if_spectral_get_tsf64(void *arg) 1515 { 1516 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1517 1518 return spectral->tsf64; 1519 } 1520 1521 /** 1522 * target_if_spectral_get_capability() - Function to get whether a 1523 * given Spectral hardware capability is available 1524 * @arg: Pointer to handle for Spectral target_if internal private data 1525 * @type: Spectral hardware capability type 1526 * 1527 * Get whether a given Spectral hardware capability is available 1528 * 1529 * Return: True if the capability is available, false if the capability is not 1530 * available 1531 */ 1532 uint32_t 1533 target_if_spectral_get_capability(void *arg, enum spectral_capability_type type) 1534 { 1535 int status = STATUS_FAIL; 1536 1537 switch (type) { 1538 case SPECTRAL_CAP_PHYDIAG: 1539 case SPECTRAL_CAP_RADAR: 1540 case SPECTRAL_CAP_SPECTRAL_SCAN: 1541 case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN: 1542 status = STATUS_PASS; 1543 break; 1544 default: 1545 status = STATUS_FAIL; 1546 } 1547 return status; 1548 } 1549 1550 /** 1551 * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start 1552 * @arg: Pointer to handle for Spectral target_if internal private data 1553 * @rxfilter: Rx filter to be used 1554 * 1555 * Note: This is only a placeholder function. It is not currently required since 1556 * FW should be taking care of setting the required filters. 1557 * 1558 * Return: 0 1559 */ 1560 uint32_t 1561 target_if_spectral_set_rxfilter(void *arg, int rxfilter) 1562 { 1563 /* 1564 * Will not be required since enabling of spectral in firmware 1565 * will take care of this 1566 */ 1567 return 0; 1568 } 1569 1570 /** 1571 * target_if_spectral_get_rxfilter() - Get the current RX Filter settings 1572 * @arg: Pointer to handle for Spectral target_if internal private data 1573 * 1574 * Note: This is only a placeholder function. It is not currently required since 1575 * FW should be taking care of setting the required filters. 1576 * 1577 * Return: 0 1578 */ 1579 uint32_t 1580 target_if_spectral_get_rxfilter(void *arg) 1581 { 1582 /* 1583 * Will not be required since enabling of spectral in firmware 1584 * will take care of this 1585 */ 1586 return 0; 1587 } 1588 1589 /** 1590 * target_if_sops_is_spectral_active() - Get whether Spectral is active 1591 * @arg: Pointer to handle for Spectral target_if internal private data 1592 * @smode: Spectral scan mode 1593 * 1594 * Function to check whether Spectral is active 1595 * 1596 * Return: True if Spectral is active, false if Spectral is not active 1597 */ 1598 uint32_t 1599 target_if_sops_is_spectral_active(void *arg, enum spectral_scan_mode smode) 1600 { 1601 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1602 uint8_t val = 0; 1603 int ret; 1604 1605 ret = target_if_spectral_info_read( 1606 spectral, 1607 smode, 1608 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1609 &val, sizeof(val)); 1610 1611 if (ret != 0) { 1612 /* 1613 * Could not determine if Spectral is active. 1614 * Return false as a safe value. 1615 * XXX: Consider changing the function prototype 1616 * to be able to indicate failure to fetch value. 1617 */ 1618 return 0; 1619 } 1620 1621 return val; 1622 } 1623 1624 /** 1625 * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled 1626 * @arg: Pointer to handle for Spectral target_if internal private data 1627 * @smode: Spectral scan mode 1628 * 1629 * Function to check whether Spectral is enabled 1630 * 1631 * Return: True if Spectral is enabled, false if Spectral is not enabled 1632 */ 1633 uint32_t 1634 target_if_sops_is_spectral_enabled(void *arg, enum spectral_scan_mode smode) 1635 { 1636 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1637 uint8_t val = 0; 1638 int ret; 1639 1640 ret = target_if_spectral_info_read( 1641 spectral, 1642 smode, 1643 TARGET_IF_SPECTRAL_INFO_ENABLED, 1644 &val, sizeof(val)); 1645 1646 if (ret != 0) { 1647 /* 1648 * Could not determine if Spectral is enabled. 1649 * Return false as a safe value. 1650 * XXX: Consider changing the function prototype 1651 * to be able to indicate failure to fetch value. 1652 */ 1653 return 0; 1654 } 1655 1656 return val; 1657 } 1658 1659 /** 1660 * target_if_sops_start_spectral_scan() - Start Spectral scan 1661 * @arg: Pointer to handle for Spectral target_if internal private data 1662 * @smode: Spectral scan mode 1663 * @err: Spectral error code 1664 * 1665 * Function to start spectral scan 1666 * 1667 * Return: 0 on success else failure 1668 */ 1669 uint32_t 1670 target_if_sops_start_spectral_scan(void *arg, enum spectral_scan_mode smode, 1671 enum spectral_cp_error_code *err) 1672 { 1673 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1674 uint8_t val = 1; 1675 uint8_t enabled = 0; 1676 int ret; 1677 1678 ret = target_if_spectral_info_read( 1679 spectral, 1680 smode, 1681 TARGET_IF_SPECTRAL_INFO_ENABLED, 1682 &enabled, sizeof(enabled)); 1683 1684 if (ret != 0) { 1685 /* 1686 * Could not determine if Spectral is enabled. Assume we need 1687 * to enable it 1688 */ 1689 enabled = 0; 1690 } 1691 1692 if (!enabled) { 1693 ret = target_if_spectral_info_write( 1694 spectral, 1695 smode, 1696 TARGET_IF_SPECTRAL_INFO_ENABLED, 1697 &val, sizeof(val)); 1698 1699 if (ret != 0) 1700 return ret; 1701 } 1702 1703 ret = target_if_spectral_info_write( 1704 spectral, 1705 smode, 1706 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1707 &val, sizeof(val)); 1708 1709 if (ret != 0) 1710 return ret; 1711 1712 return 0; 1713 } 1714 1715 /** 1716 * target_if_sops_stop_spectral_scan() - Stop Spectral scan 1717 * @arg: Pointer to handle for Spectral target_if internal private data 1718 * @smode: Spectral scan mode 1719 * 1720 * Function to stop spectral scan 1721 * 1722 * Return: 0 on success else failure 1723 */ 1724 uint32_t 1725 target_if_sops_stop_spectral_scan(void *arg, enum spectral_scan_mode smode) 1726 { 1727 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1728 uint8_t val = 0; 1729 int tempret, ret = 0; 1730 uint8_t enabled = 0; 1731 1732 tempret = target_if_spectral_info_read( 1733 spectral, 1734 smode, 1735 TARGET_IF_SPECTRAL_INFO_ENABLED, 1736 &enabled, sizeof(enabled)); 1737 1738 if (tempret) 1739 /* 1740 * Could not determine if Spectral is enabled. Assume scan is 1741 * not in progress 1742 */ 1743 enabled = 0; 1744 1745 /* if scan is not enabled, no need to send stop to FW */ 1746 if (!enabled) 1747 return -EPERM; 1748 1749 tempret = target_if_spectral_info_write( 1750 spectral, 1751 smode, 1752 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1753 &val, sizeof(val)); 1754 1755 if (tempret != 0) 1756 ret = tempret; 1757 1758 tempret = target_if_spectral_info_write( 1759 spectral, 1760 smode, 1761 TARGET_IF_SPECTRAL_INFO_ENABLED, 1762 &val, sizeof(val)); 1763 1764 if (tempret != 0) 1765 ret = tempret; 1766 1767 if (ret == 0 && smode == SPECTRAL_SCAN_MODE_AGILE) { 1768 struct target_if_spectral_ops *p_sops; 1769 struct spectral_config *sparams; 1770 1771 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 1772 sparams = &spectral->params[smode]; 1773 sparams->ss_frequency.cfreq1 = 0; 1774 sparams->ss_frequency.cfreq2 = 0; 1775 1776 p_sops->configure_spectral(spectral, sparams, smode); 1777 } 1778 1779 return ret; 1780 } 1781 1782 /** 1783 * target_if_spectral_get_extension_channel() - Get the Extension channel 1784 * @arg: Pointer to handle for Spectral target_if internal private data 1785 * @smode: Spectral scan mode 1786 * 1787 * Function to get the current Extension channel (in MHz) 1788 * 1789 * Return: Current Extension channel (in MHz) on success, 0 on failure or if 1790 * extension channel is not present. 1791 */ 1792 uint32_t 1793 target_if_spectral_get_extension_channel(void *arg, 1794 enum spectral_scan_mode smode) 1795 { 1796 /* 1797 * XXX: Once we expand to use cases where Spectral could be activated 1798 * without a channel being set to VDEV, we need to consider returning a 1799 * negative value in case of failure and having all callers handle this. 1800 */ 1801 1802 struct target_if_spectral *spectral = NULL; 1803 struct wlan_objmgr_vdev *vdev = NULL; 1804 uint16_t sec20chan_freq = 0; 1805 1806 qdf_assert_always(arg); 1807 spectral = (struct target_if_spectral *)arg; 1808 1809 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 1810 spectral_err("Invalid Spectral mode %u", smode); 1811 return 0; 1812 } 1813 vdev = target_if_spectral_get_vdev(spectral, smode); 1814 if (!vdev) 1815 return 0; 1816 1817 if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) { 1818 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1819 return 0; 1820 } 1821 1822 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1823 1824 return sec20chan_freq; 1825 } 1826 1827 /** 1828 * target_if_spectral_get_current_channel() - Get the current channel 1829 * @arg: Pointer to handle for Spectral target_if internal private data 1830 * @smode: Spectral scan mode 1831 * 1832 * Function to get the current channel (in MHz) 1833 * 1834 * Return: Current channel (in MHz) on success, 0 on failure 1835 */ 1836 uint32_t 1837 target_if_spectral_get_current_channel(void *arg, enum spectral_scan_mode smode) 1838 { 1839 /* 1840 * XXX: Once we expand to use cases where Spectral could be activated 1841 * without a channel being set to VDEV, we need to consider returning a 1842 * negative value in case of failure and having all callers handle this. 1843 */ 1844 1845 struct target_if_spectral *spectral = NULL; 1846 int16_t chan_freq = 0; 1847 struct wlan_objmgr_vdev *vdev = NULL; 1848 1849 qdf_assert_always(arg); 1850 spectral = (struct target_if_spectral *)arg; 1851 1852 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 1853 spectral_err("Invalid Spectral mode %u", smode); 1854 return 0; 1855 } 1856 vdev = target_if_spectral_get_vdev(spectral, smode); 1857 if (!vdev) 1858 return 0; 1859 1860 chan_freq = target_if_vdev_get_chan_freq(vdev); 1861 if (chan_freq < 0) { 1862 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1863 return 0; 1864 } 1865 1866 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1867 1868 return chan_freq; 1869 } 1870 1871 /** 1872 * target_if_spectral_reset_hw() - Reset the hardware 1873 * @arg: Pointer to handle for Spectral target_if internal private data 1874 * 1875 * This is only a placeholder since it is not currently required in the offload 1876 * case. 1877 * 1878 * Return: 0 1879 */ 1880 uint32_t 1881 target_if_spectral_reset_hw(void *arg) 1882 { 1883 not_yet_implemented(); 1884 return 0; 1885 } 1886 1887 /** 1888 * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from 1889 * Noisefloor history buffer 1890 * @arg: Pointer to handle for Spectral target_if internal private data 1891 * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied 1892 * 1893 * This is only a placeholder since it is not currently required in the offload 1894 * case. 1895 * 1896 * Return: 0 1897 */ 1898 uint32_t 1899 target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf) 1900 { 1901 not_yet_implemented(); 1902 return 0; 1903 } 1904 1905 /** 1906 * target_if_spectral_get_ext_noisefloor() - Get the extension channel 1907 * noisefloor 1908 * @arg: Pointer to handle for Spectral target_if internal private data 1909 * 1910 * This is only a placeholder since it is not currently required in the offload 1911 * case. 1912 * 1913 * Return: 0 1914 */ 1915 int8_t 1916 target_if_spectral_get_ext_noisefloor(void *arg) 1917 { 1918 not_yet_implemented(); 1919 return 0; 1920 } 1921 1922 /** 1923 * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor 1924 * @arg: Pointer to handle for Spectral target_if internal private data 1925 * 1926 * This is only a placeholder since it is not currently required in the offload 1927 * case. 1928 * 1929 * Return: 0 1930 */ 1931 int8_t 1932 target_if_spectral_get_ctl_noisefloor(void *arg) 1933 { 1934 not_yet_implemented(); 1935 return 0; 1936 } 1937 1938 /** 1939 * target_if_spectral_sops_configure_params() - Configure user supplied Spectral 1940 * parameters 1941 * @arg: Pointer to handle for Spectral target_if internal private data 1942 * @params: Spectral parameters 1943 * @smode: Spectral scan mode 1944 * 1945 * Function to configure spectral parameters 1946 * 1947 * Return: 0 on success else failure 1948 */ 1949 uint32_t 1950 target_if_spectral_sops_configure_params( 1951 void *arg, struct spectral_config *params, 1952 enum spectral_scan_mode smode) 1953 { 1954 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1955 1956 return target_if_spectral_info_write( 1957 spectral, 1958 smode, 1959 TARGET_IF_SPECTRAL_INFO_PARAMS, 1960 params, sizeof(*params)); 1961 } 1962 1963 /** 1964 * target_if_spectral_sops_get_params() - Get user configured Spectral 1965 * parameters 1966 * @arg: Pointer to handle for Spectral target_if internal private data 1967 * @params: Pointer to buffer into which Spectral parameters should be copied 1968 * @smode: Spectral scan mode 1969 * 1970 * Function to get the configured spectral parameters 1971 * 1972 * Return: 0 on success else failure 1973 */ 1974 uint32_t 1975 target_if_spectral_sops_get_params(void *arg, struct spectral_config *params, 1976 enum spectral_scan_mode smode) 1977 { 1978 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1979 1980 return target_if_spectral_info_read( 1981 spectral, 1982 smode, 1983 TARGET_IF_SPECTRAL_INFO_PARAMS, 1984 params, sizeof(*params)); 1985 } 1986 1987 /** 1988 * target_if_spectral_get_ent_mask() - Get enterprise mask 1989 * @arg: Pointer to handle for Spectral target_if internal private data 1990 * 1991 * This is only a placeholder since it is not currently required in the offload 1992 * case. 1993 * 1994 * Return: 0 1995 */ 1996 static uint32_t 1997 target_if_spectral_get_ent_mask(void *arg) 1998 { 1999 not_yet_implemented(); 2000 return 0; 2001 } 2002 2003 /** 2004 * target_if_spectral_get_macaddr() - Get radio MAC address 2005 * @arg: Pointer to handle for Spectral target_if internal private data 2006 * @addr: Pointer to buffer into which MAC address should be copied 2007 * 2008 * Function to get the MAC address of the pdev 2009 * 2010 * Return: 0 on success, -1 on failure 2011 */ 2012 static uint32_t 2013 target_if_spectral_get_macaddr(void *arg, char *addr) 2014 { 2015 uint8_t *myaddr = NULL; 2016 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 2017 struct wlan_objmgr_pdev *pdev = NULL; 2018 2019 pdev = spectral->pdev_obj; 2020 2021 wlan_pdev_obj_lock(pdev); 2022 myaddr = wlan_pdev_get_hw_macaddr(pdev); 2023 wlan_pdev_obj_unlock(pdev); 2024 qdf_mem_copy(addr, myaddr, QDF_MAC_ADDR_SIZE); 2025 2026 return 0; 2027 } 2028 2029 /** 2030 * target_if_init_spectral_param_min_max_be() - Initialize Spectral parameter 2031 * min and max values for beryllium chipsets 2032 * 2033 * @spectral: Spectral LMAC object 2034 * 2035 * Return: QDF_STATUS of operation 2036 */ 2037 static QDF_STATUS 2038 target_if_init_spectral_param_min_max_be(struct target_if_spectral *spectral) 2039 { 2040 struct spectral_param_min_max *param_min_max; 2041 enum phy_ch_width op_bw; 2042 QDF_STATUS status; 2043 2044 param_min_max = &spectral->param_min_max; 2045 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3_BE; 2046 2047 for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) { 2048 bool is_supported; 2049 2050 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj, 2051 op_bw, &is_supported); 2052 if (QDF_IS_STATUS_ERROR(status)) { 2053 spectral_err("Unable to check if ch_width(%d) is supported", 2054 op_bw); 2055 return QDF_STATUS_E_FAILURE; 2056 } 2057 2058 if (!is_supported) { 2059 param_min_max->fft_size_max[op_bw] = INVALID_FFT_SIZE; 2060 continue; 2061 } 2062 2063 switch (op_bw) { 2064 case CH_WIDTH_20MHZ: 2065 param_min_max->fft_size_max[op_bw] = 2066 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE_20MHZ; 2067 break; 2068 2069 case CH_WIDTH_40MHZ: 2070 param_min_max->fft_size_max[op_bw] = 2071 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE_40MHZ; 2072 break; 2073 2074 default: 2075 param_min_max->fft_size_max[op_bw] = 2076 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_BE; 2077 } 2078 } 2079 2080 return QDF_STATUS_SUCCESS; 2081 } 2082 2083 /** 2084 * target_if_init_spectral_param_min_max() - Initialize Spectral parameter 2085 * min and max values 2086 * 2087 * @spectral: Spectral LMAC object 2088 * @gen: Spectral HW generation 2089 * @target_type: Target type 2090 * 2091 * Initialize Spectral parameter min and max values 2092 * 2093 * Return: QDF_STATUS 2094 */ 2095 static QDF_STATUS 2096 target_if_init_spectral_param_min_max( 2097 struct target_if_spectral *spectral, 2098 enum spectral_gen gen, uint32_t target_type) 2099 { 2100 struct spectral_param_min_max *param_min_max; 2101 2102 if (!spectral) { 2103 spectral_err("Spectral LMAC object is null"); 2104 return QDF_STATUS_E_NULL_VALUE; 2105 } 2106 2107 if (is_spectral_arch_beryllium(target_type)) 2108 return target_if_init_spectral_param_min_max_be(spectral); 2109 2110 param_min_max = &spectral->param_min_max; 2111 switch (gen) { 2112 case SPECTRAL_GEN3: 2113 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3; 2114 param_min_max->fft_size_max[CH_WIDTH_20MHZ] = 2115 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2116 if (target_type == TARGET_TYPE_QCN9000 || 2117 target_type == TARGET_TYPE_QCN6122 || 2118 target_type == TARGET_TYPE_QCN9160 || 2119 target_type == TARGET_TYPE_QCA5018 || 2120 target_type == TARGET_TYPE_QCA6490 || 2121 target_type == TARGET_TYPE_KIWI || 2122 target_type == TARGET_TYPE_MANGO || 2123 target_type == TARGET_TYPE_PEACH) { 2124 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 2125 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2126 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 2127 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2128 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 2129 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2130 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 2131 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2132 } else { 2133 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 2134 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2135 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 2136 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2137 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 2138 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2139 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 2140 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2141 } 2142 break; 2143 2144 case SPECTRAL_GEN2: 2145 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; 2146 param_min_max->fft_size_max[CH_WIDTH_20MHZ] = 2147 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2148 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 2149 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2150 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 2151 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2152 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 2153 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2154 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 2155 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2156 break; 2157 2158 default: 2159 spectral_err("Invalid spectral generation %d", gen); 2160 return QDF_STATUS_E_INVAL; 2161 } 2162 2163 return QDF_STATUS_SUCCESS; 2164 } 2165 2166 /** 2167 * target_if_init_spectral_param_properties() - Initialize Spectral parameter 2168 * properties 2169 * @spectral: Pointer to Spectral target_if internal private data 2170 * 2171 * Initialize Spectral parameter properties 2172 * 2173 * Return: QDF_STATUS 2174 */ 2175 static QDF_STATUS 2176 target_if_init_spectral_param_properties(struct target_if_spectral *spectral) 2177 { 2178 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2179 int param; 2180 2181 /* Initialize default values for properties. 2182 * Default values are supported for all the parameters for all modes 2183 * and allows different values for each mode for all the parameters . 2184 */ 2185 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2186 for (param = 0; param < SPECTRAL_PARAM_MAX; param++) { 2187 spectral->properties[smode][param].supported = true; 2188 spectral->properties[smode][param].common_all_modes = 2189 false; 2190 } 2191 } 2192 2193 /* Once FW advertisement is in place remove this hard coding */ 2194 smode = SPECTRAL_SCAN_MODE_NORMAL; 2195 spectral->properties[SPECTRAL_SCAN_MODE_NORMAL] 2196 [SPECTRAL_PARAM_FREQUENCY].supported = false; 2197 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2198 spectral->properties[smode] 2199 [SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true; 2200 spectral->properties[smode] 2201 [SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true; 2202 spectral->properties[smode] 2203 [SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true; 2204 } 2205 2206 return QDF_STATUS_SUCCESS; 2207 } 2208 2209 /* Bandwidth to half bandwidth mapping */ 2210 static const enum phy_ch_width half_bw_map[] = { 2211 #ifdef WLAN_FEATURE_11BE 2212 [CH_WIDTH_320MHZ] = CH_WIDTH_160MHZ, 2213 #endif 2214 [CH_WIDTH_80P80MHZ] = CH_WIDTH_80MHZ, 2215 [CH_WIDTH_160MHZ] = CH_WIDTH_80MHZ, 2216 [CH_WIDTH_80MHZ] = CH_WIDTH_40MHZ, 2217 [CH_WIDTH_40MHZ] = CH_WIDTH_20MHZ, 2218 [CH_WIDTH_20MHZ] = CH_WIDTH_10MHZ, 2219 [CH_WIDTH_10MHZ] = CH_WIDTH_5MHZ, 2220 [CH_WIDTH_5MHZ] = CH_WIDTH_INVALID 2221 }; 2222 2223 /** 2224 * target_if_get_half_bandwidth() - Get half bandwidth for a given bandwidth 2225 * @bw: bandwidth 2226 * 2227 * Return: Half bandwidth of @bw 2228 */ 2229 static enum phy_ch_width target_if_get_half_bandwidth(enum phy_ch_width bw) 2230 { 2231 if (bw >= CH_WIDTH_INVALID) 2232 return CH_WIDTH_INVALID; 2233 2234 return half_bw_map[bw]; 2235 } 2236 2237 /** 2238 * target_if_populate_supported_sscan_bws_be() - Populate supported spectral 2239 * scan bandwidths for beryllium chipsets 2240 * @spectral: Spectral LMAC object 2241 * 2242 * Return: QDF_STATUS of operation 2243 */ 2244 static QDF_STATUS 2245 target_if_populate_supported_sscan_bws_be(struct target_if_spectral *spectral) 2246 { 2247 enum phy_ch_width op_bw; 2248 struct spectral_supported_bws *supported_bws; 2249 QDF_STATUS status; 2250 2251 qdf_assert_always(spectral); 2252 2253 /* 20MHz */ 2254 op_bw = CH_WIDTH_20MHZ; 2255 supported_bws = &spectral->supported_bws 2256 [SPECTRAL_SCAN_MODE_NORMAL][op_bw]; 2257 supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw); 2258 spectral->supported_sscan_bw_list 2259 [SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true; 2260 supported_bws = &spectral->supported_bws 2261 [SPECTRAL_SCAN_MODE_AGILE][op_bw]; 2262 supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw); 2263 spectral->supported_sscan_bw_list 2264 [SPECTRAL_SCAN_MODE_AGILE][op_bw] = true; 2265 2266 for (op_bw = CH_WIDTH_40MHZ; op_bw < CH_WIDTH_MAX; op_bw++) { 2267 bool is_supported; 2268 enum phy_ch_width half_op_bw; 2269 2270 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj, 2271 op_bw, &is_supported); 2272 if (QDF_IS_STATUS_ERROR(status)) { 2273 spectral_err("Unable to check if ch_width(%d) is supported", 2274 op_bw); 2275 return QDF_STATUS_E_FAILURE; 2276 } 2277 2278 if (!is_supported) 2279 continue; 2280 2281 spectral_debug("Updating supported bw for op_bw: %d", op_bw); 2282 /* Normal mode */ 2283 supported_bws = &spectral->supported_bws 2284 [SPECTRAL_SCAN_MODE_NORMAL][op_bw]; 2285 supported_bws->bandwidths |= 2286 1 << get_supported_sscan_bw_pos(op_bw); 2287 spectral->supported_sscan_bw_list 2288 [SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true; 2289 2290 /* Agile mode */ 2291 supported_bws = &spectral->supported_bws 2292 [SPECTRAL_SCAN_MODE_AGILE][op_bw]; 2293 supported_bws->bandwidths |= 2294 1 << get_supported_sscan_bw_pos(op_bw); 2295 spectral->supported_sscan_bw_list 2296 [SPECTRAL_SCAN_MODE_AGILE][op_bw] = true; 2297 2298 half_op_bw = target_if_get_half_bandwidth(op_bw); 2299 if (half_op_bw != CH_WIDTH_INVALID) { 2300 supported_bws->bandwidths |= 2301 1 << get_supported_sscan_bw_pos(half_op_bw); 2302 spectral->supported_sscan_bw_list 2303 [SPECTRAL_SCAN_MODE_AGILE][half_op_bw] = true; 2304 } 2305 } 2306 2307 return QDF_STATUS_SUCCESS; 2308 } 2309 2310 /** 2311 * target_if_populate_supported_sscan_bws() - Populate supported spectral 2312 * scan bandwidths 2313 * @spectral: Spectral LMAC object 2314 * @target_type: Target type 2315 * 2316 * Return: QDF_STATUS of operation 2317 */ 2318 static QDF_STATUS 2319 target_if_populate_supported_sscan_bws(struct target_if_spectral *spectral, 2320 uint32_t target_type) 2321 { 2322 enum spectral_scan_mode smode; 2323 enum phy_ch_width op_bw; 2324 struct spectral_supported_bws *supported_bws; 2325 struct wlan_objmgr_psoc *psoc; 2326 QDF_STATUS status; 2327 2328 qdf_assert_always(spectral); 2329 2330 if (is_spectral_arch_beryllium(target_type)) 2331 return target_if_populate_supported_sscan_bws_be(spectral); 2332 2333 psoc = wlan_pdev_get_psoc(spectral->pdev_obj); 2334 if (!psoc) { 2335 spectral_err("psoc is null"); 2336 return QDF_STATUS_E_NULL_VALUE; 2337 } 2338 2339 for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) { 2340 bool is_supported; 2341 2342 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj, 2343 op_bw, &is_supported); 2344 if (QDF_IS_STATUS_ERROR(status)) { 2345 spectral_err("Unable to check if ch_width(%d) is supported", 2346 op_bw); 2347 return QDF_STATUS_E_FAILURE; 2348 } 2349 2350 if (!is_supported) 2351 continue; 2352 2353 spectral_debug("Updating supported bw for op_bw: %d", op_bw); 2354 smode = SPECTRAL_SCAN_MODE_NORMAL; 2355 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2356 supported_bws = &spectral->supported_bws[smode][op_bw]; 2357 2358 if (is_ch_width_160_or_80p80(op_bw) && 2359 smode == SPECTRAL_SCAN_MODE_AGILE) { 2360 /** 2361 * If fragmentation is supported, then only 80Hz 2362 * agile width is supported 2363 */ 2364 if (spectral->rparams. 2365 fragmentation_160[smode]) { 2366 supported_bws->bandwidths |= 2367 1 << get_supported_sscan_bw_pos( 2368 CH_WIDTH_80MHZ); 2369 spectral->supported_sscan_bw_list 2370 [smode][CH_WIDTH_80MHZ] = true; 2371 } 2372 2373 /** 2374 * If restricted 80p80 is supported, then both 2375 * 160 and 80p80 agile widths are supported for 2376 * 160MHz, and only 160MHz agile width is 2377 * supported for 80p80 2378 */ 2379 if (wlan_psoc_nif_fw_ext_cap_get( 2380 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) { 2381 supported_bws->bandwidths |= 2382 1 << get_supported_sscan_bw_pos( 2383 CH_WIDTH_160MHZ); 2384 spectral->supported_sscan_bw_list 2385 [smode][CH_WIDTH_160MHZ] = true; 2386 2387 if (op_bw == CH_WIDTH_160MHZ) { 2388 supported_bws->bandwidths |= 2389 1 << get_supported_sscan_bw_pos( 2390 CH_WIDTH_80P80MHZ); 2391 spectral->supported_sscan_bw_list 2392 [smode][CH_WIDTH_80P80MHZ] = true; 2393 } 2394 } 2395 } else { 2396 supported_bws->bandwidths |= 2397 1 << get_supported_sscan_bw_pos( 2398 op_bw); 2399 spectral->supported_sscan_bw_list 2400 [smode][op_bw] = true; 2401 } 2402 } 2403 } 2404 2405 return QDF_STATUS_SUCCESS; 2406 } 2407 2408 QDF_STATUS 2409 target_if_init_spectral_capability(struct target_if_spectral *spectral, 2410 uint32_t target_type) 2411 { 2412 struct wlan_objmgr_psoc *psoc; 2413 struct wlan_objmgr_pdev *pdev; 2414 struct wlan_psoc_host_spectral_scaling_params *scaling_params; 2415 uint8_t num_bin_scaling_params, param_idx, pdev_id; 2416 struct target_psoc_info *tgt_psoc_info; 2417 struct wlan_psoc_host_service_ext_param *ext_svc_param; 2418 struct spectral_caps *pcap = &spectral->capability; 2419 QDF_STATUS status; 2420 2421 pdev = spectral->pdev_obj; 2422 psoc = wlan_pdev_get_psoc(pdev); 2423 if (!psoc) { 2424 spectral_err("psoc is null"); 2425 return QDF_STATUS_E_FAILURE; 2426 } 2427 2428 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 2429 if (!tgt_psoc_info) { 2430 spectral_err("target_psoc_info is null"); 2431 return QDF_STATUS_E_FAILURE; 2432 } 2433 2434 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 2435 num_bin_scaling_params = ext_svc_param->num_bin_scaling_params; 2436 scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info); 2437 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 2438 2439 /* XXX : Workaround: Set Spectral capability */ 2440 pcap = &spectral->capability; 2441 pcap->phydiag_cap = 1; 2442 pcap->radar_cap = 1; 2443 pcap->spectral_cap = wlan_pdev_nif_feat_ext_cap_get( 2444 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS); 2445 pcap->advncd_spectral_cap = pcap->spectral_cap; 2446 pcap->hw_gen = spectral->spectral_gen; 2447 2448 pcap->agile_spectral_cap = !wlan_pdev_nif_feat_ext_cap_get( 2449 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS); 2450 pcap->agile_spectral_cap_160 = !wlan_pdev_nif_feat_ext_cap_get( 2451 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS); 2452 pcap->agile_spectral_cap_80p80 = !wlan_pdev_nif_feat_ext_cap_get( 2453 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS); 2454 pcap->agile_spectral_cap_320 = !wlan_pdev_nif_feat_ext_cap_get( 2455 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS); 2456 2457 if (scaling_params) { 2458 for (param_idx = 0; param_idx < num_bin_scaling_params; 2459 param_idx++) { 2460 if (scaling_params[param_idx].pdev_id == pdev_id) { 2461 pcap->is_scaling_params_populated = true; 2462 pcap->formula_id = 2463 scaling_params[param_idx].formula_id; 2464 pcap->low_level_offset = 2465 scaling_params[param_idx].low_level_offset; 2466 pcap->high_level_offset = 2467 scaling_params[param_idx].high_level_offset; 2468 pcap->rssi_thr = 2469 scaling_params[param_idx].rssi_thr; 2470 pcap->default_agc_max_gain = 2471 scaling_params[param_idx].default_agc_max_gain; 2472 break; 2473 } 2474 } 2475 } 2476 2477 pcap->num_detectors_20mhz = 1; 2478 pcap->num_detectors_40mhz = 1; 2479 pcap->num_detectors_80mhz = 1; 2480 if (target_type == TARGET_TYPE_QCN9000 || 2481 target_type == TARGET_TYPE_QCN6122 || 2482 target_type == TARGET_TYPE_QCN9160 || 2483 target_type == TARGET_TYPE_QCA6490 || 2484 target_type == TARGET_TYPE_KIWI || 2485 target_type == TARGET_TYPE_MANGO || 2486 target_type == TARGET_TYPE_PEACH) { 2487 pcap->num_detectors_160mhz = 1; 2488 pcap->num_detectors_80p80mhz = 1; 2489 pcap->num_detectors_320mhz = 0; 2490 } else if (is_spectral_arch_beryllium(target_type)) { 2491 pcap->num_detectors_160mhz = 1; 2492 pcap->num_detectors_80p80mhz = 0; 2493 pcap->num_detectors_320mhz = 1; 2494 } else { 2495 pcap->num_detectors_160mhz = 2; 2496 pcap->num_detectors_80p80mhz = 2; 2497 pcap->num_detectors_320mhz = 0; 2498 } 2499 2500 status = target_if_populate_supported_sscan_bws(spectral, target_type); 2501 if (QDF_IS_STATUS_ERROR(status)) { 2502 spectral_err("Unable to populate supported sscan BWs"); 2503 return QDF_STATUS_E_FAILURE; 2504 } 2505 2506 return QDF_STATUS_SUCCESS; 2507 } 2508 2509 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 2510 /** 2511 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 2512 * internal operations with functions related to spectral simulation 2513 * @p_sops: spectral low level ops table 2514 * 2515 * Initialize spectral target_if internal operations with functions 2516 * related to spectral simulation 2517 * 2518 * Return: None 2519 */ 2520 static void 2521 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 2522 { 2523 /* 2524 * Spectral simulation is currently intended for platform transitions 2525 * where underlying HW support may not be available for some time. 2526 * Hence, we do not currently provide a runtime switch to turn the 2527 * simulation on or off. 2528 * In case of future requirements where runtime switches are required, 2529 * this can be added. But it is suggested to use application layer 2530 * simulation as far as possible in such cases, since the main 2531 * use of record and replay of samples would concern higher 2532 * level sample processing rather than lower level delivery. 2533 */ 2534 p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled; 2535 p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active; 2536 p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan; 2537 p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan; 2538 p_sops->configure_spectral = 2539 target_if_spectral_sops_sim_configure_params; 2540 p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params; 2541 } 2542 2543 #else 2544 /** 2545 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 2546 * internal operations 2547 * @p_sops: spectral low level ops table 2548 * 2549 * Return: None 2550 */ 2551 static void 2552 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 2553 { 2554 p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled; 2555 p_sops->is_spectral_active = target_if_sops_is_spectral_active; 2556 p_sops->start_spectral_scan = target_if_sops_start_spectral_scan; 2557 p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan; 2558 p_sops->configure_spectral = target_if_spectral_sops_configure_params; 2559 p_sops->get_spectral_config = target_if_spectral_sops_get_params; 2560 } 2561 #endif 2562 2563 /** 2564 * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal 2565 * operations common to all Spectral chipset generations 2566 * 2567 * Initializes target_if_spectral_ops common to all chipset generations 2568 * 2569 * Return: None 2570 */ 2571 static void 2572 target_if_init_spectral_ops_common(void) 2573 { 2574 struct target_if_spectral_ops *p_sops = &spectral_ops; 2575 2576 p_sops->get_tsf64 = target_if_spectral_get_tsf64; 2577 p_sops->get_capability = target_if_spectral_get_capability; 2578 p_sops->set_rxfilter = target_if_spectral_set_rxfilter; 2579 p_sops->get_rxfilter = target_if_spectral_get_rxfilter; 2580 2581 target_if_init_spectral_simulation_ops(p_sops); 2582 2583 p_sops->get_extension_channel = 2584 target_if_spectral_get_extension_channel; 2585 p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor; 2586 p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor; 2587 p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask; 2588 p_sops->get_mac_address = target_if_spectral_get_macaddr; 2589 p_sops->get_current_channel = target_if_spectral_get_current_channel; 2590 p_sops->reset_hw = target_if_spectral_reset_hw; 2591 p_sops->get_chain_noise_floor = 2592 target_if_spectral_get_chain_noise_floor; 2593 } 2594 2595 /** 2596 * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal 2597 * operations specific to Spectral chipset generation 2. 2598 * 2599 * Initializes target_if_spectral_ops specific to Spectral chipset generation 2. 2600 * 2601 * Return: None 2602 */ 2603 static void 2604 target_if_init_spectral_ops_gen2(void) 2605 { 2606 struct target_if_spectral_ops *p_sops = &spectral_ops; 2607 2608 p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2; 2609 } 2610 2611 #ifdef BIG_ENDIAN_HOST 2612 /** 2613 * spectral_is_host_byte_swap_required() - Check if byte swap has to be done 2614 * on the Host 2615 * @pdev: pdev pointer 2616 * @is_swap_required: Pointer to caller variable 2617 * 2618 * Return: QDF_STATUS of operation 2619 */ 2620 static QDF_STATUS 2621 spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev *pdev, 2622 bool *is_swap_required) 2623 { 2624 struct wlan_objmgr_psoc *psoc; 2625 struct wmi_unified *wmi_handle; 2626 2627 if (!pdev) { 2628 spectral_err("pdev is null"); 2629 return QDF_STATUS_E_INVAL; 2630 } 2631 2632 psoc = wlan_pdev_get_psoc(pdev); 2633 if (!psoc) { 2634 spectral_err("psoc is null"); 2635 return QDF_STATUS_E_INVAL; 2636 } 2637 2638 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 2639 if (!wmi_handle) { 2640 spectral_err("wmi handle is null"); 2641 return QDF_STATUS_E_INVAL; 2642 } 2643 2644 /** 2645 * If a chipset supports byte-swap inside the target itself, then no 2646 * need to apply byte swap on the Host. 2647 */ 2648 *is_swap_required = !target_if_spectral_wmi_service_enabled( 2649 psoc, wmi_handle, 2650 wmi_service_phy_dma_byte_swap_support); 2651 2652 return QDF_STATUS_SUCCESS; 2653 } 2654 2655 /** 2656 * target_if_spectral_init_byte_swap_funcs_gen3() - Initialize byte-swap 2657 * operations for Spectral chipset generation 3. 2658 * @spectral: Spectral LMAC object 2659 * @p_sops: Spectral function pointer table 2660 * 2661 * Return: None 2662 */ 2663 static void 2664 target_if_spectral_init_byte_swap_funcs_gen3( 2665 struct target_if_spectral *spectral, 2666 struct target_if_spectral_ops *p_sops) 2667 { 2668 bool is_swap_required; 2669 QDF_STATUS status; 2670 2671 qdf_assert_always(spectral); 2672 qdf_assert_always(p_sops); 2673 2674 status = spectral_is_host_byte_swap_required(spectral->pdev_obj, 2675 &is_swap_required); 2676 if (QDF_IS_STATUS_ERROR(status)) { 2677 spectral_err("Failed to check whether byte swap is required"); 2678 return; 2679 } 2680 2681 if (is_swap_required) { 2682 p_sops->byte_swap_headers = 2683 target_if_byte_swap_spectral_headers_gen3; 2684 p_sops->byte_swap_fft_bins = 2685 target_if_byte_swap_spectral_fft_bins_gen3; 2686 } else { 2687 p_sops->byte_swap_headers = NULL; 2688 p_sops->byte_swap_fft_bins = NULL; 2689 } 2690 } 2691 #else 2692 static void 2693 target_if_spectral_init_byte_swap_funcs_gen3( 2694 struct target_if_spectral *spectral, 2695 struct target_if_spectral_ops *p_sops) 2696 { 2697 qdf_assert_always(p_sops); 2698 2699 /* Byte-swap is not required for little-endian Hosts */ 2700 p_sops->byte_swap_headers = NULL; 2701 p_sops->byte_swap_fft_bins = NULL; 2702 } 2703 #endif /* BIG_ENDIAN_HOST */ 2704 2705 /** 2706 * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal 2707 * operations specific to Spectral chipset generation 3. 2708 * @spectral: Spectral LMAC object 2709 * 2710 * Initializes target_if_spectral_ops specific to Spectral chipset generation 3. 2711 * 2712 * Return: None 2713 */ 2714 static void 2715 target_if_init_spectral_ops_gen3(struct target_if_spectral *spectral) 2716 { 2717 struct target_if_spectral_ops *p_sops = &spectral_ops; 2718 2719 p_sops->process_spectral_report = 2720 target_if_spectral_process_report_gen3; 2721 2722 target_if_spectral_init_byte_swap_funcs_gen3(spectral, p_sops); 2723 } 2724 2725 /** 2726 * target_if_init_spectral_ops() - Initialize target_if internal Spectral 2727 * operations. 2728 * @spectral: Pointer to Spectral target_if internal private data 2729 * 2730 * Initializes all function pointers in target_if_spectral_ops for 2731 * all generations 2732 * 2733 * Return: None 2734 */ 2735 static void 2736 target_if_init_spectral_ops(struct target_if_spectral *spectral) 2737 { 2738 target_if_init_spectral_ops_common(); 2739 if (spectral->spectral_gen == SPECTRAL_GEN2) 2740 target_if_init_spectral_ops_gen2(); 2741 else if (spectral->spectral_gen == SPECTRAL_GEN3) 2742 target_if_init_spectral_ops_gen3(spectral); 2743 else 2744 spectral_err("Invalid Spectral generation"); 2745 } 2746 2747 /* 2748 * Dummy Functions: 2749 * These functions are initially registered to avoid any crashes due to 2750 * invocation of spectral functions before they are registered. 2751 */ 2752 2753 static uint64_t 2754 null_get_tsf64(void *arg) 2755 { 2756 spectral_ops_not_registered("get_tsf64"); 2757 return 0; 2758 } 2759 2760 static uint32_t 2761 null_get_capability(void *arg, enum spectral_capability_type type) 2762 { 2763 /* 2764 * TODO : We should have conditional compilation to get the capability 2765 * : We have not yet attahced ATH layer here, so there is no 2766 * : way to check the HAL capbalities 2767 */ 2768 spectral_ops_not_registered("get_capability"); 2769 2770 /* TODO : For the time being, we are returning TRUE */ 2771 return true; 2772 } 2773 2774 static uint32_t 2775 null_set_rxfilter(void *arg, int rxfilter) 2776 { 2777 spectral_ops_not_registered("set_rxfilter"); 2778 return 1; 2779 } 2780 2781 static uint32_t 2782 null_get_rxfilter(void *arg) 2783 { 2784 spectral_ops_not_registered("get_rxfilter"); 2785 return 0; 2786 } 2787 2788 static uint32_t 2789 null_is_spectral_active(void *arg, enum spectral_scan_mode smode) 2790 { 2791 spectral_ops_not_registered("is_spectral_active"); 2792 return 1; 2793 } 2794 2795 static uint32_t 2796 null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode) 2797 { 2798 spectral_ops_not_registered("is_spectral_enabled"); 2799 return 1; 2800 } 2801 2802 static uint32_t 2803 null_start_spectral_scan(void *arg, enum spectral_scan_mode smode, 2804 enum spectral_cp_error_code *err) 2805 { 2806 spectral_ops_not_registered("start_spectral_scan"); 2807 return 1; 2808 } 2809 2810 static uint32_t 2811 null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode) 2812 { 2813 spectral_ops_not_registered("stop_spectral_scan"); 2814 return 1; 2815 } 2816 2817 static uint32_t 2818 null_get_extension_channel(void *arg, enum spectral_scan_mode smode) 2819 { 2820 spectral_ops_not_registered("get_extension_channel"); 2821 return 1; 2822 } 2823 2824 static int8_t 2825 null_get_ctl_noisefloor(void *arg) 2826 { 2827 spectral_ops_not_registered("get_ctl_noisefloor"); 2828 return 1; 2829 } 2830 2831 static int8_t 2832 null_get_ext_noisefloor(void *arg) 2833 { 2834 spectral_ops_not_registered("get_ext_noisefloor"); 2835 return 0; 2836 } 2837 2838 static uint32_t 2839 null_configure_spectral(void *arg, struct spectral_config *params, 2840 enum spectral_scan_mode smode) 2841 { 2842 spectral_ops_not_registered("configure_spectral"); 2843 return 0; 2844 } 2845 2846 static uint32_t 2847 null_get_spectral_config(void *arg, struct spectral_config *params, 2848 enum spectral_scan_mode smode) 2849 { 2850 spectral_ops_not_registered("get_spectral_config"); 2851 return 0; 2852 } 2853 2854 static uint32_t 2855 null_get_ent_spectral_mask(void *arg) 2856 { 2857 spectral_ops_not_registered("get_ent_spectral_mask"); 2858 return 0; 2859 } 2860 2861 static uint32_t 2862 null_get_mac_address(void *arg, char *addr) 2863 { 2864 spectral_ops_not_registered("get_mac_address"); 2865 return 0; 2866 } 2867 2868 static uint32_t 2869 null_get_current_channel(void *arg, enum spectral_scan_mode smode) 2870 { 2871 spectral_ops_not_registered("get_current_channel"); 2872 return 0; 2873 } 2874 2875 static uint32_t 2876 null_reset_hw(void *arg) 2877 { 2878 spectral_ops_not_registered("get_current_channel"); 2879 return 0; 2880 } 2881 2882 static uint32_t 2883 null_get_chain_noise_floor(void *arg, int16_t *nf_buf) 2884 { 2885 spectral_ops_not_registered("get_chain_noise_floor"); 2886 return 0; 2887 } 2888 2889 static int 2890 null_spectral_process_phyerr(struct target_if_spectral *spectral, 2891 uint8_t *data, 2892 uint32_t datalen, 2893 struct target_if_spectral_rfqual_info *p_rfqual, 2894 struct target_if_spectral_chan_info *p_chaninfo, 2895 uint64_t tsf64, 2896 struct target_if_spectral_acs_stats *acs_stats) 2897 { 2898 spectral_ops_not_registered("spectral_process_phyerr"); 2899 return 0; 2900 } 2901 2902 static int 2903 null_process_spectral_report(struct wlan_objmgr_pdev *pdev, 2904 void *payload) 2905 { 2906 spectral_ops_not_registered("process_spectral_report"); 2907 return 0; 2908 } 2909 /** 2910 * target_if_spectral_init_dummy_function_table() - 2911 * Initialize target_if internal 2912 * Spectral operations to dummy functions 2913 * @ps: Pointer to Spectral target_if internal private data 2914 * 2915 * Initialize all the function pointers in target_if_spectral_ops with 2916 * dummy functions. 2917 * 2918 * Return: None 2919 */ 2920 static void 2921 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps) 2922 { 2923 struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps); 2924 2925 p_sops->get_tsf64 = null_get_tsf64; 2926 p_sops->get_capability = null_get_capability; 2927 p_sops->set_rxfilter = null_set_rxfilter; 2928 p_sops->get_rxfilter = null_get_rxfilter; 2929 p_sops->is_spectral_enabled = null_is_spectral_enabled; 2930 p_sops->is_spectral_active = null_is_spectral_active; 2931 p_sops->start_spectral_scan = null_start_spectral_scan; 2932 p_sops->stop_spectral_scan = null_stop_spectral_scan; 2933 p_sops->get_extension_channel = null_get_extension_channel; 2934 p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor; 2935 p_sops->get_ext_noisefloor = null_get_ext_noisefloor; 2936 p_sops->configure_spectral = null_configure_spectral; 2937 p_sops->get_spectral_config = null_get_spectral_config; 2938 p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask; 2939 p_sops->get_mac_address = null_get_mac_address; 2940 p_sops->get_current_channel = null_get_current_channel; 2941 p_sops->reset_hw = null_reset_hw; 2942 p_sops->get_chain_noise_floor = null_get_chain_noise_floor; 2943 p_sops->spectral_process_phyerr = null_spectral_process_phyerr; 2944 p_sops->process_spectral_report = null_process_spectral_report; 2945 } 2946 2947 /** 2948 * target_if_spectral_register_funcs() - Initialize target_if internal Spectral 2949 * operations 2950 * @spectral: Pointer to Spectral target_if internal private data 2951 * @p: Pointer to Spectral function table 2952 * 2953 * Return: None 2954 */ 2955 static void 2956 target_if_spectral_register_funcs(struct target_if_spectral *spectral, 2957 struct target_if_spectral_ops *p) 2958 { 2959 struct target_if_spectral_ops *p_sops = 2960 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2961 2962 *p_sops = *p; 2963 } 2964 2965 /** 2966 * target_if_spectral_clear_stats() - Clear Spectral stats 2967 * @spectral: Pointer to Spectral target_if internal private data 2968 * 2969 * Function to clear spectral stats 2970 * 2971 * Return: None 2972 */ 2973 static void 2974 target_if_spectral_clear_stats(struct target_if_spectral *spectral) 2975 { 2976 struct target_if_spectral_ops *p_sops = 2977 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2978 2979 qdf_mem_zero(&spectral->spectral_stats, 2980 sizeof(struct target_if_spectral_stats)); 2981 spectral->spectral_stats.last_reset_tstamp = 2982 p_sops->get_tsf64(spectral); 2983 } 2984 2985 /** 2986 * target_if_spectral_check_hw_capability() - Check whether HW supports spectral 2987 * @spectral: Pointer to Spectral target_if internal private data 2988 * 2989 * Function to check whether hardware supports spectral 2990 * 2991 * Return: True if HW supports Spectral, false if HW does not support Spectral 2992 */ 2993 static int 2994 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral) 2995 { 2996 struct target_if_spectral_ops *p_sops = NULL; 2997 struct spectral_caps *pcap = NULL; 2998 int is_spectral_supported = true; 2999 3000 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3001 pcap = &spectral->capability; 3002 3003 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) { 3004 is_spectral_supported = false; 3005 spectral_info("SPECTRAL : No PHYDIAG support"); 3006 return is_spectral_supported; 3007 } 3008 pcap->phydiag_cap = 1; 3009 3010 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) { 3011 is_spectral_supported = false; 3012 spectral_info("SPECTRAL : No RADAR support"); 3013 return is_spectral_supported; 3014 } 3015 pcap->radar_cap = 1; 3016 3017 if (p_sops->get_capability(spectral, 3018 SPECTRAL_CAP_SPECTRAL_SCAN) == false) { 3019 is_spectral_supported = false; 3020 spectral_info("SPECTRAL : No SPECTRAL SUPPORT"); 3021 return is_spectral_supported; 3022 } 3023 pcap->spectral_cap = 1; 3024 3025 if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN) 3026 == false) { 3027 spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT"); 3028 } else { 3029 pcap->advncd_spectral_cap = 1; 3030 } 3031 3032 return is_spectral_supported; 3033 } 3034 3035 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 3036 /** 3037 * target_if_spectral_detach_simulation() - De-initialize Spectral 3038 * Simulation functionality 3039 * @spectral: Pointer to Spectral target_if internal private data 3040 * 3041 * Function to de-initialize Spectral Simulation functionality 3042 * 3043 * Return: None 3044 */ 3045 static void 3046 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 3047 { 3048 target_if_spectral_sim_detach(spectral); 3049 } 3050 3051 #else 3052 static void 3053 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 3054 { 3055 } 3056 #endif 3057 3058 /** 3059 * target_if_spectral_detach() - De-initialize target_if Spectral 3060 * @pdev: Pointer to pdev object 3061 * 3062 * Function to detach target_if spectral 3063 * 3064 * Return: None 3065 */ 3066 static void 3067 target_if_spectral_detach(struct target_if_spectral *spectral) 3068 { 3069 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 3070 spectral_info("spectral detach"); 3071 3072 if (spectral) { 3073 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3074 qdf_spinlock_destroy 3075 (&spectral->param_info[smode].osps_lock); 3076 3077 target_if_spectral_detach_simulation(spectral); 3078 3079 qdf_spinlock_destroy(&spectral->spectral_lock); 3080 qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock); 3081 3082 qdf_spinlock_destroy(&spectral->detector_list_lock); 3083 qdf_spinlock_destroy(&spectral->session_report_info_lock); 3084 qdf_spinlock_destroy(&spectral->session_det_map_lock); 3085 3086 qdf_mem_free(spectral); 3087 spectral = NULL; 3088 } 3089 } 3090 3091 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 3092 /** 3093 * target_if_spectral_attach_simulation() - Initialize Spectral Simulation 3094 * functionality 3095 * @spectral: Pointer to Spectral target_if internal private data 3096 * 3097 * Function to initialize spectral simulation functionality 3098 * 3099 * Return: 0 on success, negative error code on failure 3100 */ 3101 static int 3102 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 3103 { 3104 if (target_if_spectral_sim_attach(spectral)) { 3105 qdf_mem_free(spectral); 3106 return -EPERM; 3107 } 3108 return 0; 3109 } 3110 3111 #else 3112 static int 3113 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 3114 { 3115 return 0; 3116 } 3117 #endif 3118 3119 /** 3120 * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment 3121 * related info 3122 * @swar: Pointer to Spectral FFT bin length adjustment SWAR params 3123 * @rparams: Pointer to Spectral report parameter object 3124 * @target_type: Target type 3125 * 3126 * Function to Initialize parameters related to Spectral FFT bin 3127 * length adjustment SWARs. 3128 * 3129 * Return: void 3130 */ 3131 static void 3132 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar, 3133 struct spectral_report_params *rparams, 3134 uint32_t target_type) 3135 { 3136 if (target_type == TARGET_TYPE_QCA8074V2 || 3137 target_type == TARGET_TYPE_QCA9574 || 3138 target_type == TARGET_TYPE_QCN9000 || 3139 target_type == TARGET_TYPE_QCN6122 || 3140 target_type == TARGET_TYPE_QCN9160 || 3141 target_type == TARGET_TYPE_QCA5018 || 3142 target_type == TARGET_TYPE_QCA6750 || 3143 target_type == TARGET_TYPE_QCA6490 || 3144 target_type == TARGET_TYPE_KIWI || 3145 target_type == TARGET_TYPE_MANGO || 3146 target_type == TARGET_TYPE_PEACH) { 3147 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; 3148 rparams->hw_fft_bin_width = 2; 3149 } else if (target_type == TARGET_TYPE_QCA8074 || 3150 target_type == TARGET_TYPE_QCA6018 || 3151 target_type == TARGET_TYPE_QCA6390) { 3152 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; 3153 rparams->hw_fft_bin_width = 4; 3154 } else { 3155 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; 3156 rparams->hw_fft_bin_width = 1; 3157 } 3158 3159 if (target_type == TARGET_TYPE_QCA8074 || 3160 target_type == TARGET_TYPE_QCA8074V2 || 3161 target_type == TARGET_TYPE_QCA9574 || 3162 target_type == TARGET_TYPE_QCA6018 || 3163 target_type == TARGET_TYPE_QCN6122 || 3164 target_type == TARGET_TYPE_QCN9160 || 3165 target_type == TARGET_TYPE_QCA5332 || 3166 target_type == TARGET_TYPE_QCA5018 || 3167 target_type == TARGET_TYPE_QCN9000 || 3168 target_type == TARGET_TYPE_QCA6490 || 3169 target_type == TARGET_TYPE_QCN9224 || 3170 target_type == TARGET_TYPE_KIWI || 3171 target_type == TARGET_TYPE_MANGO || 3172 target_type == TARGET_TYPE_PEACH) { 3173 swar->inband_fftbin_size_adj = 1; 3174 swar->null_fftbin_adj = 1; 3175 } else { 3176 swar->inband_fftbin_size_adj = 0; 3177 swar->null_fftbin_adj = 0; 3178 } 3179 3180 if (target_type == TARGET_TYPE_QCA8074V2) 3181 swar->packmode_fftbin_size_adj = 1; 3182 else 3183 swar->packmode_fftbin_size_adj = 0; 3184 } 3185 3186 /** 3187 * target_if_spectral_report_params_init() - Initialize parameters which 3188 * describes the structure of Spectral reports 3189 * 3190 * @rparams: Pointer to Spectral report parameter object 3191 * @target_type: target type 3192 * 3193 * Function to Initialize parameters related to the structure of Spectral 3194 * reports. 3195 * 3196 * Return: void 3197 */ 3198 static void 3199 target_if_spectral_report_params_init( 3200 struct spectral_report_params *rparams, 3201 uint32_t target_type) 3202 { 3203 enum spectral_scan_mode smode; 3204 3205 /* This entries are currently used by gen3 chipsets only. Hence 3206 * initialization is done for gen3 alone. In future if other generations 3207 * needs to use them they have to add proper initial values. 3208 */ 3209 if (target_type == TARGET_TYPE_QCN9000 || 3210 target_type == TARGET_TYPE_QCN6122 || 3211 target_type == TARGET_TYPE_QCN9160 || 3212 target_type == TARGET_TYPE_QCA5018 || 3213 target_type == TARGET_TYPE_QCA6750 || 3214 target_type == TARGET_TYPE_QCA6490 || 3215 target_type == TARGET_TYPE_QCA5332 || 3216 target_type == TARGET_TYPE_QCN9224 || 3217 target_type == TARGET_TYPE_KIWI || 3218 target_type == TARGET_TYPE_MANGO || 3219 target_type == TARGET_TYPE_PEACH) { 3220 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2; 3221 rparams->num_spectral_detectors = 3222 NUM_SPECTRAL_DETECTORS_GEN3_V2; 3223 smode = SPECTRAL_SCAN_MODE_NORMAL; 3224 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3225 rparams->fragmentation_160[smode] = false; 3226 } else { 3227 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1; 3228 rparams->num_spectral_detectors = 3229 NUM_SPECTRAL_DETECTORS_GEN3_V1; 3230 smode = SPECTRAL_SCAN_MODE_NORMAL; 3231 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3232 rparams->fragmentation_160[smode] = true; 3233 } 3234 3235 switch (rparams->version) { 3236 case SPECTRAL_REPORT_FORMAT_VERSION_1: 3237 rparams->ssumaary_padding_bytes = 3238 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1; 3239 rparams->fft_report_hdr_len = 3240 FFT_REPORT_HEADER_LENGTH_GEN3_V1; 3241 break; 3242 case SPECTRAL_REPORT_FORMAT_VERSION_2: 3243 rparams->ssumaary_padding_bytes = 3244 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2; 3245 rparams->fft_report_hdr_len = 3246 FFT_REPORT_HEADER_LENGTH_GEN3_V2; 3247 break; 3248 default: 3249 qdf_assert_always(0); 3250 } 3251 3252 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] = 3253 SPECTRAL_SCAN_MODE_NORMAL; 3254 if (target_type == TARGET_TYPE_QCN9000 || 3255 target_type == TARGET_TYPE_QCN6122 || 3256 target_type == TARGET_TYPE_QCN9224 || 3257 target_type == TARGET_TYPE_QCN9160 || 3258 target_type == TARGET_TYPE_QCA6490 || 3259 target_type == TARGET_TYPE_KIWI || 3260 target_type == TARGET_TYPE_MANGO || 3261 target_type == TARGET_TYPE_PEACH) { 3262 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 3263 SPECTRAL_SCAN_MODE_AGILE; 3264 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 3265 SPECTRAL_SCAN_MODE_INVALID; 3266 } else if (target_type == TARGET_TYPE_QCA5332) { 3267 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 3268 SPECTRAL_SCAN_MODE_INVALID; 3269 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 3270 SPECTRAL_SCAN_MODE_INVALID; 3271 } else { 3272 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 3273 SPECTRAL_SCAN_MODE_NORMAL; 3274 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 3275 SPECTRAL_SCAN_MODE_AGILE; 3276 } 3277 } 3278 3279 /** 3280 * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR 3281 * related info 3282 * @twar: Pointer to Spectral timstamp WAR related info 3283 * 3284 * Function to Initialize parameters related to Spectral timestamp WAR 3285 * 3286 * Return: void 3287 */ 3288 static void 3289 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar) 3290 { 3291 enum spectral_scan_mode smode; 3292 3293 smode = SPECTRAL_SCAN_MODE_NORMAL; 3294 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 3295 twar->last_fft_timestamp[smode] = 0; 3296 twar->timestamp_war_offset[smode] = 0; 3297 } 3298 twar->target_reset_count = 0; 3299 } 3300 3301 #ifdef OPTIMIZED_SAMP_MESSAGE 3302 /** 3303 * target_if_spectral_is_hw_mode_sbs() - Check if the given pdev is in SBS mode 3304 * @pdev: pdev pointer 3305 * @is_hw_mode_sbs: Pointer to the variable where this function should write 3306 * whether the given pdev is in SBS mode 3307 * 3308 * Return: QDF_STATUS of operation 3309 */ 3310 static QDF_STATUS 3311 target_if_spectral_is_hw_mode_sbs(struct wlan_objmgr_pdev *pdev, 3312 bool *is_hw_mode_sbs) 3313 { 3314 struct wlan_objmgr_psoc *psoc; 3315 struct target_psoc_info *tgt_hdl; 3316 enum wmi_host_hw_mode_config_type mode; 3317 3318 qdf_assert_always(is_hw_mode_sbs); 3319 3320 psoc = wlan_pdev_get_psoc(pdev); 3321 if (!psoc) { 3322 spectral_err("psoc is null"); 3323 return QDF_STATUS_E_NULL_VALUE; 3324 } 3325 3326 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 3327 if (!tgt_hdl) { 3328 spectral_err("target_psoc_info is null"); 3329 return QDF_STATUS_E_NULL_VALUE; 3330 } 3331 3332 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 3333 switch (mode) { 3334 case WMI_HOST_HW_MODE_SBS_PASSIVE: 3335 case WMI_HOST_HW_MODE_SBS: 3336 case WMI_HOST_HW_MODE_DBS_SBS: 3337 case WMI_HOST_HW_MODE_DBS_OR_SBS: 3338 *is_hw_mode_sbs = true; 3339 break; 3340 default: 3341 *is_hw_mode_sbs = false; 3342 break; 3343 } 3344 3345 return QDF_STATUS_SUCCESS; 3346 } 3347 3348 /** 3349 * target_if_get_pdev_mac_phy_caps() - Get the MAC_PHY capabilities of a pdev 3350 * @pdev: pdev pointer 3351 * 3352 * Return: On success, pointer to MAC_PHY capabilities of @pdev. 3353 * On failure, NULL 3354 */ 3355 static struct wlan_psoc_host_mac_phy_caps * 3356 target_if_get_pdev_mac_phy_caps(struct wlan_objmgr_pdev *pdev) 3357 { 3358 struct wlan_objmgr_psoc *psoc; 3359 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr; 3360 struct target_psoc_info *tgt_psoc_info; 3361 uint8_t pdev_id; 3362 3363 if (!pdev) { 3364 spectral_err("pdev is NULL"); 3365 return NULL; 3366 } 3367 3368 psoc = wlan_pdev_get_psoc(pdev); 3369 if (!psoc) { 3370 spectral_err("psoc is null"); 3371 return NULL; 3372 } 3373 3374 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 3375 if (!tgt_psoc_info) { 3376 spectral_err("target_psoc_info is null"); 3377 return NULL; 3378 } 3379 3380 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 3381 if (!mac_phy_cap_arr) { 3382 spectral_err("mac phy cap array is null"); 3383 return NULL; 3384 } 3385 3386 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 3387 return &mac_phy_cap_arr[pdev_id]; 3388 } 3389 3390 /** 3391 * struct target_if_sscan_pdev_phy_info - PHY information of the pdev on 3392 * which sscan is done. A pointer to an instance of this structure is passed 3393 * as an argument to the iterator function target_if_find_sscan_pdev_phya1() 3394 * @phy_id: PHY ID of this pdev 3395 * @is_using_phya1: Pointer to the variable where the iterator function should 3396 * populate whether the given pdev is using PHYA1 3397 */ 3398 struct target_if_sscan_pdev_phy_info { 3399 uint8_t phy_id; 3400 bool *is_using_phya1; 3401 }; 3402 3403 /** 3404 * target_if_find_sscan_pdev_phya1() - This is an iterator function to 3405 * wlan_objmgr_iterate_obj_list(). It checks whether a given sscan_pdev (pdev on 3406 * which sscan is currently issued) is using PHYA1 by comparing against the pdev 3407 * argument given by the wlan_objmgr_iterate_obj_list() 3408 * @psoc: Pointer to psoc 3409 * @object: Pointer to pdev 3410 * @arg: Pointer to target_if_sscan_pdev_phy_info of the sscan_pdev for which 3411 * we want to check if it uses PHYA1 3412 * 3413 * Return: None 3414 */ 3415 static void 3416 target_if_find_sscan_pdev_phya1(struct wlan_objmgr_psoc *psoc, 3417 void *object, void *arg) 3418 { 3419 struct target_if_sscan_pdev_phy_info *sscan_pdev_phy_info = arg; 3420 struct wlan_objmgr_pdev *cur_pdev = object; 3421 struct wlan_psoc_host_mac_phy_caps *cur_mac_phy_caps; 3422 3423 cur_mac_phy_caps = target_if_get_pdev_mac_phy_caps(cur_pdev); 3424 if (!cur_mac_phy_caps) { 3425 spectral_err("Failed to get MAC PHY Capabilities of" 3426 "pdev %pK", cur_pdev); 3427 return; 3428 } 3429 3430 spectral_debug("supported_bands: %0x phy_id: %d", 3431 cur_mac_phy_caps->supported_bands, 3432 cur_mac_phy_caps->phy_id); 3433 3434 /* No need to do anything if the current pdev is same as sscan_pdev */ 3435 if (sscan_pdev_phy_info->phy_id == cur_mac_phy_caps->phy_id) 3436 return; 3437 3438 /** 3439 * Compare the phy_id of both the SBS pdevs to figure out if 3440 * the sscan_pdev using PHYA1 3441 */ 3442 if (sscan_pdev_phy_info->phy_id > cur_mac_phy_caps->phy_id) 3443 *sscan_pdev_phy_info->is_using_phya1 = true; 3444 else 3445 *sscan_pdev_phy_info->is_using_phya1 = false; 3446 } 3447 3448 /** 3449 * target_if_spectral_detector_list_init() - Initialize Spectral detector list 3450 * based on target type 3451 * @spectral: Pointer to Spectral target_if 3452 * 3453 * Function to initialize Spectral detector list for possible combinations of 3454 * Spectral scan mode and channel width, based on target type. 3455 * 3456 * Return: Success/Failure 3457 */ 3458 static QDF_STATUS 3459 target_if_spectral_detector_list_init(struct target_if_spectral *spectral) 3460 { 3461 struct sscan_detector_list *det_list; 3462 enum spectral_scan_mode smode; 3463 enum phy_ch_width ch_width; 3464 QDF_STATUS ret; 3465 bool is_hw_mode_sbs = false, is_using_phya1 = false; 3466 3467 if (!spectral) { 3468 spectral_err_rl("Spectral LMAC object is null"); 3469 return QDF_STATUS_E_NULL_VALUE; 3470 } 3471 3472 /** 3473 * Special handling is required for SBS mode where the detector 3474 * list should be the following. 3475 * For the pdev that use PHYA0: 3476 * detector 0 for normal mode 3477 * detector 2 for agile mode 3478 * For the pdev that use PHYA1: 3479 * detector 1 for normal mode 3480 * detector 2 for agile mode 3481 * 3482 * There is no direct way of knowing which pdevs are using PHYA0 or 3483 * PHYA1. We need to look at the phy_id of a given pdev and compare 3484 * against other pdevs on the same psoc to figure out whether the given 3485 * pdev is operating using PHYA1. 3486 */ 3487 3488 /* First check whether this pdev is in SBS mode */ 3489 ret = target_if_spectral_is_hw_mode_sbs(spectral->pdev_obj, 3490 &is_hw_mode_sbs); 3491 if (QDF_IS_STATUS_ERROR(ret)) { 3492 spectral_err("Failed to check whether hw mode is SBS"); 3493 return ret; 3494 } 3495 3496 if (is_hw_mode_sbs) { 3497 struct wlan_psoc_host_mac_phy_caps *mac_phy_caps; 3498 struct target_if_sscan_pdev_phy_info pdev_phy_info; 3499 3500 mac_phy_caps = 3501 target_if_get_pdev_mac_phy_caps(spectral->pdev_obj); 3502 if (!mac_phy_caps) { 3503 spectral_err("Failed to get MAC PHY Capabilities of" 3504 "pdev %pK", spectral->pdev_obj); 3505 return QDF_STATUS_E_FAILURE; 3506 } 3507 3508 spectral_debug("bands: %0x phy_id: %d", 3509 mac_phy_caps->supported_bands, 3510 mac_phy_caps->phy_id); 3511 3512 pdev_phy_info.phy_id = mac_phy_caps->phy_id; 3513 pdev_phy_info.is_using_phya1 = &is_using_phya1; 3514 3515 /* Iterate over all pdevs on this psoc */ 3516 wlan_objmgr_iterate_obj_list 3517 (wlan_pdev_get_psoc(spectral->pdev_obj), 3518 WLAN_PDEV_OP, 3519 target_if_find_sscan_pdev_phya1, 3520 &pdev_phy_info, 0, 3521 WLAN_SPECTRAL_ID); 3522 } 3523 3524 /** 3525 * We assume there are 2 detectors. The Detector ID coming first will 3526 * always be pri80 detector, and second detector for sec80. 3527 */ 3528 ch_width = CH_WIDTH_20MHZ; 3529 for (; ch_width < CH_WIDTH_MAX; ch_width++) { 3530 /* Normal spectral scan */ 3531 smode = SPECTRAL_SCAN_MODE_NORMAL; 3532 spectral_debug("is_hw_mode_sbs: %d is_using_phya1:%d", 3533 is_hw_mode_sbs, is_using_phya1); 3534 3535 qdf_spin_lock_bh(&spectral->detector_list_lock); 3536 3537 if (!spectral->supported_sscan_bw_list[smode][ch_width]) 3538 goto agile_handling; 3539 3540 det_list = &spectral->detector_list[smode][ch_width]; 3541 det_list->num_detectors = 1; 3542 3543 if (is_hw_mode_sbs && is_using_phya1) 3544 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1; 3545 else 3546 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_0; 3547 3548 if (is_ch_width_160_or_80p80(ch_width) && 3549 spectral->rparams.fragmentation_160[smode]) { 3550 det_list->num_detectors += 1; 3551 det_list->detectors[1] = SPECTRAL_DETECTOR_ID_1; 3552 } 3553 3554 agile_handling: 3555 /* Agile spectral scan */ 3556 smode = SPECTRAL_SCAN_MODE_AGILE; 3557 if (!spectral->supported_sscan_bw_list[smode][ch_width]) { 3558 qdf_spin_unlock_bh(&spectral->detector_list_lock); 3559 continue; 3560 } 3561 3562 det_list = &spectral->detector_list[smode][ch_width]; 3563 det_list->num_detectors = 1; 3564 3565 if (spectral->rparams.fragmentation_160[smode]) 3566 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_2; 3567 else 3568 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1; 3569 3570 qdf_spin_unlock_bh(&spectral->detector_list_lock); 3571 } 3572 3573 return QDF_STATUS_SUCCESS; 3574 } 3575 #else 3576 3577 static QDF_STATUS 3578 target_if_spectral_detector_list_init(struct target_if_spectral *spectral) 3579 { 3580 return QDF_STATUS_SUCCESS; 3581 } 3582 #endif /* OPTIMIZED_SAMP_MESSAGE */ 3583 3584 /** 3585 * target_if_pdev_spectral_init() - Initialize target_if Spectral 3586 * functionality for the given pdev 3587 * @pdev: Pointer to pdev object 3588 * 3589 * Function to initialize pointer to spectral target_if internal private data 3590 * 3591 * Return: On success, pointer to Spectral target_if internal private data, on 3592 * failure, NULL 3593 */ 3594 void * 3595 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 3596 { 3597 struct target_if_spectral_ops *p_sops = NULL; 3598 struct target_if_spectral *spectral = NULL; 3599 uint32_t target_type; 3600 uint32_t target_revision; 3601 struct wlan_objmgr_psoc *psoc; 3602 struct wlan_lmac_if_target_tx_ops *tgt_tx_ops; 3603 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 3604 QDF_STATUS status; 3605 struct wlan_lmac_if_tx_ops *tx_ops; 3606 3607 if (!pdev) { 3608 spectral_err("SPECTRAL: pdev is NULL!"); 3609 return NULL; 3610 } 3611 spectral = (struct target_if_spectral *)qdf_mem_malloc( 3612 sizeof(struct target_if_spectral)); 3613 if (!spectral) 3614 return spectral; 3615 3616 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 3617 /* Store pdev in Spectral */ 3618 spectral->pdev_obj = pdev; 3619 spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID; 3620 spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID; 3621 3622 psoc = wlan_pdev_get_psoc(pdev); 3623 3624 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 3625 if (!tx_ops) { 3626 spectral_err("tx_ops is NULL"); 3627 qdf_mem_free(spectral); 3628 return NULL; 3629 } 3630 3631 tgt_tx_ops = &tx_ops->target_tx_ops; 3632 3633 if (tgt_tx_ops->tgt_get_tgt_type) { 3634 target_type = tgt_tx_ops->tgt_get_tgt_type(psoc); 3635 } else { 3636 qdf_mem_free(spectral); 3637 return NULL; 3638 } 3639 3640 if (tgt_tx_ops->tgt_get_tgt_revision) { 3641 target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc); 3642 } else { 3643 qdf_mem_free(spectral); 3644 return NULL; 3645 } 3646 3647 /* init the function ptr table */ 3648 target_if_spectral_init_dummy_function_table(spectral); 3649 3650 /* get spectral function table */ 3651 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3652 /* TODO : Should this be called here of after ath_attach ? */ 3653 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 3654 spectral_info("HAL_CAP_PHYDIAG : Capable"); 3655 3656 /* TODO: Need to fix the capability check for RADAR */ 3657 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 3658 spectral_info("HAL_CAP_RADAR : Capable"); 3659 3660 /* TODO : Need to fix the capability check for SPECTRAL */ 3661 /* TODO : Should this be called here of after ath_attach ? */ 3662 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 3663 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 3664 3665 qdf_spinlock_create(&spectral->spectral_lock); 3666 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 3667 target_if_spectral_clear_stats(spectral); 3668 3669 if (target_type == TARGET_TYPE_QCA8074 || 3670 target_type == TARGET_TYPE_QCA8074V2 || 3671 target_type == TARGET_TYPE_QCA9574 || 3672 target_type == TARGET_TYPE_QCA5332 || 3673 target_type == TARGET_TYPE_QCA6018 || 3674 target_type == TARGET_TYPE_QCA5018 || 3675 target_type == TARGET_TYPE_QCA6390 || 3676 target_type == TARGET_TYPE_QCN6122 || 3677 target_type == TARGET_TYPE_QCN9160 || 3678 target_type == TARGET_TYPE_QCA6490 || 3679 target_type == TARGET_TYPE_QCN9000 || 3680 target_type == TARGET_TYPE_QCA6750 || 3681 target_type == TARGET_TYPE_QCN9224 || 3682 target_type == TARGET_TYPE_KIWI || 3683 target_type == TARGET_TYPE_MANGO || 3684 target_type == TARGET_TYPE_PEACH) 3685 spectral->direct_dma_support = true; 3686 3687 target_if_spectral_report_params_init(&spectral->rparams, 3688 target_type); 3689 target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar, 3690 &spectral->rparams, 3691 target_type); 3692 3693 if ((target_type == TARGET_TYPE_QCA8074) || 3694 (target_type == TARGET_TYPE_QCA8074V2) || 3695 (target_type == TARGET_TYPE_QCA9574) || 3696 (target_type == TARGET_TYPE_QCA6018) || 3697 (target_type == TARGET_TYPE_QCA5018) || 3698 (target_type == TARGET_TYPE_QCA5332) || 3699 (target_type == TARGET_TYPE_QCN6122) || 3700 (target_type == TARGET_TYPE_QCN9160) || 3701 (target_type == TARGET_TYPE_QCN9000) || 3702 (target_type == TARGET_TYPE_QCA6290) || 3703 (target_type == TARGET_TYPE_QCA6390) || 3704 (target_type == TARGET_TYPE_QCA6490) || 3705 (target_type == TARGET_TYPE_QCN9224) || 3706 (target_type == TARGET_TYPE_QCA6750) || 3707 (target_type == TARGET_TYPE_KIWI) || 3708 (target_type == TARGET_TYPE_MANGO) || 3709 (target_type == TARGET_TYPE_PEACH)) { 3710 spectral->spectral_gen = SPECTRAL_GEN3; 3711 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 3712 spectral->tag_sscan_summary_exp = 3713 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 3714 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 3715 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 3716 } else { 3717 spectral->spectral_gen = SPECTRAL_GEN2; 3718 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 3719 spectral->tag_sscan_summary_exp = 3720 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 3721 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 3722 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 3723 } 3724 3725 status = target_if_init_spectral_param_min_max( 3726 spectral, 3727 spectral->spectral_gen, target_type); 3728 if (QDF_IS_STATUS_ERROR(status)) { 3729 spectral_err("Failed to initialize parameter min max values"); 3730 goto fail; 3731 } 3732 3733 target_if_init_spectral_param_properties(spectral); 3734 /* Init spectral capability */ 3735 if (target_if_init_spectral_capability(spectral, target_type) != 3736 QDF_STATUS_SUCCESS) { 3737 qdf_mem_free(spectral); 3738 return NULL; 3739 } 3740 if (target_if_spectral_attach_simulation(spectral) < 0) 3741 return NULL; 3742 3743 target_if_init_spectral_ops(spectral); 3744 target_if_spectral_timestamp_war_init(&spectral->timestamp_war); 3745 3746 /* Spectral mode specific init */ 3747 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 3748 spectral->params_valid[smode] = false; 3749 qdf_spinlock_create(&spectral->param_info[smode].osps_lock); 3750 spectral->param_info[smode].osps_cache.osc_is_valid = 0; 3751 } 3752 3753 target_if_spectral_register_funcs(spectral, &spectral_ops); 3754 3755 if (target_if_spectral_check_hw_capability(spectral) == false) { 3756 goto fail; 3757 } else { 3758 /* 3759 * TODO: Once the driver architecture transitions to chipset 3760 * versioning based checks, reflect this here. 3761 */ 3762 spectral->is_160_format = false; 3763 spectral->is_lb_edge_extrabins_format = false; 3764 spectral->is_rb_edge_extrabins_format = false; 3765 3766 if (target_type == TARGET_TYPE_QCA9984 || 3767 target_type == TARGET_TYPE_QCA9888) { 3768 spectral->is_160_format = true; 3769 spectral->is_lb_edge_extrabins_format = true; 3770 spectral->is_rb_edge_extrabins_format = true; 3771 } else if ((target_type == TARGET_TYPE_AR900B) && 3772 (target_revision == AR900B_REV_2)) { 3773 spectral->is_rb_edge_extrabins_format = true; 3774 } 3775 3776 if (target_type == TARGET_TYPE_QCA9984 || 3777 target_type == TARGET_TYPE_QCA9888) 3778 spectral->is_sec80_rssi_war_required = true; 3779 3780 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST; 3781 3782 if (spectral->spectral_gen == SPECTRAL_GEN3) 3783 init_160mhz_delivery_state_machine(spectral); 3784 } 3785 3786 qdf_spinlock_create(&spectral->detector_list_lock); 3787 qdf_spinlock_create(&spectral->session_report_info_lock); 3788 qdf_spinlock_create(&spectral->session_det_map_lock); 3789 3790 return spectral; 3791 3792 fail: 3793 target_if_spectral_detach(spectral); 3794 return NULL; 3795 } 3796 3797 /** 3798 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 3799 * functionality for the given pdev 3800 * @pdev: Pointer to pdev object 3801 * 3802 * Function to de-initialize pointer to spectral target_if internal private data 3803 * 3804 * Return: None 3805 */ 3806 void 3807 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 3808 { 3809 struct target_if_spectral *spectral = NULL; 3810 3811 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3812 if (!spectral) { 3813 spectral_err("SPECTRAL : Module doesn't exist"); 3814 return; 3815 } 3816 target_if_spectral_detach(spectral); 3817 3818 return; 3819 } 3820 3821 /** 3822 * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral 3823 * functionality for the given psoc 3824 * @psoc: Pointer to psoc object 3825 * 3826 * Function to de-initialize pointer to psoc spectral target_if internal 3827 * private data 3828 * 3829 * Return: None 3830 */ 3831 static void 3832 target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc) 3833 { 3834 struct target_if_psoc_spectral *psoc_spectral; 3835 3836 if (!psoc) { 3837 spectral_err("psoc is null"); 3838 return; 3839 } 3840 3841 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 3842 if (!psoc_spectral) { 3843 spectral_err("Spectral target_if psoc object is null"); 3844 return; 3845 } 3846 3847 qdf_mem_free(psoc_spectral); 3848 } 3849 3850 /** 3851 * target_if_psoc_spectral_init() - Initialize target_if Spectral 3852 * functionality for the given psoc 3853 * @psoc: Pointer to psoc object 3854 * 3855 * Function to initialize pointer to psoc spectral target_if internal 3856 * private data 3857 * 3858 * Return: On success, pointer to Spectral psoc target_if internal 3859 * private data, on failure, NULL 3860 */ 3861 static void * 3862 target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc) 3863 { 3864 struct target_if_psoc_spectral *psoc_spectral = NULL; 3865 3866 if (!psoc) { 3867 spectral_err("psoc is null"); 3868 goto fail; 3869 } 3870 3871 psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc( 3872 sizeof(struct target_if_psoc_spectral)); 3873 if (!psoc_spectral) { 3874 spectral_err("Spectral lmac psoc object allocation failed"); 3875 goto fail; 3876 } 3877 3878 psoc_spectral->psoc_obj = psoc; 3879 3880 return psoc_spectral; 3881 3882 fail: 3883 if (psoc_spectral) 3884 target_if_psoc_spectral_deinit(psoc); 3885 3886 return psoc_spectral; 3887 } 3888 3889 /** 3890 * target_if_calculate_center_freq() - Helper routine to 3891 * check whether given frequency is center frequency of a 3892 * WLAN channel 3893 * 3894 * @spectral: Pointer to Spectral object 3895 * @chan_freq: Center frequency of a WLAN channel 3896 * @is_valid: Indicates whether given frequency is valid 3897 * 3898 * Return: QDF_STATUS 3899 */ 3900 static QDF_STATUS 3901 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, 3902 uint32_t chan_freq, 3903 bool *is_valid) 3904 { 3905 struct regulatory_channel *cur_chan_list; 3906 int i; 3907 3908 if (!pdev) { 3909 spectral_err("pdev object is null"); 3910 return QDF_STATUS_E_FAILURE; 3911 } 3912 3913 if (!is_valid) { 3914 spectral_err("is valid argument is null"); 3915 return QDF_STATUS_E_FAILURE; 3916 } 3917 3918 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); 3919 if (!cur_chan_list) 3920 return QDF_STATUS_E_FAILURE; 3921 3922 if (wlan_reg_get_current_chan_list( 3923 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 3924 spectral_err("Failed to get cur_chan list"); 3925 qdf_mem_free(cur_chan_list); 3926 return QDF_STATUS_E_FAILURE; 3927 } 3928 3929 *is_valid = false; 3930 for (i = 0; i < NUM_CHANNELS; i++) { 3931 uint32_t flags; 3932 uint32_t center_freq; 3933 3934 flags = cur_chan_list[i].chan_flags; 3935 center_freq = cur_chan_list[i].center_freq; 3936 3937 if (!(flags & REGULATORY_CHAN_DISABLED) && 3938 (center_freq == chan_freq)) { 3939 *is_valid = true; 3940 break; 3941 } 3942 } 3943 3944 qdf_mem_free(cur_chan_list); 3945 3946 return QDF_STATUS_SUCCESS; 3947 } 3948 3949 /** 3950 * target_if_calculate_center_freq() - Helper routine to 3951 * find the center frequency of the agile span from a 3952 * WLAN channel center frequency 3953 * 3954 * @spectral: Pointer to Spectral object 3955 * @ch_width: Channel width array 3956 * @chan_freq: Center frequency of a WLAN channel 3957 * @center_freq: Pointer to center frequency 3958 * 3959 * Return: QDF_STATUS 3960 */ 3961 static QDF_STATUS 3962 target_if_calculate_center_freq(struct target_if_spectral *spectral, 3963 enum phy_ch_width *ch_width, 3964 uint16_t chan_freq, 3965 uint16_t *center_freq) 3966 { 3967 enum phy_ch_width agile_ch_width; 3968 3969 if (!spectral) { 3970 spectral_err("spectral target if object is null"); 3971 return QDF_STATUS_E_FAILURE; 3972 } 3973 3974 if (!ch_width) { 3975 spectral_err("Channel width array is null"); 3976 return QDF_STATUS_E_INVAL; 3977 } 3978 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 3979 3980 if (!center_freq) { 3981 spectral_err("center_freq argument is null"); 3982 return QDF_STATUS_E_FAILURE; 3983 } 3984 3985 if (agile_ch_width == CH_WIDTH_20MHZ) { 3986 *center_freq = chan_freq; 3987 } else { 3988 uint16_t start_freq; 3989 uint16_t end_freq; 3990 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 3991 enum channel_state state; 3992 3993 state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode 3994 (spectral->pdev_obj, chan_freq, agile_ch_width, 3995 &bonded_chan_ptr, REG_CURRENT_PWR_MODE, 3996 NO_SCHANS_PUNC); 3997 if (state == CHANNEL_STATE_DISABLE || 3998 state == CHANNEL_STATE_INVALID) { 3999 spectral_err("Channel state is disable or invalid"); 4000 return QDF_STATUS_E_FAILURE; 4001 } 4002 if (!bonded_chan_ptr) { 4003 spectral_err("Bonded channel is not found"); 4004 return QDF_STATUS_E_FAILURE; 4005 } 4006 start_freq = bonded_chan_ptr->start_freq; 4007 end_freq = bonded_chan_ptr->end_freq; 4008 *center_freq = (start_freq + end_freq) >> 1; 4009 } 4010 4011 return QDF_STATUS_SUCCESS; 4012 } 4013 4014 /** 4015 * target_if_validate_center_freq() - Helper routine to 4016 * validate user provided agile center frequency 4017 * 4018 * @spectral: Pointer to Spectral object 4019 * @ch_width: Channel width array 4020 * @center_freq: User provided agile span center frequency 4021 * @is_valid: Indicates whether agile span center frequency is valid 4022 * 4023 * Return: QDF_STATUS 4024 */ 4025 static QDF_STATUS 4026 target_if_validate_center_freq(struct target_if_spectral *spectral, 4027 enum phy_ch_width *ch_width, 4028 uint16_t center_freq, 4029 bool *is_valid) 4030 { 4031 enum phy_ch_width agile_ch_width; 4032 struct wlan_objmgr_pdev *pdev; 4033 QDF_STATUS status; 4034 4035 if (!spectral) { 4036 spectral_err("spectral target if object is null"); 4037 return QDF_STATUS_E_FAILURE; 4038 } 4039 4040 if (!ch_width) { 4041 spectral_err("channel width array is null"); 4042 return QDF_STATUS_E_INVAL; 4043 } 4044 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 4045 4046 if (!is_valid) { 4047 spectral_err("is_valid argument is null"); 4048 return QDF_STATUS_E_FAILURE; 4049 } 4050 4051 pdev = spectral->pdev_obj; 4052 4053 if (agile_ch_width == CH_WIDTH_20MHZ) { 4054 status = target_if_is_center_freq_of_any_chan 4055 (pdev, center_freq, is_valid); 4056 if (QDF_IS_STATUS_ERROR(status)) 4057 return QDF_STATUS_E_FAILURE; 4058 } else { 4059 uint16_t start_freq; 4060 uint16_t end_freq; 4061 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 4062 bool is_chan; 4063 4064 status = target_if_is_center_freq_of_any_chan 4065 (pdev, center_freq + FREQ_OFFSET_10MHZ, 4066 &is_chan); 4067 if (QDF_IS_STATUS_ERROR(status)) 4068 return QDF_STATUS_E_FAILURE; 4069 4070 if (is_chan) { 4071 uint32_t calulated_center_freq; 4072 enum channel_state st; 4073 4074 st = 4075 wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode 4076 (pdev, center_freq + FREQ_OFFSET_10MHZ, 4077 agile_ch_width, 4078 &bonded_chan_ptr, 4079 REG_CURRENT_PWR_MODE, 4080 NO_SCHANS_PUNC); 4081 if (st == CHANNEL_STATE_DISABLE || 4082 st == CHANNEL_STATE_INVALID) { 4083 spectral_err("Channel state disable/invalid"); 4084 return QDF_STATUS_E_FAILURE; 4085 } 4086 if (!bonded_chan_ptr) { 4087 spectral_err("Bonded channel is not found"); 4088 return QDF_STATUS_E_FAILURE; 4089 } 4090 start_freq = bonded_chan_ptr->start_freq; 4091 end_freq = bonded_chan_ptr->end_freq; 4092 calulated_center_freq = (start_freq + end_freq) >> 1; 4093 *is_valid = (center_freq == calulated_center_freq); 4094 } else { 4095 *is_valid = false; 4096 } 4097 } 4098 4099 return QDF_STATUS_SUCCESS; 4100 } 4101 4102 /** 4103 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to 4104 * check whether agile span overlaps with current operating band. 4105 * 4106 * @spectral: Pointer to Spectral object 4107 * @ch_width: Channel width array 4108 * @center_freq: Agile span center frequency 4109 * @is_overlapping: Indicates whether Agile span overlaps with operating span 4110 * 4111 * Helper routine to check whether agile span overlaps with current 4112 * operating band. 4113 * 4114 * Return: QDF_STATUS 4115 */ 4116 static QDF_STATUS 4117 target_if_is_agile_span_overlap_with_operating_span 4118 (struct target_if_spectral *spectral, 4119 enum phy_ch_width *ch_width, 4120 struct spectral_config_frequency *center_freq, 4121 bool *is_overlapping) 4122 { 4123 enum phy_ch_width op_ch_width; 4124 enum phy_ch_width agile_ch_width; 4125 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 4126 struct wlan_objmgr_vdev *vdev; 4127 struct wlan_objmgr_pdev *pdev; 4128 int16_t chan_freq; 4129 uint32_t op_start_freq; 4130 uint32_t op_end_freq; 4131 uint32_t agile_start_freq; 4132 uint32_t agile_end_freq; 4133 uint32_t cfreq2; 4134 4135 if (!spectral) { 4136 spectral_err("Spectral object is NULL"); 4137 return QDF_STATUS_E_FAILURE; 4138 } 4139 4140 pdev = spectral->pdev_obj; 4141 if (!pdev) { 4142 spectral_err("pdev object is NULL"); 4143 return QDF_STATUS_E_FAILURE; 4144 } 4145 4146 if (!ch_width) { 4147 spectral_err("channel width array is null"); 4148 return QDF_STATUS_E_FAILURE; 4149 } 4150 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 4151 if (op_ch_width == CH_WIDTH_INVALID) { 4152 spectral_err("Invalid channel width"); 4153 return QDF_STATUS_E_INVAL; 4154 } 4155 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 4156 if (agile_ch_width == CH_WIDTH_INVALID) { 4157 spectral_err("Invalid channel width"); 4158 return QDF_STATUS_E_INVAL; 4159 } 4160 4161 if (!is_overlapping) { 4162 spectral_err("Argument(is_overlapping) is NULL"); 4163 return QDF_STATUS_E_FAILURE; 4164 } 4165 *is_overlapping = false; 4166 4167 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 4168 if (!vdev) { 4169 spectral_err("vdev is NULL"); 4170 return QDF_STATUS_E_FAILURE; 4171 } 4172 chan_freq = target_if_vdev_get_chan_freq(vdev); 4173 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); 4174 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4175 if (cfreq2 < 0) { 4176 spectral_err("cfreq2 is invalid"); 4177 return QDF_STATUS_E_FAILURE; 4178 } 4179 4180 if (op_ch_width == CH_WIDTH_20MHZ) { 4181 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; 4182 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; 4183 } else { 4184 enum channel_state state; 4185 4186 state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode 4187 (pdev, chan_freq, op_ch_width, &bonded_chan_ptr, 4188 REG_CURRENT_PWR_MODE, NO_SCHANS_PUNC); 4189 if (state == CHANNEL_STATE_DISABLE || 4190 state == CHANNEL_STATE_INVALID) { 4191 spectral_err("Channel state is disable or invalid"); 4192 return QDF_STATUS_E_FAILURE; 4193 } 4194 if (!bonded_chan_ptr) { 4195 spectral_err("Bonded channel is not found"); 4196 return QDF_STATUS_E_FAILURE; 4197 } 4198 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; 4199 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; 4200 } 4201 4202 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 4203 agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 4204 agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 4205 if (agile_end_freq > op_start_freq && 4206 op_end_freq > agile_start_freq) 4207 *is_overlapping = true; 4208 4209 agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 4210 agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 4211 if (agile_end_freq > op_start_freq && 4212 op_end_freq > agile_start_freq) 4213 *is_overlapping = true; 4214 } else { 4215 agile_start_freq = center_freq->cfreq1 - 4216 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4217 agile_end_freq = center_freq->cfreq1 + 4218 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4219 if (agile_end_freq > op_start_freq && 4220 op_end_freq > agile_start_freq) 4221 *is_overlapping = true; 4222 } 4223 4224 if (op_ch_width == CH_WIDTH_80P80MHZ) { 4225 uint32_t sec80_start_feq; 4226 uint32_t sec80_end_freq; 4227 4228 sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ; 4229 sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ; 4230 4231 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 4232 agile_start_freq = 4233 center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 4234 agile_end_freq = 4235 center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 4236 if (agile_end_freq > sec80_start_feq && 4237 sec80_end_freq > agile_start_freq) 4238 *is_overlapping = true; 4239 4240 agile_start_freq = 4241 center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 4242 agile_end_freq = 4243 center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 4244 if (agile_end_freq > sec80_start_feq && 4245 sec80_end_freq > agile_start_freq) 4246 *is_overlapping = true; 4247 } else { 4248 agile_start_freq = center_freq->cfreq1 - 4249 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4250 agile_end_freq = center_freq->cfreq1 + 4251 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4252 if (agile_end_freq > sec80_start_feq && 4253 sec80_end_freq > agile_start_freq) 4254 *is_overlapping = true; 4255 } 4256 } 4257 4258 return QDF_STATUS_SUCCESS; 4259 } 4260 4261 /** 4262 * target_if_spectral_populate_chwidth() - Helper routine to 4263 * populate channel width for different Spectral modes 4264 * 4265 * @spectral: Pointer to Spectral object 4266 * @ch_width: Channel width array 4267 * @is_80_80_agile: Indicates whether 80+80 agile scan is requested 4268 * 4269 * Helper routine to populate channel width for different Spectral modes 4270 * 4271 * Return: QDF_STATUS 4272 */ 4273 static QDF_STATUS 4274 target_if_spectral_populate_chwidth(struct target_if_spectral *spectral, 4275 enum phy_ch_width *ch_width, 4276 bool is_80_80_agile) 4277 { 4278 enum spectral_scan_mode smode; 4279 4280 qdf_assert_always(spectral); 4281 4282 smode = SPECTRAL_SCAN_MODE_NORMAL; 4283 for (; smode < SPECTRAL_SCAN_MODE_MAX; ++smode) { 4284 /* If user has configured sscan bandwidth, use it */ 4285 if (spectral->sscan_width_configured[smode]) { 4286 ch_width[smode] = spectral->params[smode].ss_bandwidth; 4287 } else { 4288 /* Otherwise, derive the default sscan bandwidth */ 4289 ch_width[smode] = get_default_sscan_bw(spectral, smode, 4290 is_80_80_agile); 4291 if (ch_width[smode] >= CH_WIDTH_INVALID) { 4292 spectral_err("Invalid sscan BW %u", 4293 ch_width[smode]); 4294 return QDF_STATUS_E_FAILURE; 4295 } 4296 spectral->params[smode].ss_bandwidth = ch_width[smode]; 4297 } 4298 } 4299 4300 return QDF_STATUS_SUCCESS; 4301 } 4302 4303 /** 4304 * target_if_spectral_is_valid_80p80_freq() - API to check whether given 4305 * (cfreq1, cfreq2) pair forms a valid 80+80 combination 4306 * @pdev: pointer to pdev 4307 * @cfreq1: center frequency 1 4308 * @cfreq2: center frequency 2 4309 * 4310 * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80 4311 * combination 4312 * 4313 * Return: true or false 4314 */ 4315 static bool 4316 target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev, 4317 uint32_t cfreq1, uint32_t cfreq2) 4318 { 4319 struct ch_params ch_params = {0}; 4320 enum channel_state chan_state1; 4321 enum channel_state chan_state2; 4322 struct wlan_objmgr_psoc *psoc; 4323 struct ch_params temp_params = {0}; 4324 4325 qdf_assert_always(pdev); 4326 psoc = wlan_pdev_get_psoc(pdev); 4327 qdf_assert_always(psoc); 4328 4329 /* In restricted 80P80 MHz enabled, only one 80+80 MHz 4330 * channel is supported with cfreq=5690 and cfreq=5775. 4331 */ 4332 if (wlan_psoc_nif_fw_ext_cap_get( 4333 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) 4334 return CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2); 4335 4336 ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2); 4337 ch_params.mhz_freq_seg1 = cfreq2; 4338 ch_params.ch_width = CH_WIDTH_80P80MHZ; 4339 wlan_reg_set_channel_params_for_pwrmode( 4340 pdev, 4341 cfreq1 - FREQ_OFFSET_10MHZ, 4342 0, 4343 &ch_params, 4344 REG_CURRENT_PWR_MODE); 4345 4346 if (ch_params.ch_width != CH_WIDTH_80P80MHZ) 4347 return false; 4348 4349 if (ch_params.mhz_freq_seg0 != cfreq1 || 4350 ch_params.mhz_freq_seg1 != cfreq2) 4351 return false; 4352 4353 temp_params.ch_width = CH_WIDTH_80MHZ; 4354 chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode( 4355 pdev, 4356 ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ, 4357 &temp_params, 4358 REG_CURRENT_PWR_MODE); 4359 if ((chan_state1 == CHANNEL_STATE_DISABLE) || 4360 (chan_state1 == CHANNEL_STATE_INVALID)) 4361 return false; 4362 4363 temp_params.ch_width = CH_WIDTH_80MHZ; 4364 chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode( 4365 pdev, 4366 ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ, 4367 &temp_params, 4368 REG_CURRENT_PWR_MODE); 4369 if ((chan_state2 == CHANNEL_STATE_DISABLE) || 4370 (chan_state2 == CHANNEL_STATE_INVALID)) 4371 return false; 4372 4373 if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <= 4374 FREQ_OFFSET_80MHZ) 4375 return false; 4376 4377 return true; 4378 } 4379 4380 /** 4381 * _target_if_set_spectral_config() - Set spectral config 4382 * @spectral: Pointer to spectral object 4383 * @param: Spectral parameter id and value 4384 * @smode: Spectral scan mode 4385 * @err: Spectral error code 4386 * 4387 * API to set spectral configurations 4388 * 4389 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4390 */ 4391 static QDF_STATUS 4392 _target_if_set_spectral_config(struct target_if_spectral *spectral, 4393 const struct spectral_cp_param *param, 4394 const enum spectral_scan_mode smode, 4395 enum spectral_cp_error_code *err) 4396 { 4397 struct spectral_config params; 4398 struct target_if_spectral_ops *p_sops; 4399 struct spectral_config *sparams; 4400 QDF_STATUS status; 4401 bool is_overlapping; 4402 uint16_t agile_cfreq; 4403 bool is_valid_chan; 4404 struct spectral_param_min_max *param_min_max; 4405 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 4406 enum spectral_scan_mode m; 4407 struct spectral_config_frequency center_freq = {0}; 4408 bool is_bw_supported; 4409 struct wlan_objmgr_vdev *vdev; 4410 enum phy_ch_width op_bw; 4411 4412 if (!err) { 4413 spectral_err("Error code argument is null"); 4414 QDF_ASSERT(0); 4415 return QDF_STATUS_E_FAILURE; 4416 } 4417 *err = SPECTRAL_SCAN_ERR_INVALID; 4418 4419 if (!param) { 4420 spectral_err("Parameter object is null"); 4421 return QDF_STATUS_E_FAILURE; 4422 } 4423 4424 if (!spectral) { 4425 spectral_err("spectral object is NULL"); 4426 return QDF_STATUS_E_FAILURE; 4427 } 4428 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4429 param_min_max = &spectral->param_min_max; 4430 4431 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4432 spectral_err("Invalid Spectral mode %u", smode); 4433 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4434 return QDF_STATUS_E_FAILURE; 4435 } 4436 4437 sparams = &spectral->params[smode]; 4438 m = SPECTRAL_SCAN_MODE_NORMAL; 4439 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 4440 ch_width[m] = CH_WIDTH_INVALID; 4441 4442 if (!spectral->params_valid[smode]) { 4443 target_if_spectral_info_read(spectral, 4444 smode, 4445 TARGET_IF_SPECTRAL_INFO_PARAMS, 4446 &spectral->params[smode], 4447 sizeof(spectral->params[smode])); 4448 spectral->params_valid[smode] = true; 4449 } 4450 4451 switch (param->id) { 4452 case SPECTRAL_PARAM_FFT_PERIOD: 4453 sparams->ss_fft_period = param->value; 4454 break; 4455 case SPECTRAL_PARAM_SCAN_PERIOD: 4456 sparams->ss_period = param->value; 4457 if (sparams->ss_recapture && ((sparams->ss_period < 4458 SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD) || 4459 (smode == SPECTRAL_SCAN_MODE_AGILE))) { 4460 sparams->ss_recapture = false; 4461 spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d", 4462 sparams->ss_period, smode); 4463 } 4464 break; 4465 case SPECTRAL_PARAM_FFT_RECAPTURE: 4466 if (param->value) { 4467 if (sparams->ss_period >= 4468 SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD && 4469 smode == SPECTRAL_SCAN_MODE_NORMAL) { 4470 sparams->ss_recapture = true; 4471 } else { 4472 spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d", 4473 sparams->ss_period, smode); 4474 sparams->ss_recapture = false; 4475 } 4476 } else { 4477 sparams->ss_recapture = false; 4478 } 4479 break; 4480 case SPECTRAL_PARAM_SCAN_COUNT: 4481 sparams->ss_count = param->value; 4482 break; 4483 case SPECTRAL_PARAM_SHORT_REPORT: 4484 sparams->ss_short_report = (!!param->value) ? true : false; 4485 break; 4486 case SPECTRAL_PARAM_SPECT_PRI: 4487 sparams->ss_spectral_pri = (!!param->value) ? true : false; 4488 break; 4489 case SPECTRAL_PARAM_FFT_SIZE: 4490 status = target_if_spectral_populate_chwidth 4491 (spectral, ch_width, spectral->params 4492 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 4493 if (QDF_IS_STATUS_ERROR(status)) 4494 return QDF_STATUS_E_FAILURE; 4495 if ((param->value < param_min_max->fft_size_min) || 4496 (param->value > param_min_max->fft_size_max 4497 [ch_width[smode]])) { 4498 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4499 return QDF_STATUS_E_FAILURE; 4500 } 4501 sparams->ss_fft_size = param->value; 4502 break; 4503 case SPECTRAL_PARAM_GC_ENA: 4504 sparams->ss_gc_ena = !!param->value; 4505 break; 4506 case SPECTRAL_PARAM_RESTART_ENA: 4507 sparams->ss_restart_ena = !!param->value; 4508 break; 4509 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 4510 sparams->ss_noise_floor_ref = param->value; 4511 break; 4512 case SPECTRAL_PARAM_INIT_DELAY: 4513 sparams->ss_init_delay = param->value; 4514 break; 4515 case SPECTRAL_PARAM_NB_TONE_THR: 4516 sparams->ss_nb_tone_thr = param->value; 4517 break; 4518 case SPECTRAL_PARAM_STR_BIN_THR: 4519 sparams->ss_str_bin_thr = param->value; 4520 break; 4521 case SPECTRAL_PARAM_WB_RPT_MODE: 4522 sparams->ss_wb_rpt_mode = !!param->value; 4523 break; 4524 case SPECTRAL_PARAM_RSSI_RPT_MODE: 4525 sparams->ss_rssi_rpt_mode = !!param->value; 4526 break; 4527 case SPECTRAL_PARAM_RSSI_THR: 4528 sparams->ss_rssi_thr = param->value; 4529 break; 4530 case SPECTRAL_PARAM_PWR_FORMAT: 4531 sparams->ss_pwr_format = !!param->value; 4532 break; 4533 case SPECTRAL_PARAM_RPT_MODE: 4534 if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) || 4535 (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) { 4536 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4537 return QDF_STATUS_E_FAILURE; 4538 } 4539 sparams->ss_rpt_mode = param->value; 4540 break; 4541 case SPECTRAL_PARAM_BIN_SCALE: 4542 sparams->ss_bin_scale = param->value; 4543 break; 4544 case SPECTRAL_PARAM_DBM_ADJ: 4545 sparams->ss_dbm_adj = !!param->value; 4546 break; 4547 case SPECTRAL_PARAM_CHN_MASK: 4548 sparams->ss_chn_mask = param->value; 4549 break; 4550 case SPECTRAL_PARAM_FREQUENCY: 4551 status = target_if_spectral_populate_chwidth( 4552 spectral, ch_width, param->freq.cfreq2 > 0); 4553 if (QDF_IS_STATUS_ERROR(status)) { 4554 spectral_err("Failed to populate channel width"); 4555 return QDF_STATUS_E_FAILURE; 4556 } 4557 4558 if (ch_width[smode] != CH_WIDTH_80P80MHZ && 4559 param->freq.cfreq2) { 4560 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4561 spectral_err("Non zero cfreq2 expected for 80p80 only"); 4562 return QDF_STATUS_E_INVAL; 4563 } 4564 4565 if (ch_width[smode] == CH_WIDTH_80P80MHZ && 4566 !param->freq.cfreq2) { 4567 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4568 spectral_err("Non zero cfreq2 expected for 80p80"); 4569 return QDF_STATUS_E_INVAL; 4570 } 4571 4572 status = target_if_is_center_freq_of_any_chan 4573 (spectral->pdev_obj, param->freq.cfreq1, 4574 &is_valid_chan); 4575 if (QDF_IS_STATUS_ERROR(status)) 4576 return QDF_STATUS_E_FAILURE; 4577 4578 if (is_valid_chan) { 4579 status = target_if_calculate_center_freq( 4580 spectral, ch_width, 4581 param->freq.cfreq1, 4582 &agile_cfreq); 4583 if (QDF_IS_STATUS_ERROR(status)) { 4584 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4585 return QDF_STATUS_E_FAILURE; 4586 } 4587 } else { 4588 bool is_valid_agile_cfreq; 4589 4590 status = target_if_validate_center_freq 4591 (spectral, ch_width, param->freq.cfreq1, 4592 &is_valid_agile_cfreq); 4593 if (QDF_IS_STATUS_ERROR(status)) 4594 return QDF_STATUS_E_FAILURE; 4595 4596 if (!is_valid_agile_cfreq) { 4597 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4598 spectral_err("Invalid agile center frequency"); 4599 return QDF_STATUS_E_FAILURE; 4600 } 4601 4602 agile_cfreq = param->freq.cfreq1; 4603 } 4604 center_freq.cfreq1 = agile_cfreq; 4605 4606 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 4607 status = target_if_is_center_freq_of_any_chan 4608 (spectral->pdev_obj, param->freq.cfreq2, 4609 &is_valid_chan); 4610 if (QDF_IS_STATUS_ERROR(status)) 4611 return QDF_STATUS_E_FAILURE; 4612 4613 if (is_valid_chan) { 4614 status = target_if_calculate_center_freq( 4615 spectral, ch_width, 4616 param->freq.cfreq2, 4617 &agile_cfreq); 4618 if (QDF_IS_STATUS_ERROR(status)) { 4619 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4620 return QDF_STATUS_E_FAILURE; 4621 } 4622 } else { 4623 bool is_valid_agile_cfreq; 4624 4625 status = target_if_validate_center_freq 4626 (spectral, ch_width, param->freq.cfreq2, 4627 &is_valid_agile_cfreq); 4628 if (QDF_IS_STATUS_ERROR(status)) 4629 return QDF_STATUS_E_FAILURE; 4630 4631 if (!is_valid_agile_cfreq) { 4632 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4633 spectral_err("Invalid agile center frequency"); 4634 return QDF_STATUS_E_FAILURE; 4635 } 4636 4637 agile_cfreq = param->freq.cfreq2; 4638 } 4639 center_freq.cfreq2 = agile_cfreq; 4640 } 4641 4642 status = target_if_is_agile_span_overlap_with_operating_span 4643 (spectral, ch_width, 4644 ¢er_freq, &is_overlapping); 4645 if (QDF_IS_STATUS_ERROR(status)) 4646 return QDF_STATUS_E_FAILURE; 4647 4648 if (is_overlapping) { 4649 spectral_err("Agile freq %u, %u overlaps with operating span", 4650 center_freq.cfreq1, center_freq.cfreq2); 4651 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4652 return QDF_STATUS_E_FAILURE; 4653 } 4654 4655 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 4656 bool is_valid_80p80; 4657 4658 is_valid_80p80 = target_if_spectral_is_valid_80p80_freq( 4659 spectral->pdev_obj, 4660 center_freq.cfreq1, 4661 center_freq.cfreq2); 4662 4663 if (!is_valid_80p80) { 4664 spectral_err("Agile freq %u, %u is invalid 80+80 combination", 4665 center_freq.cfreq1, 4666 center_freq.cfreq2); 4667 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4668 return QDF_STATUS_E_FAILURE; 4669 } 4670 } 4671 4672 sparams->ss_frequency.cfreq1 = center_freq.cfreq1; 4673 sparams->ss_frequency.cfreq2 = center_freq.cfreq2; 4674 4675 break; 4676 4677 case SPECTRAL_PARAM_CHAN_WIDTH: 4678 if (param->value >= CH_WIDTH_INVALID) { 4679 spectral_err("invalid sscan width: %u", param->value); 4680 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4681 return QDF_STATUS_E_FAILURE; 4682 } 4683 4684 vdev = target_if_spectral_get_vdev(spectral, smode); 4685 if (!vdev) { 4686 spectral_err("vdev is null"); 4687 return QDF_STATUS_E_NULL_VALUE; 4688 } 4689 op_bw = target_if_vdev_get_ch_width(vdev); 4690 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4691 4692 /* Validate the bandwidth */ 4693 status = target_if_is_sscan_bw_supported( 4694 spectral, smode, 4695 param->value, op_bw, &is_bw_supported, 4696 spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 4697 ss_frequency.cfreq2 > 0); 4698 if (QDF_IS_STATUS_ERROR(status)) { 4699 spectral_err("Unable to check if given sscan_bw is supported"); 4700 return QDF_STATUS_E_FAILURE; 4701 } 4702 4703 if (!is_bw_supported) { 4704 spectral_err("sscan bw(%u) is not supported for the current operating width(%u) and sscan mode(%u)", 4705 param->value, op_bw, smode); 4706 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4707 return QDF_STATUS_E_FAILURE; 4708 } 4709 4710 sparams->ss_bandwidth = param->value; 4711 spectral->sscan_width_configured[smode] = true; 4712 4713 break; 4714 } 4715 4716 p_sops->configure_spectral(spectral, sparams, smode); 4717 /* only to validate the writes */ 4718 p_sops->get_spectral_config(spectral, ¶ms, smode); 4719 return QDF_STATUS_SUCCESS; 4720 } 4721 4722 QDF_STATUS 4723 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 4724 const struct spectral_cp_param *param, 4725 const enum spectral_scan_mode smode, 4726 enum spectral_cp_error_code *err) 4727 { 4728 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; 4729 struct target_if_spectral *spectral; 4730 QDF_STATUS status; 4731 4732 if (!err) { 4733 spectral_err("Error code argument is null"); 4734 QDF_ASSERT(0); 4735 return QDF_STATUS_E_FAILURE; 4736 } 4737 *err = SPECTRAL_SCAN_ERR_INVALID; 4738 4739 if (!pdev) { 4740 spectral_err("pdev object is NULL"); 4741 return QDF_STATUS_E_FAILURE; 4742 } 4743 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4744 if (!spectral) { 4745 spectral_err("spectral object is NULL"); 4746 return QDF_STATUS_E_FAILURE; 4747 } 4748 4749 if (!param) { 4750 spectral_err("parameter object is NULL"); 4751 return QDF_STATUS_E_FAILURE; 4752 } 4753 4754 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4755 spectral_err("Invalid Spectral mode %u", smode); 4756 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4757 return QDF_STATUS_E_FAILURE; 4758 } 4759 4760 if (!spectral->properties[smode][param->id].supported) { 4761 spectral_err("Spectral parameter(%u) unsupported for mode %u", 4762 param->id, smode); 4763 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 4764 return QDF_STATUS_E_FAILURE; 4765 } 4766 4767 if (spectral->properties[smode][param->id].common_all_modes) { 4768 spectral_warn("Setting Spectral parameter %u for all modes", 4769 param->id); 4770 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { 4771 status = _target_if_set_spectral_config 4772 (spectral, param, mode, err); 4773 if (QDF_IS_STATUS_ERROR(status)) 4774 return QDF_STATUS_E_FAILURE; 4775 } 4776 return QDF_STATUS_SUCCESS; 4777 } 4778 4779 return _target_if_set_spectral_config(spectral, param, smode, err); 4780 } 4781 4782 /** 4783 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 4784 * @fft_len: FFT length 4785 * @pdev: Pointer to pdev object 4786 * 4787 * API to get fft bin count for a given fft length 4788 * 4789 * Return: FFt bin count 4790 */ 4791 static int 4792 target_if_get_fft_bin_count(int fft_len) 4793 { 4794 int bin_count = 0; 4795 4796 switch (fft_len) { 4797 case 5: 4798 bin_count = 16; 4799 break; 4800 case 6: 4801 bin_count = 32; 4802 break; 4803 case 7: 4804 bin_count = 64; 4805 break; 4806 case 8: 4807 bin_count = 128; 4808 break; 4809 case 9: 4810 bin_count = 256; 4811 break; 4812 default: 4813 break; 4814 } 4815 4816 return bin_count; 4817 } 4818 4819 /** 4820 * target_if_init_upper_lower_flags() - Initializes control and extension 4821 * segment flags 4822 * @spectral: pointer to target if spectral object 4823 * @smode: Spectral scan mode 4824 * 4825 * API to initialize the control and extension flags with the lower/upper 4826 * segment based on the HT mode 4827 * 4828 * Return: FFt bin count 4829 */ 4830 static void 4831 target_if_init_upper_lower_flags(struct target_if_spectral *spectral, 4832 enum spectral_scan_mode smode) 4833 { 4834 int current_channel = 0; 4835 int ext_channel = 0; 4836 struct target_if_spectral_ops *p_sops = 4837 GET_TARGET_IF_SPECTRAL_OPS(spectral); 4838 4839 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4840 spectral_err("Invalid Spectral mode %u", smode); 4841 return; 4842 } 4843 current_channel = p_sops->get_current_channel(spectral, smode); 4844 ext_channel = p_sops->get_extension_channel(spectral, smode); 4845 4846 if ((current_channel == 0) || (ext_channel == 0)) 4847 return; 4848 4849 if (spectral->sc_spectral_20_40_mode) { 4850 /* HT40 mode */ 4851 if (ext_channel < current_channel) { 4852 spectral->lower_is_extension = 1; 4853 spectral->upper_is_control = 1; 4854 spectral->lower_is_control = 0; 4855 spectral->upper_is_extension = 0; 4856 } else { 4857 spectral->lower_is_extension = 0; 4858 spectral->upper_is_control = 0; 4859 spectral->lower_is_control = 1; 4860 spectral->upper_is_extension = 1; 4861 } 4862 } else { 4863 /* HT20 mode, lower is always control */ 4864 spectral->lower_is_extension = 0; 4865 spectral->upper_is_control = 0; 4866 spectral->lower_is_control = 1; 4867 spectral->upper_is_extension = 0; 4868 } 4869 } 4870 4871 /** 4872 * target_if_get_spectral_config() - Get spectral configuration 4873 * @pdev: Pointer to pdev object 4874 * @param: Pointer to spectral_config structure in which the configuration 4875 * should be returned 4876 * @smode: Spectral scan mode 4877 * 4878 * API to get the current spectral configuration 4879 * 4880 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4881 */ 4882 QDF_STATUS 4883 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 4884 struct spectral_config *param, 4885 enum spectral_scan_mode smode) 4886 { 4887 struct target_if_spectral_ops *p_sops = NULL; 4888 struct target_if_spectral *spectral = NULL; 4889 4890 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4891 4892 if (!spectral) { 4893 spectral_err("SPECTRAL : Module doesn't exist"); 4894 return QDF_STATUS_E_FAILURE; 4895 } 4896 4897 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4898 4899 if (!p_sops) { 4900 spectral_err("p_sops is null"); 4901 return QDF_STATUS_E_FAILURE; 4902 } 4903 4904 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4905 spectral_err("Invalid Spectral mode %u", smode); 4906 return QDF_STATUS_E_FAILURE; 4907 } 4908 4909 qdf_mem_zero(param, sizeof(struct spectral_config)); 4910 p_sops->get_spectral_config(spectral, param, smode); 4911 4912 return QDF_STATUS_SUCCESS; 4913 } 4914 4915 #ifdef WLAN_FEATURE_11BE 4916 /** 4917 * target_if_spectral_get_num_detectors_for_higher_bws() - Get number of 4918 * Spectral detectors for higher bandwidths 4919 * @spectral: Pointer to target if Spectral object 4920 * @ch_width: channel width 4921 * @num_detectors: Pointer to the variable to store number of Spectral detectors 4922 * 4923 * API to get number of Spectral detectors used for scan in the given channel 4924 * width. 4925 * 4926 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure 4927 */ 4928 static QDF_STATUS 4929 target_if_spectral_get_num_detectors_for_higher_bws( 4930 struct target_if_spectral *spectral, 4931 enum phy_ch_width ch_width, 4932 uint32_t *num_detectors) 4933 { 4934 switch (ch_width) { 4935 case CH_WIDTH_320MHZ: 4936 *num_detectors = spectral->capability.num_detectors_320mhz; 4937 break; 4938 4939 default: 4940 spectral_err("Unsupported channel width %d", ch_width); 4941 return QDF_STATUS_E_INVAL; 4942 } 4943 4944 return QDF_STATUS_SUCCESS; 4945 } 4946 #else 4947 static QDF_STATUS 4948 target_if_spectral_get_num_detectors_for_higher_bws( 4949 struct target_if_spectral *spectral, 4950 enum phy_ch_width ch_width, 4951 uint32_t *num_detectors) 4952 { 4953 spectral_err("Unsupported channel width %d", ch_width); 4954 return QDF_STATUS_E_INVAL; 4955 } 4956 #endif 4957 4958 /** 4959 * target_if_spectral_get_num_detectors() - Get number of Spectral detectors 4960 * @spectral: Pointer to target if Spectral object 4961 * @ch_width: channel width 4962 * @num_detectors: Pointer to the variable to store number of Spectral detectors 4963 * 4964 * API to get number of Spectral detectors used for scan in the given channel 4965 * width. 4966 * 4967 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure 4968 */ 4969 static QDF_STATUS 4970 target_if_spectral_get_num_detectors(struct target_if_spectral *spectral, 4971 enum phy_ch_width ch_width, 4972 uint32_t *num_detectors) 4973 { 4974 if (!spectral) { 4975 spectral_err("target if spectral object is null"); 4976 return QDF_STATUS_E_INVAL; 4977 } 4978 4979 if (ch_width >= CH_WIDTH_INVALID) { 4980 spectral_err("Invalid channel width %d", ch_width); 4981 return QDF_STATUS_E_INVAL; 4982 } 4983 4984 if (!num_detectors) { 4985 spectral_err("Invalid argument, number of detectors"); 4986 return QDF_STATUS_E_INVAL; 4987 } 4988 4989 switch (ch_width) { 4990 case CH_WIDTH_20MHZ: 4991 *num_detectors = spectral->capability.num_detectors_20mhz; 4992 break; 4993 4994 case CH_WIDTH_40MHZ: 4995 *num_detectors = spectral->capability.num_detectors_40mhz; 4996 break; 4997 4998 case CH_WIDTH_80MHZ: 4999 *num_detectors = spectral->capability.num_detectors_80mhz; 5000 break; 5001 5002 case CH_WIDTH_160MHZ: 5003 *num_detectors = spectral->capability.num_detectors_160mhz; 5004 break; 5005 5006 case CH_WIDTH_80P80MHZ: 5007 *num_detectors = spectral->capability.num_detectors_80p80mhz; 5008 break; 5009 5010 default: 5011 return target_if_spectral_get_num_detectors_for_higher_bws( 5012 spectral, ch_width, num_detectors); 5013 } 5014 5015 return QDF_STATUS_SUCCESS; 5016 } 5017 5018 /** 5019 * target_if_spectral_finite_scan_init() - Initializations required for finite 5020 * Spectral scan 5021 * @spectral: Pointer to target of Spctral object 5022 * @smode: Spectral scan mode 5023 * 5024 * This routine initializes the finite Spectral scan. Finite Spectral scan is 5025 * triggered by configuring a non zero scan count. 5026 * 5027 * Return: QDF_STATUS_SUCCESS on success 5028 */ 5029 static QDF_STATUS 5030 target_if_spectral_finite_scan_init(struct target_if_spectral *spectral, 5031 enum spectral_scan_mode smode) 5032 { 5033 struct target_if_finite_spectral_scan_params *finite_scan; 5034 enum phy_ch_width ch_width; 5035 uint32_t num_detectors; 5036 QDF_STATUS status; 5037 uint16_t sscan_count; 5038 5039 if (!spectral) { 5040 spectral_err("target if spectral object is null"); 5041 return QDF_STATUS_E_INVAL; 5042 } 5043 5044 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5045 spectral_err("Invalid Spectral mode"); 5046 return QDF_STATUS_E_INVAL; 5047 } 5048 5049 ch_width = spectral->ch_width[smode]; 5050 status = target_if_spectral_get_num_detectors(spectral, ch_width, 5051 &num_detectors); 5052 5053 if (QDF_IS_STATUS_ERROR(status)) { 5054 spectral_err("Failed to get number of detectors"); 5055 return QDF_STATUS_E_FAILURE; 5056 } 5057 5058 finite_scan = &spectral->finite_scan[smode]; 5059 sscan_count = spectral->params[smode].ss_count; 5060 5061 finite_scan->finite_spectral_scan = true; 5062 finite_scan->num_reports_expected = num_detectors * sscan_count; 5063 5064 return QDF_STATUS_SUCCESS; 5065 } 5066 5067 /** 5068 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 5069 * parameters 5070 * @spectral: Pointer to Spectral target_if internal private data 5071 * @spectral_params: Pointer to Spectral parameters 5072 * @smode: Spectral scan mode 5073 * @err: Spectral error code 5074 * 5075 * Enable use of desired Spectral parameters by configuring them into HW, and 5076 * starting Spectral scan 5077 * 5078 * Return: 0 on success, 1 on failure 5079 */ 5080 int 5081 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 5082 struct spectral_config *spectral_params, 5083 enum spectral_scan_mode smode, 5084 enum spectral_cp_error_code *err) 5085 { 5086 int extension_channel = 0; 5087 int current_channel = 0; 5088 struct target_if_spectral_ops *p_sops = NULL; 5089 QDF_STATUS status; 5090 struct wlan_objmgr_pdev *pdev; 5091 struct wlan_objmgr_psoc *psoc; 5092 5093 if (!spectral) { 5094 spectral_err("Spectral LMAC object is NULL"); 5095 return 1; 5096 } 5097 5098 pdev = spectral->pdev_obj; 5099 if (!pdev) { 5100 spectral_err("pdev is null"); 5101 return QDF_STATUS_E_INVAL; 5102 } 5103 5104 psoc = wlan_pdev_get_psoc(pdev); 5105 if (!psoc) { 5106 spectral_err("psoc is null"); 5107 return QDF_STATUS_E_INVAL; 5108 } 5109 5110 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5111 spectral_err("Invalid Spectral mode %u", smode); 5112 return 1; 5113 } 5114 5115 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5116 5117 if (!p_sops) { 5118 spectral_err("p_sops is NULL"); 5119 return 1; 5120 } 5121 5122 spectral->sc_spectral_noise_pwr_cal = 5123 spectral_params->ss_spectral_pri ? 1 : 0; 5124 5125 /* check if extension channel is present */ 5126 extension_channel = p_sops->get_extension_channel(spectral, smode); 5127 current_channel = p_sops->get_current_channel(spectral, smode); 5128 5129 if (spectral->capability.advncd_spectral_cap) { 5130 spectral->lb_edge_extrabins = 0; 5131 spectral->rb_edge_extrabins = 0; 5132 5133 if (spectral->is_lb_edge_extrabins_format && 5134 spectral->params[smode].ss_rpt_mode == 2) { 5135 spectral->lb_edge_extrabins = 4; 5136 } 5137 5138 if (spectral->is_rb_edge_extrabins_format && 5139 spectral->params[smode].ss_rpt_mode == 2) { 5140 spectral->rb_edge_extrabins = 4; 5141 } 5142 5143 if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) { 5144 spectral->sc_spectral_20_40_mode = 0; 5145 5146 spectral->spectral_numbins = 5147 target_if_get_fft_bin_count( 5148 spectral->params[smode].ss_fft_size); 5149 spectral->spectral_fft_len = 5150 target_if_get_fft_bin_count( 5151 spectral->params[smode].ss_fft_size); 5152 spectral->spectral_data_len = 5153 target_if_get_fft_bin_count( 5154 spectral->params[smode].ss_fft_size); 5155 /* 5156 * Initialize classifier params to be sent to user 5157 * space classifier 5158 */ 5159 spectral->classifier_params.lower_chan_in_mhz = 5160 current_channel; 5161 spectral->classifier_params.upper_chan_in_mhz = 0; 5162 5163 } else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) { 5164 /* TODO : Remove this variable */ 5165 spectral->sc_spectral_20_40_mode = 1; 5166 spectral->spectral_numbins = 5167 target_if_get_fft_bin_count( 5168 spectral->params[smode].ss_fft_size); 5169 spectral->spectral_fft_len = 5170 target_if_get_fft_bin_count( 5171 spectral->params[smode].ss_fft_size); 5172 spectral->spectral_data_len = 5173 target_if_get_fft_bin_count( 5174 spectral->params[smode].ss_fft_size); 5175 5176 /* 5177 * Initialize classifier params to be sent to user 5178 * space classifier 5179 */ 5180 if (extension_channel < current_channel) { 5181 spectral->classifier_params.lower_chan_in_mhz = 5182 extension_channel; 5183 spectral->classifier_params.upper_chan_in_mhz = 5184 current_channel; 5185 } else { 5186 spectral->classifier_params.lower_chan_in_mhz = 5187 current_channel; 5188 spectral->classifier_params.upper_chan_in_mhz = 5189 extension_channel; 5190 } 5191 5192 } else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) { 5193 /* Set the FFT Size */ 5194 /* TODO : Remove this variable */ 5195 spectral->sc_spectral_20_40_mode = 0; 5196 spectral->spectral_numbins = 5197 target_if_get_fft_bin_count( 5198 spectral->params[smode].ss_fft_size); 5199 spectral->spectral_fft_len = 5200 target_if_get_fft_bin_count( 5201 spectral->params[smode].ss_fft_size); 5202 spectral->spectral_data_len = 5203 target_if_get_fft_bin_count( 5204 spectral->params[smode].ss_fft_size); 5205 5206 /* 5207 * Initialize classifier params to be sent to user 5208 * space classifier 5209 */ 5210 spectral->classifier_params.lower_chan_in_mhz = 5211 current_channel; 5212 spectral->classifier_params.upper_chan_in_mhz = 0; 5213 5214 /* 5215 * Initialize classifier params to be sent to user 5216 * space classifier 5217 */ 5218 if (extension_channel < current_channel) { 5219 spectral->classifier_params.lower_chan_in_mhz = 5220 extension_channel; 5221 spectral->classifier_params.upper_chan_in_mhz = 5222 current_channel; 5223 } else { 5224 spectral->classifier_params.lower_chan_in_mhz = 5225 current_channel; 5226 spectral->classifier_params.upper_chan_in_mhz = 5227 extension_channel; 5228 } 5229 5230 } else if (is_ch_width_160_or_80p80( 5231 spectral->ch_width[smode])) { 5232 /* Set the FFT Size */ 5233 5234 /* The below applies to both 160 and 80+80 cases */ 5235 5236 /* TODO : Remove this variable */ 5237 spectral->sc_spectral_20_40_mode = 0; 5238 spectral->spectral_numbins = 5239 target_if_get_fft_bin_count( 5240 spectral->params[smode].ss_fft_size); 5241 spectral->spectral_fft_len = 5242 target_if_get_fft_bin_count( 5243 spectral->params[smode].ss_fft_size); 5244 spectral->spectral_data_len = 5245 target_if_get_fft_bin_count( 5246 spectral->params[smode].ss_fft_size); 5247 5248 /* 5249 * Initialize classifier params to be sent to user 5250 * space classifier 5251 */ 5252 spectral->classifier_params.lower_chan_in_mhz = 5253 current_channel; 5254 spectral->classifier_params.upper_chan_in_mhz = 0; 5255 5256 /* 5257 * Initialize classifier params to be sent to user 5258 * space classifier 5259 */ 5260 if (extension_channel < current_channel) { 5261 spectral->classifier_params.lower_chan_in_mhz = 5262 extension_channel; 5263 spectral->classifier_params.upper_chan_in_mhz = 5264 current_channel; 5265 } else { 5266 spectral->classifier_params.lower_chan_in_mhz = 5267 current_channel; 5268 spectral->classifier_params.upper_chan_in_mhz = 5269 extension_channel; 5270 } 5271 } 5272 5273 if (spectral->spectral_numbins) { 5274 spectral->spectral_numbins += 5275 spectral->lb_edge_extrabins; 5276 spectral->spectral_numbins += 5277 spectral->rb_edge_extrabins; 5278 } 5279 5280 if (spectral->spectral_fft_len) { 5281 spectral->spectral_fft_len += 5282 spectral->lb_edge_extrabins; 5283 spectral->spectral_fft_len += 5284 spectral->rb_edge_extrabins; 5285 } 5286 5287 if (spectral->spectral_data_len) { 5288 spectral->spectral_data_len += 5289 spectral->lb_edge_extrabins; 5290 spectral->spectral_data_len += 5291 spectral->rb_edge_extrabins; 5292 } 5293 } else { 5294 /* 5295 * The decision to find 20/40 mode is found based on the 5296 * presence of extension channel 5297 * instead of channel width, as the channel width can 5298 * dynamically change 5299 */ 5300 5301 if (extension_channel == 0) { 5302 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 5303 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 5304 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 5305 spectral->spectral_data_len = 5306 SPECTRAL_HT20_TOTAL_DATA_LEN; 5307 /* only valid in 20-40 mode */ 5308 spectral->spectral_lower_max_index_offset = -1; 5309 /* only valid in 20-40 mode */ 5310 spectral->spectral_upper_max_index_offset = -1; 5311 spectral->spectral_max_index_offset = 5312 spectral->spectral_fft_len + 2; 5313 spectral->sc_spectral_20_40_mode = 0; 5314 5315 /* 5316 * Initialize classifier params to be sent to user 5317 * space classifier 5318 */ 5319 spectral->classifier_params.lower_chan_in_mhz = 5320 current_channel; 5321 spectral->classifier_params.upper_chan_in_mhz = 0; 5322 5323 } else { 5324 spectral->spectral_numbins = 5325 SPECTRAL_HT40_TOTAL_NUM_BINS; 5326 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 5327 spectral->spectral_data_len = 5328 SPECTRAL_HT40_TOTAL_DATA_LEN; 5329 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 5330 /* only valid in 20 mode */ 5331 spectral->spectral_max_index_offset = -1; 5332 spectral->spectral_lower_max_index_offset = 5333 spectral->spectral_fft_len + 2; 5334 spectral->spectral_upper_max_index_offset = 5335 spectral->spectral_fft_len + 5; 5336 spectral->sc_spectral_20_40_mode = 1; 5337 5338 /* 5339 * Initialize classifier params to be sent to user 5340 * space classifier 5341 */ 5342 if (extension_channel < current_channel) { 5343 spectral->classifier_params.lower_chan_in_mhz = 5344 extension_channel; 5345 spectral->classifier_params.upper_chan_in_mhz = 5346 current_channel; 5347 } else { 5348 spectral->classifier_params.lower_chan_in_mhz = 5349 current_channel; 5350 spectral->classifier_params.upper_chan_in_mhz = 5351 extension_channel; 5352 } 5353 } 5354 } 5355 5356 spectral->send_single_packet = 0; 5357 spectral->classifier_params.spectral_20_40_mode = 5358 spectral->sc_spectral_20_40_mode; 5359 spectral->classifier_params.spectral_dc_index = 5360 spectral->spectral_dc_index; 5361 spectral->spectral_sent_msg = 0; 5362 spectral->classify_scan = 0; 5363 spectral->num_spectral_data = 0; 5364 5365 if (!p_sops->is_spectral_active(spectral, smode)) { 5366 p_sops->configure_spectral(spectral, spectral_params, smode); 5367 spectral->rparams.marker[smode].is_valid = false; 5368 5369 if (spectral->params[smode].ss_count) { 5370 status = target_if_spectral_finite_scan_init(spectral, 5371 smode); 5372 if (QDF_IS_STATUS_ERROR(status)) { 5373 spectral_err("Failed to init finite scan"); 5374 return 1; 5375 } 5376 } 5377 p_sops->start_spectral_scan(spectral, smode, err); 5378 spectral->timestamp_war.timestamp_war_offset[smode] = 0; 5379 spectral->timestamp_war.last_fft_timestamp[smode] = 0; 5380 } 5381 5382 /* get current spectral configuration */ 5383 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode); 5384 5385 target_if_init_upper_lower_flags(spectral, smode); 5386 5387 return 0; 5388 } 5389 5390 /** 5391 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by 5392 * Agile DFS 5393 * @psoc: Pointer to psoc 5394 * @object: Pointer to pdev 5395 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited 5396 * 5397 * This API checks whether Agile DFS is running on any of the pdevs. If so, it 5398 * indicates that Agile Spectral scan is prohibited by Agile DFS. 5399 * 5400 * Return: void 5401 */ 5402 static void 5403 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, 5404 void *object, void *arg) 5405 { 5406 bool *is_aspectral_prohibited = arg; 5407 struct wlan_objmgr_pdev *cur_pdev = object; 5408 bool is_agile_precac_enabled_cur_pdev = false; 5409 bool is_agile_rcac_enabled_cur_pdev = false; 5410 QDF_STATUS status; 5411 5412 qdf_assert_always(is_aspectral_prohibited); 5413 if (*is_aspectral_prohibited) 5414 return; 5415 5416 qdf_assert_always(psoc); 5417 qdf_assert_always(cur_pdev); 5418 5419 status = ucfg_dfs_get_agile_precac_enable 5420 (cur_pdev, 5421 &is_agile_precac_enabled_cur_pdev); 5422 if (QDF_IS_STATUS_ERROR(status)) { 5423 spectral_err("Get agile precac failed, prohibiting aSpectral"); 5424 *is_aspectral_prohibited = true; 5425 return; 5426 } 5427 5428 status = ucfg_dfs_get_rcac_enable(cur_pdev, 5429 &is_agile_rcac_enabled_cur_pdev); 5430 5431 if (QDF_IS_STATUS_ERROR(status)) { 5432 spectral_err("Get agile RCAC failed, prohibiting aSpectral"); 5433 *is_aspectral_prohibited = true; 5434 return; 5435 } 5436 5437 if (is_agile_precac_enabled_cur_pdev) { 5438 spectral_err("aDFS preCAC is in progress on one of the pdevs"); 5439 *is_aspectral_prohibited = true; 5440 } else if (is_agile_rcac_enabled_cur_pdev) { 5441 spectral_err("aDFS RCAC is in progress on one of the pdevs"); 5442 *is_aspectral_prohibited = true; 5443 } 5444 } 5445 5446 /** 5447 * target_if_get_curr_band() - Get current operating band of pdev 5448 * 5449 * @pdev: pointer to pdev object 5450 * 5451 * API to get current operating band of a given pdev. 5452 * 5453 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure 5454 */ 5455 static enum reg_wifi_band 5456 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 5457 { 5458 struct wlan_objmgr_vdev *vdev; 5459 int16_t chan_freq; 5460 enum reg_wifi_band cur_band; 5461 5462 if (!pdev) { 5463 spectral_err("pdev is NULL"); 5464 return REG_BAND_UNKNOWN; 5465 } 5466 5467 if (vdev_id == WLAN_INVALID_VDEV_ID) 5468 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); 5469 else 5470 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 5471 WLAN_SPECTRAL_ID); 5472 if (!vdev) { 5473 spectral_debug("vdev is NULL"); 5474 return REG_BAND_UNKNOWN; 5475 } 5476 chan_freq = target_if_vdev_get_chan_freq(vdev); 5477 cur_band = wlan_reg_freq_to_band(chan_freq); 5478 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5479 5480 return cur_band; 5481 } 5482 5483 /** 5484 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on 5485 * any of the 5G pdevs 5486 * @psoc: Pointer to psoc 5487 * @object: Pointer to pdev 5488 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in 5489 * progress in any 5G pdevs 5490 * 5491 * Return: void 5492 */ 5493 static void 5494 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, 5495 void *object, void *arg) 5496 { 5497 enum reg_wifi_band band; 5498 bool *is_agile_scan_inprog_5g_pdev = arg; 5499 struct target_if_spectral *spectral; 5500 struct wlan_objmgr_pdev *cur_pdev = object; 5501 struct target_if_spectral_ops *p_sops; 5502 5503 if (*is_agile_scan_inprog_5g_pdev) 5504 return; 5505 5506 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); 5507 if (!spectral) { 5508 spectral_err("target if spectral handle is NULL"); 5509 return; 5510 } 5511 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5512 5513 band = target_if_get_curr_band( 5514 cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]); 5515 if (band == REG_BAND_UNKNOWN) { 5516 spectral_debug("Failed to get current band"); 5517 return; 5518 } 5519 5520 if (band == REG_BAND_5G && 5521 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) 5522 *is_agile_scan_inprog_5g_pdev = true; 5523 } 5524 5525 /** 5526 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported 5527 * for current vdev rx chainmask. 5528 * 5529 * @spectral: Pointer to Spectral object 5530 * @is_supported: Pointer to is_supported 5531 * 5532 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 5533 */ 5534 static QDF_STATUS 5535 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, 5536 bool *is_supported) 5537 { 5538 struct wlan_objmgr_vdev *vdev; 5539 uint8_t vdev_rxchainmask; 5540 struct wlan_objmgr_psoc *psoc; 5541 struct wlan_objmgr_pdev *pdev; 5542 struct target_psoc_info *tgt_psoc_info; 5543 struct wlan_psoc_host_service_ext_param *ext_svc_param; 5544 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 5545 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 5546 struct wlan_psoc_host_chainmask_table *table; 5547 int j; 5548 uint32_t table_id; 5549 enum phy_ch_width ch_width; 5550 uint8_t pdev_id; 5551 5552 if (!spectral) { 5553 spectral_err("spectral target if object is null"); 5554 return QDF_STATUS_E_FAILURE; 5555 } 5556 5557 if (!is_supported) { 5558 spectral_err("is supported argument is null"); 5559 return QDF_STATUS_E_FAILURE; 5560 } 5561 5562 if (spectral->spectral_gen <= SPECTRAL_GEN2) { 5563 spectral_err("HW Agile mode is not supported up to gen 2"); 5564 return QDF_STATUS_E_FAILURE; 5565 } 5566 5567 pdev = spectral->pdev_obj; 5568 if (!pdev) { 5569 spectral_err("pdev is null"); 5570 return QDF_STATUS_E_FAILURE; 5571 } 5572 5573 psoc = wlan_pdev_get_psoc(pdev); 5574 if (!psoc) { 5575 spectral_err("psoc is null"); 5576 return QDF_STATUS_E_FAILURE; 5577 } 5578 5579 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 5580 if (!vdev) { 5581 spectral_err("First vdev is NULL"); 5582 return QDF_STATUS_E_FAILURE; 5583 } 5584 5585 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 5586 if (!vdev_rxchainmask) { 5587 spectral_err("vdev rx chainmask is zero"); 5588 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5589 return QDF_STATUS_E_FAILURE; 5590 } 5591 5592 ch_width = target_if_vdev_get_ch_width(vdev); 5593 if (ch_width == CH_WIDTH_INVALID) { 5594 spectral_err("Invalid channel width"); 5595 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5596 return QDF_STATUS_E_FAILURE; 5597 } 5598 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5599 5600 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 5601 if (!tgt_psoc_info) { 5602 spectral_err("target_psoc_info is null"); 5603 return QDF_STATUS_E_FAILURE; 5604 } 5605 5606 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 5607 if (!ext_svc_param) { 5608 spectral_err("Extended service ready param null"); 5609 return QDF_STATUS_E_FAILURE; 5610 } 5611 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 5612 5613 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 5614 if (!mac_phy_cap_arr) { 5615 spectral_err("mac phy cap array is null"); 5616 return QDF_STATUS_E_FAILURE; 5617 } 5618 5619 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 5620 if (!mac_phy_cap) { 5621 spectral_err("mac phy cap is null"); 5622 return QDF_STATUS_E_FAILURE; 5623 } 5624 5625 table_id = mac_phy_cap->chainmask_table_id; 5626 table = &ext_svc_param->chainmask_table[table_id]; 5627 if (!table) { 5628 spectral_err("chainmask table not found"); 5629 return QDF_STATUS_E_FAILURE; 5630 } 5631 5632 for (j = 0; j < table->num_valid_chainmasks; j++) { 5633 if (table->cap_list[j].chainmask == vdev_rxchainmask) { 5634 if (ch_width <= CH_WIDTH_80MHZ) 5635 *is_supported = 5636 table->cap_list[j].supports_aSpectral; 5637 else 5638 *is_supported = 5639 table->cap_list[j].supports_aSpectral_160; 5640 break; 5641 } 5642 } 5643 5644 if (j == table->num_valid_chainmasks) { 5645 spectral_err("vdev rx chainmask %u not found in table id = %u", 5646 vdev_rxchainmask, table_id); 5647 return QDF_STATUS_E_FAILURE; 5648 } 5649 5650 return QDF_STATUS_SUCCESS; 5651 } 5652 5653 #define INVALID_SPAN_NUM (-1) 5654 /** 5655 * target_if_spectral_get_num_spans() - Get number of spans for a given sscan_bw 5656 * @pdev: Pointer to pdev object 5657 * @sscan_bw: Spectral scan bandwidth 5658 * 5659 * Return: Number of spans on success, INVALID_SPAN_NUM on failure 5660 */ 5661 static int 5662 target_if_spectral_get_num_spans( 5663 struct wlan_objmgr_pdev *pdev, 5664 enum phy_ch_width sscan_bw) 5665 { 5666 struct wlan_objmgr_psoc *psoc; 5667 int num_spans; 5668 5669 if (!pdev) { 5670 spectral_err_rl("pdev is null"); 5671 return INVALID_SPAN_NUM; 5672 } 5673 5674 psoc = wlan_pdev_get_psoc(pdev); 5675 if (!psoc) { 5676 spectral_err_rl("psoc is null"); 5677 return INVALID_SPAN_NUM; 5678 } 5679 5680 if (sscan_bw == CH_WIDTH_80P80MHZ) { 5681 num_spans = 2; 5682 if (wlan_psoc_nif_fw_ext_cap_get( 5683 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) 5684 /* 5 MHz frequency span in restricted 80p80 case */ 5685 num_spans += 1; 5686 } else { 5687 num_spans = 1; 5688 } 5689 5690 return num_spans; 5691 } 5692 5693 #ifdef OPTIMIZED_SAMP_MESSAGE 5694 /** 5695 * target_if_spectral_populate_session_report_info() - Populate per-session 5696 * report level information. 5697 * 5698 * @spectral: Pointer to Spectral object 5699 * @smode: Spectral scan mode 5700 * 5701 * Return: Success/Failure 5702 */ 5703 static QDF_STATUS 5704 target_if_spectral_populate_session_report_info( 5705 struct target_if_spectral *spectral, 5706 enum spectral_scan_mode smode) 5707 { 5708 struct per_session_report_info *rpt_info; 5709 5710 if (!spectral) { 5711 spectral_err_rl("Spectral LMAC object is null"); 5712 return QDF_STATUS_E_NULL_VALUE; 5713 } 5714 if (smode > SPECTRAL_SCAN_MODE_MAX) { 5715 spectral_err_rl("Invalid Spectral scan mode"); 5716 return QDF_STATUS_E_FAILURE; 5717 } 5718 5719 5720 qdf_spin_lock_bh(&spectral->session_report_info_lock); 5721 /* Fill per-session report information, based on the spectral mode */ 5722 rpt_info = &spectral->report_info[smode]; 5723 5724 rpt_info->operating_bw = spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 5725 rpt_info->sscan_bw = spectral->ch_width[smode]; 5726 rpt_info->sscan_cfreq1 = spectral->params[smode].ss_frequency.cfreq1; 5727 rpt_info->sscan_cfreq2 = spectral->params[smode].ss_frequency.cfreq2; 5728 rpt_info->num_spans = target_if_spectral_get_num_spans( 5729 spectral->pdev_obj, 5730 rpt_info->sscan_bw); 5731 5732 qdf_assert_always(rpt_info->num_spans != INVALID_SPAN_NUM); 5733 rpt_info->valid = true; 5734 5735 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 5736 5737 return QDF_STATUS_SUCCESS; 5738 } 5739 5740 /** 5741 * target_if_spectral_populate_session_det_host_info() - Populate per-session 5742 * detector level information that is known to the Host 5743 * 5744 * @spectral: Pointer to Spectral object 5745 * @smode: Spectral scan mode 5746 * 5747 * Return: Success/Failure 5748 */ 5749 static QDF_STATUS 5750 target_if_spectral_populate_session_det_host_info( 5751 struct target_if_spectral *spectral, 5752 enum spectral_scan_mode smode) 5753 { 5754 struct per_session_report_info *rpt_info; 5755 struct sscan_detector_list *detector_list; 5756 struct wlan_objmgr_psoc *psoc; 5757 uint16_t dest_det_idx = 0; 5758 uint16_t dest_span_idx = 0; 5759 bool is_sec80 = false; 5760 uint8_t det, dest_det; 5761 5762 if (!spectral) { 5763 spectral_err_rl("Spectral LMAC object is null"); 5764 return QDF_STATUS_E_NULL_VALUE; 5765 } 5766 if (smode > SPECTRAL_SCAN_MODE_MAX) { 5767 spectral_err_rl("Invalid Spectral scan mode"); 5768 return QDF_STATUS_E_FAILURE; 5769 } 5770 5771 if (!spectral->pdev_obj) { 5772 spectral_err_rl("Spectral PDEV is null"); 5773 return QDF_STATUS_E_NULL_VALUE; 5774 } 5775 5776 psoc = wlan_pdev_get_psoc(spectral->pdev_obj); 5777 if (!psoc) { 5778 spectral_err_rl("psoc is null"); 5779 return QDF_STATUS_E_NULL_VALUE; 5780 } 5781 5782 qdf_spin_lock_bh(&spectral->session_report_info_lock); 5783 rpt_info = &spectral->report_info[smode]; 5784 5785 qdf_spin_lock_bh(&spectral->detector_list_lock); 5786 /* Fill per-sesion detector-level information */ 5787 detector_list = &spectral->detector_list[smode][rpt_info->sscan_bw]; 5788 5789 for (det = 0; det < detector_list->num_detectors; det++) { 5790 struct per_session_det_map *det_map; 5791 5792 qdf_spin_lock_bh(&spectral->session_det_map_lock); 5793 det_map = &spectral->det_map[detector_list->detectors[det]]; 5794 if (detector_list->num_detectors > 1) { 5795 if (det == 0) { 5796 det_map->buf_type = SPECTRAL_MSG_BUF_NEW; 5797 det_map->send_to_upper_layers = false; 5798 } else if (det == detector_list->num_detectors - 1) { 5799 det_map->buf_type = SPECTRAL_MSG_BUF_SAVED; 5800 det_map->send_to_upper_layers = true; 5801 } else { 5802 /* middle fragments */ 5803 det_map->buf_type = SPECTRAL_MSG_BUF_SAVED; 5804 det_map->send_to_upper_layers = false; 5805 } 5806 } else { 5807 det_map->buf_type = SPECTRAL_MSG_BUF_NEW; 5808 det_map->send_to_upper_layers = true; 5809 } 5810 5811 det_map->num_dest_det_info = 1; 5812 if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ && 5813 wlan_psoc_nif_fw_ext_cap_get( 5814 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) { 5815 /** 5816 * In 165MHz case, 1 Spectral HW detector maps to 3 5817 * detectors in SAMP msg. 5818 */ 5819 det_map->num_dest_det_info += 2; 5820 } 5821 5822 for (dest_det = 0; dest_det < det_map->num_dest_det_info; 5823 dest_det++) { 5824 struct per_session_dest_det_info *map_det_info; 5825 5826 map_det_info = &det_map->dest_det_info[dest_det]; 5827 map_det_info->freq_span_id = dest_span_idx; 5828 map_det_info->det_id = dest_det_idx; 5829 map_det_info->is_sec80 = is_sec80; 5830 if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ) { 5831 /* Increment span ID for non-contiguous modes */ 5832 dest_det_idx = 0; 5833 dest_span_idx++; 5834 } else { 5835 /* Increment detector ID for contiguous modes */ 5836 dest_det_idx++; 5837 } 5838 is_sec80 = !is_sec80; 5839 } 5840 det_map->det_map_valid[smode] = true; 5841 qdf_spin_unlock_bh(&spectral->session_det_map_lock); 5842 } 5843 qdf_spin_unlock_bh(&spectral->detector_list_lock); 5844 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 5845 5846 return QDF_STATUS_SUCCESS; 5847 } 5848 5849 #else 5850 static QDF_STATUS 5851 target_if_spectral_populate_session_report_info( 5852 struct target_if_spectral *spectral, 5853 enum spectral_scan_mode smode) 5854 { 5855 return QDF_STATUS_SUCCESS; 5856 } 5857 5858 static QDF_STATUS 5859 target_if_spectral_populate_session_det_host_info( 5860 struct target_if_spectral *spectral, 5861 enum spectral_scan_mode smode) 5862 { 5863 return QDF_STATUS_SUCCESS; 5864 } 5865 #endif /* OPTIMIZED_SAMP_MESSAGE */ 5866 5867 QDF_STATUS 5868 spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev *pdev, 5869 bool *is_session_info_expected) 5870 { 5871 struct wlan_objmgr_psoc *psoc; 5872 struct wmi_unified *wmi_handle; 5873 5874 if (!pdev) { 5875 spectral_err("pdev is null"); 5876 return QDF_STATUS_E_NULL_VALUE; 5877 } 5878 5879 psoc = wlan_pdev_get_psoc(pdev); 5880 if (!psoc) { 5881 spectral_err("psoc is null"); 5882 return QDF_STATUS_E_NULL_VALUE; 5883 } 5884 5885 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 5886 if (!wmi_handle) { 5887 spectral_err("wmi handle is null"); 5888 return QDF_STATUS_E_NULL_VALUE; 5889 } 5890 5891 *is_session_info_expected = target_if_spectral_wmi_service_enabled( 5892 psoc, wmi_handle, 5893 wmi_service_spectral_session_info_support); 5894 5895 return QDF_STATUS_SUCCESS; 5896 } 5897 5898 QDF_STATUS 5899 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, 5900 uint8_t vdev_id, 5901 const enum spectral_scan_mode smode, 5902 enum spectral_cp_error_code *err) 5903 { 5904 struct target_if_spectral_ops *p_sops; 5905 struct target_if_spectral *spectral; 5906 struct wlan_objmgr_psoc *psoc; 5907 enum reg_wifi_band band; 5908 QDF_STATUS ret; 5909 bool is_session_info_expected; 5910 5911 if (!err) { 5912 spectral_err("Error code argument is null"); 5913 QDF_ASSERT(0); 5914 return QDF_STATUS_E_FAILURE; 5915 } 5916 *err = SPECTRAL_SCAN_ERR_INVALID; 5917 5918 if (!pdev) { 5919 spectral_err("pdev object is NUll"); 5920 return QDF_STATUS_E_FAILURE; 5921 } 5922 5923 psoc = wlan_pdev_get_psoc(pdev); 5924 if (!psoc) { 5925 spectral_err("psoc is null"); 5926 return QDF_STATUS_E_FAILURE; 5927 } 5928 5929 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5930 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 5931 spectral_err("Invalid Spectral mode %u", smode); 5932 return QDF_STATUS_E_FAILURE; 5933 } 5934 5935 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5936 if (!spectral) { 5937 spectral_err("Spectral LMAC object is NUll"); 5938 return QDF_STATUS_E_FAILURE; 5939 } 5940 5941 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5942 if (!p_sops) { 5943 spectral_err("p_sops is null"); 5944 return QDF_STATUS_E_FAILURE; 5945 } 5946 5947 if (p_sops->is_spectral_active(spectral, smode)) { 5948 spectral_err("spectral in progress in current pdev, mode %d", 5949 smode); 5950 return QDF_STATUS_E_FAILURE; 5951 } 5952 spectral->vdev_id[smode] = vdev_id; 5953 5954 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 5955 QDF_STATUS status; 5956 bool is_supported = false; 5957 5958 status = target_if_is_agile_supported_cur_chmask(spectral, 5959 &is_supported); 5960 if (QDF_IS_STATUS_ERROR(status)) { 5961 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 5962 return QDF_STATUS_E_FAILURE; 5963 } 5964 5965 if (!is_supported) { 5966 spectral_err("aSpectral unsupported for cur chainmask"); 5967 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 5968 return QDF_STATUS_E_FAILURE; 5969 } 5970 } 5971 5972 band = target_if_get_curr_band(spectral->pdev_obj, vdev_id); 5973 if (band == REG_BAND_UNKNOWN) { 5974 spectral_err("Failed to get current band"); 5975 return QDF_STATUS_E_FAILURE; 5976 } 5977 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { 5978 struct target_psoc_info *tgt_hdl; 5979 enum wmi_host_hw_mode_config_type mode; 5980 bool is_agile_scan_inprog_5g_pdev; 5981 5982 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 5983 if (!tgt_hdl) { 5984 target_if_err("target_psoc_info is null"); 5985 return QDF_STATUS_E_FAILURE; 5986 } 5987 5988 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 5989 switch (mode) { 5990 case WMI_HOST_HW_MODE_SBS_PASSIVE: 5991 case WMI_HOST_HW_MODE_SBS: 5992 case WMI_HOST_HW_MODE_DBS_SBS: 5993 case WMI_HOST_HW_MODE_DBS_OR_SBS: 5994 is_agile_scan_inprog_5g_pdev = false; 5995 wlan_objmgr_iterate_obj_list 5996 (psoc, WLAN_PDEV_OP, 5997 target_if_is_agile_scan_active_in_5g, 5998 &is_agile_scan_inprog_5g_pdev, 0, 5999 WLAN_SPECTRAL_ID); 6000 break; 6001 default: 6002 is_agile_scan_inprog_5g_pdev = false; 6003 break; 6004 } 6005 6006 if (is_agile_scan_inprog_5g_pdev) { 6007 spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); 6008 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6009 return QDF_STATUS_E_FAILURE; 6010 } 6011 } 6012 6013 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 6014 bool is_aspectral_prohibited = false; 6015 QDF_STATUS status; 6016 6017 status = wlan_objmgr_iterate_obj_list 6018 (psoc, WLAN_PDEV_OP, 6019 target_if_is_aspectral_prohibited_by_adfs, 6020 &is_aspectral_prohibited, 0, 6021 WLAN_SPECTRAL_ID); 6022 if (QDF_IS_STATUS_ERROR(status)) { 6023 spectral_err("Failed to iterate over pdevs"); 6024 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6025 return QDF_STATUS_E_FAILURE; 6026 } 6027 6028 if (is_aspectral_prohibited) { 6029 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6030 return QDF_STATUS_E_FAILURE; 6031 } 6032 } 6033 6034 if (!spectral->params_valid[smode]) { 6035 target_if_spectral_info_read(spectral, 6036 smode, 6037 TARGET_IF_SPECTRAL_INFO_PARAMS, 6038 &spectral->params[smode], 6039 sizeof(spectral->params[smode])); 6040 spectral->params_valid[smode] = true; 6041 } 6042 6043 qdf_spin_lock_bh(&spectral->spectral_lock); 6044 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 6045 QDF_STATUS status; 6046 bool is_overlapping; 6047 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 6048 enum spectral_scan_mode m; 6049 enum phy_ch_width agile_ch_width; 6050 6051 m = SPECTRAL_SCAN_MODE_NORMAL; 6052 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 6053 ch_width[m] = CH_WIDTH_INVALID; 6054 status = target_if_spectral_populate_chwidth 6055 (spectral, ch_width, spectral->params 6056 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 6057 if (QDF_IS_STATUS_ERROR(status)) { 6058 qdf_spin_unlock_bh(&spectral->spectral_lock); 6059 spectral_err("Failed to populate channel width"); 6060 return QDF_STATUS_E_FAILURE; 6061 } 6062 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 6063 6064 if (!spectral->params[smode].ss_frequency.cfreq1) { 6065 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 6066 qdf_spin_unlock_bh(&spectral->spectral_lock); 6067 spectral_err("Agile Spectral cfreq1 is 0"); 6068 return QDF_STATUS_E_FAILURE; 6069 } else if (agile_ch_width == CH_WIDTH_80P80MHZ && 6070 !spectral->params[smode].ss_frequency.cfreq2) { 6071 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 6072 qdf_spin_unlock_bh(&spectral->spectral_lock); 6073 spectral_err("Agile Spectral cfreq2 is 0"); 6074 return QDF_STATUS_E_FAILURE; 6075 } 6076 6077 status = target_if_is_agile_span_overlap_with_operating_span 6078 (spectral, ch_width, 6079 &spectral->params[smode].ss_frequency, 6080 &is_overlapping); 6081 if (QDF_IS_STATUS_ERROR(status)) { 6082 qdf_spin_unlock_bh(&spectral->spectral_lock); 6083 return QDF_STATUS_E_FAILURE; 6084 } 6085 6086 if (is_overlapping) { 6087 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 6088 qdf_spin_unlock_bh(&spectral->spectral_lock); 6089 return QDF_STATUS_E_FAILURE; 6090 } 6091 } 6092 6093 /* Populate detectot list first */ 6094 ret = target_if_spectral_detector_list_init(spectral); 6095 if (QDF_IS_STATUS_ERROR(ret)) { 6096 qdf_spin_unlock_bh(&spectral->spectral_lock); 6097 spectral_err("Failed to initialize detector list"); 6098 return ret; 6099 } 6100 6101 ret = target_if_spectral_populate_chwidth( 6102 spectral, spectral->ch_width, 6103 spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 6104 ss_frequency.cfreq2 > 0); 6105 if (QDF_IS_STATUS_ERROR(ret)) { 6106 qdf_spin_unlock_bh(&spectral->spectral_lock); 6107 spectral_err("Failed to get channel widths"); 6108 return ret; 6109 } 6110 6111 ret = spectral_is_session_info_expected_from_target( 6112 spectral->pdev_obj, 6113 &is_session_info_expected); 6114 if (QDF_IS_STATUS_ERROR(ret)) { 6115 qdf_spin_unlock_bh(&spectral->spectral_lock); 6116 spectral_err("Failed to check if session info is expected"); 6117 return ret; 6118 } 6119 6120 /* If FW doesn't send session info, populate it */ 6121 if (!is_session_info_expected) { 6122 ret = target_if_spectral_populate_session_report_info(spectral, 6123 smode); 6124 if (QDF_IS_STATUS_ERROR(ret)) { 6125 qdf_spin_unlock_bh(&spectral->spectral_lock); 6126 spectral_err("Failed to populate per-session report info"); 6127 return QDF_STATUS_E_FAILURE; 6128 } 6129 6130 ret = target_if_spectral_populate_session_det_host_info( 6131 spectral, smode); 6132 if (QDF_IS_STATUS_ERROR(ret)) { 6133 qdf_spin_unlock_bh(&spectral->spectral_lock); 6134 spectral_err("Failed to populate per-session detector info"); 6135 return QDF_STATUS_E_FAILURE; 6136 } 6137 } 6138 6139 target_if_spectral_scan_enable_params(spectral, 6140 &spectral->params[smode], smode, 6141 err); 6142 6143 spectral->sscan_width_configured[smode] = false; 6144 qdf_spin_unlock_bh(&spectral->spectral_lock); 6145 6146 return QDF_STATUS_SUCCESS; 6147 } 6148 6149 QDF_STATUS 6150 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, 6151 const enum spectral_scan_mode smode, 6152 enum spectral_cp_error_code *err) 6153 { 6154 struct target_if_spectral_ops *p_sops; 6155 struct target_if_spectral *spectral; 6156 uint8_t det; 6157 6158 if (!pdev) { 6159 spectral_err("pdev object is NULL"); 6160 return QDF_STATUS_E_INVAL; 6161 } 6162 6163 if (target_if_spectral_is_feature_disabled_pdev(pdev)) { 6164 spectral_info("Spectral feature is disabled"); 6165 return QDF_STATUS_COMP_DISABLED; 6166 } 6167 6168 if (!err) { 6169 spectral_err("Error code argument is null"); 6170 QDF_ASSERT(0); 6171 return QDF_STATUS_E_FAILURE; 6172 } 6173 *err = SPECTRAL_SCAN_ERR_INVALID; 6174 6175 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 6176 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6177 spectral_err("Invalid Spectral mode %u", smode); 6178 return QDF_STATUS_E_FAILURE; 6179 } 6180 6181 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6182 if (!spectral) { 6183 spectral_err("Spectral LMAC object is NUll "); 6184 return QDF_STATUS_E_FAILURE; 6185 } 6186 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6187 6188 qdf_spin_lock_bh(&spectral->spectral_lock); 6189 p_sops->stop_spectral_scan(spectral, smode); 6190 if (spectral->classify_scan) { 6191 /* TODO : Check if this logic is necessary */ 6192 spectral->detects_control_channel = 0; 6193 spectral->detects_extension_channel = 0; 6194 spectral->detects_above_dc = 0; 6195 spectral->detects_below_dc = 0; 6196 spectral->classify_scan = 0; 6197 } 6198 6199 spectral->send_single_packet = 0; 6200 spectral->sc_spectral_scan = 0; 6201 6202 qdf_spin_lock_bh(&spectral->session_det_map_lock); 6203 for (det = 0; det < MAX_DETECTORS_PER_PDEV; det++) 6204 spectral->det_map[det].det_map_valid[smode] = false; 6205 6206 qdf_spin_unlock_bh(&spectral->session_det_map_lock); 6207 6208 /* Mark report info as invalid */ 6209 qdf_spin_lock_bh(&spectral->session_report_info_lock); 6210 spectral->report_info[smode].valid = false; 6211 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 6212 6213 qdf_spin_unlock_bh(&spectral->spectral_lock); 6214 6215 return QDF_STATUS_SUCCESS; 6216 } 6217 6218 /** 6219 * target_if_is_spectral_active() - Get whether Spectral is active 6220 * @pdev: Pointer to pdev object 6221 * @smode: Spectral scan mode 6222 * 6223 * API to get whether Spectral is active 6224 * 6225 * Return: True if Spectral is active, false if Spectral is not active 6226 */ 6227 bool 6228 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, 6229 const enum spectral_scan_mode smode) 6230 { 6231 struct target_if_spectral *spectral = NULL; 6232 struct target_if_spectral_ops *p_sops = NULL; 6233 6234 if (!pdev) { 6235 spectral_err("pdev is null"); 6236 return false; 6237 } 6238 6239 if (target_if_spectral_is_feature_disabled_pdev(pdev)) { 6240 spectral_info("Spectral feature is disabled"); 6241 return false; 6242 } 6243 6244 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6245 6246 if (!spectral) { 6247 spectral_err("SPECTRAL : Module doesn't exist"); 6248 return false; 6249 } 6250 6251 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6252 6253 if (!p_sops) { 6254 spectral_err("p_sops is null"); 6255 return false; 6256 } 6257 6258 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 6259 spectral_err("Invalid Spectral mode %u", smode); 6260 return false; 6261 } 6262 6263 return p_sops->is_spectral_active(spectral, smode); 6264 } 6265 6266 /** 6267 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 6268 * @pdev: Pointer to pdev object 6269 * @smode: Spectral scan mode 6270 * 6271 * API to get whether Spectral is enabled 6272 * 6273 * Return: True if Spectral is enabled, false if Spectral is not enabled 6274 */ 6275 bool 6276 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, 6277 enum spectral_scan_mode smode) 6278 { 6279 struct target_if_spectral *spectral = NULL; 6280 struct target_if_spectral_ops *p_sops = NULL; 6281 6282 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6283 6284 if (!spectral) { 6285 spectral_err("SPECTRAL : Module doesn't exist"); 6286 return false; 6287 } 6288 6289 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6290 6291 if (!p_sops) { 6292 spectral_err("p_sops is null"); 6293 return false; 6294 } 6295 6296 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 6297 spectral_err("Invalid Spectral mode %u", smode); 6298 return false; 6299 } 6300 6301 return p_sops->is_spectral_enabled(spectral, smode); 6302 } 6303 6304 #ifdef DIRECT_BUF_RX_DEBUG 6305 /** 6306 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug 6307 * @pdev: Pointer to pdev object 6308 * @enable: Enable/Disable Spectral DMA ring debug 6309 * 6310 * Start/stop Spectral DMA ring debug based on @enable. 6311 * Also save the state for future use. 6312 * 6313 * Return: QDF_STATUS of operation 6314 */ 6315 static QDF_STATUS 6316 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) 6317 { 6318 struct target_if_spectral *spectral; 6319 struct wlan_lmac_if_tx_ops *tx_ops; 6320 struct wlan_objmgr_psoc *psoc; 6321 6322 if (!pdev) 6323 return QDF_STATUS_E_FAILURE; 6324 6325 psoc = wlan_pdev_get_psoc(pdev); 6326 if (!psoc) { 6327 spectral_err("psoc is null"); 6328 return QDF_STATUS_E_INVAL; 6329 } 6330 6331 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 6332 if (!tx_ops) { 6333 spectral_err("tx_ops is NULL"); 6334 return QDF_STATUS_E_INVAL; 6335 } 6336 6337 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6338 if (!spectral) { 6339 spectral_err("Spectal LMAC object is NULL"); 6340 return QDF_STATUS_E_INVAL; 6341 } 6342 6343 /* Save the state */ 6344 spectral->dbr_ring_debug = enable; 6345 6346 if (enable) 6347 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( 6348 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); 6349 else 6350 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( 6351 pdev, 0); 6352 6353 return QDF_STATUS_SUCCESS; 6354 } 6355 6356 /** 6357 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug 6358 * @pdev: Pointer to pdev object 6359 * @enable: Enable/Disable Spectral DMA buffer debug 6360 * 6361 * Start/stop Spectral DMA buffer debug based on @enable. 6362 * Also save the state for future use. 6363 * 6364 * Return: QDF_STATUS of operation 6365 */ 6366 static QDF_STATUS 6367 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) 6368 { 6369 struct target_if_spectral *spectral; 6370 struct wlan_lmac_if_tx_ops *tx_ops; 6371 struct wlan_objmgr_psoc *psoc; 6372 6373 if (!pdev) 6374 return QDF_STATUS_E_FAILURE; 6375 6376 psoc = wlan_pdev_get_psoc(pdev); 6377 if (!psoc) { 6378 spectral_err("psoc is null"); 6379 return QDF_STATUS_E_INVAL; 6380 } 6381 6382 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 6383 if (!tx_ops) { 6384 spectral_err("tx_ops is NULL"); 6385 return QDF_STATUS_E_INVAL; 6386 } 6387 6388 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6389 if (!spectral) { 6390 spectral_err("Spectal LMAC object is NULL"); 6391 return QDF_STATUS_E_INVAL; 6392 } 6393 6394 /* Save the state */ 6395 spectral->dbr_buff_debug = enable; 6396 6397 if (enable) 6398 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( 6399 pdev, 0, MEM_POISON_SIGNATURE); 6400 else 6401 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( 6402 pdev, 0); 6403 } 6404 6405 /** 6406 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer 6407 * debug based on the previous state 6408 * @pdev: Pointer to pdev object 6409 * 6410 * Return: QDF_STATUS of operation 6411 */ 6412 static QDF_STATUS 6413 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) 6414 { 6415 struct target_if_spectral *spectral; 6416 6417 if (!pdev) { 6418 spectral_err("pdev is NULL!"); 6419 return QDF_STATUS_E_FAILURE; 6420 } 6421 6422 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6423 if (!spectral) { 6424 spectral_err("Spectal LMAC object is NULL"); 6425 return QDF_STATUS_E_INVAL; 6426 } 6427 6428 if (spectral->dbr_buff_debug) 6429 return target_if_spectral_do_dbr_buff_debug(pdev, true); 6430 else 6431 return target_if_spectral_do_dbr_buff_debug(pdev, false); 6432 } 6433 6434 /** 6435 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring 6436 * debug based on the previous state 6437 * @pdev: Pointer to pdev object 6438 * 6439 * Return: QDF_STATUS of operation 6440 */ 6441 static QDF_STATUS 6442 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) 6443 { 6444 struct target_if_spectral *spectral; 6445 6446 if (!pdev) { 6447 spectral_err("pdev is NULL!"); 6448 return QDF_STATUS_E_FAILURE; 6449 } 6450 6451 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6452 if (!spectral) { 6453 spectral_err("Spectal LMAC object is NULL"); 6454 return QDF_STATUS_E_INVAL; 6455 } 6456 6457 if (spectral->dbr_ring_debug) 6458 return target_if_spectral_do_dbr_ring_debug(pdev, true); 6459 else 6460 return target_if_spectral_do_dbr_ring_debug(pdev, false); 6461 } 6462 6463 /** 6464 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral 6465 * @pdev: Pointer to pdev object 6466 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug 6467 * @debug_value: Value to be set for @dma_debug_type 6468 * 6469 * Set DMA debug for Spectral and start/stop Spectral DMA debug function 6470 * based on @debug_value 6471 * 6472 * Return: QDF_STATUS of operation 6473 */ 6474 static QDF_STATUS 6475 target_if_spectral_set_dma_debug( 6476 struct wlan_objmgr_pdev *pdev, 6477 enum spectral_dma_debug dma_debug_type, 6478 bool debug_value) 6479 { 6480 struct target_if_spectral_ops *p_sops; 6481 struct wlan_objmgr_psoc *psoc; 6482 struct wlan_lmac_if_tx_ops *tx_ops; 6483 struct target_if_spectral *spectral; 6484 6485 if (!pdev) 6486 return QDF_STATUS_E_FAILURE; 6487 6488 psoc = wlan_pdev_get_psoc(pdev); 6489 if (!psoc) { 6490 spectral_err("psoc is null"); 6491 return QDF_STATUS_E_INVAL; 6492 } 6493 6494 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 6495 if (!tx_ops) { 6496 spectral_err("tx_ops is NULL"); 6497 return QDF_STATUS_E_FAILURE; 6498 } 6499 6500 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { 6501 spectral_err("Unable to fetch target type"); 6502 return QDF_STATUS_E_FAILURE; 6503 } 6504 6505 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6506 if (!spectral) { 6507 spectral_err("Spectal LMAC object is NULL"); 6508 return QDF_STATUS_E_INVAL; 6509 } 6510 6511 if (spectral->direct_dma_support) { 6512 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6513 if (p_sops->is_spectral_active(spectral, 6514 SPECTRAL_SCAN_MODE_NORMAL) || 6515 p_sops->is_spectral_active(spectral, 6516 SPECTRAL_SCAN_MODE_AGILE)) { 6517 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); 6518 return QDF_STATUS_E_FAILURE; 6519 } 6520 6521 switch (dma_debug_type) { 6522 case SPECTRAL_DMA_RING_DEBUG: 6523 target_if_spectral_do_dbr_ring_debug(pdev, debug_value); 6524 break; 6525 6526 case SPECTRAL_DMA_BUFFER_DEBUG: 6527 target_if_spectral_do_dbr_buff_debug(pdev, debug_value); 6528 break; 6529 6530 default: 6531 spectral_err("Unsupported DMA debug type : %d", 6532 dma_debug_type); 6533 return QDF_STATUS_E_FAILURE; 6534 } 6535 } 6536 return QDF_STATUS_SUCCESS; 6537 } 6538 #endif /* DIRECT_BUF_RX_DEBUG */ 6539 6540 /** 6541 * target_if_spectral_direct_dma_support() - Get Direct-DMA support 6542 * @pdev: Pointer to pdev object 6543 * 6544 * Return: Whether Direct-DMA is supported on this radio 6545 */ 6546 static bool 6547 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) 6548 { 6549 struct target_if_spectral *spectral; 6550 6551 if (!pdev) { 6552 spectral_err("pdev is NULL!"); 6553 return false; 6554 } 6555 6556 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6557 if (!spectral) { 6558 spectral_err("Spectral LMAC object is NULL"); 6559 return false; 6560 } 6561 6562 return spectral->direct_dma_support; 6563 } 6564 6565 /** 6566 * target_if_set_debug_level() - Set debug level for Spectral 6567 * @pdev: Pointer to pdev object 6568 * @debug_level: Debug level 6569 * 6570 * API to set the debug level for Spectral 6571 * 6572 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 6573 */ 6574 QDF_STATUS 6575 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 6576 { 6577 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 6578 6579 return QDF_STATUS_SUCCESS; 6580 } 6581 6582 /** 6583 * target_if_get_debug_level() - Get debug level for Spectral 6584 * @pdev: Pointer to pdev object 6585 * 6586 * API to get the debug level for Spectral 6587 * 6588 * Return: Current debug level 6589 */ 6590 uint32_t 6591 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 6592 { 6593 return spectral_debug_level; 6594 } 6595 6596 /** 6597 * target_if_get_spectral_capinfo() - Get Spectral capability information 6598 * @pdev: Pointer to pdev object 6599 * @scaps: Buffer into which data should be copied 6600 * 6601 * API to get the spectral capability information 6602 * 6603 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 6604 */ 6605 QDF_STATUS 6606 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, 6607 struct spectral_caps *scaps) 6608 { 6609 struct target_if_spectral *spectral = NULL; 6610 6611 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6612 if (!spectral) { 6613 spectral_err("SPECTRAL : Module doesn't exist"); 6614 return QDF_STATUS_E_FAILURE; 6615 } 6616 6617 qdf_mem_copy(scaps, &spectral->capability, 6618 sizeof(struct spectral_caps)); 6619 6620 return QDF_STATUS_SUCCESS; 6621 } 6622 6623 /** 6624 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 6625 * @pdev: Pointer to pdev object 6626 * @stats: Buffer into which data should be copied 6627 * 6628 * API to get the spectral diagnostic statistics 6629 * 6630 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 6631 */ 6632 QDF_STATUS 6633 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, 6634 struct spectral_diag_stats *stats) 6635 { 6636 struct target_if_spectral *spectral = NULL; 6637 6638 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6639 if (!spectral) { 6640 spectral_err("SPECTRAL : Module doesn't exist"); 6641 return QDF_STATUS_E_FAILURE; 6642 } 6643 6644 qdf_mem_copy(stats, &spectral->diag_stats, 6645 sizeof(struct spectral_diag_stats)); 6646 6647 return QDF_STATUS_SUCCESS; 6648 } 6649 6650 /** 6651 * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations 6652 * @psoc: Pointer to psoc object 6653 * @wmi_ops: Pointer to the structure having Spectral WMI operations 6654 * 6655 * API for registering Spectral WMI operations in 6656 * spectral internal data structure 6657 * 6658 * Return: QDF_STATUS 6659 */ 6660 static QDF_STATUS 6661 target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 6662 struct spectral_wmi_ops *wmi_ops) 6663 { 6664 struct target_if_psoc_spectral *psoc_spectral; 6665 6666 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6667 if (!psoc_spectral) { 6668 spectral_err("Spectral LMAC object is null"); 6669 return QDF_STATUS_E_INVAL; 6670 } 6671 6672 psoc_spectral->wmi_ops = *wmi_ops; 6673 6674 return QDF_STATUS_SUCCESS; 6675 } 6676 6677 /** 6678 * target_if_register_spectral_tgt_ops() - Register Spectral target operations 6679 * @psoc: Pointer to psoc object 6680 * @tgt_ops: Pointer to the structure having Spectral target operations 6681 * 6682 * API for registering Spectral target operations in 6683 * spectral internal data structure 6684 * 6685 * Return: QDF_STATUS 6686 */ 6687 static QDF_STATUS 6688 target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 6689 struct spectral_tgt_ops *tgt_ops) 6690 { 6691 if (!psoc) { 6692 spectral_err("psoc is null"); 6693 return QDF_STATUS_E_INVAL; 6694 } 6695 6696 ops_tgt = *tgt_ops; 6697 6698 return QDF_STATUS_SUCCESS; 6699 } 6700 6701 /** 6702 * target_if_register_netlink_cb() - Register Netlink callbacks 6703 * @pdev: Pointer to pdev object 6704 * @nl_cb: Netlink callbacks to register 6705 * 6706 * Return: void 6707 */ 6708 static void 6709 target_if_register_netlink_cb( 6710 struct wlan_objmgr_pdev *pdev, 6711 struct spectral_nl_cb *nl_cb) 6712 { 6713 struct target_if_spectral *spectral = NULL; 6714 6715 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6716 6717 if (!spectral) { 6718 spectral_err("SPECTRAL : Module doesn't exist"); 6719 return; 6720 } 6721 6722 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 6723 6724 if (spectral->use_nl_bcast) 6725 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 6726 else 6727 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 6728 } 6729 6730 /** 6731 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 6732 * Netlink messages to the application layer 6733 * @pdev: Pointer to pdev object 6734 * 6735 * Return: true for broadcast, false for unicast 6736 */ 6737 static bool 6738 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 6739 { 6740 struct target_if_spectral *spectral = NULL; 6741 6742 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6743 6744 if (!spectral) { 6745 spectral_err("SPECTRAL : Module doesn't exist"); 6746 return false; 6747 } 6748 6749 return spectral->use_nl_bcast; 6750 } 6751 6752 /** 6753 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 6754 * @pdev: Pointer to pdev object 6755 * 6756 * Return: void 6757 */ 6758 static void 6759 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 6760 { 6761 struct target_if_spectral *spectral = NULL; 6762 6763 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6764 if (!spectral) { 6765 spectral_err("SPECTRAL : Module doesn't exist"); 6766 return; 6767 } 6768 6769 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 6770 } 6771 6772 static int 6773 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, 6774 void *payload) 6775 { 6776 struct target_if_spectral *spectral = NULL; 6777 struct target_if_spectral_ops *p_sops = NULL; 6778 6779 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6780 if (!spectral) { 6781 spectral_err("SPECTRAL : Module doesn't exist"); 6782 return -EPERM; 6783 } 6784 6785 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6786 6787 if (!p_sops) { 6788 spectral_err("p_sops is null"); 6789 return -EPERM; 6790 } 6791 6792 return p_sops->process_spectral_report(pdev, payload); 6793 } 6794 6795 #ifdef DIRECT_BUF_RX_DEBUG 6796 static inline void 6797 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 6798 { 6799 if (!tx_ops) { 6800 spectral_err("tx_ops is NULL"); 6801 return; 6802 } 6803 6804 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = 6805 target_if_spectral_set_dma_debug; 6806 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = 6807 target_if_spectral_check_and_do_dbr_ring_debug; 6808 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = 6809 target_if_spectral_check_and_do_dbr_buff_debug; 6810 } 6811 #else 6812 static inline void 6813 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 6814 { 6815 } 6816 #endif 6817 6818 #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE) 6819 /** 6820 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 6821 * register WMI event handler 6822 * @psoc: Pointer to psoc object 6823 * @event_id: Event id 6824 * @handler_func: Handler function 6825 * @rx_ctx: Context of WMI event processing 6826 * 6827 * Wrapper function to register WMI event handler 6828 * 6829 * Return: 0 for success else failure 6830 */ 6831 static int 6832 target_if_spectral_wmi_unified_register_event_handler( 6833 struct wlan_objmgr_psoc *psoc, 6834 wmi_conv_event_id event_id, 6835 wmi_unified_event_handler handler_func, 6836 uint8_t rx_ctx) 6837 { 6838 wmi_unified_t wmi_handle; 6839 struct target_if_psoc_spectral *psoc_spectral; 6840 QDF_STATUS ret; 6841 6842 if (!psoc) { 6843 spectral_err("psoc is null"); 6844 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6845 } 6846 6847 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6848 if (!wmi_handle) { 6849 spectral_err("WMI handle is null"); 6850 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6851 } 6852 6853 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6854 if (!psoc_spectral) { 6855 spectral_err("spectral object is null"); 6856 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 6857 } 6858 6859 ret = psoc_spectral->wmi_ops.wmi_unified_register_event_handler( 6860 wmi_handle, event_id, handler_func, rx_ctx); 6861 6862 return qdf_status_to_os_return(ret); 6863 } 6864 6865 /** 6866 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 6867 * to unregister WMI event handler 6868 * @psoc: Pointer to psoc object 6869 * @event_id: Event id 6870 * 6871 * Wrapper function to unregister WMI event handler 6872 * 6873 * Return: 0 for success else failure 6874 */ 6875 static int 6876 target_if_spectral_wmi_unified_unregister_event_handler( 6877 struct wlan_objmgr_psoc *psoc, 6878 wmi_conv_event_id event_id) 6879 { 6880 wmi_unified_t wmi_handle; 6881 struct target_if_psoc_spectral *psoc_spectral; 6882 QDF_STATUS ret; 6883 6884 if (!psoc) { 6885 spectral_err("psoc is null"); 6886 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6887 } 6888 6889 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6890 if (!wmi_handle) { 6891 spectral_err("WMI handle is null"); 6892 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6893 } 6894 6895 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6896 if (!psoc_spectral) { 6897 spectral_err("spectral object is null"); 6898 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 6899 } 6900 6901 ret = psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler( 6902 wmi_handle, event_id); 6903 6904 return qdf_status_to_os_return(ret); 6905 } 6906 6907 /** 6908 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 6909 * function to extract fixed parameters from start scan response event 6910 * @psoc: Pointer to psoc object 6911 * @evt_buf: Event buffer 6912 * @param: Start scan response parameters 6913 * 6914 * Wrapper function to extract fixed parameters from start scan response event 6915 * 6916 * Return: QDF_STATUS 6917 */ 6918 static QDF_STATUS 6919 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 6920 struct wlan_objmgr_psoc *psoc, 6921 uint8_t *evt_buf, 6922 struct spectral_startscan_resp_params *param) 6923 { 6924 wmi_unified_t wmi_handle; 6925 struct target_if_psoc_spectral *psoc_spectral; 6926 6927 if (!psoc) { 6928 spectral_err("psoc is null"); 6929 return QDF_STATUS_E_INVAL; 6930 } 6931 6932 if (!evt_buf) { 6933 spectral_err("WMI event buffer is null"); 6934 return QDF_STATUS_E_INVAL; 6935 } 6936 6937 if (!param) { 6938 spectral_err("Spectral startscan response parameters is null"); 6939 return QDF_STATUS_E_INVAL; 6940 } 6941 6942 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6943 if (!wmi_handle) { 6944 spectral_err("WMI handle is null"); 6945 return QDF_STATUS_E_INVAL; 6946 } 6947 6948 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6949 if (!psoc_spectral) { 6950 spectral_err("spectral object is null"); 6951 return QDF_STATUS_E_FAILURE; 6952 } 6953 6954 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param( 6955 wmi_handle, evt_buf, param); 6956 } 6957 6958 /** 6959 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 6960 * function to extract start and end indices of primary 80 MHz, 5 MHz and 6961 * secondary 80 MHz FFT bins 6962 * @psoc: Pointer to psoc object 6963 * @evt_buf: Event buffer 6964 * @param: FFT bin start and end indices 6965 * 6966 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 6967 * and secondary 80 MHz FFT bins 6968 * 6969 * Return: QDF_STATUS 6970 */ 6971 static QDF_STATUS 6972 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 6973 struct wlan_objmgr_psoc *psoc, 6974 uint8_t *evt_buf, 6975 struct spectral_fft_bin_markers_160_165mhz *param) 6976 { 6977 wmi_unified_t wmi_handle; 6978 struct target_if_psoc_spectral *psoc_spectral; 6979 6980 if (!psoc) { 6981 spectral_err("psoc is null"); 6982 return QDF_STATUS_E_INVAL; 6983 } 6984 6985 if (!evt_buf) { 6986 spectral_err("WMI event buffer is null"); 6987 return QDF_STATUS_E_INVAL; 6988 } 6989 6990 if (!param) { 6991 spectral_err("Spectral FFT bin markers is null"); 6992 return QDF_STATUS_E_INVAL; 6993 } 6994 6995 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6996 if (!wmi_handle) { 6997 spectral_err("WMI handle is null"); 6998 return QDF_STATUS_E_INVAL; 6999 } 7000 7001 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7002 if (!psoc_spectral) { 7003 spectral_err("spectral object is null"); 7004 return QDF_STATUS_E_FAILURE; 7005 } 7006 7007 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index( 7008 wmi_handle, evt_buf, param); 7009 } 7010 7011 /** 7012 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 7013 * object from scn handle 7014 * @scn: scn handle 7015 * 7016 * Wrapper function to get psoc object from scn handle 7017 * 7018 * Return: Pointer to psoc object 7019 */ 7020 static struct wlan_objmgr_psoc * 7021 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 7022 { 7023 if (!scn) { 7024 spectral_err("scn is null"); 7025 return NULL; 7026 } 7027 7028 return ops_tgt.tgt_get_psoc_from_scn_hdl(scn); 7029 } 7030 7031 /** 7032 * target_if_extract_pdev_spectral_session_chan_info() - Wrapper 7033 * function to extract channel information for a spectral scan session 7034 * @psoc: Pointer to psoc object 7035 * @evt_buf: Event buffer 7036 * @chan_info: Spectral session channel information data structure to be filled 7037 * by this API 7038 * 7039 * Return: QDF_STATUS of operation 7040 */ 7041 static QDF_STATUS 7042 target_if_extract_pdev_spectral_session_chan_info( 7043 struct wlan_objmgr_psoc *psoc, 7044 void *evt_buf, 7045 struct spectral_session_chan_info *chan_info) 7046 { 7047 wmi_unified_t wmi_handle; 7048 struct target_if_psoc_spectral *psoc_spectral; 7049 7050 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7051 if (!wmi_handle) { 7052 spectral_err("WMI handle is null"); 7053 return QDF_STATUS_E_NULL_VALUE; 7054 } 7055 7056 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7057 if (!psoc_spectral) { 7058 spectral_err("spectral object is null"); 7059 return QDF_STATUS_E_NULL_VALUE; 7060 } 7061 7062 return psoc_spectral->wmi_ops.extract_pdev_spectral_session_chan_info( 7063 wmi_handle, evt_buf, chan_info); 7064 } 7065 7066 /** 7067 * target_if_extract_pdev_spectral_session_detector_info() - Wrapper 7068 * function to extract detector information for a spectral scan session 7069 * @psoc: Pointer to psoc object 7070 * @evt_buf: Event buffer 7071 * @det_info: Spectral session detector information data structure to be filled 7072 * by this API 7073 * @det_info_idx: index in the array of spectral scan detector info TLVs 7074 * 7075 * Return: QDF_STATUS of operation 7076 */ 7077 static QDF_STATUS 7078 target_if_extract_pdev_spectral_session_detector_info( 7079 struct wlan_objmgr_psoc *psoc, void *evt_buf, 7080 struct spectral_session_det_info *det_info, 7081 uint8_t det_info_idx) 7082 { 7083 wmi_unified_t wmi_handle; 7084 struct target_if_psoc_spectral *psoc_spectral; 7085 7086 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7087 if (!wmi_handle) { 7088 spectral_err("WMI handle is null"); 7089 return QDF_STATUS_E_NULL_VALUE; 7090 } 7091 7092 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7093 if (!psoc_spectral) { 7094 spectral_err("spectral object is null"); 7095 return QDF_STATUS_E_NULL_VALUE; 7096 } 7097 7098 return psoc_spectral->wmi_ops. 7099 extract_pdev_spectral_session_detector_info( 7100 wmi_handle, evt_buf, det_info, det_info_idx); 7101 } 7102 7103 /** 7104 * target_if_wmi_extract_spectral_caps_fixed_param() - Wrapper function to 7105 * extract fixed params from Spectral capabilities WMI event 7106 * @psoc: Pointer to psoc object 7107 * @evt_buf: Event buffer 7108 * @param: Spectral capabilities event parameters data structure to be filled 7109 * by this API 7110 * 7111 * Return: QDF_STATUS of operation 7112 */ 7113 QDF_STATUS 7114 target_if_wmi_extract_spectral_caps_fixed_param( 7115 struct wlan_objmgr_psoc *psoc, 7116 uint8_t *evt_buf, 7117 struct spectral_capabilities_event_params *param) 7118 { 7119 struct target_if_psoc_spectral *psoc_spectral; 7120 wmi_unified_t wmi_handle; 7121 7122 if (!psoc) { 7123 spectral_err("psoc is null"); 7124 return QDF_STATUS_E_NULL_VALUE; 7125 } 7126 7127 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7128 if (!wmi_handle) { 7129 spectral_err("WMI handle is null"); 7130 return QDF_STATUS_E_NULL_VALUE; 7131 } 7132 7133 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7134 if (!psoc_spectral) { 7135 spectral_err("spectral object is null"); 7136 return QDF_STATUS_E_FAILURE; 7137 } 7138 7139 return psoc_spectral->wmi_ops.extract_spectral_caps_fixed_param( 7140 wmi_handle, evt_buf, param); 7141 } 7142 7143 /** 7144 * target_if_wmi_extract_spectral_scan_bw_caps() - Wrapper function to 7145 * extract bandwidth capabilities from Spectral capabilities WMI event 7146 * @psoc: Pointer to psoc object 7147 * @evt_buf: Event buffer 7148 * @bw_caps: Data structure to be filled by this API after extraction 7149 * 7150 * Return: QDF_STATUS of operation 7151 */ 7152 QDF_STATUS 7153 target_if_wmi_extract_spectral_scan_bw_caps( 7154 struct wlan_objmgr_psoc *psoc, 7155 uint8_t *evt_buf, 7156 struct spectral_scan_bw_capabilities *bw_caps) 7157 { 7158 struct target_if_psoc_spectral *psoc_spectral; 7159 wmi_unified_t wmi_handle; 7160 7161 if (!psoc) { 7162 spectral_err("psoc is null"); 7163 return QDF_STATUS_E_INVAL; 7164 } 7165 7166 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7167 if (!wmi_handle) { 7168 spectral_err("WMI handle is null"); 7169 return QDF_STATUS_E_INVAL; 7170 } 7171 7172 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7173 if (!psoc_spectral) { 7174 spectral_err("spectral object is null"); 7175 return QDF_STATUS_E_FAILURE; 7176 } 7177 7178 return psoc_spectral->wmi_ops.extract_spectral_scan_bw_caps( 7179 wmi_handle, evt_buf, bw_caps); 7180 } 7181 7182 /** 7183 * target_if_wmi_extract_spectral_fft_size_caps() - Wrapper function to 7184 * extract fft size capabilities from Spectral capabilities WMI event 7185 * @psoc: Pointer to psoc object 7186 * @evt_buf: Event buffer 7187 * @fft_size_caps: Data structure to be filled by this API after extraction 7188 * 7189 * Return: QDF_STATUS of operation 7190 */ 7191 QDF_STATUS 7192 target_if_wmi_extract_spectral_fft_size_caps( 7193 struct wlan_objmgr_psoc *psoc, 7194 uint8_t *evt_buf, 7195 struct spectral_fft_size_capabilities *fft_size_caps) 7196 { 7197 struct target_if_psoc_spectral *psoc_spectral; 7198 wmi_unified_t wmi_handle; 7199 7200 if (!psoc) { 7201 spectral_err("psoc is null"); 7202 return QDF_STATUS_E_INVAL; 7203 } 7204 7205 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7206 if (!wmi_handle) { 7207 spectral_err("WMI handle is null"); 7208 return QDF_STATUS_E_INVAL; 7209 } 7210 7211 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7212 if (!psoc_spectral) { 7213 spectral_err("spectral object is null"); 7214 return QDF_STATUS_E_FAILURE; 7215 } 7216 7217 return psoc_spectral->wmi_ops.extract_spectral_fft_size_caps( 7218 wmi_handle, evt_buf, fft_size_caps); 7219 } 7220 #else 7221 /** 7222 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 7223 * register WMI event handler 7224 * @psoc: Pointer to psoc object 7225 * @event_id: Event id 7226 * @handler_func: Handler function 7227 * @rx_ctx: Context of WMI event processing 7228 * 7229 * Wrapper function to register WMI event handler 7230 * 7231 * Return: 0 for success else failure 7232 */ 7233 static int 7234 target_if_spectral_wmi_unified_register_event_handler( 7235 struct wlan_objmgr_psoc *psoc, 7236 wmi_conv_event_id event_id, 7237 wmi_unified_event_handler handler_func, 7238 uint8_t rx_ctx) 7239 { 7240 wmi_unified_t wmi_handle; 7241 QDF_STATUS ret; 7242 7243 if (!psoc) { 7244 spectral_err("psoc is null"); 7245 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7246 } 7247 7248 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7249 if (!wmi_handle) { 7250 spectral_err("WMI handle is null"); 7251 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7252 } 7253 7254 ret = wmi_unified_register_event_handler(wmi_handle, event_id, 7255 handler_func, rx_ctx); 7256 7257 return qdf_status_to_os_return(ret); 7258 } 7259 7260 /** 7261 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 7262 * to unregister WMI event handler 7263 * @psoc: Pointer to psoc object 7264 * @event_id: Event id 7265 * 7266 * Wrapper function to unregister WMI event handler 7267 * 7268 * Return: 0 for success else failure 7269 */ 7270 static int 7271 target_if_spectral_wmi_unified_unregister_event_handler( 7272 struct wlan_objmgr_psoc *psoc, 7273 wmi_conv_event_id event_id) 7274 { 7275 wmi_unified_t wmi_handle; 7276 QDF_STATUS ret; 7277 7278 if (!psoc) { 7279 spectral_err("psoc is null"); 7280 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7281 } 7282 7283 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7284 if (!wmi_handle) { 7285 spectral_err("WMI handle is null"); 7286 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7287 } 7288 7289 ret = wmi_unified_unregister_event_handler(wmi_handle, event_id); 7290 7291 return qdf_status_to_os_return(ret); 7292 } 7293 7294 /** 7295 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 7296 * function to extract fixed parameters from start scan response event 7297 * @psoc: Pointer to psoc object 7298 * @evt_buf: Event buffer 7299 * @param: Start scan response parameters 7300 * 7301 * Wrapper function to extract fixed parameters from start scan response event 7302 * 7303 * Return: QDF_STATUS 7304 */ 7305 static QDF_STATUS 7306 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 7307 struct wlan_objmgr_psoc *psoc, 7308 uint8_t *evt_buf, 7309 struct spectral_startscan_resp_params *param) 7310 { 7311 wmi_unified_t wmi_handle; 7312 7313 if (!psoc) { 7314 spectral_err("psoc is null"); 7315 return QDF_STATUS_E_INVAL; 7316 } 7317 7318 if (!evt_buf) { 7319 spectral_err("WMI event buffer is null"); 7320 return QDF_STATUS_E_INVAL; 7321 } 7322 7323 if (!param) { 7324 spectral_err("Spectral startscan response parameters is null"); 7325 return QDF_STATUS_E_INVAL; 7326 } 7327 7328 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7329 if (!wmi_handle) { 7330 spectral_err("WMI handle is null"); 7331 return QDF_STATUS_E_INVAL; 7332 } 7333 7334 return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf, 7335 param); 7336 } 7337 7338 /** 7339 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 7340 * function to extract start and end indices of primary 80 MHz, 5 MHz and 7341 * secondary 80 MHz FFT bins 7342 * @psoc: Pointer to psoc object 7343 * @evt_buf: Event buffer 7344 * @param: FFT bin start and end indices 7345 * 7346 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 7347 * and secondary 80 MHz FFT bins 7348 * 7349 * Return: QDF_STATUS 7350 */ 7351 static QDF_STATUS 7352 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 7353 struct wlan_objmgr_psoc *psoc, 7354 uint8_t *evt_buf, 7355 struct spectral_fft_bin_markers_160_165mhz *param) 7356 { 7357 wmi_unified_t wmi_handle; 7358 7359 if (!psoc) { 7360 spectral_err("psoc is null"); 7361 return QDF_STATUS_E_INVAL; 7362 } 7363 7364 if (!evt_buf) { 7365 spectral_err("WMI event buffer is null"); 7366 return QDF_STATUS_E_INVAL; 7367 } 7368 7369 if (!param) { 7370 spectral_err("Spectral FFT bin markers is null"); 7371 return QDF_STATUS_E_INVAL; 7372 } 7373 7374 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7375 if (!wmi_handle) { 7376 spectral_err("WMI handle is null"); 7377 return QDF_STATUS_E_INVAL; 7378 } 7379 7380 return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param); 7381 } 7382 7383 /** 7384 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 7385 * object from scn handle 7386 * @scn: scn handle 7387 * 7388 * Wrapper function to get psoc object from scn handle 7389 * 7390 * Return: Pointer to psoc object 7391 */ 7392 static struct wlan_objmgr_psoc * 7393 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 7394 { 7395 if (!scn) { 7396 spectral_err("scn is null"); 7397 return NULL; 7398 } 7399 7400 return target_if_get_psoc_from_scn_hdl(scn); 7401 } 7402 7403 /** 7404 * target_if_extract_pdev_spectral_session_chan_info() - Wrapper 7405 * function to extract channel information for a spectral scan session 7406 * @psoc: Pointer to psoc object 7407 * @evt_buf: Event buffer 7408 * @chan_info: Spectral session channel information data structure to be filled 7409 * by this API 7410 * 7411 * Return: QDF_STATUS of operation 7412 */ 7413 static QDF_STATUS 7414 target_if_extract_pdev_spectral_session_chan_info( 7415 struct wlan_objmgr_psoc *psoc, 7416 void *evt_buf, 7417 struct spectral_session_chan_info *chan_info) 7418 { 7419 wmi_unified_t wmi_handle; 7420 7421 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7422 if (!wmi_handle) { 7423 spectral_err("WMI handle is null"); 7424 return QDF_STATUS_E_NULL_VALUE; 7425 } 7426 7427 return wmi_extract_pdev_spectral_session_chan_info( 7428 wmi_handle, evt_buf, chan_info); 7429 } 7430 7431 /** 7432 * target_if_extract_pdev_spectral_session_detector_info() - Wrapper 7433 * function to extract detector information for a spectral scan session 7434 * @psoc: Pointer to psoc object 7435 * @evt_buf: Event buffer 7436 * @det_info: Spectral session detector information data structure to be filled 7437 * by this API 7438 * @det_info_idx: index in the array of spectral scan detector info TLVs 7439 * 7440 * Return: QDF_STATUS of operation 7441 */ 7442 static QDF_STATUS 7443 target_if_extract_pdev_spectral_session_detector_info( 7444 struct wlan_objmgr_psoc *psoc, void *evt_buf, 7445 struct spectral_session_det_info *det_info, 7446 uint8_t det_info_idx) 7447 { 7448 wmi_unified_t wmi_handle; 7449 7450 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7451 if (!wmi_handle) { 7452 spectral_err("WMI handle is null"); 7453 return QDF_STATUS_E_NULL_VALUE; 7454 } 7455 7456 return wmi_extract_pdev_spectral_session_detector_info( 7457 wmi_handle, evt_buf, det_info, det_info_idx); 7458 } 7459 7460 QDF_STATUS 7461 target_if_wmi_extract_spectral_caps_fixed_param( 7462 struct wlan_objmgr_psoc *psoc, 7463 uint8_t *evt_buf, 7464 struct spectral_capabilities_event_params *param) 7465 { 7466 wmi_unified_t wmi_handle; 7467 7468 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7469 if (!wmi_handle) { 7470 spectral_err("WMI handle is null"); 7471 return QDF_STATUS_E_INVAL; 7472 } 7473 7474 return wmi_extract_spectral_caps_fixed_param(wmi_handle, evt_buf, 7475 param); 7476 } 7477 7478 QDF_STATUS 7479 target_if_wmi_extract_spectral_scan_bw_caps( 7480 struct wlan_objmgr_psoc *psoc, 7481 uint8_t *evt_buf, 7482 struct spectral_scan_bw_capabilities *bw_caps) 7483 { 7484 wmi_unified_t wmi_handle; 7485 7486 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7487 if (!wmi_handle) { 7488 spectral_err("WMI handle is null"); 7489 return QDF_STATUS_E_INVAL; 7490 } 7491 7492 return wmi_extract_spectral_scan_bw_caps(wmi_handle, evt_buf, bw_caps); 7493 } 7494 7495 QDF_STATUS 7496 target_if_wmi_extract_spectral_fft_size_caps( 7497 struct wlan_objmgr_psoc *psoc, 7498 uint8_t *evt_buf, 7499 struct spectral_fft_size_capabilities *fft_size_caps) 7500 { 7501 wmi_unified_t wmi_handle; 7502 7503 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7504 if (!wmi_handle) { 7505 spectral_err("WMI handle is null"); 7506 return QDF_STATUS_E_INVAL; 7507 } 7508 7509 return wmi_extract_spectral_fft_size_caps(wmi_handle, evt_buf, 7510 fft_size_caps); 7511 } 7512 #endif 7513 7514 /** 7515 * target_if_update_det_info_in_spectral_session() - Update detector 7516 * information in spectral scan session 7517 * @spectral: Spectral LMAC object 7518 * @det_info: Pointer to spectral session detector information 7519 * @smode: Spectral scan mode 7520 * 7521 * Return: QDF_STATUS of operation 7522 */ 7523 static QDF_STATUS 7524 target_if_update_det_info_in_spectral_session( 7525 struct target_if_spectral *spectral, 7526 const struct spectral_session_det_info *det_info, 7527 enum spectral_scan_mode smode) 7528 { 7529 struct per_session_det_map *det_map; 7530 struct per_session_dest_det_info *dest_det_info; 7531 7532 if (!spectral) { 7533 spectral_err_rl("Spectral LMAC object is null"); 7534 return QDF_STATUS_E_NULL_VALUE; 7535 } 7536 7537 qdf_assert_always(det_info->det_id < MAX_DETECTORS_PER_PDEV); 7538 7539 qdf_spin_lock_bh(&spectral->session_det_map_lock); 7540 7541 det_map = &spectral->det_map[det_info->det_id]; 7542 dest_det_info = &det_map->dest_det_info[0]; 7543 7544 dest_det_info->start_freq = det_info->start_freq; 7545 dest_det_info->end_freq = det_info->end_freq; 7546 7547 qdf_spin_unlock_bh(&spectral->session_det_map_lock); 7548 7549 /* This detector will be used for this smode throughout this session */ 7550 spectral->rparams.detid_mode_table[det_info->det_id] = smode; 7551 7552 return QDF_STATUS_SUCCESS; 7553 } 7554 7555 /** 7556 * target_if_update_chan_info_in_spectral_session() - Update channel information 7557 * in spectral scan session 7558 * @spectral: Spectral LMAC object 7559 * @chan_info: Pointer to spectral session channel information 7560 * @smode: Spectral scan mode 7561 * 7562 * Return: QDF_STATUS of operation 7563 */ 7564 static QDF_STATUS 7565 target_if_update_chan_info_in_spectral_session( 7566 struct target_if_spectral *spectral, 7567 const struct spectral_session_chan_info *chan_info, 7568 enum spectral_scan_mode smode) 7569 { 7570 struct per_session_report_info *rpt_info; 7571 7572 if (!spectral) { 7573 spectral_err_rl("Spectral LMAC object is null"); 7574 return QDF_STATUS_E_NULL_VALUE; 7575 } 7576 7577 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 7578 spectral_err_rl("Invalid Spectral scan mode :%u", smode); 7579 return QDF_STATUS_E_FAILURE; 7580 } 7581 7582 qdf_spin_lock_bh(&spectral->session_report_info_lock); 7583 rpt_info = &spectral->report_info[smode]; 7584 7585 /* Update per-session report info */ 7586 rpt_info->pri20_freq = chan_info->operating_pri20_freq; 7587 rpt_info->cfreq1 = chan_info->operating_cfreq1; 7588 rpt_info->cfreq2 = chan_info->operating_cfreq2; 7589 rpt_info->operating_bw = chan_info->operating_bw; 7590 rpt_info->sscan_cfreq1 = chan_info->sscan_cfreq1; 7591 rpt_info->sscan_cfreq2 = chan_info->sscan_cfreq2; 7592 rpt_info->sscan_bw = chan_info->sscan_bw; 7593 7594 /* num_spans depends on sscan_bw, update it */ 7595 rpt_info->num_spans = target_if_spectral_get_num_spans( 7596 spectral->pdev_obj, 7597 rpt_info->sscan_bw); 7598 qdf_assert_always(rpt_info->num_spans != INVALID_SPAN_NUM); 7599 7600 rpt_info->valid = true; 7601 7602 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 7603 7604 return QDF_STATUS_SUCCESS; 7605 } 7606 7607 /** 7608 * target_if_spectral_fw_param_event_handler() - WMI event handler to 7609 * process start scan response event 7610 * @scn: Pointer to scn object 7611 * @data_buf: Pointer to event buffer 7612 * @data_len: Length of event buffer 7613 * 7614 * Return: 0 for success, else failure 7615 */ 7616 static int 7617 target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf, 7618 uint32_t data_len) 7619 { 7620 QDF_STATUS status; 7621 struct wlan_objmgr_psoc *psoc; 7622 struct wlan_objmgr_pdev *pdev; 7623 struct wmi_unified *wmi_handle; 7624 struct spectral_startscan_resp_params event_params = {0}; 7625 struct target_if_psoc_spectral *psoc_spectral; 7626 struct target_if_spectral *spectral; 7627 bool is_session_info_expected; 7628 7629 if (!scn) { 7630 spectral_err("scn handle is null"); 7631 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7632 } 7633 7634 if (!data_buf) { 7635 spectral_err("WMI event buffer null"); 7636 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7637 } 7638 7639 psoc = target_if_spectral_get_psoc_from_scn_handle(scn); 7640 if (!psoc) { 7641 spectral_err("psoc is null"); 7642 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7643 } 7644 7645 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7646 if (!psoc_spectral) { 7647 spectral_err("spectral object is null"); 7648 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7649 } 7650 7651 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7652 if (!wmi_handle) { 7653 spectral_err("WMI handle is null"); 7654 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7655 } 7656 7657 status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 7658 psoc, data_buf, &event_params); 7659 if (QDF_IS_STATUS_ERROR(status)) { 7660 spectral_err("unable to extract sscan fw fixed params"); 7661 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7662 } 7663 7664 if (event_params.smode >= SPECTRAL_SCAN_MODE_MAX || 7665 event_params.smode < SPECTRAL_SCAN_MODE_NORMAL) { 7666 spectral_err("Invalid smode %d", event_params.smode); 7667 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7668 } 7669 7670 pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id, 7671 WLAN_SPECTRAL_ID); 7672 if (!pdev) { 7673 spectral_err("pdev is null"); 7674 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7675 } 7676 7677 spectral = get_target_if_spectral_handle_from_pdev(pdev); 7678 if (!spectral) { 7679 spectral_err("spectral object is null"); 7680 status = QDF_STATUS_E_FAILURE; 7681 goto release_pdev_ref; 7682 } 7683 7684 if (event_params.num_fft_bin_index == 1) { 7685 status = 7686 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 7687 psoc, data_buf, 7688 &spectral->rparams.marker[event_params.smode]); 7689 if (QDF_IS_STATUS_ERROR(status)) { 7690 spectral_err("unable to extract sscan fw fixed params"); 7691 goto release_pdev_ref; 7692 } 7693 } else { 7694 spectral->rparams.marker[event_params.smode].is_valid = false; 7695 } 7696 7697 status = spectral_is_session_info_expected_from_target( 7698 pdev, &is_session_info_expected); 7699 if (QDF_IS_STATUS_ERROR(status)) { 7700 spectral_err("Failed to check if session info is expected"); 7701 goto release_pdev_ref; 7702 } 7703 7704 if (is_session_info_expected) { 7705 struct spectral_session_chan_info chan_info; 7706 uint8_t det_info_idx = 0; 7707 7708 status = target_if_extract_pdev_spectral_session_chan_info( 7709 psoc, data_buf, &chan_info); 7710 if (QDF_IS_STATUS_ERROR(status)) { 7711 spectral_err("Unable to extract spectral session channel info"); 7712 goto release_pdev_ref; 7713 } 7714 7715 status = target_if_update_chan_info_in_spectral_session( 7716 spectral, &chan_info, event_params.smode); 7717 if (QDF_IS_STATUS_ERROR(status)) { 7718 spectral_err("Unable to update channel info"); 7719 goto release_pdev_ref; 7720 } 7721 7722 /* FFT bins info depends upon sscan_bw, update it */ 7723 status = target_if_populate_fft_bins_info(spectral, 7724 event_params.smode); 7725 if (QDF_IS_STATUS_ERROR(status)) { 7726 spectral_err("Failed to populate FFT bins info"); 7727 goto release_pdev_ref; 7728 } 7729 7730 /** 7731 * per-session det info that depends on sscan_bw needs to be 7732 * updated here 7733 */ 7734 status = target_if_spectral_populate_session_det_host_info( 7735 spectral, event_params.smode); 7736 if (QDF_IS_STATUS_ERROR(status)) { 7737 spectral_err("Failed to populate per-session det info"); 7738 goto release_pdev_ref; 7739 } 7740 7741 for (; det_info_idx < event_params.num_det_info; 7742 ++det_info_idx) { 7743 struct spectral_session_det_info det_info; 7744 7745 status = 7746 target_if_extract_pdev_spectral_session_detector_info 7747 (psoc, data_buf, &det_info, det_info_idx); 7748 7749 if (QDF_IS_STATUS_ERROR(status)) { 7750 spectral_err("Unable to extract spectral session detector info for %u", 7751 det_info_idx); 7752 goto release_pdev_ref; 7753 } 7754 7755 status = target_if_update_det_info_in_spectral_session( 7756 spectral, &det_info, 7757 event_params.smode); 7758 if (QDF_IS_STATUS_ERROR(status)) { 7759 spectral_err("Unable to update detector info"); 7760 goto release_pdev_ref; 7761 } 7762 } 7763 } 7764 7765 status = QDF_STATUS_SUCCESS; 7766 7767 release_pdev_ref: 7768 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 7769 return qdf_status_to_os_return(status); 7770 } 7771 7772 /** 7773 * target_if_spectral_capabilities_event_handler() - Handler for the Spectral 7774 * Capabilities event 7775 * @scn: Pointer to scn object 7776 * @data_buf: Pointer to event buffer 7777 * @data_len: Length of event buffer 7778 * 7779 * Return: 0 for success, else failure 7780 */ 7781 static int 7782 target_if_spectral_capabilities_event_handler(ol_scn_t scn, uint8_t *data_buf, 7783 uint32_t data_len) 7784 { 7785 QDF_STATUS status; 7786 struct wlan_objmgr_psoc *psoc; 7787 struct wmi_unified *wmi_handle; 7788 struct spectral_capabilities_event_params event_params = {0}; 7789 struct spectral_scan_bw_capabilities *bw_caps; 7790 struct spectral_fft_size_capabilities *fft_size_caps; 7791 7792 if (!scn) { 7793 spectral_err("scn handle is null"); 7794 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7795 } 7796 7797 if (!data_buf) { 7798 spectral_err("WMI event buffer null"); 7799 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7800 } 7801 7802 psoc = target_if_spectral_get_psoc_from_scn_handle(scn); 7803 if (!psoc) { 7804 spectral_err("psoc is null"); 7805 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7806 } 7807 7808 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7809 if (!wmi_handle) { 7810 spectral_err("WMI handle is null"); 7811 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7812 } 7813 7814 status = target_if_wmi_extract_spectral_caps_fixed_param( 7815 psoc, data_buf, &event_params); 7816 if (QDF_IS_STATUS_ERROR(status)) { 7817 spectral_err("Failed to extract fixed parameters"); 7818 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7819 } 7820 7821 /* There should be atleast one capability */ 7822 qdf_assert(event_params.num_sscan_bw_caps > 0); 7823 qdf_assert(event_params.num_fft_size_caps > 0); 7824 7825 bw_caps = qdf_mem_malloc( 7826 sizeof(*bw_caps) * event_params.num_sscan_bw_caps); 7827 if (!bw_caps) { 7828 spectral_err("memory allocation failed"); 7829 return qdf_status_to_os_return(QDF_STATUS_E_NOMEM); 7830 } 7831 7832 status = target_if_wmi_extract_spectral_scan_bw_caps(psoc, data_buf, 7833 bw_caps); 7834 if (QDF_IS_STATUS_ERROR(status)) { 7835 spectral_err("Failed to extract BW caps"); 7836 status = QDF_STATUS_E_FAILURE; 7837 goto free_bw_caps; 7838 } 7839 7840 fft_size_caps = qdf_mem_malloc( 7841 sizeof(*fft_size_caps) * event_params.num_fft_size_caps); 7842 if (!fft_size_caps) { 7843 spectral_err("memory allocation failed"); 7844 status = QDF_STATUS_E_NOMEM; 7845 goto free_bw_caps; 7846 } 7847 7848 status = target_if_wmi_extract_spectral_fft_size_caps(psoc, data_buf, 7849 fft_size_caps); 7850 if (QDF_IS_STATUS_ERROR(status)) { 7851 spectral_err("Failed to extract fft size caps"); 7852 status = QDF_STATUS_E_FAILURE; 7853 goto free_fft_size_caps; 7854 } 7855 7856 status = QDF_STATUS_SUCCESS; 7857 7858 free_fft_size_caps: 7859 qdf_mem_free(fft_size_caps); 7860 7861 free_bw_caps: 7862 qdf_mem_free(bw_caps); 7863 7864 return qdf_status_to_os_return(status); 7865 } 7866 7867 static QDF_STATUS 7868 target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc) 7869 { 7870 int ret; 7871 7872 if (!psoc) { 7873 spectral_err("psoc is null"); 7874 return QDF_STATUS_E_INVAL; 7875 } 7876 7877 ret = target_if_spectral_wmi_unified_register_event_handler( 7878 psoc, 7879 wmi_pdev_sscan_fw_param_eventid, 7880 target_if_spectral_fw_param_event_handler, 7881 WMI_RX_UMAC_CTX); 7882 7883 if (ret) 7884 spectral_debug("event handler not supported, ret=%d", ret); 7885 7886 ret = target_if_spectral_wmi_unified_register_event_handler( 7887 psoc, 7888 wmi_spectral_capabilities_eventid, 7889 target_if_spectral_capabilities_event_handler, 7890 WMI_RX_UMAC_CTX); 7891 if (ret) 7892 spectral_debug("event handler not supported, ret=%d", ret); 7893 7894 return QDF_STATUS_SUCCESS; 7895 } 7896 7897 static QDF_STATUS 7898 target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc) 7899 { 7900 int ret; 7901 7902 if (!psoc) { 7903 spectral_err("psoc is null"); 7904 return QDF_STATUS_E_INVAL; 7905 } 7906 7907 target_if_spectral_wmi_unified_unregister_event_handler( 7908 psoc, wmi_spectral_capabilities_eventid); 7909 7910 ret = target_if_spectral_wmi_unified_unregister_event_handler( 7911 psoc, wmi_pdev_sscan_fw_param_eventid); 7912 7913 if (ret) 7914 spectral_debug("Unregister WMI event handler failed, ret = %d", 7915 ret); 7916 7917 return QDF_STATUS_SUCCESS; 7918 } 7919 7920 void 7921 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 7922 { 7923 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 7924 target_if_pdev_spectral_init; 7925 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 7926 target_if_pdev_spectral_deinit; 7927 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init = 7928 target_if_psoc_spectral_init; 7929 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit = 7930 target_if_psoc_spectral_deinit; 7931 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 7932 target_if_set_spectral_config; 7933 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 7934 target_if_get_spectral_config; 7935 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 7936 target_if_start_spectral_scan; 7937 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 7938 target_if_stop_spectral_scan; 7939 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 7940 target_if_is_spectral_active; 7941 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 7942 target_if_is_spectral_enabled; 7943 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 7944 target_if_set_debug_level; 7945 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 7946 target_if_get_debug_level; 7947 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 7948 target_if_get_spectral_capinfo; 7949 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 7950 target_if_get_spectral_diagstats; 7951 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops = 7952 target_if_register_spectral_wmi_ops; 7953 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops = 7954 target_if_register_spectral_tgt_ops; 7955 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 7956 target_if_register_netlink_cb; 7957 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 7958 target_if_use_nl_bcast; 7959 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 7960 target_if_deregister_netlink_cb; 7961 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = 7962 target_if_process_spectral_report; 7963 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = 7964 target_if_spectral_direct_dma_support; 7965 tx_ops->sptrl_tx_ops.sptrlto_register_events = 7966 target_if_spectral_register_events; 7967 tx_ops->sptrl_tx_ops.sptrlto_unregister_events = 7968 target_if_spectral_unregister_events; 7969 tx_ops->sptrl_tx_ops.sptrlto_init_pdev_feature_caps = 7970 target_if_spectral_init_pdev_feature_caps; 7971 7972 target_if_sptrl_debug_register_tx_ops(tx_ops); 7973 } 7974 qdf_export_symbol(target_if_sptrl_register_tx_ops); 7975 7976 void 7977 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 7978 uint16_t cw_int, uint32_t dcs_enabled) 7979 { 7980 struct spectral_samp_msg *msg = NULL; 7981 struct target_if_spectral_ops *p_sops = NULL; 7982 struct target_if_spectral *spectral = NULL; 7983 7984 spectral = get_target_if_spectral_handle_from_pdev(pdev); 7985 7986 if (!spectral) { 7987 spectral_err("SPECTRAL : Module doesn't exist"); 7988 return; 7989 } 7990 7991 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 7992 if (!p_sops) { 7993 spectral_err("p_sops is null"); 7994 return; 7995 } 7996 7997 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( 7998 spectral->pdev_obj, 7999 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, 8000 SPECTRAL_MSG_BUF_NEW); 8001 8002 if (msg) { 8003 msg->int_type = cw_int ? 8004 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 8005 msg->dcs_enabled = dcs_enabled; 8006 msg->signature = SPECTRAL_SIGNATURE; 8007 p_sops->get_mac_address(spectral, msg->macaddr); 8008 if (spectral->send_phy_data 8009 (pdev, 8010 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0) 8011 spectral->spectral_sent_msg++; 8012 } 8013 } 8014 qdf_export_symbol(target_if_spectral_send_intf_found_msg); 8015 8016 QDF_STATUS 8017 target_if_spectral_is_finite_scan(struct target_if_spectral *spectral, 8018 enum spectral_scan_mode smode, 8019 bool *finite_spectral_scan) 8020 { 8021 struct target_if_finite_spectral_scan_params *finite_scan; 8022 8023 if (!spectral) { 8024 spectral_err_rl("target if spectral object is null"); 8025 return QDF_STATUS_E_INVAL; 8026 } 8027 8028 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 8029 spectral_err_rl("invalid spectral mode %d", smode); 8030 return QDF_STATUS_E_INVAL; 8031 } 8032 8033 if (!finite_spectral_scan) { 8034 spectral_err_rl("Invalid pointer"); 8035 return QDF_STATUS_E_INVAL; 8036 } 8037 8038 finite_scan = &spectral->finite_scan[smode]; 8039 *finite_spectral_scan = finite_scan->finite_spectral_scan; 8040 8041 return QDF_STATUS_SUCCESS; 8042 } 8043 8044 QDF_STATUS 8045 target_if_spectral_finite_scan_update(struct target_if_spectral *spectral, 8046 enum spectral_scan_mode smode) 8047 { 8048 struct target_if_finite_spectral_scan_params *finite_scan; 8049 8050 if (!spectral) { 8051 spectral_err_rl("target if spectral object is null"); 8052 return QDF_STATUS_E_INVAL; 8053 } 8054 8055 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 8056 spectral_err_rl("Invalid Spectral mode"); 8057 return QDF_STATUS_E_INVAL; 8058 } 8059 8060 finite_scan = &spectral->finite_scan[smode]; 8061 8062 if (!finite_scan->num_reports_expected) { 8063 spectral_err_rl("Error, No reports expected"); 8064 return QDF_STATUS_E_FAILURE; 8065 } 8066 8067 finite_scan->num_reports_expected--; 8068 if (!finite_scan->num_reports_expected) { 8069 QDF_STATUS status; 8070 enum spectral_cp_error_code err; 8071 8072 /* received expected number of reports from target, stop scan */ 8073 status = target_if_stop_spectral_scan(spectral->pdev_obj, smode, 8074 &err); 8075 if (QDF_IS_STATUS_ERROR(status)) { 8076 spectral_err_rl("Failed to stop finite Spectral scan"); 8077 return QDF_STATUS_E_FAILURE; 8078 } 8079 finite_scan->finite_spectral_scan = false; 8080 } 8081 8082 return QDF_STATUS_SUCCESS; 8083 } 8084