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 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 2124 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2125 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 2126 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2127 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 2128 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2129 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 2130 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2131 } else { 2132 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 2133 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2134 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 2135 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2136 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 2137 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2138 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 2139 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2140 } 2141 break; 2142 2143 case SPECTRAL_GEN2: 2144 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; 2145 param_min_max->fft_size_max[CH_WIDTH_20MHZ] = 2146 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2147 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 2148 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2149 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 2150 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2151 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 2152 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2153 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 2154 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2155 break; 2156 2157 default: 2158 spectral_err("Invalid spectral generation %d", gen); 2159 return QDF_STATUS_E_INVAL; 2160 } 2161 2162 return QDF_STATUS_SUCCESS; 2163 } 2164 2165 /** 2166 * target_if_init_spectral_param_properties() - Initialize Spectral parameter 2167 * properties 2168 * @spectral: Pointer to Spectral target_if internal private data 2169 * 2170 * Initialize Spectral parameter properties 2171 * 2172 * Return: QDF_STATUS 2173 */ 2174 static QDF_STATUS 2175 target_if_init_spectral_param_properties(struct target_if_spectral *spectral) 2176 { 2177 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2178 int param; 2179 2180 /* Initialize default values for properties. 2181 * Default values are supported for all the parameters for all modes 2182 * and allows different values for each mode for all the parameters . 2183 */ 2184 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2185 for (param = 0; param < SPECTRAL_PARAM_MAX; param++) { 2186 spectral->properties[smode][param].supported = true; 2187 spectral->properties[smode][param].common_all_modes = 2188 false; 2189 } 2190 } 2191 2192 /* Once FW advertisement is in place remove this hard coding */ 2193 smode = SPECTRAL_SCAN_MODE_NORMAL; 2194 spectral->properties[SPECTRAL_SCAN_MODE_NORMAL] 2195 [SPECTRAL_PARAM_FREQUENCY].supported = false; 2196 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2197 spectral->properties[smode] 2198 [SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true; 2199 spectral->properties[smode] 2200 [SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true; 2201 spectral->properties[smode] 2202 [SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true; 2203 } 2204 2205 return QDF_STATUS_SUCCESS; 2206 } 2207 2208 /* Bandwidth to half bandwidth mapping */ 2209 static const enum phy_ch_width half_bw_map[] = { 2210 #ifdef WLAN_FEATURE_11BE 2211 [CH_WIDTH_320MHZ] = CH_WIDTH_160MHZ, 2212 #endif 2213 [CH_WIDTH_80P80MHZ] = CH_WIDTH_80MHZ, 2214 [CH_WIDTH_160MHZ] = CH_WIDTH_80MHZ, 2215 [CH_WIDTH_80MHZ] = CH_WIDTH_40MHZ, 2216 [CH_WIDTH_40MHZ] = CH_WIDTH_20MHZ, 2217 [CH_WIDTH_20MHZ] = CH_WIDTH_10MHZ, 2218 [CH_WIDTH_10MHZ] = CH_WIDTH_5MHZ, 2219 [CH_WIDTH_5MHZ] = CH_WIDTH_INVALID 2220 }; 2221 2222 /** 2223 * target_if_get_half_bandwidth() - Get half bandwidth for a given bandwidth 2224 * @bw: bandwidth 2225 * 2226 * Return: Half bandwidth of @bw 2227 */ 2228 static enum phy_ch_width target_if_get_half_bandwidth(enum phy_ch_width bw) 2229 { 2230 if (bw >= CH_WIDTH_INVALID) 2231 return CH_WIDTH_INVALID; 2232 2233 return half_bw_map[bw]; 2234 } 2235 2236 /** 2237 * target_if_populate_supported_sscan_bws_be() - Populate supported spectral 2238 * scan bandwidths for beryllium chipsets 2239 * @spectral: Spectral LMAC object 2240 * 2241 * Return: QDF_STATUS of operation 2242 */ 2243 static QDF_STATUS 2244 target_if_populate_supported_sscan_bws_be(struct target_if_spectral *spectral) 2245 { 2246 enum phy_ch_width op_bw; 2247 struct spectral_supported_bws *supported_bws; 2248 QDF_STATUS status; 2249 2250 qdf_assert_always(spectral); 2251 2252 /* 20MHz */ 2253 op_bw = CH_WIDTH_20MHZ; 2254 supported_bws = &spectral->supported_bws 2255 [SPECTRAL_SCAN_MODE_NORMAL][op_bw]; 2256 supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw); 2257 spectral->supported_sscan_bw_list 2258 [SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true; 2259 supported_bws = &spectral->supported_bws 2260 [SPECTRAL_SCAN_MODE_AGILE][op_bw]; 2261 supported_bws->bandwidths |= 1 << get_supported_sscan_bw_pos(op_bw); 2262 spectral->supported_sscan_bw_list 2263 [SPECTRAL_SCAN_MODE_AGILE][op_bw] = true; 2264 2265 for (op_bw = CH_WIDTH_40MHZ; op_bw < CH_WIDTH_MAX; op_bw++) { 2266 bool is_supported; 2267 enum phy_ch_width half_op_bw; 2268 2269 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj, 2270 op_bw, &is_supported); 2271 if (QDF_IS_STATUS_ERROR(status)) { 2272 spectral_err("Unable to check if ch_width(%d) is supported", 2273 op_bw); 2274 return QDF_STATUS_E_FAILURE; 2275 } 2276 2277 if (!is_supported) 2278 continue; 2279 2280 spectral_debug("Updating supported bw for op_bw: %d", op_bw); 2281 /* Normal mode */ 2282 supported_bws = &spectral->supported_bws 2283 [SPECTRAL_SCAN_MODE_NORMAL][op_bw]; 2284 supported_bws->bandwidths |= 2285 1 << get_supported_sscan_bw_pos(op_bw); 2286 spectral->supported_sscan_bw_list 2287 [SPECTRAL_SCAN_MODE_NORMAL][op_bw] = true; 2288 2289 /* Agile mode */ 2290 supported_bws = &spectral->supported_bws 2291 [SPECTRAL_SCAN_MODE_AGILE][op_bw]; 2292 supported_bws->bandwidths |= 2293 1 << get_supported_sscan_bw_pos(op_bw); 2294 spectral->supported_sscan_bw_list 2295 [SPECTRAL_SCAN_MODE_AGILE][op_bw] = true; 2296 2297 half_op_bw = target_if_get_half_bandwidth(op_bw); 2298 if (half_op_bw != CH_WIDTH_INVALID) { 2299 supported_bws->bandwidths |= 2300 1 << get_supported_sscan_bw_pos(half_op_bw); 2301 spectral->supported_sscan_bw_list 2302 [SPECTRAL_SCAN_MODE_AGILE][half_op_bw] = true; 2303 } 2304 } 2305 2306 return QDF_STATUS_SUCCESS; 2307 } 2308 2309 /** 2310 * target_if_populate_supported_sscan_bws() - Populate supported spectral 2311 * scan bandwidths 2312 * @spectral: Spectral LMAC object 2313 * @target_type: Target type 2314 * 2315 * Return: QDF_STATUS of operation 2316 */ 2317 static QDF_STATUS 2318 target_if_populate_supported_sscan_bws(struct target_if_spectral *spectral, 2319 uint32_t target_type) 2320 { 2321 enum spectral_scan_mode smode; 2322 enum phy_ch_width op_bw; 2323 struct spectral_supported_bws *supported_bws; 2324 struct wlan_objmgr_psoc *psoc; 2325 QDF_STATUS status; 2326 2327 qdf_assert_always(spectral); 2328 2329 if (is_spectral_arch_beryllium(target_type)) 2330 return target_if_populate_supported_sscan_bws_be(spectral); 2331 2332 psoc = wlan_pdev_get_psoc(spectral->pdev_obj); 2333 if (!psoc) { 2334 spectral_err("psoc is null"); 2335 return QDF_STATUS_E_NULL_VALUE; 2336 } 2337 2338 for (op_bw = CH_WIDTH_20MHZ; op_bw < CH_WIDTH_MAX; op_bw++) { 2339 bool is_supported; 2340 2341 status = wlan_reg_is_chwidth_supported(spectral->pdev_obj, 2342 op_bw, &is_supported); 2343 if (QDF_IS_STATUS_ERROR(status)) { 2344 spectral_err("Unable to check if ch_width(%d) is supported", 2345 op_bw); 2346 return QDF_STATUS_E_FAILURE; 2347 } 2348 2349 if (!is_supported) 2350 continue; 2351 2352 spectral_debug("Updating supported bw for op_bw: %d", op_bw); 2353 smode = SPECTRAL_SCAN_MODE_NORMAL; 2354 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2355 supported_bws = &spectral->supported_bws[smode][op_bw]; 2356 2357 if (is_ch_width_160_or_80p80(op_bw) && 2358 smode == SPECTRAL_SCAN_MODE_AGILE) { 2359 /** 2360 * If fragmentation is supported, then only 80Hz 2361 * agile width is supported 2362 */ 2363 if (spectral->rparams. 2364 fragmentation_160[smode]) { 2365 supported_bws->bandwidths |= 2366 1 << get_supported_sscan_bw_pos( 2367 CH_WIDTH_80MHZ); 2368 spectral->supported_sscan_bw_list 2369 [smode][CH_WIDTH_80MHZ] = true; 2370 } 2371 2372 /** 2373 * If restricted 80p80 is supported, then both 2374 * 160 and 80p80 agile widths are supported for 2375 * 160MHz, and only 160MHz agile width is 2376 * supported for 80p80 2377 */ 2378 if (wlan_psoc_nif_fw_ext_cap_get( 2379 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) { 2380 supported_bws->bandwidths |= 2381 1 << get_supported_sscan_bw_pos( 2382 CH_WIDTH_160MHZ); 2383 spectral->supported_sscan_bw_list 2384 [smode][CH_WIDTH_160MHZ] = true; 2385 2386 if (op_bw == CH_WIDTH_160MHZ) { 2387 supported_bws->bandwidths |= 2388 1 << get_supported_sscan_bw_pos( 2389 CH_WIDTH_80P80MHZ); 2390 spectral->supported_sscan_bw_list 2391 [smode][CH_WIDTH_80P80MHZ] = true; 2392 } 2393 } 2394 } else { 2395 supported_bws->bandwidths |= 2396 1 << get_supported_sscan_bw_pos( 2397 op_bw); 2398 spectral->supported_sscan_bw_list 2399 [smode][op_bw] = true; 2400 } 2401 } 2402 } 2403 2404 return QDF_STATUS_SUCCESS; 2405 } 2406 2407 QDF_STATUS 2408 target_if_init_spectral_capability(struct target_if_spectral *spectral, 2409 uint32_t target_type) 2410 { 2411 struct wlan_objmgr_psoc *psoc; 2412 struct wlan_objmgr_pdev *pdev; 2413 struct wlan_psoc_host_spectral_scaling_params *scaling_params; 2414 uint8_t num_bin_scaling_params, param_idx, pdev_id; 2415 struct target_psoc_info *tgt_psoc_info; 2416 struct wlan_psoc_host_service_ext_param *ext_svc_param; 2417 struct spectral_caps *pcap = &spectral->capability; 2418 QDF_STATUS status; 2419 2420 pdev = spectral->pdev_obj; 2421 psoc = wlan_pdev_get_psoc(pdev); 2422 if (!psoc) { 2423 spectral_err("psoc is null"); 2424 return QDF_STATUS_E_FAILURE; 2425 } 2426 2427 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 2428 if (!tgt_psoc_info) { 2429 spectral_err("target_psoc_info is null"); 2430 return QDF_STATUS_E_FAILURE; 2431 } 2432 2433 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 2434 num_bin_scaling_params = ext_svc_param->num_bin_scaling_params; 2435 scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info); 2436 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 2437 2438 /* XXX : Workaround: Set Spectral capability */ 2439 pcap = &spectral->capability; 2440 pcap->phydiag_cap = 1; 2441 pcap->radar_cap = 1; 2442 pcap->spectral_cap = wlan_pdev_nif_feat_ext_cap_get( 2443 pdev, WLAN_PDEV_FEXT_NORMAL_SPECTRAL_SCAN_DIS); 2444 pcap->advncd_spectral_cap = pcap->spectral_cap; 2445 pcap->hw_gen = spectral->spectral_gen; 2446 2447 pcap->agile_spectral_cap = !wlan_pdev_nif_feat_ext_cap_get( 2448 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_DIS); 2449 pcap->agile_spectral_cap_160 = !wlan_pdev_nif_feat_ext_cap_get( 2450 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_160_DIS); 2451 pcap->agile_spectral_cap_80p80 = !wlan_pdev_nif_feat_ext_cap_get( 2452 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_80P80_DIS); 2453 pcap->agile_spectral_cap_320 = !wlan_pdev_nif_feat_ext_cap_get( 2454 pdev, WLAN_PDEV_FEXT_AGILE_SPECTRAL_SCAN_320_DIS); 2455 2456 if (scaling_params) { 2457 for (param_idx = 0; param_idx < num_bin_scaling_params; 2458 param_idx++) { 2459 if (scaling_params[param_idx].pdev_id == pdev_id) { 2460 pcap->is_scaling_params_populated = true; 2461 pcap->formula_id = 2462 scaling_params[param_idx].formula_id; 2463 pcap->low_level_offset = 2464 scaling_params[param_idx].low_level_offset; 2465 pcap->high_level_offset = 2466 scaling_params[param_idx].high_level_offset; 2467 pcap->rssi_thr = 2468 scaling_params[param_idx].rssi_thr; 2469 pcap->default_agc_max_gain = 2470 scaling_params[param_idx].default_agc_max_gain; 2471 break; 2472 } 2473 } 2474 } 2475 2476 pcap->num_detectors_20mhz = 1; 2477 pcap->num_detectors_40mhz = 1; 2478 pcap->num_detectors_80mhz = 1; 2479 if (target_type == TARGET_TYPE_QCN9000 || 2480 target_type == TARGET_TYPE_QCN6122 || 2481 target_type == TARGET_TYPE_QCN9160 || 2482 target_type == TARGET_TYPE_QCA6490 || 2483 target_type == TARGET_TYPE_KIWI || 2484 target_type == TARGET_TYPE_MANGO) { 2485 pcap->num_detectors_160mhz = 1; 2486 pcap->num_detectors_80p80mhz = 1; 2487 pcap->num_detectors_320mhz = 0; 2488 } else if (is_spectral_arch_beryllium(target_type)) { 2489 pcap->num_detectors_160mhz = 1; 2490 pcap->num_detectors_80p80mhz = 0; 2491 pcap->num_detectors_320mhz = 1; 2492 } else { 2493 pcap->num_detectors_160mhz = 2; 2494 pcap->num_detectors_80p80mhz = 2; 2495 pcap->num_detectors_320mhz = 0; 2496 } 2497 2498 status = target_if_populate_supported_sscan_bws(spectral, target_type); 2499 if (QDF_IS_STATUS_ERROR(status)) { 2500 spectral_err("Unable to populate supported sscan BWs"); 2501 return QDF_STATUS_E_FAILURE; 2502 } 2503 2504 return QDF_STATUS_SUCCESS; 2505 } 2506 2507 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 2508 /** 2509 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 2510 * internal operations with functions related to spectral simulation 2511 * @p_sops: spectral low level ops table 2512 * 2513 * Initialize spectral target_if internal operations with functions 2514 * related to spectral simulation 2515 * 2516 * Return: None 2517 */ 2518 static void 2519 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 2520 { 2521 /* 2522 * Spectral simulation is currently intended for platform transitions 2523 * where underlying HW support may not be available for some time. 2524 * Hence, we do not currently provide a runtime switch to turn the 2525 * simulation on or off. 2526 * In case of future requirements where runtime switches are required, 2527 * this can be added. But it is suggested to use application layer 2528 * simulation as far as possible in such cases, since the main 2529 * use of record and replay of samples would concern higher 2530 * level sample processing rather than lower level delivery. 2531 */ 2532 p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled; 2533 p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active; 2534 p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan; 2535 p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan; 2536 p_sops->configure_spectral = 2537 target_if_spectral_sops_sim_configure_params; 2538 p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params; 2539 } 2540 2541 #else 2542 /** 2543 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 2544 * internal operations 2545 * @p_sops: spectral low level ops table 2546 * 2547 * Return: None 2548 */ 2549 static void 2550 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 2551 { 2552 p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled; 2553 p_sops->is_spectral_active = target_if_sops_is_spectral_active; 2554 p_sops->start_spectral_scan = target_if_sops_start_spectral_scan; 2555 p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan; 2556 p_sops->configure_spectral = target_if_spectral_sops_configure_params; 2557 p_sops->get_spectral_config = target_if_spectral_sops_get_params; 2558 } 2559 #endif 2560 2561 /** 2562 * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal 2563 * operations common to all Spectral chipset generations 2564 * 2565 * Initializes target_if_spectral_ops common to all chipset generations 2566 * 2567 * Return: None 2568 */ 2569 static void 2570 target_if_init_spectral_ops_common(void) 2571 { 2572 struct target_if_spectral_ops *p_sops = &spectral_ops; 2573 2574 p_sops->get_tsf64 = target_if_spectral_get_tsf64; 2575 p_sops->get_capability = target_if_spectral_get_capability; 2576 p_sops->set_rxfilter = target_if_spectral_set_rxfilter; 2577 p_sops->get_rxfilter = target_if_spectral_get_rxfilter; 2578 2579 target_if_init_spectral_simulation_ops(p_sops); 2580 2581 p_sops->get_extension_channel = 2582 target_if_spectral_get_extension_channel; 2583 p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor; 2584 p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor; 2585 p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask; 2586 p_sops->get_mac_address = target_if_spectral_get_macaddr; 2587 p_sops->get_current_channel = target_if_spectral_get_current_channel; 2588 p_sops->reset_hw = target_if_spectral_reset_hw; 2589 p_sops->get_chain_noise_floor = 2590 target_if_spectral_get_chain_noise_floor; 2591 } 2592 2593 /** 2594 * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal 2595 * operations specific to Spectral chipset generation 2. 2596 * 2597 * Initializes target_if_spectral_ops specific to Spectral chipset generation 2. 2598 * 2599 * Return: None 2600 */ 2601 static void 2602 target_if_init_spectral_ops_gen2(void) 2603 { 2604 struct target_if_spectral_ops *p_sops = &spectral_ops; 2605 2606 p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2; 2607 } 2608 2609 #ifdef BIG_ENDIAN_HOST 2610 /** 2611 * spectral_is_host_byte_swap_required() - Check if byte swap has to be done 2612 * on the Host 2613 * @pdev: pdev pointer 2614 * @is_swap_required: Pointer to caller variable 2615 * 2616 * Return: QDF_STATUS of operation 2617 */ 2618 static QDF_STATUS 2619 spectral_is_host_byte_swap_required(struct wlan_objmgr_pdev *pdev, 2620 bool *is_swap_required) 2621 { 2622 struct wlan_objmgr_psoc *psoc; 2623 struct wmi_unified *wmi_handle; 2624 2625 if (!pdev) { 2626 spectral_err("pdev is null"); 2627 return QDF_STATUS_E_INVAL; 2628 } 2629 2630 psoc = wlan_pdev_get_psoc(pdev); 2631 if (!psoc) { 2632 spectral_err("psoc is null"); 2633 return QDF_STATUS_E_INVAL; 2634 } 2635 2636 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 2637 if (!wmi_handle) { 2638 spectral_err("wmi handle is null"); 2639 return QDF_STATUS_E_INVAL; 2640 } 2641 2642 /** 2643 * If a chipset supports byte-swap inside the target itself, then no 2644 * need to apply byte swap on the Host. 2645 */ 2646 *is_swap_required = !target_if_spectral_wmi_service_enabled( 2647 psoc, wmi_handle, 2648 wmi_service_phy_dma_byte_swap_support); 2649 2650 return QDF_STATUS_SUCCESS; 2651 } 2652 2653 /** 2654 * target_if_spectral_init_byte_swap_funcs_gen3() - Initialize byte-swap 2655 * operations for Spectral chipset generation 3. 2656 * @spectral: Spectral LMAC object 2657 * @p_sops: Spectral function pointer table 2658 * 2659 * Return: None 2660 */ 2661 static void 2662 target_if_spectral_init_byte_swap_funcs_gen3( 2663 struct target_if_spectral *spectral, 2664 struct target_if_spectral_ops *p_sops) 2665 { 2666 bool is_swap_required; 2667 QDF_STATUS status; 2668 2669 qdf_assert_always(spectral); 2670 qdf_assert_always(p_sops); 2671 2672 status = spectral_is_host_byte_swap_required(spectral->pdev_obj, 2673 &is_swap_required); 2674 if (QDF_IS_STATUS_ERROR(status)) { 2675 spectral_err("Failed to check whether byte swap is required"); 2676 return; 2677 } 2678 2679 if (is_swap_required) { 2680 p_sops->byte_swap_headers = 2681 target_if_byte_swap_spectral_headers_gen3; 2682 p_sops->byte_swap_fft_bins = 2683 target_if_byte_swap_spectral_fft_bins_gen3; 2684 } else { 2685 p_sops->byte_swap_headers = NULL; 2686 p_sops->byte_swap_fft_bins = NULL; 2687 } 2688 } 2689 #else 2690 static void 2691 target_if_spectral_init_byte_swap_funcs_gen3( 2692 struct target_if_spectral *spectral, 2693 struct target_if_spectral_ops *p_sops) 2694 { 2695 qdf_assert_always(p_sops); 2696 2697 /* Byte-swap is not required for little-endian Hosts */ 2698 p_sops->byte_swap_headers = NULL; 2699 p_sops->byte_swap_fft_bins = NULL; 2700 } 2701 #endif /* BIG_ENDIAN_HOST */ 2702 2703 /** 2704 * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal 2705 * operations specific to Spectral chipset generation 3. 2706 * @spectral: Spectral LMAC object 2707 * 2708 * Initializes target_if_spectral_ops specific to Spectral chipset generation 3. 2709 * 2710 * Return: None 2711 */ 2712 static void 2713 target_if_init_spectral_ops_gen3(struct target_if_spectral *spectral) 2714 { 2715 struct target_if_spectral_ops *p_sops = &spectral_ops; 2716 2717 p_sops->process_spectral_report = 2718 target_if_spectral_process_report_gen3; 2719 2720 target_if_spectral_init_byte_swap_funcs_gen3(spectral, p_sops); 2721 } 2722 2723 /** 2724 * target_if_init_spectral_ops() - Initialize target_if internal Spectral 2725 * operations. 2726 * @spectral: Pointer to Spectral target_if internal private data 2727 * 2728 * Initializes all function pointers in target_if_spectral_ops for 2729 * all generations 2730 * 2731 * Return: None 2732 */ 2733 static void 2734 target_if_init_spectral_ops(struct target_if_spectral *spectral) 2735 { 2736 target_if_init_spectral_ops_common(); 2737 if (spectral->spectral_gen == SPECTRAL_GEN2) 2738 target_if_init_spectral_ops_gen2(); 2739 else if (spectral->spectral_gen == SPECTRAL_GEN3) 2740 target_if_init_spectral_ops_gen3(spectral); 2741 else 2742 spectral_err("Invalid Spectral generation"); 2743 } 2744 2745 /* 2746 * Dummy Functions: 2747 * These functions are initially registered to avoid any crashes due to 2748 * invocation of spectral functions before they are registered. 2749 */ 2750 2751 static uint64_t 2752 null_get_tsf64(void *arg) 2753 { 2754 spectral_ops_not_registered("get_tsf64"); 2755 return 0; 2756 } 2757 2758 static uint32_t 2759 null_get_capability(void *arg, enum spectral_capability_type type) 2760 { 2761 /* 2762 * TODO : We should have conditional compilation to get the capability 2763 * : We have not yet attahced ATH layer here, so there is no 2764 * : way to check the HAL capbalities 2765 */ 2766 spectral_ops_not_registered("get_capability"); 2767 2768 /* TODO : For the time being, we are returning TRUE */ 2769 return true; 2770 } 2771 2772 static uint32_t 2773 null_set_rxfilter(void *arg, int rxfilter) 2774 { 2775 spectral_ops_not_registered("set_rxfilter"); 2776 return 1; 2777 } 2778 2779 static uint32_t 2780 null_get_rxfilter(void *arg) 2781 { 2782 spectral_ops_not_registered("get_rxfilter"); 2783 return 0; 2784 } 2785 2786 static uint32_t 2787 null_is_spectral_active(void *arg, enum spectral_scan_mode smode) 2788 { 2789 spectral_ops_not_registered("is_spectral_active"); 2790 return 1; 2791 } 2792 2793 static uint32_t 2794 null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode) 2795 { 2796 spectral_ops_not_registered("is_spectral_enabled"); 2797 return 1; 2798 } 2799 2800 static uint32_t 2801 null_start_spectral_scan(void *arg, enum spectral_scan_mode smode, 2802 enum spectral_cp_error_code *err) 2803 { 2804 spectral_ops_not_registered("start_spectral_scan"); 2805 return 1; 2806 } 2807 2808 static uint32_t 2809 null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode) 2810 { 2811 spectral_ops_not_registered("stop_spectral_scan"); 2812 return 1; 2813 } 2814 2815 static uint32_t 2816 null_get_extension_channel(void *arg, enum spectral_scan_mode smode) 2817 { 2818 spectral_ops_not_registered("get_extension_channel"); 2819 return 1; 2820 } 2821 2822 static int8_t 2823 null_get_ctl_noisefloor(void *arg) 2824 { 2825 spectral_ops_not_registered("get_ctl_noisefloor"); 2826 return 1; 2827 } 2828 2829 static int8_t 2830 null_get_ext_noisefloor(void *arg) 2831 { 2832 spectral_ops_not_registered("get_ext_noisefloor"); 2833 return 0; 2834 } 2835 2836 static uint32_t 2837 null_configure_spectral(void *arg, struct spectral_config *params, 2838 enum spectral_scan_mode smode) 2839 { 2840 spectral_ops_not_registered("configure_spectral"); 2841 return 0; 2842 } 2843 2844 static uint32_t 2845 null_get_spectral_config(void *arg, struct spectral_config *params, 2846 enum spectral_scan_mode smode) 2847 { 2848 spectral_ops_not_registered("get_spectral_config"); 2849 return 0; 2850 } 2851 2852 static uint32_t 2853 null_get_ent_spectral_mask(void *arg) 2854 { 2855 spectral_ops_not_registered("get_ent_spectral_mask"); 2856 return 0; 2857 } 2858 2859 static uint32_t 2860 null_get_mac_address(void *arg, char *addr) 2861 { 2862 spectral_ops_not_registered("get_mac_address"); 2863 return 0; 2864 } 2865 2866 static uint32_t 2867 null_get_current_channel(void *arg, enum spectral_scan_mode smode) 2868 { 2869 spectral_ops_not_registered("get_current_channel"); 2870 return 0; 2871 } 2872 2873 static uint32_t 2874 null_reset_hw(void *arg) 2875 { 2876 spectral_ops_not_registered("get_current_channel"); 2877 return 0; 2878 } 2879 2880 static uint32_t 2881 null_get_chain_noise_floor(void *arg, int16_t *nf_buf) 2882 { 2883 spectral_ops_not_registered("get_chain_noise_floor"); 2884 return 0; 2885 } 2886 2887 static int 2888 null_spectral_process_phyerr(struct target_if_spectral *spectral, 2889 uint8_t *data, 2890 uint32_t datalen, 2891 struct target_if_spectral_rfqual_info *p_rfqual, 2892 struct target_if_spectral_chan_info *p_chaninfo, 2893 uint64_t tsf64, 2894 struct target_if_spectral_acs_stats *acs_stats) 2895 { 2896 spectral_ops_not_registered("spectral_process_phyerr"); 2897 return 0; 2898 } 2899 2900 static int 2901 null_process_spectral_report(struct wlan_objmgr_pdev *pdev, 2902 void *payload) 2903 { 2904 spectral_ops_not_registered("process_spectral_report"); 2905 return 0; 2906 } 2907 /** 2908 * target_if_spectral_init_dummy_function_table() - 2909 * Initialize target_if internal 2910 * Spectral operations to dummy functions 2911 * @ps: Pointer to Spectral target_if internal private data 2912 * 2913 * Initialize all the function pointers in target_if_spectral_ops with 2914 * dummy functions. 2915 * 2916 * Return: None 2917 */ 2918 static void 2919 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps) 2920 { 2921 struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps); 2922 2923 p_sops->get_tsf64 = null_get_tsf64; 2924 p_sops->get_capability = null_get_capability; 2925 p_sops->set_rxfilter = null_set_rxfilter; 2926 p_sops->get_rxfilter = null_get_rxfilter; 2927 p_sops->is_spectral_enabled = null_is_spectral_enabled; 2928 p_sops->is_spectral_active = null_is_spectral_active; 2929 p_sops->start_spectral_scan = null_start_spectral_scan; 2930 p_sops->stop_spectral_scan = null_stop_spectral_scan; 2931 p_sops->get_extension_channel = null_get_extension_channel; 2932 p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor; 2933 p_sops->get_ext_noisefloor = null_get_ext_noisefloor; 2934 p_sops->configure_spectral = null_configure_spectral; 2935 p_sops->get_spectral_config = null_get_spectral_config; 2936 p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask; 2937 p_sops->get_mac_address = null_get_mac_address; 2938 p_sops->get_current_channel = null_get_current_channel; 2939 p_sops->reset_hw = null_reset_hw; 2940 p_sops->get_chain_noise_floor = null_get_chain_noise_floor; 2941 p_sops->spectral_process_phyerr = null_spectral_process_phyerr; 2942 p_sops->process_spectral_report = null_process_spectral_report; 2943 } 2944 2945 /** 2946 * target_if_spectral_register_funcs() - Initialize target_if internal Spectral 2947 * operations 2948 * @spectral: Pointer to Spectral target_if internal private data 2949 * @p: Pointer to Spectral function table 2950 * 2951 * Return: None 2952 */ 2953 static void 2954 target_if_spectral_register_funcs(struct target_if_spectral *spectral, 2955 struct target_if_spectral_ops *p) 2956 { 2957 struct target_if_spectral_ops *p_sops = 2958 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2959 2960 *p_sops = *p; 2961 } 2962 2963 /** 2964 * target_if_spectral_clear_stats() - Clear Spectral stats 2965 * @spectral: Pointer to Spectral target_if internal private data 2966 * 2967 * Function to clear spectral stats 2968 * 2969 * Return: None 2970 */ 2971 static void 2972 target_if_spectral_clear_stats(struct target_if_spectral *spectral) 2973 { 2974 struct target_if_spectral_ops *p_sops = 2975 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2976 2977 qdf_mem_zero(&spectral->spectral_stats, 2978 sizeof(struct target_if_spectral_stats)); 2979 spectral->spectral_stats.last_reset_tstamp = 2980 p_sops->get_tsf64(spectral); 2981 } 2982 2983 /** 2984 * target_if_spectral_check_hw_capability() - Check whether HW supports spectral 2985 * @spectral: Pointer to Spectral target_if internal private data 2986 * 2987 * Function to check whether hardware supports spectral 2988 * 2989 * Return: True if HW supports Spectral, false if HW does not support Spectral 2990 */ 2991 static int 2992 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral) 2993 { 2994 struct target_if_spectral_ops *p_sops = NULL; 2995 struct spectral_caps *pcap = NULL; 2996 int is_spectral_supported = true; 2997 2998 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2999 pcap = &spectral->capability; 3000 3001 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) { 3002 is_spectral_supported = false; 3003 spectral_info("SPECTRAL : No PHYDIAG support"); 3004 return is_spectral_supported; 3005 } 3006 pcap->phydiag_cap = 1; 3007 3008 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) { 3009 is_spectral_supported = false; 3010 spectral_info("SPECTRAL : No RADAR support"); 3011 return is_spectral_supported; 3012 } 3013 pcap->radar_cap = 1; 3014 3015 if (p_sops->get_capability(spectral, 3016 SPECTRAL_CAP_SPECTRAL_SCAN) == false) { 3017 is_spectral_supported = false; 3018 spectral_info("SPECTRAL : No SPECTRAL SUPPORT"); 3019 return is_spectral_supported; 3020 } 3021 pcap->spectral_cap = 1; 3022 3023 if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN) 3024 == false) { 3025 spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT"); 3026 } else { 3027 pcap->advncd_spectral_cap = 1; 3028 } 3029 3030 return is_spectral_supported; 3031 } 3032 3033 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 3034 /** 3035 * target_if_spectral_detach_simulation() - De-initialize Spectral 3036 * Simulation functionality 3037 * @spectral: Pointer to Spectral target_if internal private data 3038 * 3039 * Function to de-initialize Spectral Simulation functionality 3040 * 3041 * Return: None 3042 */ 3043 static void 3044 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 3045 { 3046 target_if_spectral_sim_detach(spectral); 3047 } 3048 3049 #else 3050 static void 3051 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 3052 { 3053 } 3054 #endif 3055 3056 /** 3057 * target_if_spectral_detach() - De-initialize target_if Spectral 3058 * @pdev: Pointer to pdev object 3059 * 3060 * Function to detach target_if spectral 3061 * 3062 * Return: None 3063 */ 3064 static void 3065 target_if_spectral_detach(struct target_if_spectral *spectral) 3066 { 3067 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 3068 spectral_info("spectral detach"); 3069 3070 if (spectral) { 3071 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3072 qdf_spinlock_destroy 3073 (&spectral->param_info[smode].osps_lock); 3074 3075 target_if_spectral_detach_simulation(spectral); 3076 3077 qdf_spinlock_destroy(&spectral->spectral_lock); 3078 qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock); 3079 3080 qdf_spinlock_destroy(&spectral->detector_list_lock); 3081 qdf_spinlock_destroy(&spectral->session_report_info_lock); 3082 qdf_spinlock_destroy(&spectral->session_det_map_lock); 3083 3084 qdf_mem_free(spectral); 3085 spectral = NULL; 3086 } 3087 } 3088 3089 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 3090 /** 3091 * target_if_spectral_attach_simulation() - Initialize Spectral Simulation 3092 * functionality 3093 * @spectral: Pointer to Spectral target_if internal private data 3094 * 3095 * Function to initialize spectral simulation functionality 3096 * 3097 * Return: 0 on success, negative error code on failure 3098 */ 3099 static int 3100 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 3101 { 3102 if (target_if_spectral_sim_attach(spectral)) { 3103 qdf_mem_free(spectral); 3104 return -EPERM; 3105 } 3106 return 0; 3107 } 3108 3109 #else 3110 static int 3111 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 3112 { 3113 return 0; 3114 } 3115 #endif 3116 3117 /** 3118 * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment 3119 * related info 3120 * @swar: Pointer to Spectral FFT bin length adjustment SWAR params 3121 * @rparams: Pointer to Spectral report parameter object 3122 * @target_type: Target type 3123 * 3124 * Function to Initialize parameters related to Spectral FFT bin 3125 * length adjustment SWARs. 3126 * 3127 * Return: void 3128 */ 3129 static void 3130 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar, 3131 struct spectral_report_params *rparams, 3132 uint32_t target_type) 3133 { 3134 if (target_type == TARGET_TYPE_QCA8074V2 || 3135 target_type == TARGET_TYPE_QCA9574 || 3136 target_type == TARGET_TYPE_QCN9000 || 3137 target_type == TARGET_TYPE_QCN6122 || 3138 target_type == TARGET_TYPE_QCN9160 || 3139 target_type == TARGET_TYPE_QCA5018 || 3140 target_type == TARGET_TYPE_QCA6750 || 3141 target_type == TARGET_TYPE_QCA6490 || 3142 target_type == TARGET_TYPE_KIWI || 3143 target_type == TARGET_TYPE_MANGO) { 3144 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; 3145 rparams->hw_fft_bin_width = 2; 3146 } else if (target_type == TARGET_TYPE_QCA8074 || 3147 target_type == TARGET_TYPE_QCA6018 || 3148 target_type == TARGET_TYPE_QCA6390) { 3149 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; 3150 rparams->hw_fft_bin_width = 4; 3151 } else { 3152 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; 3153 rparams->hw_fft_bin_width = 1; 3154 } 3155 3156 if (target_type == TARGET_TYPE_QCA8074 || 3157 target_type == TARGET_TYPE_QCA8074V2 || 3158 target_type == TARGET_TYPE_QCA9574 || 3159 target_type == TARGET_TYPE_QCA6018 || 3160 target_type == TARGET_TYPE_QCN6122 || 3161 target_type == TARGET_TYPE_QCN9160 || 3162 target_type == TARGET_TYPE_QCA5332 || 3163 target_type == TARGET_TYPE_QCA5018 || 3164 target_type == TARGET_TYPE_QCN9000 || 3165 target_type == TARGET_TYPE_QCA6490 || 3166 target_type == TARGET_TYPE_QCN9224 || 3167 target_type == TARGET_TYPE_KIWI || 3168 target_type == TARGET_TYPE_MANGO) { 3169 swar->inband_fftbin_size_adj = 1; 3170 swar->null_fftbin_adj = 1; 3171 } else { 3172 swar->inband_fftbin_size_adj = 0; 3173 swar->null_fftbin_adj = 0; 3174 } 3175 3176 if (target_type == TARGET_TYPE_QCA8074V2) 3177 swar->packmode_fftbin_size_adj = 1; 3178 else 3179 swar->packmode_fftbin_size_adj = 0; 3180 } 3181 3182 /** 3183 * target_if_spectral_report_params_init() - Initialize parameters which 3184 * describes the structure of Spectral reports 3185 * 3186 * @rparams: Pointer to Spectral report parameter object 3187 * @target_type: target type 3188 * 3189 * Function to Initialize parameters related to the structure of Spectral 3190 * reports. 3191 * 3192 * Return: void 3193 */ 3194 static void 3195 target_if_spectral_report_params_init( 3196 struct spectral_report_params *rparams, 3197 uint32_t target_type) 3198 { 3199 enum spectral_scan_mode smode; 3200 3201 /* This entries are currently used by gen3 chipsets only. Hence 3202 * initialization is done for gen3 alone. In future if other generations 3203 * needs to use them they have to add proper initial values. 3204 */ 3205 if (target_type == TARGET_TYPE_QCN9000 || 3206 target_type == TARGET_TYPE_QCN6122 || 3207 target_type == TARGET_TYPE_QCN9160 || 3208 target_type == TARGET_TYPE_QCA5018 || 3209 target_type == TARGET_TYPE_QCA6750 || 3210 target_type == TARGET_TYPE_QCA6490 || 3211 target_type == TARGET_TYPE_QCA5332 || 3212 target_type == TARGET_TYPE_QCN9224 || 3213 target_type == TARGET_TYPE_KIWI || 3214 target_type == TARGET_TYPE_MANGO) { 3215 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2; 3216 rparams->num_spectral_detectors = 3217 NUM_SPECTRAL_DETECTORS_GEN3_V2; 3218 smode = SPECTRAL_SCAN_MODE_NORMAL; 3219 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3220 rparams->fragmentation_160[smode] = false; 3221 } else { 3222 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1; 3223 rparams->num_spectral_detectors = 3224 NUM_SPECTRAL_DETECTORS_GEN3_V1; 3225 smode = SPECTRAL_SCAN_MODE_NORMAL; 3226 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3227 rparams->fragmentation_160[smode] = true; 3228 } 3229 3230 switch (rparams->version) { 3231 case SPECTRAL_REPORT_FORMAT_VERSION_1: 3232 rparams->ssumaary_padding_bytes = 3233 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1; 3234 rparams->fft_report_hdr_len = 3235 FFT_REPORT_HEADER_LENGTH_GEN3_V1; 3236 break; 3237 case SPECTRAL_REPORT_FORMAT_VERSION_2: 3238 rparams->ssumaary_padding_bytes = 3239 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2; 3240 rparams->fft_report_hdr_len = 3241 FFT_REPORT_HEADER_LENGTH_GEN3_V2; 3242 break; 3243 default: 3244 qdf_assert_always(0); 3245 } 3246 3247 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] = 3248 SPECTRAL_SCAN_MODE_NORMAL; 3249 if (target_type == TARGET_TYPE_QCN9000 || 3250 target_type == TARGET_TYPE_QCN6122 || 3251 target_type == TARGET_TYPE_QCN9224 || 3252 target_type == TARGET_TYPE_QCN9160 || 3253 target_type == TARGET_TYPE_QCA6490 || 3254 target_type == TARGET_TYPE_KIWI || 3255 target_type == TARGET_TYPE_MANGO) { 3256 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 3257 SPECTRAL_SCAN_MODE_AGILE; 3258 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 3259 SPECTRAL_SCAN_MODE_INVALID; 3260 } else if (target_type == TARGET_TYPE_QCA5332) { 3261 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 3262 SPECTRAL_SCAN_MODE_INVALID; 3263 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 3264 SPECTRAL_SCAN_MODE_INVALID; 3265 } else { 3266 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 3267 SPECTRAL_SCAN_MODE_NORMAL; 3268 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 3269 SPECTRAL_SCAN_MODE_AGILE; 3270 } 3271 } 3272 3273 /** 3274 * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR 3275 * related info 3276 * @twar: Pointer to Spectral timstamp WAR related info 3277 * 3278 * Function to Initialize parameters related to Spectral timestamp WAR 3279 * 3280 * Return: void 3281 */ 3282 static void 3283 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar) 3284 { 3285 enum spectral_scan_mode smode; 3286 3287 smode = SPECTRAL_SCAN_MODE_NORMAL; 3288 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 3289 twar->last_fft_timestamp[smode] = 0; 3290 twar->timestamp_war_offset[smode] = 0; 3291 } 3292 twar->target_reset_count = 0; 3293 } 3294 3295 #ifdef OPTIMIZED_SAMP_MESSAGE 3296 /** 3297 * target_if_spectral_is_hw_mode_sbs() - Check if the given pdev is in SBS mode 3298 * @pdev: pdev pointer 3299 * @is_hw_mode_sbs: Pointer to the variable where this function should write 3300 * whether the given pdev is in SBS mode 3301 * 3302 * Return: QDF_STATUS of operation 3303 */ 3304 static QDF_STATUS 3305 target_if_spectral_is_hw_mode_sbs(struct wlan_objmgr_pdev *pdev, 3306 bool *is_hw_mode_sbs) 3307 { 3308 struct wlan_objmgr_psoc *psoc; 3309 struct target_psoc_info *tgt_hdl; 3310 enum wmi_host_hw_mode_config_type mode; 3311 3312 qdf_assert_always(is_hw_mode_sbs); 3313 3314 psoc = wlan_pdev_get_psoc(pdev); 3315 if (!psoc) { 3316 spectral_err("psoc is null"); 3317 return QDF_STATUS_E_NULL_VALUE; 3318 } 3319 3320 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 3321 if (!tgt_hdl) { 3322 spectral_err("target_psoc_info is null"); 3323 return QDF_STATUS_E_NULL_VALUE; 3324 } 3325 3326 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 3327 switch (mode) { 3328 case WMI_HOST_HW_MODE_SBS_PASSIVE: 3329 case WMI_HOST_HW_MODE_SBS: 3330 case WMI_HOST_HW_MODE_DBS_SBS: 3331 case WMI_HOST_HW_MODE_DBS_OR_SBS: 3332 *is_hw_mode_sbs = true; 3333 break; 3334 default: 3335 *is_hw_mode_sbs = false; 3336 break; 3337 } 3338 3339 return QDF_STATUS_SUCCESS; 3340 } 3341 3342 /** 3343 * target_if_get_pdev_mac_phy_caps() - Get the MAC_PHY capabilities of a pdev 3344 * @pdev: pdev pointer 3345 * 3346 * Return: On success, pointer to MAC_PHY capabilities of @pdev. 3347 * On failure, NULL 3348 */ 3349 static struct wlan_psoc_host_mac_phy_caps * 3350 target_if_get_pdev_mac_phy_caps(struct wlan_objmgr_pdev *pdev) 3351 { 3352 struct wlan_objmgr_psoc *psoc; 3353 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr; 3354 struct target_psoc_info *tgt_psoc_info; 3355 uint8_t pdev_id; 3356 3357 if (!pdev) { 3358 spectral_err("pdev is NULL"); 3359 return NULL; 3360 } 3361 3362 psoc = wlan_pdev_get_psoc(pdev); 3363 if (!psoc) { 3364 spectral_err("psoc is null"); 3365 return NULL; 3366 } 3367 3368 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 3369 if (!tgt_psoc_info) { 3370 spectral_err("target_psoc_info is null"); 3371 return NULL; 3372 } 3373 3374 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 3375 if (!mac_phy_cap_arr) { 3376 spectral_err("mac phy cap array is null"); 3377 return NULL; 3378 } 3379 3380 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 3381 return &mac_phy_cap_arr[pdev_id]; 3382 } 3383 3384 /** 3385 * struct target_if_sscan_pdev_phy_info - PHY information of the pdev on 3386 * which sscan is done. A pointer to an instance of this structure is passed 3387 * as an argument to the iterator function target_if_find_sscan_pdev_phya1() 3388 * @phy_id: PHY ID of this pdev 3389 * @is_using_phya1: Pointer to the variable where the iterator function should 3390 * populate whether the given pdev is using PHYA1 3391 */ 3392 struct target_if_sscan_pdev_phy_info { 3393 uint8_t phy_id; 3394 bool *is_using_phya1; 3395 }; 3396 3397 /** 3398 * target_if_find_sscan_pdev_phya1() - This is an iterator function to 3399 * wlan_objmgr_iterate_obj_list(). It checks whether a given sscan_pdev (pdev on 3400 * which sscan is currently issued) is using PHYA1 by comparing against the pdev 3401 * argument given by the wlan_objmgr_iterate_obj_list() 3402 * @psoc: Pointer to psoc 3403 * @object: Pointer to pdev 3404 * @arg: Pointer to target_if_sscan_pdev_phy_info of the sscan_pdev for which 3405 * we want to check if it uses PHYA1 3406 * 3407 * Return: None 3408 */ 3409 static void 3410 target_if_find_sscan_pdev_phya1(struct wlan_objmgr_psoc *psoc, 3411 void *object, void *arg) 3412 { 3413 struct target_if_sscan_pdev_phy_info *sscan_pdev_phy_info = arg; 3414 struct wlan_objmgr_pdev *cur_pdev = object; 3415 struct wlan_psoc_host_mac_phy_caps *cur_mac_phy_caps; 3416 3417 cur_mac_phy_caps = target_if_get_pdev_mac_phy_caps(cur_pdev); 3418 if (!cur_mac_phy_caps) { 3419 spectral_err("Failed to get MAC PHY Capabilities of" 3420 "pdev %pK", cur_pdev); 3421 return; 3422 } 3423 3424 spectral_debug("supported_bands: %0x phy_id: %d", 3425 cur_mac_phy_caps->supported_bands, 3426 cur_mac_phy_caps->phy_id); 3427 3428 /* No need to do anything if the current pdev is same as sscan_pdev */ 3429 if (sscan_pdev_phy_info->phy_id == cur_mac_phy_caps->phy_id) 3430 return; 3431 3432 /** 3433 * Compare the phy_id of both the SBS pdevs to figure out if 3434 * the sscan_pdev using PHYA1 3435 */ 3436 if (sscan_pdev_phy_info->phy_id > cur_mac_phy_caps->phy_id) 3437 *sscan_pdev_phy_info->is_using_phya1 = true; 3438 else 3439 *sscan_pdev_phy_info->is_using_phya1 = false; 3440 } 3441 3442 /** 3443 * target_if_spectral_detector_list_init() - Initialize Spectral detector list 3444 * based on target type 3445 * @spectral: Pointer to Spectral target_if 3446 * 3447 * Function to initialize Spectral detector list for possible combinations of 3448 * Spectral scan mode and channel width, based on target type. 3449 * 3450 * Return: Success/Failure 3451 */ 3452 static QDF_STATUS 3453 target_if_spectral_detector_list_init(struct target_if_spectral *spectral) 3454 { 3455 struct sscan_detector_list *det_list; 3456 enum spectral_scan_mode smode; 3457 enum phy_ch_width ch_width; 3458 QDF_STATUS ret; 3459 bool is_hw_mode_sbs = false, is_using_phya1 = false; 3460 3461 if (!spectral) { 3462 spectral_err_rl("Spectral LMAC object is null"); 3463 return QDF_STATUS_E_NULL_VALUE; 3464 } 3465 3466 /** 3467 * Special handling is required for SBS mode where the detector 3468 * list should be the following. 3469 * For the pdev that use PHYA0: 3470 * detector 0 for normal mode 3471 * detector 2 for agile mode 3472 * For the pdev that use PHYA1: 3473 * detector 1 for normal mode 3474 * detector 2 for agile mode 3475 * 3476 * There is no direct way of knowing which pdevs are using PHYA0 or 3477 * PHYA1. We need to look at the phy_id of a given pdev and compare 3478 * against other pdevs on the same psoc to figure out whether the given 3479 * pdev is operating using PHYA1. 3480 */ 3481 3482 /* First check whether this pdev is in SBS mode */ 3483 ret = target_if_spectral_is_hw_mode_sbs(spectral->pdev_obj, 3484 &is_hw_mode_sbs); 3485 if (QDF_IS_STATUS_ERROR(ret)) { 3486 spectral_err("Failed to check whether hw mode is SBS"); 3487 return ret; 3488 } 3489 3490 if (is_hw_mode_sbs) { 3491 struct wlan_psoc_host_mac_phy_caps *mac_phy_caps; 3492 struct target_if_sscan_pdev_phy_info pdev_phy_info; 3493 3494 mac_phy_caps = 3495 target_if_get_pdev_mac_phy_caps(spectral->pdev_obj); 3496 if (!mac_phy_caps) { 3497 spectral_err("Failed to get MAC PHY Capabilities of" 3498 "pdev %pK", spectral->pdev_obj); 3499 return QDF_STATUS_E_FAILURE; 3500 } 3501 3502 spectral_debug("bands: %0x phy_id: %d", 3503 mac_phy_caps->supported_bands, 3504 mac_phy_caps->phy_id); 3505 3506 pdev_phy_info.phy_id = mac_phy_caps->phy_id; 3507 pdev_phy_info.is_using_phya1 = &is_using_phya1; 3508 3509 /* Iterate over all pdevs on this psoc */ 3510 wlan_objmgr_iterate_obj_list 3511 (wlan_pdev_get_psoc(spectral->pdev_obj), 3512 WLAN_PDEV_OP, 3513 target_if_find_sscan_pdev_phya1, 3514 &pdev_phy_info, 0, 3515 WLAN_SPECTRAL_ID); 3516 } 3517 3518 /** 3519 * We assume there are 2 detectors. The Detector ID coming first will 3520 * always be pri80 detector, and second detector for sec80. 3521 */ 3522 ch_width = CH_WIDTH_20MHZ; 3523 for (; ch_width < CH_WIDTH_MAX; ch_width++) { 3524 /* Normal spectral scan */ 3525 smode = SPECTRAL_SCAN_MODE_NORMAL; 3526 spectral_debug("is_hw_mode_sbs: %d is_using_phya1:%d", 3527 is_hw_mode_sbs, is_using_phya1); 3528 3529 qdf_spin_lock_bh(&spectral->detector_list_lock); 3530 3531 if (!spectral->supported_sscan_bw_list[smode][ch_width]) 3532 goto agile_handling; 3533 3534 det_list = &spectral->detector_list[smode][ch_width]; 3535 det_list->num_detectors = 1; 3536 3537 if (is_hw_mode_sbs && is_using_phya1) 3538 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1; 3539 else 3540 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_0; 3541 3542 if (is_ch_width_160_or_80p80(ch_width) && 3543 spectral->rparams.fragmentation_160[smode]) { 3544 det_list->num_detectors += 1; 3545 det_list->detectors[1] = SPECTRAL_DETECTOR_ID_1; 3546 } 3547 3548 agile_handling: 3549 /* Agile spectral scan */ 3550 smode = SPECTRAL_SCAN_MODE_AGILE; 3551 if (!spectral->supported_sscan_bw_list[smode][ch_width]) { 3552 qdf_spin_unlock_bh(&spectral->detector_list_lock); 3553 continue; 3554 } 3555 3556 det_list = &spectral->detector_list[smode][ch_width]; 3557 det_list->num_detectors = 1; 3558 3559 if (spectral->rparams.fragmentation_160[smode]) 3560 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_2; 3561 else 3562 det_list->detectors[0] = SPECTRAL_DETECTOR_ID_1; 3563 3564 qdf_spin_unlock_bh(&spectral->detector_list_lock); 3565 } 3566 3567 return QDF_STATUS_SUCCESS; 3568 } 3569 #else 3570 3571 static QDF_STATUS 3572 target_if_spectral_detector_list_init(struct target_if_spectral *spectral) 3573 { 3574 return QDF_STATUS_SUCCESS; 3575 } 3576 #endif /* OPTIMIZED_SAMP_MESSAGE */ 3577 3578 /** 3579 * target_if_pdev_spectral_init() - Initialize target_if Spectral 3580 * functionality for the given pdev 3581 * @pdev: Pointer to pdev object 3582 * 3583 * Function to initialize pointer to spectral target_if internal private data 3584 * 3585 * Return: On success, pointer to Spectral target_if internal private data, on 3586 * failure, NULL 3587 */ 3588 void * 3589 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 3590 { 3591 struct target_if_spectral_ops *p_sops = NULL; 3592 struct target_if_spectral *spectral = NULL; 3593 uint32_t target_type; 3594 uint32_t target_revision; 3595 struct wlan_objmgr_psoc *psoc; 3596 struct wlan_lmac_if_target_tx_ops *tgt_tx_ops; 3597 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 3598 QDF_STATUS status; 3599 struct wlan_lmac_if_tx_ops *tx_ops; 3600 3601 if (!pdev) { 3602 spectral_err("SPECTRAL: pdev is NULL!"); 3603 return NULL; 3604 } 3605 spectral = (struct target_if_spectral *)qdf_mem_malloc( 3606 sizeof(struct target_if_spectral)); 3607 if (!spectral) 3608 return spectral; 3609 3610 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 3611 /* Store pdev in Spectral */ 3612 spectral->pdev_obj = pdev; 3613 spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID; 3614 spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID; 3615 3616 psoc = wlan_pdev_get_psoc(pdev); 3617 3618 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 3619 if (!tx_ops) { 3620 spectral_err("tx_ops is NULL"); 3621 qdf_mem_free(spectral); 3622 return NULL; 3623 } 3624 3625 tgt_tx_ops = &tx_ops->target_tx_ops; 3626 3627 if (tgt_tx_ops->tgt_get_tgt_type) { 3628 target_type = tgt_tx_ops->tgt_get_tgt_type(psoc); 3629 } else { 3630 qdf_mem_free(spectral); 3631 return NULL; 3632 } 3633 3634 if (tgt_tx_ops->tgt_get_tgt_revision) { 3635 target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc); 3636 } else { 3637 qdf_mem_free(spectral); 3638 return NULL; 3639 } 3640 3641 /* init the function ptr table */ 3642 target_if_spectral_init_dummy_function_table(spectral); 3643 3644 /* get spectral function table */ 3645 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3646 /* TODO : Should this be called here of after ath_attach ? */ 3647 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 3648 spectral_info("HAL_CAP_PHYDIAG : Capable"); 3649 3650 /* TODO: Need to fix the capability check for RADAR */ 3651 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 3652 spectral_info("HAL_CAP_RADAR : Capable"); 3653 3654 /* TODO : Need to fix the capability check for SPECTRAL */ 3655 /* TODO : Should this be called here of after ath_attach ? */ 3656 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 3657 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 3658 3659 qdf_spinlock_create(&spectral->spectral_lock); 3660 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 3661 target_if_spectral_clear_stats(spectral); 3662 3663 if (target_type == TARGET_TYPE_QCA8074 || 3664 target_type == TARGET_TYPE_QCA8074V2 || 3665 target_type == TARGET_TYPE_QCA9574 || 3666 target_type == TARGET_TYPE_QCA5332 || 3667 target_type == TARGET_TYPE_QCA6018 || 3668 target_type == TARGET_TYPE_QCA5018 || 3669 target_type == TARGET_TYPE_QCA6390 || 3670 target_type == TARGET_TYPE_QCN6122 || 3671 target_type == TARGET_TYPE_QCN9160 || 3672 target_type == TARGET_TYPE_QCA6490 || 3673 target_type == TARGET_TYPE_QCN9000 || 3674 target_type == TARGET_TYPE_QCA6750 || 3675 target_type == TARGET_TYPE_QCN9224 || 3676 target_type == TARGET_TYPE_KIWI || 3677 target_type == TARGET_TYPE_MANGO) 3678 spectral->direct_dma_support = true; 3679 3680 target_if_spectral_report_params_init(&spectral->rparams, 3681 target_type); 3682 target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar, 3683 &spectral->rparams, 3684 target_type); 3685 3686 if ((target_type == TARGET_TYPE_QCA8074) || 3687 (target_type == TARGET_TYPE_QCA8074V2) || 3688 (target_type == TARGET_TYPE_QCA9574) || 3689 (target_type == TARGET_TYPE_QCA6018) || 3690 (target_type == TARGET_TYPE_QCA5018) || 3691 (target_type == TARGET_TYPE_QCA5332) || 3692 (target_type == TARGET_TYPE_QCN6122) || 3693 (target_type == TARGET_TYPE_QCN9160) || 3694 (target_type == TARGET_TYPE_QCN9000) || 3695 (target_type == TARGET_TYPE_QCA6290) || 3696 (target_type == TARGET_TYPE_QCA6390) || 3697 (target_type == TARGET_TYPE_QCA6490) || 3698 (target_type == TARGET_TYPE_QCN9224) || 3699 (target_type == TARGET_TYPE_QCA6750) || 3700 (target_type == TARGET_TYPE_KIWI) || 3701 (target_type == TARGET_TYPE_MANGO)) { 3702 spectral->spectral_gen = SPECTRAL_GEN3; 3703 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 3704 spectral->tag_sscan_summary_exp = 3705 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 3706 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 3707 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 3708 } else { 3709 spectral->spectral_gen = SPECTRAL_GEN2; 3710 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 3711 spectral->tag_sscan_summary_exp = 3712 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 3713 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 3714 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 3715 } 3716 3717 status = target_if_init_spectral_param_min_max( 3718 spectral, 3719 spectral->spectral_gen, target_type); 3720 if (QDF_IS_STATUS_ERROR(status)) { 3721 spectral_err("Failed to initialize parameter min max values"); 3722 goto fail; 3723 } 3724 3725 target_if_init_spectral_param_properties(spectral); 3726 /* Init spectral capability */ 3727 if (target_if_init_spectral_capability(spectral, target_type) != 3728 QDF_STATUS_SUCCESS) { 3729 qdf_mem_free(spectral); 3730 return NULL; 3731 } 3732 if (target_if_spectral_attach_simulation(spectral) < 0) 3733 return NULL; 3734 3735 target_if_init_spectral_ops(spectral); 3736 target_if_spectral_timestamp_war_init(&spectral->timestamp_war); 3737 3738 /* Spectral mode specific init */ 3739 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 3740 spectral->params_valid[smode] = false; 3741 qdf_spinlock_create(&spectral->param_info[smode].osps_lock); 3742 spectral->param_info[smode].osps_cache.osc_is_valid = 0; 3743 } 3744 3745 target_if_spectral_register_funcs(spectral, &spectral_ops); 3746 3747 if (target_if_spectral_check_hw_capability(spectral) == false) { 3748 goto fail; 3749 } else { 3750 /* 3751 * TODO: Once the driver architecture transitions to chipset 3752 * versioning based checks, reflect this here. 3753 */ 3754 spectral->is_160_format = false; 3755 spectral->is_lb_edge_extrabins_format = false; 3756 spectral->is_rb_edge_extrabins_format = false; 3757 3758 if (target_type == TARGET_TYPE_QCA9984 || 3759 target_type == TARGET_TYPE_QCA9888) { 3760 spectral->is_160_format = true; 3761 spectral->is_lb_edge_extrabins_format = true; 3762 spectral->is_rb_edge_extrabins_format = true; 3763 } else if ((target_type == TARGET_TYPE_AR900B) && 3764 (target_revision == AR900B_REV_2)) { 3765 spectral->is_rb_edge_extrabins_format = true; 3766 } 3767 3768 if (target_type == TARGET_TYPE_QCA9984 || 3769 target_type == TARGET_TYPE_QCA9888) 3770 spectral->is_sec80_rssi_war_required = true; 3771 3772 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST; 3773 3774 if (spectral->spectral_gen == SPECTRAL_GEN3) 3775 init_160mhz_delivery_state_machine(spectral); 3776 } 3777 3778 qdf_spinlock_create(&spectral->detector_list_lock); 3779 qdf_spinlock_create(&spectral->session_report_info_lock); 3780 qdf_spinlock_create(&spectral->session_det_map_lock); 3781 3782 return spectral; 3783 3784 fail: 3785 target_if_spectral_detach(spectral); 3786 return NULL; 3787 } 3788 3789 /** 3790 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 3791 * functionality for the given pdev 3792 * @pdev: Pointer to pdev object 3793 * 3794 * Function to de-initialize pointer to spectral target_if internal private data 3795 * 3796 * Return: None 3797 */ 3798 void 3799 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 3800 { 3801 struct target_if_spectral *spectral = NULL; 3802 3803 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3804 if (!spectral) { 3805 spectral_err("SPECTRAL : Module doesn't exist"); 3806 return; 3807 } 3808 target_if_spectral_detach(spectral); 3809 3810 return; 3811 } 3812 3813 /** 3814 * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral 3815 * functionality for the given psoc 3816 * @psoc: Pointer to psoc object 3817 * 3818 * Function to de-initialize pointer to psoc spectral target_if internal 3819 * private data 3820 * 3821 * Return: None 3822 */ 3823 static void 3824 target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc) 3825 { 3826 struct target_if_psoc_spectral *psoc_spectral; 3827 3828 if (!psoc) { 3829 spectral_err("psoc is null"); 3830 return; 3831 } 3832 3833 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 3834 if (!psoc_spectral) { 3835 spectral_err("Spectral target_if psoc object is null"); 3836 return; 3837 } 3838 3839 qdf_mem_free(psoc_spectral); 3840 } 3841 3842 /** 3843 * target_if_psoc_spectral_init() - Initialize target_if Spectral 3844 * functionality for the given psoc 3845 * @psoc: Pointer to psoc object 3846 * 3847 * Function to initialize pointer to psoc spectral target_if internal 3848 * private data 3849 * 3850 * Return: On success, pointer to Spectral psoc target_if internal 3851 * private data, on failure, NULL 3852 */ 3853 static void * 3854 target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc) 3855 { 3856 struct target_if_psoc_spectral *psoc_spectral = NULL; 3857 3858 if (!psoc) { 3859 spectral_err("psoc is null"); 3860 goto fail; 3861 } 3862 3863 psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc( 3864 sizeof(struct target_if_psoc_spectral)); 3865 if (!psoc_spectral) { 3866 spectral_err("Spectral lmac psoc object allocation failed"); 3867 goto fail; 3868 } 3869 3870 psoc_spectral->psoc_obj = psoc; 3871 3872 return psoc_spectral; 3873 3874 fail: 3875 if (psoc_spectral) 3876 target_if_psoc_spectral_deinit(psoc); 3877 3878 return psoc_spectral; 3879 } 3880 3881 /** 3882 * target_if_calculate_center_freq() - Helper routine to 3883 * check whether given frequency is center frequency of a 3884 * WLAN channel 3885 * 3886 * @spectral: Pointer to Spectral object 3887 * @chan_freq: Center frequency of a WLAN channel 3888 * @is_valid: Indicates whether given frequency is valid 3889 * 3890 * Return: QDF_STATUS 3891 */ 3892 static QDF_STATUS 3893 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, 3894 uint32_t chan_freq, 3895 bool *is_valid) 3896 { 3897 struct regulatory_channel *cur_chan_list; 3898 int i; 3899 3900 if (!pdev) { 3901 spectral_err("pdev object is null"); 3902 return QDF_STATUS_E_FAILURE; 3903 } 3904 3905 if (!is_valid) { 3906 spectral_err("is valid argument is null"); 3907 return QDF_STATUS_E_FAILURE; 3908 } 3909 3910 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); 3911 if (!cur_chan_list) 3912 return QDF_STATUS_E_FAILURE; 3913 3914 if (wlan_reg_get_current_chan_list( 3915 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 3916 spectral_err("Failed to get cur_chan list"); 3917 qdf_mem_free(cur_chan_list); 3918 return QDF_STATUS_E_FAILURE; 3919 } 3920 3921 *is_valid = false; 3922 for (i = 0; i < NUM_CHANNELS; i++) { 3923 uint32_t flags; 3924 uint32_t center_freq; 3925 3926 flags = cur_chan_list[i].chan_flags; 3927 center_freq = cur_chan_list[i].center_freq; 3928 3929 if (!(flags & REGULATORY_CHAN_DISABLED) && 3930 (center_freq == chan_freq)) { 3931 *is_valid = true; 3932 break; 3933 } 3934 } 3935 3936 qdf_mem_free(cur_chan_list); 3937 3938 return QDF_STATUS_SUCCESS; 3939 } 3940 3941 /** 3942 * target_if_calculate_center_freq() - Helper routine to 3943 * find the center frequency of the agile span from a 3944 * WLAN channel center frequency 3945 * 3946 * @spectral: Pointer to Spectral object 3947 * @ch_width: Channel width array 3948 * @chan_freq: Center frequency of a WLAN channel 3949 * @center_freq: Pointer to center frequency 3950 * 3951 * Return: QDF_STATUS 3952 */ 3953 static QDF_STATUS 3954 target_if_calculate_center_freq(struct target_if_spectral *spectral, 3955 enum phy_ch_width *ch_width, 3956 uint16_t chan_freq, 3957 uint16_t *center_freq) 3958 { 3959 enum phy_ch_width agile_ch_width; 3960 3961 if (!spectral) { 3962 spectral_err("spectral target if object is null"); 3963 return QDF_STATUS_E_FAILURE; 3964 } 3965 3966 if (!ch_width) { 3967 spectral_err("Channel width array is null"); 3968 return QDF_STATUS_E_INVAL; 3969 } 3970 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 3971 3972 if (!center_freq) { 3973 spectral_err("center_freq argument is null"); 3974 return QDF_STATUS_E_FAILURE; 3975 } 3976 3977 if (agile_ch_width == CH_WIDTH_20MHZ) { 3978 *center_freq = chan_freq; 3979 } else { 3980 uint16_t start_freq; 3981 uint16_t end_freq; 3982 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 3983 enum channel_state state; 3984 3985 state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode 3986 (spectral->pdev_obj, chan_freq, agile_ch_width, 3987 &bonded_chan_ptr, REG_CURRENT_PWR_MODE, 3988 NO_SCHANS_PUNC); 3989 if (state == CHANNEL_STATE_DISABLE || 3990 state == CHANNEL_STATE_INVALID) { 3991 spectral_err("Channel state is disable or invalid"); 3992 return QDF_STATUS_E_FAILURE; 3993 } 3994 if (!bonded_chan_ptr) { 3995 spectral_err("Bonded channel is not found"); 3996 return QDF_STATUS_E_FAILURE; 3997 } 3998 start_freq = bonded_chan_ptr->start_freq; 3999 end_freq = bonded_chan_ptr->end_freq; 4000 *center_freq = (start_freq + end_freq) >> 1; 4001 } 4002 4003 return QDF_STATUS_SUCCESS; 4004 } 4005 4006 /** 4007 * target_if_validate_center_freq() - Helper routine to 4008 * validate user provided agile center frequency 4009 * 4010 * @spectral: Pointer to Spectral object 4011 * @ch_width: Channel width array 4012 * @center_freq: User provided agile span center frequency 4013 * @is_valid: Indicates whether agile span center frequency is valid 4014 * 4015 * Return: QDF_STATUS 4016 */ 4017 static QDF_STATUS 4018 target_if_validate_center_freq(struct target_if_spectral *spectral, 4019 enum phy_ch_width *ch_width, 4020 uint16_t center_freq, 4021 bool *is_valid) 4022 { 4023 enum phy_ch_width agile_ch_width; 4024 struct wlan_objmgr_pdev *pdev; 4025 QDF_STATUS status; 4026 4027 if (!spectral) { 4028 spectral_err("spectral target if object is null"); 4029 return QDF_STATUS_E_FAILURE; 4030 } 4031 4032 if (!ch_width) { 4033 spectral_err("channel width array is null"); 4034 return QDF_STATUS_E_INVAL; 4035 } 4036 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 4037 4038 if (!is_valid) { 4039 spectral_err("is_valid argument is null"); 4040 return QDF_STATUS_E_FAILURE; 4041 } 4042 4043 pdev = spectral->pdev_obj; 4044 4045 if (agile_ch_width == CH_WIDTH_20MHZ) { 4046 status = target_if_is_center_freq_of_any_chan 4047 (pdev, center_freq, is_valid); 4048 if (QDF_IS_STATUS_ERROR(status)) 4049 return QDF_STATUS_E_FAILURE; 4050 } else { 4051 uint16_t start_freq; 4052 uint16_t end_freq; 4053 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 4054 bool is_chan; 4055 4056 status = target_if_is_center_freq_of_any_chan 4057 (pdev, center_freq + FREQ_OFFSET_10MHZ, 4058 &is_chan); 4059 if (QDF_IS_STATUS_ERROR(status)) 4060 return QDF_STATUS_E_FAILURE; 4061 4062 if (is_chan) { 4063 uint32_t calulated_center_freq; 4064 enum channel_state st; 4065 4066 st = 4067 wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode 4068 (pdev, center_freq + FREQ_OFFSET_10MHZ, 4069 agile_ch_width, 4070 &bonded_chan_ptr, 4071 REG_CURRENT_PWR_MODE, 4072 NO_SCHANS_PUNC); 4073 if (st == CHANNEL_STATE_DISABLE || 4074 st == CHANNEL_STATE_INVALID) { 4075 spectral_err("Channel state disable/invalid"); 4076 return QDF_STATUS_E_FAILURE; 4077 } 4078 if (!bonded_chan_ptr) { 4079 spectral_err("Bonded channel is not found"); 4080 return QDF_STATUS_E_FAILURE; 4081 } 4082 start_freq = bonded_chan_ptr->start_freq; 4083 end_freq = bonded_chan_ptr->end_freq; 4084 calulated_center_freq = (start_freq + end_freq) >> 1; 4085 *is_valid = (center_freq == calulated_center_freq); 4086 } else { 4087 *is_valid = false; 4088 } 4089 } 4090 4091 return QDF_STATUS_SUCCESS; 4092 } 4093 4094 /** 4095 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to 4096 * check whether agile span overlaps with current operating band. 4097 * 4098 * @spectral: Pointer to Spectral object 4099 * @ch_width: Channel width array 4100 * @center_freq: Agile span center frequency 4101 * @is_overlapping: Indicates whether Agile span overlaps with operating span 4102 * 4103 * Helper routine to check whether agile span overlaps with current 4104 * operating band. 4105 * 4106 * Return: QDF_STATUS 4107 */ 4108 static QDF_STATUS 4109 target_if_is_agile_span_overlap_with_operating_span 4110 (struct target_if_spectral *spectral, 4111 enum phy_ch_width *ch_width, 4112 struct spectral_config_frequency *center_freq, 4113 bool *is_overlapping) 4114 { 4115 enum phy_ch_width op_ch_width; 4116 enum phy_ch_width agile_ch_width; 4117 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 4118 struct wlan_objmgr_vdev *vdev; 4119 struct wlan_objmgr_pdev *pdev; 4120 int16_t chan_freq; 4121 uint32_t op_start_freq; 4122 uint32_t op_end_freq; 4123 uint32_t agile_start_freq; 4124 uint32_t agile_end_freq; 4125 uint32_t cfreq2; 4126 4127 if (!spectral) { 4128 spectral_err("Spectral object is NULL"); 4129 return QDF_STATUS_E_FAILURE; 4130 } 4131 4132 pdev = spectral->pdev_obj; 4133 if (!pdev) { 4134 spectral_err("pdev object is NULL"); 4135 return QDF_STATUS_E_FAILURE; 4136 } 4137 4138 if (!ch_width) { 4139 spectral_err("channel width array is null"); 4140 return QDF_STATUS_E_FAILURE; 4141 } 4142 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 4143 if (op_ch_width == CH_WIDTH_INVALID) { 4144 spectral_err("Invalid channel width"); 4145 return QDF_STATUS_E_INVAL; 4146 } 4147 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 4148 if (agile_ch_width == CH_WIDTH_INVALID) { 4149 spectral_err("Invalid channel width"); 4150 return QDF_STATUS_E_INVAL; 4151 } 4152 4153 if (!is_overlapping) { 4154 spectral_err("Argument(is_overlapping) is NULL"); 4155 return QDF_STATUS_E_FAILURE; 4156 } 4157 *is_overlapping = false; 4158 4159 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 4160 if (!vdev) { 4161 spectral_err("vdev is NULL"); 4162 return QDF_STATUS_E_FAILURE; 4163 } 4164 chan_freq = target_if_vdev_get_chan_freq(vdev); 4165 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); 4166 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4167 if (cfreq2 < 0) { 4168 spectral_err("cfreq2 is invalid"); 4169 return QDF_STATUS_E_FAILURE; 4170 } 4171 4172 if (op_ch_width == CH_WIDTH_20MHZ) { 4173 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; 4174 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; 4175 } else { 4176 enum channel_state state; 4177 4178 state = wlan_reg_get_5g_bonded_channel_and_state_for_pwrmode 4179 (pdev, chan_freq, op_ch_width, &bonded_chan_ptr, 4180 REG_CURRENT_PWR_MODE, NO_SCHANS_PUNC); 4181 if (state == CHANNEL_STATE_DISABLE || 4182 state == CHANNEL_STATE_INVALID) { 4183 spectral_err("Channel state is disable or invalid"); 4184 return QDF_STATUS_E_FAILURE; 4185 } 4186 if (!bonded_chan_ptr) { 4187 spectral_err("Bonded channel is not found"); 4188 return QDF_STATUS_E_FAILURE; 4189 } 4190 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; 4191 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; 4192 } 4193 4194 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 4195 agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 4196 agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 4197 if (agile_end_freq > op_start_freq && 4198 op_end_freq > agile_start_freq) 4199 *is_overlapping = true; 4200 4201 agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 4202 agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 4203 if (agile_end_freq > op_start_freq && 4204 op_end_freq > agile_start_freq) 4205 *is_overlapping = true; 4206 } else { 4207 agile_start_freq = center_freq->cfreq1 - 4208 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4209 agile_end_freq = center_freq->cfreq1 + 4210 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4211 if (agile_end_freq > op_start_freq && 4212 op_end_freq > agile_start_freq) 4213 *is_overlapping = true; 4214 } 4215 4216 if (op_ch_width == CH_WIDTH_80P80MHZ) { 4217 uint32_t sec80_start_feq; 4218 uint32_t sec80_end_freq; 4219 4220 sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ; 4221 sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ; 4222 4223 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 4224 agile_start_freq = 4225 center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 4226 agile_end_freq = 4227 center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 4228 if (agile_end_freq > sec80_start_feq && 4229 sec80_end_freq > agile_start_freq) 4230 *is_overlapping = true; 4231 4232 agile_start_freq = 4233 center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 4234 agile_end_freq = 4235 center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 4236 if (agile_end_freq > sec80_start_feq && 4237 sec80_end_freq > agile_start_freq) 4238 *is_overlapping = true; 4239 } else { 4240 agile_start_freq = center_freq->cfreq1 - 4241 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4242 agile_end_freq = center_freq->cfreq1 + 4243 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 4244 if (agile_end_freq > sec80_start_feq && 4245 sec80_end_freq > agile_start_freq) 4246 *is_overlapping = true; 4247 } 4248 } 4249 4250 return QDF_STATUS_SUCCESS; 4251 } 4252 4253 /** 4254 * target_if_spectral_populate_chwidth() - Helper routine to 4255 * populate channel width for different Spectral modes 4256 * 4257 * @spectral: Pointer to Spectral object 4258 * @ch_width: Channel width array 4259 * @is_80_80_agile: Indicates whether 80+80 agile scan is requested 4260 * 4261 * Helper routine to populate channel width for different Spectral modes 4262 * 4263 * Return: QDF_STATUS 4264 */ 4265 static QDF_STATUS 4266 target_if_spectral_populate_chwidth(struct target_if_spectral *spectral, 4267 enum phy_ch_width *ch_width, 4268 bool is_80_80_agile) 4269 { 4270 enum spectral_scan_mode smode; 4271 4272 qdf_assert_always(spectral); 4273 4274 smode = SPECTRAL_SCAN_MODE_NORMAL; 4275 for (; smode < SPECTRAL_SCAN_MODE_MAX; ++smode) { 4276 /* If user has configured sscan bandwidth, use it */ 4277 if (spectral->sscan_width_configured[smode]) { 4278 ch_width[smode] = spectral->params[smode].ss_bandwidth; 4279 } else { 4280 /* Otherwise, derive the default sscan bandwidth */ 4281 ch_width[smode] = get_default_sscan_bw(spectral, smode, 4282 is_80_80_agile); 4283 if (ch_width[smode] >= CH_WIDTH_INVALID) { 4284 spectral_err("Invalid sscan BW %u", 4285 ch_width[smode]); 4286 return QDF_STATUS_E_FAILURE; 4287 } 4288 spectral->params[smode].ss_bandwidth = ch_width[smode]; 4289 } 4290 } 4291 4292 return QDF_STATUS_SUCCESS; 4293 } 4294 4295 /** 4296 * target_if_spectral_is_valid_80p80_freq() - API to check whether given 4297 * (cfreq1, cfreq2) pair forms a valid 80+80 combination 4298 * @pdev: pointer to pdev 4299 * @cfreq1: center frequency 1 4300 * @cfreq2: center frequency 2 4301 * 4302 * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80 4303 * combination 4304 * 4305 * Return: true or false 4306 */ 4307 static bool 4308 target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev, 4309 uint32_t cfreq1, uint32_t cfreq2) 4310 { 4311 struct ch_params ch_params = {0}; 4312 enum channel_state chan_state1; 4313 enum channel_state chan_state2; 4314 struct wlan_objmgr_psoc *psoc; 4315 struct ch_params temp_params = {0}; 4316 4317 qdf_assert_always(pdev); 4318 psoc = wlan_pdev_get_psoc(pdev); 4319 qdf_assert_always(psoc); 4320 4321 /* In restricted 80P80 MHz enabled, only one 80+80 MHz 4322 * channel is supported with cfreq=5690 and cfreq=5775. 4323 */ 4324 if (wlan_psoc_nif_fw_ext_cap_get( 4325 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) 4326 return CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2); 4327 4328 ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2); 4329 ch_params.mhz_freq_seg1 = cfreq2; 4330 ch_params.ch_width = CH_WIDTH_80P80MHZ; 4331 wlan_reg_set_channel_params_for_pwrmode( 4332 pdev, 4333 cfreq1 - FREQ_OFFSET_10MHZ, 4334 0, 4335 &ch_params, 4336 REG_CURRENT_PWR_MODE); 4337 4338 if (ch_params.ch_width != CH_WIDTH_80P80MHZ) 4339 return false; 4340 4341 if (ch_params.mhz_freq_seg0 != cfreq1 || 4342 ch_params.mhz_freq_seg1 != cfreq2) 4343 return false; 4344 4345 temp_params.ch_width = CH_WIDTH_80MHZ; 4346 chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode( 4347 pdev, 4348 ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ, 4349 &temp_params, 4350 REG_CURRENT_PWR_MODE); 4351 if ((chan_state1 == CHANNEL_STATE_DISABLE) || 4352 (chan_state1 == CHANNEL_STATE_INVALID)) 4353 return false; 4354 4355 temp_params.ch_width = CH_WIDTH_80MHZ; 4356 chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_pwrmode( 4357 pdev, 4358 ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ, 4359 &temp_params, 4360 REG_CURRENT_PWR_MODE); 4361 if ((chan_state2 == CHANNEL_STATE_DISABLE) || 4362 (chan_state2 == CHANNEL_STATE_INVALID)) 4363 return false; 4364 4365 if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <= 4366 FREQ_OFFSET_80MHZ) 4367 return false; 4368 4369 return true; 4370 } 4371 4372 /** 4373 * _target_if_set_spectral_config() - Set spectral config 4374 * @spectral: Pointer to spectral object 4375 * @param: Spectral parameter id and value 4376 * @smode: Spectral scan mode 4377 * @err: Spectral error code 4378 * 4379 * API to set spectral configurations 4380 * 4381 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4382 */ 4383 static QDF_STATUS 4384 _target_if_set_spectral_config(struct target_if_spectral *spectral, 4385 const struct spectral_cp_param *param, 4386 const enum spectral_scan_mode smode, 4387 enum spectral_cp_error_code *err) 4388 { 4389 struct spectral_config params; 4390 struct target_if_spectral_ops *p_sops; 4391 struct spectral_config *sparams; 4392 QDF_STATUS status; 4393 bool is_overlapping; 4394 uint16_t agile_cfreq; 4395 bool is_valid_chan; 4396 struct spectral_param_min_max *param_min_max; 4397 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 4398 enum spectral_scan_mode m; 4399 struct spectral_config_frequency center_freq = {0}; 4400 bool is_bw_supported; 4401 struct wlan_objmgr_vdev *vdev; 4402 enum phy_ch_width op_bw; 4403 4404 if (!err) { 4405 spectral_err("Error code argument is null"); 4406 QDF_ASSERT(0); 4407 return QDF_STATUS_E_FAILURE; 4408 } 4409 *err = SPECTRAL_SCAN_ERR_INVALID; 4410 4411 if (!param) { 4412 spectral_err("Parameter object is null"); 4413 return QDF_STATUS_E_FAILURE; 4414 } 4415 4416 if (!spectral) { 4417 spectral_err("spectral object is NULL"); 4418 return QDF_STATUS_E_FAILURE; 4419 } 4420 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4421 param_min_max = &spectral->param_min_max; 4422 4423 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4424 spectral_err("Invalid Spectral mode %u", smode); 4425 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4426 return QDF_STATUS_E_FAILURE; 4427 } 4428 4429 sparams = &spectral->params[smode]; 4430 m = SPECTRAL_SCAN_MODE_NORMAL; 4431 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 4432 ch_width[m] = CH_WIDTH_INVALID; 4433 4434 if (!spectral->params_valid[smode]) { 4435 target_if_spectral_info_read(spectral, 4436 smode, 4437 TARGET_IF_SPECTRAL_INFO_PARAMS, 4438 &spectral->params[smode], 4439 sizeof(spectral->params[smode])); 4440 spectral->params_valid[smode] = true; 4441 } 4442 4443 switch (param->id) { 4444 case SPECTRAL_PARAM_FFT_PERIOD: 4445 sparams->ss_fft_period = param->value; 4446 break; 4447 case SPECTRAL_PARAM_SCAN_PERIOD: 4448 sparams->ss_period = param->value; 4449 if (sparams->ss_recapture && ((sparams->ss_period < 4450 SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD) || 4451 (smode == SPECTRAL_SCAN_MODE_AGILE))) { 4452 sparams->ss_recapture = false; 4453 spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d", 4454 sparams->ss_period, smode); 4455 } 4456 break; 4457 case SPECTRAL_PARAM_FFT_RECAPTURE: 4458 if (param->value) { 4459 if (sparams->ss_period >= 4460 SPECTRAL_RECAPTURE_SCAN_PERIOD_THRESHOLD && 4461 smode == SPECTRAL_SCAN_MODE_NORMAL) { 4462 sparams->ss_recapture = true; 4463 } else { 4464 spectral_err("FFT recapture cannot be enabled due to scan period: %d us or spectral scan mode: %d", 4465 sparams->ss_period, smode); 4466 sparams->ss_recapture = false; 4467 } 4468 } else { 4469 sparams->ss_recapture = false; 4470 } 4471 break; 4472 case SPECTRAL_PARAM_SCAN_COUNT: 4473 sparams->ss_count = param->value; 4474 break; 4475 case SPECTRAL_PARAM_SHORT_REPORT: 4476 sparams->ss_short_report = (!!param->value) ? true : false; 4477 break; 4478 case SPECTRAL_PARAM_SPECT_PRI: 4479 sparams->ss_spectral_pri = (!!param->value) ? true : false; 4480 break; 4481 case SPECTRAL_PARAM_FFT_SIZE: 4482 status = target_if_spectral_populate_chwidth 4483 (spectral, ch_width, spectral->params 4484 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 4485 if (QDF_IS_STATUS_ERROR(status)) 4486 return QDF_STATUS_E_FAILURE; 4487 if ((param->value < param_min_max->fft_size_min) || 4488 (param->value > param_min_max->fft_size_max 4489 [ch_width[smode]])) { 4490 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4491 return QDF_STATUS_E_FAILURE; 4492 } 4493 sparams->ss_fft_size = param->value; 4494 break; 4495 case SPECTRAL_PARAM_GC_ENA: 4496 sparams->ss_gc_ena = !!param->value; 4497 break; 4498 case SPECTRAL_PARAM_RESTART_ENA: 4499 sparams->ss_restart_ena = !!param->value; 4500 break; 4501 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 4502 sparams->ss_noise_floor_ref = param->value; 4503 break; 4504 case SPECTRAL_PARAM_INIT_DELAY: 4505 sparams->ss_init_delay = param->value; 4506 break; 4507 case SPECTRAL_PARAM_NB_TONE_THR: 4508 sparams->ss_nb_tone_thr = param->value; 4509 break; 4510 case SPECTRAL_PARAM_STR_BIN_THR: 4511 sparams->ss_str_bin_thr = param->value; 4512 break; 4513 case SPECTRAL_PARAM_WB_RPT_MODE: 4514 sparams->ss_wb_rpt_mode = !!param->value; 4515 break; 4516 case SPECTRAL_PARAM_RSSI_RPT_MODE: 4517 sparams->ss_rssi_rpt_mode = !!param->value; 4518 break; 4519 case SPECTRAL_PARAM_RSSI_THR: 4520 sparams->ss_rssi_thr = param->value; 4521 break; 4522 case SPECTRAL_PARAM_PWR_FORMAT: 4523 sparams->ss_pwr_format = !!param->value; 4524 break; 4525 case SPECTRAL_PARAM_RPT_MODE: 4526 if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) || 4527 (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) { 4528 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4529 return QDF_STATUS_E_FAILURE; 4530 } 4531 sparams->ss_rpt_mode = param->value; 4532 break; 4533 case SPECTRAL_PARAM_BIN_SCALE: 4534 sparams->ss_bin_scale = param->value; 4535 break; 4536 case SPECTRAL_PARAM_DBM_ADJ: 4537 sparams->ss_dbm_adj = !!param->value; 4538 break; 4539 case SPECTRAL_PARAM_CHN_MASK: 4540 sparams->ss_chn_mask = param->value; 4541 break; 4542 case SPECTRAL_PARAM_FREQUENCY: 4543 status = target_if_spectral_populate_chwidth( 4544 spectral, ch_width, param->freq.cfreq2 > 0); 4545 if (QDF_IS_STATUS_ERROR(status)) { 4546 spectral_err("Failed to populate channel width"); 4547 return QDF_STATUS_E_FAILURE; 4548 } 4549 4550 if (ch_width[smode] != CH_WIDTH_80P80MHZ && 4551 param->freq.cfreq2) { 4552 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4553 spectral_err("Non zero cfreq2 expected for 80p80 only"); 4554 return QDF_STATUS_E_INVAL; 4555 } 4556 4557 if (ch_width[smode] == CH_WIDTH_80P80MHZ && 4558 !param->freq.cfreq2) { 4559 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4560 spectral_err("Non zero cfreq2 expected for 80p80"); 4561 return QDF_STATUS_E_INVAL; 4562 } 4563 4564 status = target_if_is_center_freq_of_any_chan 4565 (spectral->pdev_obj, param->freq.cfreq1, 4566 &is_valid_chan); 4567 if (QDF_IS_STATUS_ERROR(status)) 4568 return QDF_STATUS_E_FAILURE; 4569 4570 if (is_valid_chan) { 4571 status = target_if_calculate_center_freq( 4572 spectral, ch_width, 4573 param->freq.cfreq1, 4574 &agile_cfreq); 4575 if (QDF_IS_STATUS_ERROR(status)) { 4576 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4577 return QDF_STATUS_E_FAILURE; 4578 } 4579 } else { 4580 bool is_valid_agile_cfreq; 4581 4582 status = target_if_validate_center_freq 4583 (spectral, ch_width, param->freq.cfreq1, 4584 &is_valid_agile_cfreq); 4585 if (QDF_IS_STATUS_ERROR(status)) 4586 return QDF_STATUS_E_FAILURE; 4587 4588 if (!is_valid_agile_cfreq) { 4589 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4590 spectral_err("Invalid agile center frequency"); 4591 return QDF_STATUS_E_FAILURE; 4592 } 4593 4594 agile_cfreq = param->freq.cfreq1; 4595 } 4596 center_freq.cfreq1 = agile_cfreq; 4597 4598 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 4599 status = target_if_is_center_freq_of_any_chan 4600 (spectral->pdev_obj, param->freq.cfreq2, 4601 &is_valid_chan); 4602 if (QDF_IS_STATUS_ERROR(status)) 4603 return QDF_STATUS_E_FAILURE; 4604 4605 if (is_valid_chan) { 4606 status = target_if_calculate_center_freq( 4607 spectral, ch_width, 4608 param->freq.cfreq2, 4609 &agile_cfreq); 4610 if (QDF_IS_STATUS_ERROR(status)) { 4611 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4612 return QDF_STATUS_E_FAILURE; 4613 } 4614 } else { 4615 bool is_valid_agile_cfreq; 4616 4617 status = target_if_validate_center_freq 4618 (spectral, ch_width, param->freq.cfreq2, 4619 &is_valid_agile_cfreq); 4620 if (QDF_IS_STATUS_ERROR(status)) 4621 return QDF_STATUS_E_FAILURE; 4622 4623 if (!is_valid_agile_cfreq) { 4624 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4625 spectral_err("Invalid agile center frequency"); 4626 return QDF_STATUS_E_FAILURE; 4627 } 4628 4629 agile_cfreq = param->freq.cfreq2; 4630 } 4631 center_freq.cfreq2 = agile_cfreq; 4632 } 4633 4634 status = target_if_is_agile_span_overlap_with_operating_span 4635 (spectral, ch_width, 4636 ¢er_freq, &is_overlapping); 4637 if (QDF_IS_STATUS_ERROR(status)) 4638 return QDF_STATUS_E_FAILURE; 4639 4640 if (is_overlapping) { 4641 spectral_err("Agile freq %u, %u overlaps with operating span", 4642 center_freq.cfreq1, center_freq.cfreq2); 4643 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4644 return QDF_STATUS_E_FAILURE; 4645 } 4646 4647 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 4648 bool is_valid_80p80; 4649 4650 is_valid_80p80 = target_if_spectral_is_valid_80p80_freq( 4651 spectral->pdev_obj, 4652 center_freq.cfreq1, 4653 center_freq.cfreq2); 4654 4655 if (!is_valid_80p80) { 4656 spectral_err("Agile freq %u, %u is invalid 80+80 combination", 4657 center_freq.cfreq1, 4658 center_freq.cfreq2); 4659 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4660 return QDF_STATUS_E_FAILURE; 4661 } 4662 } 4663 4664 sparams->ss_frequency.cfreq1 = center_freq.cfreq1; 4665 sparams->ss_frequency.cfreq2 = center_freq.cfreq2; 4666 4667 break; 4668 4669 case SPECTRAL_PARAM_CHAN_WIDTH: 4670 if (param->value >= CH_WIDTH_INVALID) { 4671 spectral_err("invalid sscan width: %u", param->value); 4672 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4673 return QDF_STATUS_E_FAILURE; 4674 } 4675 4676 vdev = target_if_spectral_get_vdev(spectral, smode); 4677 if (!vdev) { 4678 spectral_err("vdev is null"); 4679 return QDF_STATUS_E_NULL_VALUE; 4680 } 4681 op_bw = target_if_vdev_get_ch_width(vdev); 4682 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4683 4684 /* Validate the bandwidth */ 4685 status = target_if_is_sscan_bw_supported( 4686 spectral, smode, 4687 param->value, op_bw, &is_bw_supported, 4688 spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 4689 ss_frequency.cfreq2 > 0); 4690 if (QDF_IS_STATUS_ERROR(status)) { 4691 spectral_err("Unable to check if given sscan_bw is supported"); 4692 return QDF_STATUS_E_FAILURE; 4693 } 4694 4695 if (!is_bw_supported) { 4696 spectral_err("sscan bw(%u) is not supported for the current operating width(%u) and sscan mode(%u)", 4697 param->value, op_bw, smode); 4698 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4699 return QDF_STATUS_E_FAILURE; 4700 } 4701 4702 sparams->ss_bandwidth = param->value; 4703 spectral->sscan_width_configured[smode] = true; 4704 4705 break; 4706 } 4707 4708 p_sops->configure_spectral(spectral, sparams, smode); 4709 /* only to validate the writes */ 4710 p_sops->get_spectral_config(spectral, ¶ms, smode); 4711 return QDF_STATUS_SUCCESS; 4712 } 4713 4714 QDF_STATUS 4715 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 4716 const struct spectral_cp_param *param, 4717 const enum spectral_scan_mode smode, 4718 enum spectral_cp_error_code *err) 4719 { 4720 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; 4721 struct target_if_spectral *spectral; 4722 QDF_STATUS status; 4723 4724 if (!err) { 4725 spectral_err("Error code argument is null"); 4726 QDF_ASSERT(0); 4727 return QDF_STATUS_E_FAILURE; 4728 } 4729 *err = SPECTRAL_SCAN_ERR_INVALID; 4730 4731 if (!pdev) { 4732 spectral_err("pdev object is NULL"); 4733 return QDF_STATUS_E_FAILURE; 4734 } 4735 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4736 if (!spectral) { 4737 spectral_err("spectral object is NULL"); 4738 return QDF_STATUS_E_FAILURE; 4739 } 4740 4741 if (!param) { 4742 spectral_err("parameter object is NULL"); 4743 return QDF_STATUS_E_FAILURE; 4744 } 4745 4746 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4747 spectral_err("Invalid Spectral mode %u", smode); 4748 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4749 return QDF_STATUS_E_FAILURE; 4750 } 4751 4752 if (!spectral->properties[smode][param->id].supported) { 4753 spectral_err("Spectral parameter(%u) unsupported for mode %u", 4754 param->id, smode); 4755 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 4756 return QDF_STATUS_E_FAILURE; 4757 } 4758 4759 if (spectral->properties[smode][param->id].common_all_modes) { 4760 spectral_warn("Setting Spectral parameter %u for all modes", 4761 param->id); 4762 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { 4763 status = _target_if_set_spectral_config 4764 (spectral, param, mode, err); 4765 if (QDF_IS_STATUS_ERROR(status)) 4766 return QDF_STATUS_E_FAILURE; 4767 } 4768 return QDF_STATUS_SUCCESS; 4769 } 4770 4771 return _target_if_set_spectral_config(spectral, param, smode, err); 4772 } 4773 4774 /** 4775 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 4776 * @fft_len: FFT length 4777 * @pdev: Pointer to pdev object 4778 * 4779 * API to get fft bin count for a given fft length 4780 * 4781 * Return: FFt bin count 4782 */ 4783 static int 4784 target_if_get_fft_bin_count(int fft_len) 4785 { 4786 int bin_count = 0; 4787 4788 switch (fft_len) { 4789 case 5: 4790 bin_count = 16; 4791 break; 4792 case 6: 4793 bin_count = 32; 4794 break; 4795 case 7: 4796 bin_count = 64; 4797 break; 4798 case 8: 4799 bin_count = 128; 4800 break; 4801 case 9: 4802 bin_count = 256; 4803 break; 4804 default: 4805 break; 4806 } 4807 4808 return bin_count; 4809 } 4810 4811 /** 4812 * target_if_init_upper_lower_flags() - Initializes control and extension 4813 * segment flags 4814 * @spectral: pointer to target if spectral object 4815 * @smode: Spectral scan mode 4816 * 4817 * API to initialize the control and extension flags with the lower/upper 4818 * segment based on the HT mode 4819 * 4820 * Return: FFt bin count 4821 */ 4822 static void 4823 target_if_init_upper_lower_flags(struct target_if_spectral *spectral, 4824 enum spectral_scan_mode smode) 4825 { 4826 int current_channel = 0; 4827 int ext_channel = 0; 4828 struct target_if_spectral_ops *p_sops = 4829 GET_TARGET_IF_SPECTRAL_OPS(spectral); 4830 4831 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4832 spectral_err("Invalid Spectral mode %u", smode); 4833 return; 4834 } 4835 current_channel = p_sops->get_current_channel(spectral, smode); 4836 ext_channel = p_sops->get_extension_channel(spectral, smode); 4837 4838 if ((current_channel == 0) || (ext_channel == 0)) 4839 return; 4840 4841 if (spectral->sc_spectral_20_40_mode) { 4842 /* HT40 mode */ 4843 if (ext_channel < current_channel) { 4844 spectral->lower_is_extension = 1; 4845 spectral->upper_is_control = 1; 4846 spectral->lower_is_control = 0; 4847 spectral->upper_is_extension = 0; 4848 } else { 4849 spectral->lower_is_extension = 0; 4850 spectral->upper_is_control = 0; 4851 spectral->lower_is_control = 1; 4852 spectral->upper_is_extension = 1; 4853 } 4854 } else { 4855 /* HT20 mode, lower is always control */ 4856 spectral->lower_is_extension = 0; 4857 spectral->upper_is_control = 0; 4858 spectral->lower_is_control = 1; 4859 spectral->upper_is_extension = 0; 4860 } 4861 } 4862 4863 /** 4864 * target_if_get_spectral_config() - Get spectral configuration 4865 * @pdev: Pointer to pdev object 4866 * @param: Pointer to spectral_config structure in which the configuration 4867 * should be returned 4868 * @smode: Spectral scan mode 4869 * 4870 * API to get the current spectral configuration 4871 * 4872 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4873 */ 4874 QDF_STATUS 4875 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 4876 struct spectral_config *param, 4877 enum spectral_scan_mode smode) 4878 { 4879 struct target_if_spectral_ops *p_sops = NULL; 4880 struct target_if_spectral *spectral = NULL; 4881 4882 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4883 4884 if (!spectral) { 4885 spectral_err("SPECTRAL : Module doesn't exist"); 4886 return QDF_STATUS_E_FAILURE; 4887 } 4888 4889 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4890 4891 if (!p_sops) { 4892 spectral_err("p_sops is null"); 4893 return QDF_STATUS_E_FAILURE; 4894 } 4895 4896 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4897 spectral_err("Invalid Spectral mode %u", smode); 4898 return QDF_STATUS_E_FAILURE; 4899 } 4900 4901 qdf_mem_zero(param, sizeof(struct spectral_config)); 4902 p_sops->get_spectral_config(spectral, param, smode); 4903 4904 return QDF_STATUS_SUCCESS; 4905 } 4906 4907 #ifdef WLAN_FEATURE_11BE 4908 /** 4909 * target_if_spectral_get_num_detectors_for_higher_bws() - Get number of 4910 * Spectral detectors for higher bandwidths 4911 * @spectral: Pointer to target if Spectral object 4912 * @ch_width: channel width 4913 * @num_detectors: Pointer to the variable to store number of Spectral detectors 4914 * 4915 * API to get number of Spectral detectors used for scan in the given channel 4916 * width. 4917 * 4918 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure 4919 */ 4920 static QDF_STATUS 4921 target_if_spectral_get_num_detectors_for_higher_bws( 4922 struct target_if_spectral *spectral, 4923 enum phy_ch_width ch_width, 4924 uint32_t *num_detectors) 4925 { 4926 switch (ch_width) { 4927 case CH_WIDTH_320MHZ: 4928 *num_detectors = spectral->capability.num_detectors_320mhz; 4929 break; 4930 4931 default: 4932 spectral_err("Unsupported channel width %d", ch_width); 4933 return QDF_STATUS_E_INVAL; 4934 } 4935 4936 return QDF_STATUS_SUCCESS; 4937 } 4938 #else 4939 static QDF_STATUS 4940 target_if_spectral_get_num_detectors_for_higher_bws( 4941 struct target_if_spectral *spectral, 4942 enum phy_ch_width ch_width, 4943 uint32_t *num_detectors) 4944 { 4945 spectral_err("Unsupported channel width %d", ch_width); 4946 return QDF_STATUS_E_INVAL; 4947 } 4948 #endif 4949 4950 /** 4951 * target_if_spectral_get_num_detectors() - Get number of Spectral detectors 4952 * @spectral: Pointer to target if Spectral object 4953 * @ch_width: channel width 4954 * @num_detectors: Pointer to the variable to store number of Spectral detectors 4955 * 4956 * API to get number of Spectral detectors used for scan in the given channel 4957 * width. 4958 * 4959 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure 4960 */ 4961 static QDF_STATUS 4962 target_if_spectral_get_num_detectors(struct target_if_spectral *spectral, 4963 enum phy_ch_width ch_width, 4964 uint32_t *num_detectors) 4965 { 4966 if (!spectral) { 4967 spectral_err("target if spectral object is null"); 4968 return QDF_STATUS_E_INVAL; 4969 } 4970 4971 if (ch_width >= CH_WIDTH_INVALID) { 4972 spectral_err("Invalid channel width %d", ch_width); 4973 return QDF_STATUS_E_INVAL; 4974 } 4975 4976 if (!num_detectors) { 4977 spectral_err("Invalid argument, number of detectors"); 4978 return QDF_STATUS_E_INVAL; 4979 } 4980 4981 switch (ch_width) { 4982 case CH_WIDTH_20MHZ: 4983 *num_detectors = spectral->capability.num_detectors_20mhz; 4984 break; 4985 4986 case CH_WIDTH_40MHZ: 4987 *num_detectors = spectral->capability.num_detectors_40mhz; 4988 break; 4989 4990 case CH_WIDTH_80MHZ: 4991 *num_detectors = spectral->capability.num_detectors_80mhz; 4992 break; 4993 4994 case CH_WIDTH_160MHZ: 4995 *num_detectors = spectral->capability.num_detectors_160mhz; 4996 break; 4997 4998 case CH_WIDTH_80P80MHZ: 4999 *num_detectors = spectral->capability.num_detectors_80p80mhz; 5000 break; 5001 5002 default: 5003 return target_if_spectral_get_num_detectors_for_higher_bws( 5004 spectral, ch_width, num_detectors); 5005 } 5006 5007 return QDF_STATUS_SUCCESS; 5008 } 5009 5010 /** 5011 * target_if_spectral_finite_scan_init() - Initializations required for finite 5012 * Spectral scan 5013 * @spectral: Pointer to target of Spctral object 5014 * @smode: Spectral scan mode 5015 * 5016 * This routine initializes the finite Spectral scan. Finite Spectral scan is 5017 * triggered by configuring a non zero scan count. 5018 * 5019 * Return: QDF_STATUS_SUCCESS on success 5020 */ 5021 static QDF_STATUS 5022 target_if_spectral_finite_scan_init(struct target_if_spectral *spectral, 5023 enum spectral_scan_mode smode) 5024 { 5025 struct target_if_finite_spectral_scan_params *finite_scan; 5026 enum phy_ch_width ch_width; 5027 uint32_t num_detectors; 5028 QDF_STATUS status; 5029 uint16_t sscan_count; 5030 5031 if (!spectral) { 5032 spectral_err("target if spectral object is null"); 5033 return QDF_STATUS_E_INVAL; 5034 } 5035 5036 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5037 spectral_err("Invalid Spectral mode"); 5038 return QDF_STATUS_E_INVAL; 5039 } 5040 5041 ch_width = spectral->ch_width[smode]; 5042 status = target_if_spectral_get_num_detectors(spectral, ch_width, 5043 &num_detectors); 5044 5045 if (QDF_IS_STATUS_ERROR(status)) { 5046 spectral_err("Failed to get number of detectors"); 5047 return QDF_STATUS_E_FAILURE; 5048 } 5049 5050 finite_scan = &spectral->finite_scan[smode]; 5051 sscan_count = spectral->params[smode].ss_count; 5052 5053 finite_scan->finite_spectral_scan = true; 5054 finite_scan->num_reports_expected = num_detectors * sscan_count; 5055 5056 return QDF_STATUS_SUCCESS; 5057 } 5058 5059 /** 5060 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 5061 * parameters 5062 * @spectral: Pointer to Spectral target_if internal private data 5063 * @spectral_params: Pointer to Spectral parameters 5064 * @smode: Spectral scan mode 5065 * @err: Spectral error code 5066 * 5067 * Enable use of desired Spectral parameters by configuring them into HW, and 5068 * starting Spectral scan 5069 * 5070 * Return: 0 on success, 1 on failure 5071 */ 5072 int 5073 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 5074 struct spectral_config *spectral_params, 5075 enum spectral_scan_mode smode, 5076 enum spectral_cp_error_code *err) 5077 { 5078 int extension_channel = 0; 5079 int current_channel = 0; 5080 struct target_if_spectral_ops *p_sops = NULL; 5081 QDF_STATUS status; 5082 struct wlan_objmgr_pdev *pdev; 5083 struct wlan_objmgr_psoc *psoc; 5084 5085 if (!spectral) { 5086 spectral_err("Spectral LMAC object is NULL"); 5087 return 1; 5088 } 5089 5090 pdev = spectral->pdev_obj; 5091 if (!pdev) { 5092 spectral_err("pdev is null"); 5093 return QDF_STATUS_E_INVAL; 5094 } 5095 5096 psoc = wlan_pdev_get_psoc(pdev); 5097 if (!psoc) { 5098 spectral_err("psoc is null"); 5099 return QDF_STATUS_E_INVAL; 5100 } 5101 5102 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5103 spectral_err("Invalid Spectral mode %u", smode); 5104 return 1; 5105 } 5106 5107 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5108 5109 if (!p_sops) { 5110 spectral_err("p_sops is NULL"); 5111 return 1; 5112 } 5113 5114 spectral->sc_spectral_noise_pwr_cal = 5115 spectral_params->ss_spectral_pri ? 1 : 0; 5116 5117 /* check if extension channel is present */ 5118 extension_channel = p_sops->get_extension_channel(spectral, smode); 5119 current_channel = p_sops->get_current_channel(spectral, smode); 5120 5121 if (spectral->capability.advncd_spectral_cap) { 5122 spectral->lb_edge_extrabins = 0; 5123 spectral->rb_edge_extrabins = 0; 5124 5125 if (spectral->is_lb_edge_extrabins_format && 5126 spectral->params[smode].ss_rpt_mode == 2) { 5127 spectral->lb_edge_extrabins = 4; 5128 } 5129 5130 if (spectral->is_rb_edge_extrabins_format && 5131 spectral->params[smode].ss_rpt_mode == 2) { 5132 spectral->rb_edge_extrabins = 4; 5133 } 5134 5135 if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) { 5136 spectral->sc_spectral_20_40_mode = 0; 5137 5138 spectral->spectral_numbins = 5139 target_if_get_fft_bin_count( 5140 spectral->params[smode].ss_fft_size); 5141 spectral->spectral_fft_len = 5142 target_if_get_fft_bin_count( 5143 spectral->params[smode].ss_fft_size); 5144 spectral->spectral_data_len = 5145 target_if_get_fft_bin_count( 5146 spectral->params[smode].ss_fft_size); 5147 /* 5148 * Initialize classifier params to be sent to user 5149 * space classifier 5150 */ 5151 spectral->classifier_params.lower_chan_in_mhz = 5152 current_channel; 5153 spectral->classifier_params.upper_chan_in_mhz = 0; 5154 5155 } else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) { 5156 /* TODO : Remove this variable */ 5157 spectral->sc_spectral_20_40_mode = 1; 5158 spectral->spectral_numbins = 5159 target_if_get_fft_bin_count( 5160 spectral->params[smode].ss_fft_size); 5161 spectral->spectral_fft_len = 5162 target_if_get_fft_bin_count( 5163 spectral->params[smode].ss_fft_size); 5164 spectral->spectral_data_len = 5165 target_if_get_fft_bin_count( 5166 spectral->params[smode].ss_fft_size); 5167 5168 /* 5169 * Initialize classifier params to be sent to user 5170 * space classifier 5171 */ 5172 if (extension_channel < current_channel) { 5173 spectral->classifier_params.lower_chan_in_mhz = 5174 extension_channel; 5175 spectral->classifier_params.upper_chan_in_mhz = 5176 current_channel; 5177 } else { 5178 spectral->classifier_params.lower_chan_in_mhz = 5179 current_channel; 5180 spectral->classifier_params.upper_chan_in_mhz = 5181 extension_channel; 5182 } 5183 5184 } else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) { 5185 /* Set the FFT Size */ 5186 /* TODO : Remove this variable */ 5187 spectral->sc_spectral_20_40_mode = 0; 5188 spectral->spectral_numbins = 5189 target_if_get_fft_bin_count( 5190 spectral->params[smode].ss_fft_size); 5191 spectral->spectral_fft_len = 5192 target_if_get_fft_bin_count( 5193 spectral->params[smode].ss_fft_size); 5194 spectral->spectral_data_len = 5195 target_if_get_fft_bin_count( 5196 spectral->params[smode].ss_fft_size); 5197 5198 /* 5199 * Initialize classifier params to be sent to user 5200 * space classifier 5201 */ 5202 spectral->classifier_params.lower_chan_in_mhz = 5203 current_channel; 5204 spectral->classifier_params.upper_chan_in_mhz = 0; 5205 5206 /* 5207 * Initialize classifier params to be sent to user 5208 * space classifier 5209 */ 5210 if (extension_channel < current_channel) { 5211 spectral->classifier_params.lower_chan_in_mhz = 5212 extension_channel; 5213 spectral->classifier_params.upper_chan_in_mhz = 5214 current_channel; 5215 } else { 5216 spectral->classifier_params.lower_chan_in_mhz = 5217 current_channel; 5218 spectral->classifier_params.upper_chan_in_mhz = 5219 extension_channel; 5220 } 5221 5222 } else if (is_ch_width_160_or_80p80( 5223 spectral->ch_width[smode])) { 5224 /* Set the FFT Size */ 5225 5226 /* The below applies to both 160 and 80+80 cases */ 5227 5228 /* TODO : Remove this variable */ 5229 spectral->sc_spectral_20_40_mode = 0; 5230 spectral->spectral_numbins = 5231 target_if_get_fft_bin_count( 5232 spectral->params[smode].ss_fft_size); 5233 spectral->spectral_fft_len = 5234 target_if_get_fft_bin_count( 5235 spectral->params[smode].ss_fft_size); 5236 spectral->spectral_data_len = 5237 target_if_get_fft_bin_count( 5238 spectral->params[smode].ss_fft_size); 5239 5240 /* 5241 * Initialize classifier params to be sent to user 5242 * space classifier 5243 */ 5244 spectral->classifier_params.lower_chan_in_mhz = 5245 current_channel; 5246 spectral->classifier_params.upper_chan_in_mhz = 0; 5247 5248 /* 5249 * Initialize classifier params to be sent to user 5250 * space classifier 5251 */ 5252 if (extension_channel < current_channel) { 5253 spectral->classifier_params.lower_chan_in_mhz = 5254 extension_channel; 5255 spectral->classifier_params.upper_chan_in_mhz = 5256 current_channel; 5257 } else { 5258 spectral->classifier_params.lower_chan_in_mhz = 5259 current_channel; 5260 spectral->classifier_params.upper_chan_in_mhz = 5261 extension_channel; 5262 } 5263 } 5264 5265 if (spectral->spectral_numbins) { 5266 spectral->spectral_numbins += 5267 spectral->lb_edge_extrabins; 5268 spectral->spectral_numbins += 5269 spectral->rb_edge_extrabins; 5270 } 5271 5272 if (spectral->spectral_fft_len) { 5273 spectral->spectral_fft_len += 5274 spectral->lb_edge_extrabins; 5275 spectral->spectral_fft_len += 5276 spectral->rb_edge_extrabins; 5277 } 5278 5279 if (spectral->spectral_data_len) { 5280 spectral->spectral_data_len += 5281 spectral->lb_edge_extrabins; 5282 spectral->spectral_data_len += 5283 spectral->rb_edge_extrabins; 5284 } 5285 } else { 5286 /* 5287 * The decision to find 20/40 mode is found based on the 5288 * presence of extension channel 5289 * instead of channel width, as the channel width can 5290 * dynamically change 5291 */ 5292 5293 if (extension_channel == 0) { 5294 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 5295 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 5296 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 5297 spectral->spectral_data_len = 5298 SPECTRAL_HT20_TOTAL_DATA_LEN; 5299 /* only valid in 20-40 mode */ 5300 spectral->spectral_lower_max_index_offset = -1; 5301 /* only valid in 20-40 mode */ 5302 spectral->spectral_upper_max_index_offset = -1; 5303 spectral->spectral_max_index_offset = 5304 spectral->spectral_fft_len + 2; 5305 spectral->sc_spectral_20_40_mode = 0; 5306 5307 /* 5308 * Initialize classifier params to be sent to user 5309 * space classifier 5310 */ 5311 spectral->classifier_params.lower_chan_in_mhz = 5312 current_channel; 5313 spectral->classifier_params.upper_chan_in_mhz = 0; 5314 5315 } else { 5316 spectral->spectral_numbins = 5317 SPECTRAL_HT40_TOTAL_NUM_BINS; 5318 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 5319 spectral->spectral_data_len = 5320 SPECTRAL_HT40_TOTAL_DATA_LEN; 5321 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 5322 /* only valid in 20 mode */ 5323 spectral->spectral_max_index_offset = -1; 5324 spectral->spectral_lower_max_index_offset = 5325 spectral->spectral_fft_len + 2; 5326 spectral->spectral_upper_max_index_offset = 5327 spectral->spectral_fft_len + 5; 5328 spectral->sc_spectral_20_40_mode = 1; 5329 5330 /* 5331 * Initialize classifier params to be sent to user 5332 * space classifier 5333 */ 5334 if (extension_channel < current_channel) { 5335 spectral->classifier_params.lower_chan_in_mhz = 5336 extension_channel; 5337 spectral->classifier_params.upper_chan_in_mhz = 5338 current_channel; 5339 } else { 5340 spectral->classifier_params.lower_chan_in_mhz = 5341 current_channel; 5342 spectral->classifier_params.upper_chan_in_mhz = 5343 extension_channel; 5344 } 5345 } 5346 } 5347 5348 spectral->send_single_packet = 0; 5349 spectral->classifier_params.spectral_20_40_mode = 5350 spectral->sc_spectral_20_40_mode; 5351 spectral->classifier_params.spectral_dc_index = 5352 spectral->spectral_dc_index; 5353 spectral->spectral_sent_msg = 0; 5354 spectral->classify_scan = 0; 5355 spectral->num_spectral_data = 0; 5356 5357 if (!p_sops->is_spectral_active(spectral, smode)) { 5358 p_sops->configure_spectral(spectral, spectral_params, smode); 5359 spectral->rparams.marker[smode].is_valid = false; 5360 5361 if (spectral->params[smode].ss_count) { 5362 status = target_if_spectral_finite_scan_init(spectral, 5363 smode); 5364 if (QDF_IS_STATUS_ERROR(status)) { 5365 spectral_err("Failed to init finite scan"); 5366 return 1; 5367 } 5368 } 5369 p_sops->start_spectral_scan(spectral, smode, err); 5370 spectral->timestamp_war.timestamp_war_offset[smode] = 0; 5371 spectral->timestamp_war.last_fft_timestamp[smode] = 0; 5372 } 5373 5374 /* get current spectral configuration */ 5375 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode); 5376 5377 target_if_init_upper_lower_flags(spectral, smode); 5378 5379 return 0; 5380 } 5381 5382 /** 5383 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by 5384 * Agile DFS 5385 * @psoc: Pointer to psoc 5386 * @object: Pointer to pdev 5387 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited 5388 * 5389 * This API checks whether Agile DFS is running on any of the pdevs. If so, it 5390 * indicates that Agile Spectral scan is prohibited by Agile DFS. 5391 * 5392 * Return: void 5393 */ 5394 static void 5395 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, 5396 void *object, void *arg) 5397 { 5398 bool *is_aspectral_prohibited = arg; 5399 struct wlan_objmgr_pdev *cur_pdev = object; 5400 bool is_agile_precac_enabled_cur_pdev = false; 5401 bool is_agile_rcac_enabled_cur_pdev = false; 5402 QDF_STATUS status; 5403 5404 qdf_assert_always(is_aspectral_prohibited); 5405 if (*is_aspectral_prohibited) 5406 return; 5407 5408 qdf_assert_always(psoc); 5409 qdf_assert_always(cur_pdev); 5410 5411 status = ucfg_dfs_get_agile_precac_enable 5412 (cur_pdev, 5413 &is_agile_precac_enabled_cur_pdev); 5414 if (QDF_IS_STATUS_ERROR(status)) { 5415 spectral_err("Get agile precac failed, prohibiting aSpectral"); 5416 *is_aspectral_prohibited = true; 5417 return; 5418 } 5419 5420 status = ucfg_dfs_get_rcac_enable(cur_pdev, 5421 &is_agile_rcac_enabled_cur_pdev); 5422 5423 if (QDF_IS_STATUS_ERROR(status)) { 5424 spectral_err("Get agile RCAC failed, prohibiting aSpectral"); 5425 *is_aspectral_prohibited = true; 5426 return; 5427 } 5428 5429 if (is_agile_precac_enabled_cur_pdev) { 5430 spectral_err("aDFS preCAC is in progress on one of the pdevs"); 5431 *is_aspectral_prohibited = true; 5432 } else if (is_agile_rcac_enabled_cur_pdev) { 5433 spectral_err("aDFS RCAC is in progress on one of the pdevs"); 5434 *is_aspectral_prohibited = true; 5435 } 5436 } 5437 5438 /** 5439 * target_if_get_curr_band() - Get current operating band of pdev 5440 * 5441 * @pdev: pointer to pdev object 5442 * 5443 * API to get current operating band of a given pdev. 5444 * 5445 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure 5446 */ 5447 static enum reg_wifi_band 5448 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 5449 { 5450 struct wlan_objmgr_vdev *vdev; 5451 int16_t chan_freq; 5452 enum reg_wifi_band cur_band; 5453 5454 if (!pdev) { 5455 spectral_err("pdev is NULL"); 5456 return REG_BAND_UNKNOWN; 5457 } 5458 5459 if (vdev_id == WLAN_INVALID_VDEV_ID) 5460 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); 5461 else 5462 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 5463 WLAN_SPECTRAL_ID); 5464 if (!vdev) { 5465 spectral_debug("vdev is NULL"); 5466 return REG_BAND_UNKNOWN; 5467 } 5468 chan_freq = target_if_vdev_get_chan_freq(vdev); 5469 cur_band = wlan_reg_freq_to_band(chan_freq); 5470 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5471 5472 return cur_band; 5473 } 5474 5475 /** 5476 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on 5477 * any of the 5G pdevs 5478 * @psoc: Pointer to psoc 5479 * @object: Pointer to pdev 5480 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in 5481 * progress in any 5G pdevs 5482 * 5483 * Return: void 5484 */ 5485 static void 5486 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, 5487 void *object, void *arg) 5488 { 5489 enum reg_wifi_band band; 5490 bool *is_agile_scan_inprog_5g_pdev = arg; 5491 struct target_if_spectral *spectral; 5492 struct wlan_objmgr_pdev *cur_pdev = object; 5493 struct target_if_spectral_ops *p_sops; 5494 5495 if (*is_agile_scan_inprog_5g_pdev) 5496 return; 5497 5498 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); 5499 if (!spectral) { 5500 spectral_err("target if spectral handle is NULL"); 5501 return; 5502 } 5503 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5504 5505 band = target_if_get_curr_band( 5506 cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]); 5507 if (band == REG_BAND_UNKNOWN) { 5508 spectral_debug("Failed to get current band"); 5509 return; 5510 } 5511 5512 if (band == REG_BAND_5G && 5513 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) 5514 *is_agile_scan_inprog_5g_pdev = true; 5515 } 5516 5517 /** 5518 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported 5519 * for current vdev rx chainmask. 5520 * 5521 * @spectral: Pointer to Spectral object 5522 * @is_supported: Pointer to is_supported 5523 * 5524 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 5525 */ 5526 static QDF_STATUS 5527 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, 5528 bool *is_supported) 5529 { 5530 struct wlan_objmgr_vdev *vdev; 5531 uint8_t vdev_rxchainmask; 5532 struct wlan_objmgr_psoc *psoc; 5533 struct wlan_objmgr_pdev *pdev; 5534 struct target_psoc_info *tgt_psoc_info; 5535 struct wlan_psoc_host_service_ext_param *ext_svc_param; 5536 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 5537 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 5538 struct wlan_psoc_host_chainmask_table *table; 5539 int j; 5540 uint32_t table_id; 5541 enum phy_ch_width ch_width; 5542 uint8_t pdev_id; 5543 5544 if (!spectral) { 5545 spectral_err("spectral target if object is null"); 5546 return QDF_STATUS_E_FAILURE; 5547 } 5548 5549 if (!is_supported) { 5550 spectral_err("is supported argument is null"); 5551 return QDF_STATUS_E_FAILURE; 5552 } 5553 5554 if (spectral->spectral_gen <= SPECTRAL_GEN2) { 5555 spectral_err("HW Agile mode is not supported up to gen 2"); 5556 return QDF_STATUS_E_FAILURE; 5557 } 5558 5559 pdev = spectral->pdev_obj; 5560 if (!pdev) { 5561 spectral_err("pdev is null"); 5562 return QDF_STATUS_E_FAILURE; 5563 } 5564 5565 psoc = wlan_pdev_get_psoc(pdev); 5566 if (!psoc) { 5567 spectral_err("psoc is null"); 5568 return QDF_STATUS_E_FAILURE; 5569 } 5570 5571 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 5572 if (!vdev) { 5573 spectral_err("First vdev is NULL"); 5574 return QDF_STATUS_E_FAILURE; 5575 } 5576 5577 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 5578 if (!vdev_rxchainmask) { 5579 spectral_err("vdev rx chainmask is zero"); 5580 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5581 return QDF_STATUS_E_FAILURE; 5582 } 5583 5584 ch_width = target_if_vdev_get_ch_width(vdev); 5585 if (ch_width == CH_WIDTH_INVALID) { 5586 spectral_err("Invalid channel width"); 5587 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5588 return QDF_STATUS_E_FAILURE; 5589 } 5590 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 5591 5592 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 5593 if (!tgt_psoc_info) { 5594 spectral_err("target_psoc_info is null"); 5595 return QDF_STATUS_E_FAILURE; 5596 } 5597 5598 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 5599 if (!ext_svc_param) { 5600 spectral_err("Extended service ready param null"); 5601 return QDF_STATUS_E_FAILURE; 5602 } 5603 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 5604 5605 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 5606 if (!mac_phy_cap_arr) { 5607 spectral_err("mac phy cap array is null"); 5608 return QDF_STATUS_E_FAILURE; 5609 } 5610 5611 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 5612 if (!mac_phy_cap) { 5613 spectral_err("mac phy cap is null"); 5614 return QDF_STATUS_E_FAILURE; 5615 } 5616 5617 table_id = mac_phy_cap->chainmask_table_id; 5618 table = &ext_svc_param->chainmask_table[table_id]; 5619 if (!table) { 5620 spectral_err("chainmask table not found"); 5621 return QDF_STATUS_E_FAILURE; 5622 } 5623 5624 for (j = 0; j < table->num_valid_chainmasks; j++) { 5625 if (table->cap_list[j].chainmask == vdev_rxchainmask) { 5626 if (ch_width <= CH_WIDTH_80MHZ) 5627 *is_supported = 5628 table->cap_list[j].supports_aSpectral; 5629 else 5630 *is_supported = 5631 table->cap_list[j].supports_aSpectral_160; 5632 break; 5633 } 5634 } 5635 5636 if (j == table->num_valid_chainmasks) { 5637 spectral_err("vdev rx chainmask %u not found in table id = %u", 5638 vdev_rxchainmask, table_id); 5639 return QDF_STATUS_E_FAILURE; 5640 } 5641 5642 return QDF_STATUS_SUCCESS; 5643 } 5644 5645 #define INVALID_SPAN_NUM (-1) 5646 /** 5647 * target_if_spectral_get_num_spans() - Get number of spans for a given sscan_bw 5648 * @pdev: Pointer to pdev object 5649 * @sscan_bw: Spectral scan bandwidth 5650 * 5651 * Return: Number of spans on success, INVALID_SPAN_NUM on failure 5652 */ 5653 static int 5654 target_if_spectral_get_num_spans( 5655 struct wlan_objmgr_pdev *pdev, 5656 enum phy_ch_width sscan_bw) 5657 { 5658 struct wlan_objmgr_psoc *psoc; 5659 int num_spans; 5660 5661 if (!pdev) { 5662 spectral_err_rl("pdev is null"); 5663 return INVALID_SPAN_NUM; 5664 } 5665 5666 psoc = wlan_pdev_get_psoc(pdev); 5667 if (!psoc) { 5668 spectral_err_rl("psoc is null"); 5669 return INVALID_SPAN_NUM; 5670 } 5671 5672 if (sscan_bw == CH_WIDTH_80P80MHZ) { 5673 num_spans = 2; 5674 if (wlan_psoc_nif_fw_ext_cap_get( 5675 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) 5676 /* 5 MHz frequency span in restricted 80p80 case */ 5677 num_spans += 1; 5678 } else { 5679 num_spans = 1; 5680 } 5681 5682 return num_spans; 5683 } 5684 5685 #ifdef OPTIMIZED_SAMP_MESSAGE 5686 /** 5687 * target_if_spectral_populate_session_report_info() - Populate per-session 5688 * report level information. 5689 * 5690 * @spectral: Pointer to Spectral object 5691 * @smode: Spectral scan mode 5692 * 5693 * Return: Success/Failure 5694 */ 5695 static QDF_STATUS 5696 target_if_spectral_populate_session_report_info( 5697 struct target_if_spectral *spectral, 5698 enum spectral_scan_mode smode) 5699 { 5700 struct per_session_report_info *rpt_info; 5701 5702 if (!spectral) { 5703 spectral_err_rl("Spectral LMAC object is null"); 5704 return QDF_STATUS_E_NULL_VALUE; 5705 } 5706 if (smode > SPECTRAL_SCAN_MODE_MAX) { 5707 spectral_err_rl("Invalid Spectral scan mode"); 5708 return QDF_STATUS_E_FAILURE; 5709 } 5710 5711 5712 qdf_spin_lock_bh(&spectral->session_report_info_lock); 5713 /* Fill per-session report information, based on the spectral mode */ 5714 rpt_info = &spectral->report_info[smode]; 5715 5716 rpt_info->operating_bw = spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 5717 rpt_info->sscan_bw = spectral->ch_width[smode]; 5718 rpt_info->sscan_cfreq1 = spectral->params[smode].ss_frequency.cfreq1; 5719 rpt_info->sscan_cfreq2 = spectral->params[smode].ss_frequency.cfreq2; 5720 rpt_info->num_spans = target_if_spectral_get_num_spans( 5721 spectral->pdev_obj, 5722 rpt_info->sscan_bw); 5723 5724 qdf_assert_always(rpt_info->num_spans != INVALID_SPAN_NUM); 5725 rpt_info->valid = true; 5726 5727 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 5728 5729 return QDF_STATUS_SUCCESS; 5730 } 5731 5732 /** 5733 * target_if_spectral_populate_session_det_host_info() - Populate per-session 5734 * detector level information that is known to the Host 5735 * 5736 * @spectral: Pointer to Spectral object 5737 * @smode: Spectral scan mode 5738 * 5739 * Return: Success/Failure 5740 */ 5741 static QDF_STATUS 5742 target_if_spectral_populate_session_det_host_info( 5743 struct target_if_spectral *spectral, 5744 enum spectral_scan_mode smode) 5745 { 5746 struct per_session_report_info *rpt_info; 5747 struct sscan_detector_list *detector_list; 5748 struct wlan_objmgr_psoc *psoc; 5749 uint16_t dest_det_idx = 0; 5750 uint16_t dest_span_idx = 0; 5751 bool is_sec80 = false; 5752 uint8_t det, dest_det; 5753 5754 if (!spectral) { 5755 spectral_err_rl("Spectral LMAC object is null"); 5756 return QDF_STATUS_E_NULL_VALUE; 5757 } 5758 if (smode > SPECTRAL_SCAN_MODE_MAX) { 5759 spectral_err_rl("Invalid Spectral scan mode"); 5760 return QDF_STATUS_E_FAILURE; 5761 } 5762 5763 if (!spectral->pdev_obj) { 5764 spectral_err_rl("Spectral PDEV is null"); 5765 return QDF_STATUS_E_NULL_VALUE; 5766 } 5767 5768 psoc = wlan_pdev_get_psoc(spectral->pdev_obj); 5769 if (!psoc) { 5770 spectral_err_rl("psoc is null"); 5771 return QDF_STATUS_E_NULL_VALUE; 5772 } 5773 5774 qdf_spin_lock_bh(&spectral->session_report_info_lock); 5775 rpt_info = &spectral->report_info[smode]; 5776 5777 qdf_spin_lock_bh(&spectral->detector_list_lock); 5778 /* Fill per-sesion detector-level information */ 5779 detector_list = &spectral->detector_list[smode][rpt_info->sscan_bw]; 5780 5781 for (det = 0; det < detector_list->num_detectors; det++) { 5782 struct per_session_det_map *det_map; 5783 5784 qdf_spin_lock_bh(&spectral->session_det_map_lock); 5785 det_map = &spectral->det_map[detector_list->detectors[det]]; 5786 if (detector_list->num_detectors > 1) { 5787 if (det == 0) { 5788 det_map->buf_type = SPECTRAL_MSG_BUF_NEW; 5789 det_map->send_to_upper_layers = false; 5790 } else if (det == detector_list->num_detectors - 1) { 5791 det_map->buf_type = SPECTRAL_MSG_BUF_SAVED; 5792 det_map->send_to_upper_layers = true; 5793 } else { 5794 /* middle fragments */ 5795 det_map->buf_type = SPECTRAL_MSG_BUF_SAVED; 5796 det_map->send_to_upper_layers = false; 5797 } 5798 } else { 5799 det_map->buf_type = SPECTRAL_MSG_BUF_NEW; 5800 det_map->send_to_upper_layers = true; 5801 } 5802 5803 det_map->num_dest_det_info = 1; 5804 if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ && 5805 wlan_psoc_nif_fw_ext_cap_get( 5806 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) { 5807 /** 5808 * In 165MHz case, 1 Spectral HW detector maps to 3 5809 * detectors in SAMP msg. 5810 */ 5811 det_map->num_dest_det_info += 2; 5812 } 5813 5814 for (dest_det = 0; dest_det < det_map->num_dest_det_info; 5815 dest_det++) { 5816 struct per_session_dest_det_info *map_det_info; 5817 5818 map_det_info = &det_map->dest_det_info[dest_det]; 5819 map_det_info->freq_span_id = dest_span_idx; 5820 map_det_info->det_id = dest_det_idx; 5821 map_det_info->is_sec80 = is_sec80; 5822 if (rpt_info->sscan_bw == CH_WIDTH_80P80MHZ) { 5823 /* Increment span ID for non-contiguous modes */ 5824 dest_det_idx = 0; 5825 dest_span_idx++; 5826 } else { 5827 /* Increment detector ID for contiguous modes */ 5828 dest_det_idx++; 5829 } 5830 is_sec80 = !is_sec80; 5831 } 5832 det_map->det_map_valid[smode] = true; 5833 qdf_spin_unlock_bh(&spectral->session_det_map_lock); 5834 } 5835 qdf_spin_unlock_bh(&spectral->detector_list_lock); 5836 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 5837 5838 return QDF_STATUS_SUCCESS; 5839 } 5840 5841 #else 5842 static QDF_STATUS 5843 target_if_spectral_populate_session_report_info( 5844 struct target_if_spectral *spectral, 5845 enum spectral_scan_mode smode) 5846 { 5847 return QDF_STATUS_SUCCESS; 5848 } 5849 5850 static QDF_STATUS 5851 target_if_spectral_populate_session_det_host_info( 5852 struct target_if_spectral *spectral, 5853 enum spectral_scan_mode smode) 5854 { 5855 return QDF_STATUS_SUCCESS; 5856 } 5857 #endif /* OPTIMIZED_SAMP_MESSAGE */ 5858 5859 QDF_STATUS 5860 spectral_is_session_info_expected_from_target(struct wlan_objmgr_pdev *pdev, 5861 bool *is_session_info_expected) 5862 { 5863 struct wlan_objmgr_psoc *psoc; 5864 struct wmi_unified *wmi_handle; 5865 5866 if (!pdev) { 5867 spectral_err("pdev is null"); 5868 return QDF_STATUS_E_NULL_VALUE; 5869 } 5870 5871 psoc = wlan_pdev_get_psoc(pdev); 5872 if (!psoc) { 5873 spectral_err("psoc is null"); 5874 return QDF_STATUS_E_NULL_VALUE; 5875 } 5876 5877 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 5878 if (!wmi_handle) { 5879 spectral_err("wmi handle is null"); 5880 return QDF_STATUS_E_NULL_VALUE; 5881 } 5882 5883 *is_session_info_expected = target_if_spectral_wmi_service_enabled( 5884 psoc, wmi_handle, 5885 wmi_service_spectral_session_info_support); 5886 5887 return QDF_STATUS_SUCCESS; 5888 } 5889 5890 QDF_STATUS 5891 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, 5892 uint8_t vdev_id, 5893 const enum spectral_scan_mode smode, 5894 enum spectral_cp_error_code *err) 5895 { 5896 struct target_if_spectral_ops *p_sops; 5897 struct target_if_spectral *spectral; 5898 struct wlan_objmgr_psoc *psoc; 5899 enum reg_wifi_band band; 5900 QDF_STATUS ret; 5901 bool is_session_info_expected; 5902 5903 if (!err) { 5904 spectral_err("Error code argument is null"); 5905 QDF_ASSERT(0); 5906 return QDF_STATUS_E_FAILURE; 5907 } 5908 *err = SPECTRAL_SCAN_ERR_INVALID; 5909 5910 if (!pdev) { 5911 spectral_err("pdev object is NUll"); 5912 return QDF_STATUS_E_FAILURE; 5913 } 5914 5915 psoc = wlan_pdev_get_psoc(pdev); 5916 if (!psoc) { 5917 spectral_err("psoc is null"); 5918 return QDF_STATUS_E_FAILURE; 5919 } 5920 5921 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5922 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 5923 spectral_err("Invalid Spectral mode %u", smode); 5924 return QDF_STATUS_E_FAILURE; 5925 } 5926 5927 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5928 if (!spectral) { 5929 spectral_err("Spectral LMAC object is NUll"); 5930 return QDF_STATUS_E_FAILURE; 5931 } 5932 5933 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5934 if (!p_sops) { 5935 spectral_err("p_sops is null"); 5936 return QDF_STATUS_E_FAILURE; 5937 } 5938 5939 if (p_sops->is_spectral_active(spectral, smode)) { 5940 spectral_err("spectral in progress in current pdev, mode %d", 5941 smode); 5942 return QDF_STATUS_E_FAILURE; 5943 } 5944 spectral->vdev_id[smode] = vdev_id; 5945 5946 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 5947 QDF_STATUS status; 5948 bool is_supported = false; 5949 5950 status = target_if_is_agile_supported_cur_chmask(spectral, 5951 &is_supported); 5952 if (QDF_IS_STATUS_ERROR(status)) { 5953 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 5954 return QDF_STATUS_E_FAILURE; 5955 } 5956 5957 if (!is_supported) { 5958 spectral_err("aSpectral unsupported for cur chainmask"); 5959 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 5960 return QDF_STATUS_E_FAILURE; 5961 } 5962 } 5963 5964 band = target_if_get_curr_band(spectral->pdev_obj, vdev_id); 5965 if (band == REG_BAND_UNKNOWN) { 5966 spectral_err("Failed to get current band"); 5967 return QDF_STATUS_E_FAILURE; 5968 } 5969 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { 5970 struct target_psoc_info *tgt_hdl; 5971 enum wmi_host_hw_mode_config_type mode; 5972 bool is_agile_scan_inprog_5g_pdev; 5973 5974 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 5975 if (!tgt_hdl) { 5976 target_if_err("target_psoc_info is null"); 5977 return QDF_STATUS_E_FAILURE; 5978 } 5979 5980 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 5981 switch (mode) { 5982 case WMI_HOST_HW_MODE_SBS_PASSIVE: 5983 case WMI_HOST_HW_MODE_SBS: 5984 case WMI_HOST_HW_MODE_DBS_SBS: 5985 case WMI_HOST_HW_MODE_DBS_OR_SBS: 5986 is_agile_scan_inprog_5g_pdev = false; 5987 wlan_objmgr_iterate_obj_list 5988 (psoc, WLAN_PDEV_OP, 5989 target_if_is_agile_scan_active_in_5g, 5990 &is_agile_scan_inprog_5g_pdev, 0, 5991 WLAN_SPECTRAL_ID); 5992 break; 5993 default: 5994 is_agile_scan_inprog_5g_pdev = false; 5995 break; 5996 } 5997 5998 if (is_agile_scan_inprog_5g_pdev) { 5999 spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); 6000 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6001 return QDF_STATUS_E_FAILURE; 6002 } 6003 } 6004 6005 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 6006 bool is_aspectral_prohibited = false; 6007 QDF_STATUS status; 6008 6009 status = wlan_objmgr_iterate_obj_list 6010 (psoc, WLAN_PDEV_OP, 6011 target_if_is_aspectral_prohibited_by_adfs, 6012 &is_aspectral_prohibited, 0, 6013 WLAN_SPECTRAL_ID); 6014 if (QDF_IS_STATUS_ERROR(status)) { 6015 spectral_err("Failed to iterate over pdevs"); 6016 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6017 return QDF_STATUS_E_FAILURE; 6018 } 6019 6020 if (is_aspectral_prohibited) { 6021 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6022 return QDF_STATUS_E_FAILURE; 6023 } 6024 } 6025 6026 if (!spectral->params_valid[smode]) { 6027 target_if_spectral_info_read(spectral, 6028 smode, 6029 TARGET_IF_SPECTRAL_INFO_PARAMS, 6030 &spectral->params[smode], 6031 sizeof(spectral->params[smode])); 6032 spectral->params_valid[smode] = true; 6033 } 6034 6035 qdf_spin_lock_bh(&spectral->spectral_lock); 6036 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 6037 QDF_STATUS status; 6038 bool is_overlapping; 6039 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 6040 enum spectral_scan_mode m; 6041 enum phy_ch_width agile_ch_width; 6042 6043 m = SPECTRAL_SCAN_MODE_NORMAL; 6044 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 6045 ch_width[m] = CH_WIDTH_INVALID; 6046 status = target_if_spectral_populate_chwidth 6047 (spectral, ch_width, spectral->params 6048 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 6049 if (QDF_IS_STATUS_ERROR(status)) { 6050 qdf_spin_unlock_bh(&spectral->spectral_lock); 6051 spectral_err("Failed to populate channel width"); 6052 return QDF_STATUS_E_FAILURE; 6053 } 6054 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 6055 6056 if (!spectral->params[smode].ss_frequency.cfreq1) { 6057 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 6058 qdf_spin_unlock_bh(&spectral->spectral_lock); 6059 spectral_err("Agile Spectral cfreq1 is 0"); 6060 return QDF_STATUS_E_FAILURE; 6061 } else if (agile_ch_width == CH_WIDTH_80P80MHZ && 6062 !spectral->params[smode].ss_frequency.cfreq2) { 6063 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 6064 qdf_spin_unlock_bh(&spectral->spectral_lock); 6065 spectral_err("Agile Spectral cfreq2 is 0"); 6066 return QDF_STATUS_E_FAILURE; 6067 } 6068 6069 status = target_if_is_agile_span_overlap_with_operating_span 6070 (spectral, ch_width, 6071 &spectral->params[smode].ss_frequency, 6072 &is_overlapping); 6073 if (QDF_IS_STATUS_ERROR(status)) { 6074 qdf_spin_unlock_bh(&spectral->spectral_lock); 6075 return QDF_STATUS_E_FAILURE; 6076 } 6077 6078 if (is_overlapping) { 6079 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 6080 qdf_spin_unlock_bh(&spectral->spectral_lock); 6081 return QDF_STATUS_E_FAILURE; 6082 } 6083 } 6084 6085 /* Populate detectot list first */ 6086 ret = target_if_spectral_detector_list_init(spectral); 6087 if (QDF_IS_STATUS_ERROR(ret)) { 6088 qdf_spin_unlock_bh(&spectral->spectral_lock); 6089 spectral_err("Failed to initialize detector list"); 6090 return ret; 6091 } 6092 6093 ret = target_if_spectral_populate_chwidth( 6094 spectral, spectral->ch_width, 6095 spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 6096 ss_frequency.cfreq2 > 0); 6097 if (QDF_IS_STATUS_ERROR(ret)) { 6098 qdf_spin_unlock_bh(&spectral->spectral_lock); 6099 spectral_err("Failed to get channel widths"); 6100 return ret; 6101 } 6102 6103 ret = spectral_is_session_info_expected_from_target( 6104 spectral->pdev_obj, 6105 &is_session_info_expected); 6106 if (QDF_IS_STATUS_ERROR(ret)) { 6107 qdf_spin_unlock_bh(&spectral->spectral_lock); 6108 spectral_err("Failed to check if session info is expected"); 6109 return ret; 6110 } 6111 6112 /* If FW doesn't send session info, populate it */ 6113 if (!is_session_info_expected) { 6114 ret = target_if_spectral_populate_session_report_info(spectral, 6115 smode); 6116 if (QDF_IS_STATUS_ERROR(ret)) { 6117 qdf_spin_unlock_bh(&spectral->spectral_lock); 6118 spectral_err("Failed to populate per-session report info"); 6119 return QDF_STATUS_E_FAILURE; 6120 } 6121 6122 ret = target_if_spectral_populate_session_det_host_info( 6123 spectral, smode); 6124 if (QDF_IS_STATUS_ERROR(ret)) { 6125 qdf_spin_unlock_bh(&spectral->spectral_lock); 6126 spectral_err("Failed to populate per-session detector info"); 6127 return QDF_STATUS_E_FAILURE; 6128 } 6129 } 6130 6131 target_if_spectral_scan_enable_params(spectral, 6132 &spectral->params[smode], smode, 6133 err); 6134 6135 spectral->sscan_width_configured[smode] = false; 6136 qdf_spin_unlock_bh(&spectral->spectral_lock); 6137 6138 return QDF_STATUS_SUCCESS; 6139 } 6140 6141 QDF_STATUS 6142 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, 6143 const enum spectral_scan_mode smode, 6144 enum spectral_cp_error_code *err) 6145 { 6146 struct target_if_spectral_ops *p_sops; 6147 struct target_if_spectral *spectral; 6148 uint8_t det; 6149 6150 if (!pdev) { 6151 spectral_err("pdev object is NULL"); 6152 return QDF_STATUS_E_INVAL; 6153 } 6154 6155 if (target_if_spectral_is_feature_disabled_pdev(pdev)) { 6156 spectral_info("Spectral feature is disabled"); 6157 return QDF_STATUS_COMP_DISABLED; 6158 } 6159 6160 if (!err) { 6161 spectral_err("Error code argument is null"); 6162 QDF_ASSERT(0); 6163 return QDF_STATUS_E_FAILURE; 6164 } 6165 *err = SPECTRAL_SCAN_ERR_INVALID; 6166 6167 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 6168 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 6169 spectral_err("Invalid Spectral mode %u", smode); 6170 return QDF_STATUS_E_FAILURE; 6171 } 6172 6173 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6174 if (!spectral) { 6175 spectral_err("Spectral LMAC object is NUll "); 6176 return QDF_STATUS_E_FAILURE; 6177 } 6178 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6179 6180 qdf_spin_lock_bh(&spectral->spectral_lock); 6181 p_sops->stop_spectral_scan(spectral, smode); 6182 if (spectral->classify_scan) { 6183 /* TODO : Check if this logic is necessary */ 6184 spectral->detects_control_channel = 0; 6185 spectral->detects_extension_channel = 0; 6186 spectral->detects_above_dc = 0; 6187 spectral->detects_below_dc = 0; 6188 spectral->classify_scan = 0; 6189 } 6190 6191 spectral->send_single_packet = 0; 6192 spectral->sc_spectral_scan = 0; 6193 6194 qdf_spin_lock_bh(&spectral->session_det_map_lock); 6195 for (det = 0; det < MAX_DETECTORS_PER_PDEV; det++) 6196 spectral->det_map[det].det_map_valid[smode] = false; 6197 6198 qdf_spin_unlock_bh(&spectral->session_det_map_lock); 6199 6200 /* Mark report info as invalid */ 6201 qdf_spin_lock_bh(&spectral->session_report_info_lock); 6202 spectral->report_info[smode].valid = false; 6203 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 6204 6205 qdf_spin_unlock_bh(&spectral->spectral_lock); 6206 6207 return QDF_STATUS_SUCCESS; 6208 } 6209 6210 /** 6211 * target_if_is_spectral_active() - Get whether Spectral is active 6212 * @pdev: Pointer to pdev object 6213 * @smode: Spectral scan mode 6214 * 6215 * API to get whether Spectral is active 6216 * 6217 * Return: True if Spectral is active, false if Spectral is not active 6218 */ 6219 bool 6220 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, 6221 const enum spectral_scan_mode smode) 6222 { 6223 struct target_if_spectral *spectral = NULL; 6224 struct target_if_spectral_ops *p_sops = NULL; 6225 6226 if (!pdev) { 6227 spectral_err("pdev is null"); 6228 return false; 6229 } 6230 6231 if (target_if_spectral_is_feature_disabled_pdev(pdev)) { 6232 spectral_info("Spectral feature is disabled"); 6233 return false; 6234 } 6235 6236 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6237 6238 if (!spectral) { 6239 spectral_err("SPECTRAL : Module doesn't exist"); 6240 return false; 6241 } 6242 6243 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6244 6245 if (!p_sops) { 6246 spectral_err("p_sops is null"); 6247 return false; 6248 } 6249 6250 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 6251 spectral_err("Invalid Spectral mode %u", smode); 6252 return false; 6253 } 6254 6255 return p_sops->is_spectral_active(spectral, smode); 6256 } 6257 6258 /** 6259 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 6260 * @pdev: Pointer to pdev object 6261 * @smode: Spectral scan mode 6262 * 6263 * API to get whether Spectral is enabled 6264 * 6265 * Return: True if Spectral is enabled, false if Spectral is not enabled 6266 */ 6267 bool 6268 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, 6269 enum spectral_scan_mode smode) 6270 { 6271 struct target_if_spectral *spectral = NULL; 6272 struct target_if_spectral_ops *p_sops = NULL; 6273 6274 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6275 6276 if (!spectral) { 6277 spectral_err("SPECTRAL : Module doesn't exist"); 6278 return false; 6279 } 6280 6281 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6282 6283 if (!p_sops) { 6284 spectral_err("p_sops is null"); 6285 return false; 6286 } 6287 6288 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 6289 spectral_err("Invalid Spectral mode %u", smode); 6290 return false; 6291 } 6292 6293 return p_sops->is_spectral_enabled(spectral, smode); 6294 } 6295 6296 #ifdef DIRECT_BUF_RX_DEBUG 6297 /** 6298 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug 6299 * @pdev: Pointer to pdev object 6300 * @enable: Enable/Disable Spectral DMA ring debug 6301 * 6302 * Start/stop Spectral DMA ring debug based on @enable. 6303 * Also save the state for future use. 6304 * 6305 * Return: QDF_STATUS of operation 6306 */ 6307 static QDF_STATUS 6308 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) 6309 { 6310 struct target_if_spectral *spectral; 6311 struct wlan_lmac_if_tx_ops *tx_ops; 6312 struct wlan_objmgr_psoc *psoc; 6313 6314 if (!pdev) 6315 return QDF_STATUS_E_FAILURE; 6316 6317 psoc = wlan_pdev_get_psoc(pdev); 6318 if (!psoc) { 6319 spectral_err("psoc is null"); 6320 return QDF_STATUS_E_INVAL; 6321 } 6322 6323 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 6324 if (!tx_ops) { 6325 spectral_err("tx_ops is NULL"); 6326 return QDF_STATUS_E_INVAL; 6327 } 6328 6329 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6330 if (!spectral) { 6331 spectral_err("Spectal LMAC object is NULL"); 6332 return QDF_STATUS_E_INVAL; 6333 } 6334 6335 /* Save the state */ 6336 spectral->dbr_ring_debug = enable; 6337 6338 if (enable) 6339 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( 6340 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); 6341 else 6342 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( 6343 pdev, 0); 6344 6345 return QDF_STATUS_SUCCESS; 6346 } 6347 6348 /** 6349 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug 6350 * @pdev: Pointer to pdev object 6351 * @enable: Enable/Disable Spectral DMA buffer debug 6352 * 6353 * Start/stop Spectral DMA buffer debug based on @enable. 6354 * Also save the state for future use. 6355 * 6356 * Return: QDF_STATUS of operation 6357 */ 6358 static QDF_STATUS 6359 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) 6360 { 6361 struct target_if_spectral *spectral; 6362 struct wlan_lmac_if_tx_ops *tx_ops; 6363 struct wlan_objmgr_psoc *psoc; 6364 6365 if (!pdev) 6366 return QDF_STATUS_E_FAILURE; 6367 6368 psoc = wlan_pdev_get_psoc(pdev); 6369 if (!psoc) { 6370 spectral_err("psoc is null"); 6371 return QDF_STATUS_E_INVAL; 6372 } 6373 6374 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 6375 if (!tx_ops) { 6376 spectral_err("tx_ops is NULL"); 6377 return QDF_STATUS_E_INVAL; 6378 } 6379 6380 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6381 if (!spectral) { 6382 spectral_err("Spectal LMAC object is NULL"); 6383 return QDF_STATUS_E_INVAL; 6384 } 6385 6386 /* Save the state */ 6387 spectral->dbr_buff_debug = enable; 6388 6389 if (enable) 6390 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( 6391 pdev, 0, MEM_POISON_SIGNATURE); 6392 else 6393 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( 6394 pdev, 0); 6395 } 6396 6397 /** 6398 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer 6399 * debug based on the previous state 6400 * @pdev: Pointer to pdev object 6401 * 6402 * Return: QDF_STATUS of operation 6403 */ 6404 static QDF_STATUS 6405 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) 6406 { 6407 struct target_if_spectral *spectral; 6408 6409 if (!pdev) { 6410 spectral_err("pdev is NULL!"); 6411 return QDF_STATUS_E_FAILURE; 6412 } 6413 6414 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6415 if (!spectral) { 6416 spectral_err("Spectal LMAC object is NULL"); 6417 return QDF_STATUS_E_INVAL; 6418 } 6419 6420 if (spectral->dbr_buff_debug) 6421 return target_if_spectral_do_dbr_buff_debug(pdev, true); 6422 else 6423 return target_if_spectral_do_dbr_buff_debug(pdev, false); 6424 } 6425 6426 /** 6427 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring 6428 * debug based on the previous state 6429 * @pdev: Pointer to pdev object 6430 * 6431 * Return: QDF_STATUS of operation 6432 */ 6433 static QDF_STATUS 6434 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) 6435 { 6436 struct target_if_spectral *spectral; 6437 6438 if (!pdev) { 6439 spectral_err("pdev is NULL!"); 6440 return QDF_STATUS_E_FAILURE; 6441 } 6442 6443 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6444 if (!spectral) { 6445 spectral_err("Spectal LMAC object is NULL"); 6446 return QDF_STATUS_E_INVAL; 6447 } 6448 6449 if (spectral->dbr_ring_debug) 6450 return target_if_spectral_do_dbr_ring_debug(pdev, true); 6451 else 6452 return target_if_spectral_do_dbr_ring_debug(pdev, false); 6453 } 6454 6455 /** 6456 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral 6457 * @pdev: Pointer to pdev object 6458 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug 6459 * @debug_value: Value to be set for @dma_debug_type 6460 * 6461 * Set DMA debug for Spectral and start/stop Spectral DMA debug function 6462 * based on @debug_value 6463 * 6464 * Return: QDF_STATUS of operation 6465 */ 6466 static QDF_STATUS 6467 target_if_spectral_set_dma_debug( 6468 struct wlan_objmgr_pdev *pdev, 6469 enum spectral_dma_debug dma_debug_type, 6470 bool debug_value) 6471 { 6472 struct target_if_spectral_ops *p_sops; 6473 struct wlan_objmgr_psoc *psoc; 6474 struct wlan_lmac_if_tx_ops *tx_ops; 6475 struct target_if_spectral *spectral; 6476 6477 if (!pdev) 6478 return QDF_STATUS_E_FAILURE; 6479 6480 psoc = wlan_pdev_get_psoc(pdev); 6481 if (!psoc) { 6482 spectral_err("psoc is null"); 6483 return QDF_STATUS_E_INVAL; 6484 } 6485 6486 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 6487 if (!tx_ops) { 6488 spectral_err("tx_ops is NULL"); 6489 return QDF_STATUS_E_FAILURE; 6490 } 6491 6492 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { 6493 spectral_err("Unable to fetch target type"); 6494 return QDF_STATUS_E_FAILURE; 6495 } 6496 6497 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6498 if (!spectral) { 6499 spectral_err("Spectal LMAC object is NULL"); 6500 return QDF_STATUS_E_INVAL; 6501 } 6502 6503 if (spectral->direct_dma_support) { 6504 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6505 if (p_sops->is_spectral_active(spectral, 6506 SPECTRAL_SCAN_MODE_NORMAL) || 6507 p_sops->is_spectral_active(spectral, 6508 SPECTRAL_SCAN_MODE_AGILE)) { 6509 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); 6510 return QDF_STATUS_E_FAILURE; 6511 } 6512 6513 switch (dma_debug_type) { 6514 case SPECTRAL_DMA_RING_DEBUG: 6515 target_if_spectral_do_dbr_ring_debug(pdev, debug_value); 6516 break; 6517 6518 case SPECTRAL_DMA_BUFFER_DEBUG: 6519 target_if_spectral_do_dbr_buff_debug(pdev, debug_value); 6520 break; 6521 6522 default: 6523 spectral_err("Unsupported DMA debug type : %d", 6524 dma_debug_type); 6525 return QDF_STATUS_E_FAILURE; 6526 } 6527 } 6528 return QDF_STATUS_SUCCESS; 6529 } 6530 #endif /* DIRECT_BUF_RX_DEBUG */ 6531 6532 /** 6533 * target_if_spectral_direct_dma_support() - Get Direct-DMA support 6534 * @pdev: Pointer to pdev object 6535 * 6536 * Return: Whether Direct-DMA is supported on this radio 6537 */ 6538 static bool 6539 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) 6540 { 6541 struct target_if_spectral *spectral; 6542 6543 if (!pdev) { 6544 spectral_err("pdev is NULL!"); 6545 return false; 6546 } 6547 6548 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6549 if (!spectral) { 6550 spectral_err("Spectral LMAC object is NULL"); 6551 return false; 6552 } 6553 6554 return spectral->direct_dma_support; 6555 } 6556 6557 /** 6558 * target_if_set_debug_level() - Set debug level for Spectral 6559 * @pdev: Pointer to pdev object 6560 * @debug_level: Debug level 6561 * 6562 * API to set the debug level for Spectral 6563 * 6564 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 6565 */ 6566 QDF_STATUS 6567 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 6568 { 6569 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 6570 6571 return QDF_STATUS_SUCCESS; 6572 } 6573 6574 /** 6575 * target_if_get_debug_level() - Get debug level for Spectral 6576 * @pdev: Pointer to pdev object 6577 * 6578 * API to get the debug level for Spectral 6579 * 6580 * Return: Current debug level 6581 */ 6582 uint32_t 6583 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 6584 { 6585 return spectral_debug_level; 6586 } 6587 6588 /** 6589 * target_if_get_spectral_capinfo() - Get Spectral capability information 6590 * @pdev: Pointer to pdev object 6591 * @scaps: Buffer into which data should be copied 6592 * 6593 * API to get the spectral capability information 6594 * 6595 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 6596 */ 6597 QDF_STATUS 6598 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, 6599 struct spectral_caps *scaps) 6600 { 6601 struct target_if_spectral *spectral = NULL; 6602 6603 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6604 if (!spectral) { 6605 spectral_err("SPECTRAL : Module doesn't exist"); 6606 return QDF_STATUS_E_FAILURE; 6607 } 6608 6609 qdf_mem_copy(scaps, &spectral->capability, 6610 sizeof(struct spectral_caps)); 6611 6612 return QDF_STATUS_SUCCESS; 6613 } 6614 6615 /** 6616 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 6617 * @pdev: Pointer to pdev object 6618 * @stats: Buffer into which data should be copied 6619 * 6620 * API to get the spectral diagnostic statistics 6621 * 6622 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 6623 */ 6624 QDF_STATUS 6625 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, 6626 struct spectral_diag_stats *stats) 6627 { 6628 struct target_if_spectral *spectral = NULL; 6629 6630 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6631 if (!spectral) { 6632 spectral_err("SPECTRAL : Module doesn't exist"); 6633 return QDF_STATUS_E_FAILURE; 6634 } 6635 6636 qdf_mem_copy(stats, &spectral->diag_stats, 6637 sizeof(struct spectral_diag_stats)); 6638 6639 return QDF_STATUS_SUCCESS; 6640 } 6641 6642 /** 6643 * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations 6644 * @psoc: Pointer to psoc object 6645 * @wmi_ops: Pointer to the structure having Spectral WMI operations 6646 * 6647 * API for registering Spectral WMI operations in 6648 * spectral internal data structure 6649 * 6650 * Return: QDF_STATUS 6651 */ 6652 static QDF_STATUS 6653 target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 6654 struct spectral_wmi_ops *wmi_ops) 6655 { 6656 struct target_if_psoc_spectral *psoc_spectral; 6657 6658 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6659 if (!psoc_spectral) { 6660 spectral_err("Spectral LMAC object is null"); 6661 return QDF_STATUS_E_INVAL; 6662 } 6663 6664 psoc_spectral->wmi_ops = *wmi_ops; 6665 6666 return QDF_STATUS_SUCCESS; 6667 } 6668 6669 /** 6670 * target_if_register_spectral_tgt_ops() - Register Spectral target operations 6671 * @psoc: Pointer to psoc object 6672 * @tgt_ops: Pointer to the structure having Spectral target operations 6673 * 6674 * API for registering Spectral target operations in 6675 * spectral internal data structure 6676 * 6677 * Return: QDF_STATUS 6678 */ 6679 static QDF_STATUS 6680 target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 6681 struct spectral_tgt_ops *tgt_ops) 6682 { 6683 if (!psoc) { 6684 spectral_err("psoc is null"); 6685 return QDF_STATUS_E_INVAL; 6686 } 6687 6688 ops_tgt = *tgt_ops; 6689 6690 return QDF_STATUS_SUCCESS; 6691 } 6692 6693 /** 6694 * target_if_register_netlink_cb() - Register Netlink callbacks 6695 * @pdev: Pointer to pdev object 6696 * @nl_cb: Netlink callbacks to register 6697 * 6698 * Return: void 6699 */ 6700 static void 6701 target_if_register_netlink_cb( 6702 struct wlan_objmgr_pdev *pdev, 6703 struct spectral_nl_cb *nl_cb) 6704 { 6705 struct target_if_spectral *spectral = NULL; 6706 6707 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6708 6709 if (!spectral) { 6710 spectral_err("SPECTRAL : Module doesn't exist"); 6711 return; 6712 } 6713 6714 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 6715 6716 if (spectral->use_nl_bcast) 6717 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 6718 else 6719 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 6720 } 6721 6722 /** 6723 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 6724 * Netlink messages to the application layer 6725 * @pdev: Pointer to pdev object 6726 * 6727 * Return: true for broadcast, false for unicast 6728 */ 6729 static bool 6730 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 6731 { 6732 struct target_if_spectral *spectral = NULL; 6733 6734 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6735 6736 if (!spectral) { 6737 spectral_err("SPECTRAL : Module doesn't exist"); 6738 return false; 6739 } 6740 6741 return spectral->use_nl_bcast; 6742 } 6743 6744 /** 6745 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 6746 * @pdev: Pointer to pdev object 6747 * 6748 * Return: void 6749 */ 6750 static void 6751 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 6752 { 6753 struct target_if_spectral *spectral = NULL; 6754 6755 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6756 if (!spectral) { 6757 spectral_err("SPECTRAL : Module doesn't exist"); 6758 return; 6759 } 6760 6761 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 6762 } 6763 6764 static int 6765 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, 6766 void *payload) 6767 { 6768 struct target_if_spectral *spectral = NULL; 6769 struct target_if_spectral_ops *p_sops = NULL; 6770 6771 spectral = get_target_if_spectral_handle_from_pdev(pdev); 6772 if (!spectral) { 6773 spectral_err("SPECTRAL : Module doesn't exist"); 6774 return -EPERM; 6775 } 6776 6777 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 6778 6779 if (!p_sops) { 6780 spectral_err("p_sops is null"); 6781 return -EPERM; 6782 } 6783 6784 return p_sops->process_spectral_report(pdev, payload); 6785 } 6786 6787 #ifdef DIRECT_BUF_RX_DEBUG 6788 static inline void 6789 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 6790 { 6791 if (!tx_ops) { 6792 spectral_err("tx_ops is NULL"); 6793 return; 6794 } 6795 6796 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = 6797 target_if_spectral_set_dma_debug; 6798 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = 6799 target_if_spectral_check_and_do_dbr_ring_debug; 6800 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = 6801 target_if_spectral_check_and_do_dbr_buff_debug; 6802 } 6803 #else 6804 static inline void 6805 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 6806 { 6807 } 6808 #endif 6809 6810 #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE) 6811 /** 6812 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 6813 * register WMI event handler 6814 * @psoc: Pointer to psoc object 6815 * @event_id: Event id 6816 * @handler_func: Handler function 6817 * @rx_ctx: Context of WMI event processing 6818 * 6819 * Wrapper function to register WMI event handler 6820 * 6821 * Return: 0 for success else failure 6822 */ 6823 static int 6824 target_if_spectral_wmi_unified_register_event_handler( 6825 struct wlan_objmgr_psoc *psoc, 6826 wmi_conv_event_id event_id, 6827 wmi_unified_event_handler handler_func, 6828 uint8_t rx_ctx) 6829 { 6830 wmi_unified_t wmi_handle; 6831 struct target_if_psoc_spectral *psoc_spectral; 6832 QDF_STATUS ret; 6833 6834 if (!psoc) { 6835 spectral_err("psoc is null"); 6836 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6837 } 6838 6839 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6840 if (!wmi_handle) { 6841 spectral_err("WMI handle is null"); 6842 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6843 } 6844 6845 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6846 if (!psoc_spectral) { 6847 spectral_err("spectral object is null"); 6848 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 6849 } 6850 6851 ret = psoc_spectral->wmi_ops.wmi_unified_register_event_handler( 6852 wmi_handle, event_id, handler_func, rx_ctx); 6853 6854 return qdf_status_to_os_return(ret); 6855 } 6856 6857 /** 6858 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 6859 * to unregister WMI event handler 6860 * @psoc: Pointer to psoc object 6861 * @event_id: Event id 6862 * 6863 * Wrapper function to unregister WMI event handler 6864 * 6865 * Return: 0 for success else failure 6866 */ 6867 static int 6868 target_if_spectral_wmi_unified_unregister_event_handler( 6869 struct wlan_objmgr_psoc *psoc, 6870 wmi_conv_event_id event_id) 6871 { 6872 wmi_unified_t wmi_handle; 6873 struct target_if_psoc_spectral *psoc_spectral; 6874 QDF_STATUS ret; 6875 6876 if (!psoc) { 6877 spectral_err("psoc is null"); 6878 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6879 } 6880 6881 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6882 if (!wmi_handle) { 6883 spectral_err("WMI handle is null"); 6884 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 6885 } 6886 6887 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6888 if (!psoc_spectral) { 6889 spectral_err("spectral object is null"); 6890 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 6891 } 6892 6893 ret = psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler( 6894 wmi_handle, event_id); 6895 6896 return qdf_status_to_os_return(ret); 6897 } 6898 6899 /** 6900 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 6901 * function to extract fixed parameters from start scan response event 6902 * @psoc: Pointer to psoc object 6903 * @evt_buf: Event buffer 6904 * @param: Start scan response parameters 6905 * 6906 * Wrapper function to extract fixed parameters from start scan response event 6907 * 6908 * Return: QDF_STATUS 6909 */ 6910 static QDF_STATUS 6911 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 6912 struct wlan_objmgr_psoc *psoc, 6913 uint8_t *evt_buf, 6914 struct spectral_startscan_resp_params *param) 6915 { 6916 wmi_unified_t wmi_handle; 6917 struct target_if_psoc_spectral *psoc_spectral; 6918 6919 if (!psoc) { 6920 spectral_err("psoc is null"); 6921 return QDF_STATUS_E_INVAL; 6922 } 6923 6924 if (!evt_buf) { 6925 spectral_err("WMI event buffer is null"); 6926 return QDF_STATUS_E_INVAL; 6927 } 6928 6929 if (!param) { 6930 spectral_err("Spectral startscan response parameters is null"); 6931 return QDF_STATUS_E_INVAL; 6932 } 6933 6934 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6935 if (!wmi_handle) { 6936 spectral_err("WMI handle is null"); 6937 return QDF_STATUS_E_INVAL; 6938 } 6939 6940 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6941 if (!psoc_spectral) { 6942 spectral_err("spectral object is null"); 6943 return QDF_STATUS_E_FAILURE; 6944 } 6945 6946 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param( 6947 wmi_handle, evt_buf, param); 6948 } 6949 6950 /** 6951 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 6952 * function to extract start and end indices of primary 80 MHz, 5 MHz and 6953 * secondary 80 MHz FFT bins 6954 * @psoc: Pointer to psoc object 6955 * @evt_buf: Event buffer 6956 * @param: FFT bin start and end indices 6957 * 6958 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 6959 * and secondary 80 MHz FFT bins 6960 * 6961 * Return: QDF_STATUS 6962 */ 6963 static QDF_STATUS 6964 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 6965 struct wlan_objmgr_psoc *psoc, 6966 uint8_t *evt_buf, 6967 struct spectral_fft_bin_markers_160_165mhz *param) 6968 { 6969 wmi_unified_t wmi_handle; 6970 struct target_if_psoc_spectral *psoc_spectral; 6971 6972 if (!psoc) { 6973 spectral_err("psoc is null"); 6974 return QDF_STATUS_E_INVAL; 6975 } 6976 6977 if (!evt_buf) { 6978 spectral_err("WMI event buffer is null"); 6979 return QDF_STATUS_E_INVAL; 6980 } 6981 6982 if (!param) { 6983 spectral_err("Spectral FFT bin markers is null"); 6984 return QDF_STATUS_E_INVAL; 6985 } 6986 6987 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 6988 if (!wmi_handle) { 6989 spectral_err("WMI handle is null"); 6990 return QDF_STATUS_E_INVAL; 6991 } 6992 6993 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 6994 if (!psoc_spectral) { 6995 spectral_err("spectral object is null"); 6996 return QDF_STATUS_E_FAILURE; 6997 } 6998 6999 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index( 7000 wmi_handle, evt_buf, param); 7001 } 7002 7003 /** 7004 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 7005 * object from scn handle 7006 * @scn: scn handle 7007 * 7008 * Wrapper function to get psoc object from scn handle 7009 * 7010 * Return: Pointer to psoc object 7011 */ 7012 static struct wlan_objmgr_psoc * 7013 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 7014 { 7015 if (!scn) { 7016 spectral_err("scn is null"); 7017 return NULL; 7018 } 7019 7020 return ops_tgt.tgt_get_psoc_from_scn_hdl(scn); 7021 } 7022 7023 /** 7024 * target_if_extract_pdev_spectral_session_chan_info() - Wrapper 7025 * function to extract channel information for a spectral scan session 7026 * @psoc: Pointer to psoc object 7027 * @evt_buf: Event buffer 7028 * @chan_info: Spectral session channel information data structure to be filled 7029 * by this API 7030 * 7031 * Return: QDF_STATUS of operation 7032 */ 7033 static QDF_STATUS 7034 target_if_extract_pdev_spectral_session_chan_info( 7035 struct wlan_objmgr_psoc *psoc, 7036 void *evt_buf, 7037 struct spectral_session_chan_info *chan_info) 7038 { 7039 wmi_unified_t wmi_handle; 7040 struct target_if_psoc_spectral *psoc_spectral; 7041 7042 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7043 if (!wmi_handle) { 7044 spectral_err("WMI handle is null"); 7045 return QDF_STATUS_E_NULL_VALUE; 7046 } 7047 7048 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7049 if (!psoc_spectral) { 7050 spectral_err("spectral object is null"); 7051 return QDF_STATUS_E_NULL_VALUE; 7052 } 7053 7054 return psoc_spectral->wmi_ops.extract_pdev_spectral_session_chan_info( 7055 wmi_handle, evt_buf, chan_info); 7056 } 7057 7058 /** 7059 * target_if_extract_pdev_spectral_session_detector_info() - Wrapper 7060 * function to extract detector information for a spectral scan session 7061 * @psoc: Pointer to psoc object 7062 * @evt_buf: Event buffer 7063 * @det_info: Spectral session detector information data structure to be filled 7064 * by this API 7065 * @det_info_idx: index in the array of spectral scan detector info TLVs 7066 * 7067 * Return: QDF_STATUS of operation 7068 */ 7069 static QDF_STATUS 7070 target_if_extract_pdev_spectral_session_detector_info( 7071 struct wlan_objmgr_psoc *psoc, void *evt_buf, 7072 struct spectral_session_det_info *det_info, 7073 uint8_t det_info_idx) 7074 { 7075 wmi_unified_t wmi_handle; 7076 struct target_if_psoc_spectral *psoc_spectral; 7077 7078 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7079 if (!wmi_handle) { 7080 spectral_err("WMI handle is null"); 7081 return QDF_STATUS_E_NULL_VALUE; 7082 } 7083 7084 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7085 if (!psoc_spectral) { 7086 spectral_err("spectral object is null"); 7087 return QDF_STATUS_E_NULL_VALUE; 7088 } 7089 7090 return psoc_spectral->wmi_ops. 7091 extract_pdev_spectral_session_detector_info( 7092 wmi_handle, evt_buf, det_info, det_info_idx); 7093 } 7094 7095 /** 7096 * target_if_wmi_extract_spectral_caps_fixed_param() - Wrapper function to 7097 * extract fixed params from Spectral capabilities WMI event 7098 * @psoc: Pointer to psoc object 7099 * @evt_buf: Event buffer 7100 * @param: Spectral capabilities event parameters data structure to be filled 7101 * by this API 7102 * 7103 * Return: QDF_STATUS of operation 7104 */ 7105 QDF_STATUS 7106 target_if_wmi_extract_spectral_caps_fixed_param( 7107 struct wlan_objmgr_psoc *psoc, 7108 uint8_t *evt_buf, 7109 struct spectral_capabilities_event_params *param) 7110 { 7111 struct target_if_psoc_spectral *psoc_spectral; 7112 wmi_unified_t wmi_handle; 7113 7114 if (!psoc) { 7115 spectral_err("psoc is null"); 7116 return QDF_STATUS_E_NULL_VALUE; 7117 } 7118 7119 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7120 if (!wmi_handle) { 7121 spectral_err("WMI handle is null"); 7122 return QDF_STATUS_E_NULL_VALUE; 7123 } 7124 7125 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7126 if (!psoc_spectral) { 7127 spectral_err("spectral object is null"); 7128 return QDF_STATUS_E_FAILURE; 7129 } 7130 7131 return psoc_spectral->wmi_ops.extract_spectral_caps_fixed_param( 7132 wmi_handle, evt_buf, param); 7133 } 7134 7135 /** 7136 * target_if_wmi_extract_spectral_scan_bw_caps() - Wrapper function to 7137 * extract bandwidth capabilities from Spectral capabilities WMI event 7138 * @psoc: Pointer to psoc object 7139 * @evt_buf: Event buffer 7140 * @bw_caps: Data structure to be filled by this API after extraction 7141 * 7142 * Return: QDF_STATUS of operation 7143 */ 7144 QDF_STATUS 7145 target_if_wmi_extract_spectral_scan_bw_caps( 7146 struct wlan_objmgr_psoc *psoc, 7147 uint8_t *evt_buf, 7148 struct spectral_scan_bw_capabilities *bw_caps) 7149 { 7150 struct target_if_psoc_spectral *psoc_spectral; 7151 wmi_unified_t wmi_handle; 7152 7153 if (!psoc) { 7154 spectral_err("psoc is null"); 7155 return QDF_STATUS_E_INVAL; 7156 } 7157 7158 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7159 if (!wmi_handle) { 7160 spectral_err("WMI handle is null"); 7161 return QDF_STATUS_E_INVAL; 7162 } 7163 7164 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7165 if (!psoc_spectral) { 7166 spectral_err("spectral object is null"); 7167 return QDF_STATUS_E_FAILURE; 7168 } 7169 7170 return psoc_spectral->wmi_ops.extract_spectral_scan_bw_caps( 7171 wmi_handle, evt_buf, bw_caps); 7172 } 7173 7174 /** 7175 * target_if_wmi_extract_spectral_fft_size_caps() - Wrapper function to 7176 * extract fft size capabilities from Spectral capabilities WMI event 7177 * @psoc: Pointer to psoc object 7178 * @evt_buf: Event buffer 7179 * @fft_size_caps: Data structure to be filled by this API after extraction 7180 * 7181 * Return: QDF_STATUS of operation 7182 */ 7183 QDF_STATUS 7184 target_if_wmi_extract_spectral_fft_size_caps( 7185 struct wlan_objmgr_psoc *psoc, 7186 uint8_t *evt_buf, 7187 struct spectral_fft_size_capabilities *fft_size_caps) 7188 { 7189 struct target_if_psoc_spectral *psoc_spectral; 7190 wmi_unified_t wmi_handle; 7191 7192 if (!psoc) { 7193 spectral_err("psoc is null"); 7194 return QDF_STATUS_E_INVAL; 7195 } 7196 7197 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7198 if (!wmi_handle) { 7199 spectral_err("WMI handle is null"); 7200 return QDF_STATUS_E_INVAL; 7201 } 7202 7203 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7204 if (!psoc_spectral) { 7205 spectral_err("spectral object is null"); 7206 return QDF_STATUS_E_FAILURE; 7207 } 7208 7209 return psoc_spectral->wmi_ops.extract_spectral_fft_size_caps( 7210 wmi_handle, evt_buf, fft_size_caps); 7211 } 7212 #else 7213 /** 7214 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 7215 * register WMI event handler 7216 * @psoc: Pointer to psoc object 7217 * @event_id: Event id 7218 * @handler_func: Handler function 7219 * @rx_ctx: Context of WMI event processing 7220 * 7221 * Wrapper function to register WMI event handler 7222 * 7223 * Return: 0 for success else failure 7224 */ 7225 static int 7226 target_if_spectral_wmi_unified_register_event_handler( 7227 struct wlan_objmgr_psoc *psoc, 7228 wmi_conv_event_id event_id, 7229 wmi_unified_event_handler handler_func, 7230 uint8_t rx_ctx) 7231 { 7232 wmi_unified_t wmi_handle; 7233 QDF_STATUS ret; 7234 7235 if (!psoc) { 7236 spectral_err("psoc is null"); 7237 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7238 } 7239 7240 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7241 if (!wmi_handle) { 7242 spectral_err("WMI handle is null"); 7243 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7244 } 7245 7246 ret = wmi_unified_register_event_handler(wmi_handle, event_id, 7247 handler_func, rx_ctx); 7248 7249 return qdf_status_to_os_return(ret); 7250 } 7251 7252 /** 7253 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 7254 * to unregister WMI event handler 7255 * @psoc: Pointer to psoc object 7256 * @event_id: Event id 7257 * 7258 * Wrapper function to unregister WMI event handler 7259 * 7260 * Return: 0 for success else failure 7261 */ 7262 static int 7263 target_if_spectral_wmi_unified_unregister_event_handler( 7264 struct wlan_objmgr_psoc *psoc, 7265 wmi_conv_event_id event_id) 7266 { 7267 wmi_unified_t wmi_handle; 7268 QDF_STATUS ret; 7269 7270 if (!psoc) { 7271 spectral_err("psoc is null"); 7272 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7273 } 7274 7275 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7276 if (!wmi_handle) { 7277 spectral_err("WMI handle is null"); 7278 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7279 } 7280 7281 ret = wmi_unified_unregister_event_handler(wmi_handle, event_id); 7282 7283 return qdf_status_to_os_return(ret); 7284 } 7285 7286 /** 7287 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 7288 * function to extract fixed parameters from start scan response event 7289 * @psoc: Pointer to psoc object 7290 * @evt_buf: Event buffer 7291 * @param: Start scan response parameters 7292 * 7293 * Wrapper function to extract fixed parameters from start scan response event 7294 * 7295 * Return: QDF_STATUS 7296 */ 7297 static QDF_STATUS 7298 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 7299 struct wlan_objmgr_psoc *psoc, 7300 uint8_t *evt_buf, 7301 struct spectral_startscan_resp_params *param) 7302 { 7303 wmi_unified_t wmi_handle; 7304 7305 if (!psoc) { 7306 spectral_err("psoc is null"); 7307 return QDF_STATUS_E_INVAL; 7308 } 7309 7310 if (!evt_buf) { 7311 spectral_err("WMI event buffer is null"); 7312 return QDF_STATUS_E_INVAL; 7313 } 7314 7315 if (!param) { 7316 spectral_err("Spectral startscan response parameters is null"); 7317 return QDF_STATUS_E_INVAL; 7318 } 7319 7320 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7321 if (!wmi_handle) { 7322 spectral_err("WMI handle is null"); 7323 return QDF_STATUS_E_INVAL; 7324 } 7325 7326 return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf, 7327 param); 7328 } 7329 7330 /** 7331 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 7332 * function to extract start and end indices of primary 80 MHz, 5 MHz and 7333 * secondary 80 MHz FFT bins 7334 * @psoc: Pointer to psoc object 7335 * @evt_buf: Event buffer 7336 * @param: FFT bin start and end indices 7337 * 7338 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 7339 * and secondary 80 MHz FFT bins 7340 * 7341 * Return: QDF_STATUS 7342 */ 7343 static QDF_STATUS 7344 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 7345 struct wlan_objmgr_psoc *psoc, 7346 uint8_t *evt_buf, 7347 struct spectral_fft_bin_markers_160_165mhz *param) 7348 { 7349 wmi_unified_t wmi_handle; 7350 7351 if (!psoc) { 7352 spectral_err("psoc is null"); 7353 return QDF_STATUS_E_INVAL; 7354 } 7355 7356 if (!evt_buf) { 7357 spectral_err("WMI event buffer is null"); 7358 return QDF_STATUS_E_INVAL; 7359 } 7360 7361 if (!param) { 7362 spectral_err("Spectral FFT bin markers is null"); 7363 return QDF_STATUS_E_INVAL; 7364 } 7365 7366 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7367 if (!wmi_handle) { 7368 spectral_err("WMI handle is null"); 7369 return QDF_STATUS_E_INVAL; 7370 } 7371 7372 return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param); 7373 } 7374 7375 /** 7376 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 7377 * object from scn handle 7378 * @scn: scn handle 7379 * 7380 * Wrapper function to get psoc object from scn handle 7381 * 7382 * Return: Pointer to psoc object 7383 */ 7384 static struct wlan_objmgr_psoc * 7385 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 7386 { 7387 if (!scn) { 7388 spectral_err("scn is null"); 7389 return NULL; 7390 } 7391 7392 return target_if_get_psoc_from_scn_hdl(scn); 7393 } 7394 7395 /** 7396 * target_if_extract_pdev_spectral_session_chan_info() - Wrapper 7397 * function to extract channel information for a spectral scan session 7398 * @psoc: Pointer to psoc object 7399 * @evt_buf: Event buffer 7400 * @chan_info: Spectral session channel information data structure to be filled 7401 * by this API 7402 * 7403 * Return: QDF_STATUS of operation 7404 */ 7405 static QDF_STATUS 7406 target_if_extract_pdev_spectral_session_chan_info( 7407 struct wlan_objmgr_psoc *psoc, 7408 void *evt_buf, 7409 struct spectral_session_chan_info *chan_info) 7410 { 7411 wmi_unified_t wmi_handle; 7412 7413 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7414 if (!wmi_handle) { 7415 spectral_err("WMI handle is null"); 7416 return QDF_STATUS_E_NULL_VALUE; 7417 } 7418 7419 return wmi_extract_pdev_spectral_session_chan_info( 7420 wmi_handle, evt_buf, chan_info); 7421 } 7422 7423 /** 7424 * target_if_extract_pdev_spectral_session_detector_info() - Wrapper 7425 * function to extract detector information for a spectral scan session 7426 * @psoc: Pointer to psoc object 7427 * @evt_buf: Event buffer 7428 * @det_info: Spectral session detector information data structure to be filled 7429 * by this API 7430 * @det_info_idx: index in the array of spectral scan detector info TLVs 7431 * 7432 * Return: QDF_STATUS of operation 7433 */ 7434 static QDF_STATUS 7435 target_if_extract_pdev_spectral_session_detector_info( 7436 struct wlan_objmgr_psoc *psoc, void *evt_buf, 7437 struct spectral_session_det_info *det_info, 7438 uint8_t det_info_idx) 7439 { 7440 wmi_unified_t wmi_handle; 7441 7442 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7443 if (!wmi_handle) { 7444 spectral_err("WMI handle is null"); 7445 return QDF_STATUS_E_NULL_VALUE; 7446 } 7447 7448 return wmi_extract_pdev_spectral_session_detector_info( 7449 wmi_handle, evt_buf, det_info, det_info_idx); 7450 } 7451 7452 QDF_STATUS 7453 target_if_wmi_extract_spectral_caps_fixed_param( 7454 struct wlan_objmgr_psoc *psoc, 7455 uint8_t *evt_buf, 7456 struct spectral_capabilities_event_params *param) 7457 { 7458 wmi_unified_t wmi_handle; 7459 7460 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7461 if (!wmi_handle) { 7462 spectral_err("WMI handle is null"); 7463 return QDF_STATUS_E_INVAL; 7464 } 7465 7466 return wmi_extract_spectral_caps_fixed_param(wmi_handle, evt_buf, 7467 param); 7468 } 7469 7470 QDF_STATUS 7471 target_if_wmi_extract_spectral_scan_bw_caps( 7472 struct wlan_objmgr_psoc *psoc, 7473 uint8_t *evt_buf, 7474 struct spectral_scan_bw_capabilities *bw_caps) 7475 { 7476 wmi_unified_t wmi_handle; 7477 7478 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7479 if (!wmi_handle) { 7480 spectral_err("WMI handle is null"); 7481 return QDF_STATUS_E_INVAL; 7482 } 7483 7484 return wmi_extract_spectral_scan_bw_caps(wmi_handle, evt_buf, bw_caps); 7485 } 7486 7487 QDF_STATUS 7488 target_if_wmi_extract_spectral_fft_size_caps( 7489 struct wlan_objmgr_psoc *psoc, 7490 uint8_t *evt_buf, 7491 struct spectral_fft_size_capabilities *fft_size_caps) 7492 { 7493 wmi_unified_t wmi_handle; 7494 7495 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7496 if (!wmi_handle) { 7497 spectral_err("WMI handle is null"); 7498 return QDF_STATUS_E_INVAL; 7499 } 7500 7501 return wmi_extract_spectral_fft_size_caps(wmi_handle, evt_buf, 7502 fft_size_caps); 7503 } 7504 #endif 7505 7506 /** 7507 * target_if_update_det_info_in_spectral_session() - Update detector 7508 * information in spectral scan session 7509 * @spectral: Spectral LMAC object 7510 * @det_info: Pointer to spectral session detector information 7511 * @smode: Spectral scan mode 7512 * 7513 * Return: QDF_STATUS of operation 7514 */ 7515 static QDF_STATUS 7516 target_if_update_det_info_in_spectral_session( 7517 struct target_if_spectral *spectral, 7518 const struct spectral_session_det_info *det_info, 7519 enum spectral_scan_mode smode) 7520 { 7521 struct per_session_det_map *det_map; 7522 struct per_session_dest_det_info *dest_det_info; 7523 7524 if (!spectral) { 7525 spectral_err_rl("Spectral LMAC object is null"); 7526 return QDF_STATUS_E_NULL_VALUE; 7527 } 7528 7529 qdf_assert_always(det_info->det_id < MAX_DETECTORS_PER_PDEV); 7530 7531 qdf_spin_lock_bh(&spectral->session_det_map_lock); 7532 7533 det_map = &spectral->det_map[det_info->det_id]; 7534 dest_det_info = &det_map->dest_det_info[0]; 7535 7536 dest_det_info->start_freq = det_info->start_freq; 7537 dest_det_info->end_freq = det_info->end_freq; 7538 7539 qdf_spin_unlock_bh(&spectral->session_det_map_lock); 7540 7541 /* This detector will be used for this smode throughout this session */ 7542 spectral->rparams.detid_mode_table[det_info->det_id] = smode; 7543 7544 return QDF_STATUS_SUCCESS; 7545 } 7546 7547 /** 7548 * target_if_update_chan_info_in_spectral_session() - Update channel information 7549 * in spectral scan session 7550 * @spectral: Spectral LMAC object 7551 * @chan_info: Pointer to spectral session channel information 7552 * @smode: Spectral scan mode 7553 * 7554 * Return: QDF_STATUS of operation 7555 */ 7556 static QDF_STATUS 7557 target_if_update_chan_info_in_spectral_session( 7558 struct target_if_spectral *spectral, 7559 const struct spectral_session_chan_info *chan_info, 7560 enum spectral_scan_mode smode) 7561 { 7562 struct per_session_report_info *rpt_info; 7563 7564 if (!spectral) { 7565 spectral_err_rl("Spectral LMAC object is null"); 7566 return QDF_STATUS_E_NULL_VALUE; 7567 } 7568 7569 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 7570 spectral_err_rl("Invalid Spectral scan mode :%u", smode); 7571 return QDF_STATUS_E_FAILURE; 7572 } 7573 7574 qdf_spin_lock_bh(&spectral->session_report_info_lock); 7575 rpt_info = &spectral->report_info[smode]; 7576 7577 /* Update per-session report info */ 7578 rpt_info->pri20_freq = chan_info->operating_pri20_freq; 7579 rpt_info->cfreq1 = chan_info->operating_cfreq1; 7580 rpt_info->cfreq2 = chan_info->operating_cfreq2; 7581 rpt_info->operating_bw = chan_info->operating_bw; 7582 rpt_info->sscan_cfreq1 = chan_info->sscan_cfreq1; 7583 rpt_info->sscan_cfreq2 = chan_info->sscan_cfreq2; 7584 rpt_info->sscan_bw = chan_info->sscan_bw; 7585 7586 /* num_spans depends on sscan_bw, update it */ 7587 rpt_info->num_spans = target_if_spectral_get_num_spans( 7588 spectral->pdev_obj, 7589 rpt_info->sscan_bw); 7590 qdf_assert_always(rpt_info->num_spans != INVALID_SPAN_NUM); 7591 7592 rpt_info->valid = true; 7593 7594 qdf_spin_unlock_bh(&spectral->session_report_info_lock); 7595 7596 return QDF_STATUS_SUCCESS; 7597 } 7598 7599 /** 7600 * target_if_spectral_fw_param_event_handler() - WMI event handler to 7601 * process start scan response event 7602 * @scn: Pointer to scn object 7603 * @data_buf: Pointer to event buffer 7604 * @data_len: Length of event buffer 7605 * 7606 * Return: 0 for success, else failure 7607 */ 7608 static int 7609 target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf, 7610 uint32_t data_len) 7611 { 7612 QDF_STATUS status; 7613 struct wlan_objmgr_psoc *psoc; 7614 struct wlan_objmgr_pdev *pdev; 7615 struct wmi_unified *wmi_handle; 7616 struct spectral_startscan_resp_params event_params = {0}; 7617 struct target_if_psoc_spectral *psoc_spectral; 7618 struct target_if_spectral *spectral; 7619 bool is_session_info_expected; 7620 7621 if (!scn) { 7622 spectral_err("scn handle is null"); 7623 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7624 } 7625 7626 if (!data_buf) { 7627 spectral_err("WMI event buffer null"); 7628 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7629 } 7630 7631 psoc = target_if_spectral_get_psoc_from_scn_handle(scn); 7632 if (!psoc) { 7633 spectral_err("psoc is null"); 7634 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7635 } 7636 7637 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 7638 if (!psoc_spectral) { 7639 spectral_err("spectral object is null"); 7640 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7641 } 7642 7643 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7644 if (!wmi_handle) { 7645 spectral_err("WMI handle is null"); 7646 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7647 } 7648 7649 status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 7650 psoc, data_buf, &event_params); 7651 if (QDF_IS_STATUS_ERROR(status)) { 7652 spectral_err("unable to extract sscan fw fixed params"); 7653 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7654 } 7655 7656 if (event_params.smode >= SPECTRAL_SCAN_MODE_MAX || 7657 event_params.smode < SPECTRAL_SCAN_MODE_NORMAL) { 7658 spectral_err("Invalid smode %d", event_params.smode); 7659 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7660 } 7661 7662 pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id, 7663 WLAN_SPECTRAL_ID); 7664 if (!pdev) { 7665 spectral_err("pdev is null"); 7666 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7667 } 7668 7669 spectral = get_target_if_spectral_handle_from_pdev(pdev); 7670 if (!spectral) { 7671 spectral_err("spectral object is null"); 7672 status = QDF_STATUS_E_FAILURE; 7673 goto release_pdev_ref; 7674 } 7675 7676 if (event_params.num_fft_bin_index == 1) { 7677 status = 7678 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 7679 psoc, data_buf, 7680 &spectral->rparams.marker[event_params.smode]); 7681 if (QDF_IS_STATUS_ERROR(status)) { 7682 spectral_err("unable to extract sscan fw fixed params"); 7683 goto release_pdev_ref; 7684 } 7685 } else { 7686 spectral->rparams.marker[event_params.smode].is_valid = false; 7687 } 7688 7689 status = spectral_is_session_info_expected_from_target( 7690 pdev, &is_session_info_expected); 7691 if (QDF_IS_STATUS_ERROR(status)) { 7692 spectral_err("Failed to check if session info is expected"); 7693 goto release_pdev_ref; 7694 } 7695 7696 if (is_session_info_expected) { 7697 struct spectral_session_chan_info chan_info; 7698 uint8_t det_info_idx = 0; 7699 7700 status = target_if_extract_pdev_spectral_session_chan_info( 7701 psoc, data_buf, &chan_info); 7702 if (QDF_IS_STATUS_ERROR(status)) { 7703 spectral_err("Unable to extract spectral session channel info"); 7704 goto release_pdev_ref; 7705 } 7706 7707 status = target_if_update_chan_info_in_spectral_session( 7708 spectral, &chan_info, event_params.smode); 7709 if (QDF_IS_STATUS_ERROR(status)) { 7710 spectral_err("Unable to update channel info"); 7711 goto release_pdev_ref; 7712 } 7713 7714 /* FFT bins info depends upon sscan_bw, update it */ 7715 status = target_if_populate_fft_bins_info(spectral, 7716 event_params.smode); 7717 if (QDF_IS_STATUS_ERROR(status)) { 7718 spectral_err("Failed to populate FFT bins info"); 7719 goto release_pdev_ref; 7720 } 7721 7722 /** 7723 * per-session det info that depends on sscan_bw needs to be 7724 * updated here 7725 */ 7726 status = target_if_spectral_populate_session_det_host_info( 7727 spectral, event_params.smode); 7728 if (QDF_IS_STATUS_ERROR(status)) { 7729 spectral_err("Failed to populate per-session det info"); 7730 goto release_pdev_ref; 7731 } 7732 7733 for (; det_info_idx < event_params.num_det_info; 7734 ++det_info_idx) { 7735 struct spectral_session_det_info det_info; 7736 7737 status = 7738 target_if_extract_pdev_spectral_session_detector_info 7739 (psoc, data_buf, &det_info, det_info_idx); 7740 7741 if (QDF_IS_STATUS_ERROR(status)) { 7742 spectral_err("Unable to extract spectral session detector info for %u", 7743 det_info_idx); 7744 goto release_pdev_ref; 7745 } 7746 7747 status = target_if_update_det_info_in_spectral_session( 7748 spectral, &det_info, 7749 event_params.smode); 7750 if (QDF_IS_STATUS_ERROR(status)) { 7751 spectral_err("Unable to update detector info"); 7752 goto release_pdev_ref; 7753 } 7754 } 7755 } 7756 7757 status = QDF_STATUS_SUCCESS; 7758 7759 release_pdev_ref: 7760 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 7761 return qdf_status_to_os_return(status); 7762 } 7763 7764 /** 7765 * target_if_spectral_capabilities_event_handler() - Handler for the Spectral 7766 * Capabilities event 7767 * @scn: Pointer to scn object 7768 * @data_buf: Pointer to event buffer 7769 * @data_len: Length of event buffer 7770 * 7771 * Return: 0 for success, else failure 7772 */ 7773 static int 7774 target_if_spectral_capabilities_event_handler(ol_scn_t scn, uint8_t *data_buf, 7775 uint32_t data_len) 7776 { 7777 QDF_STATUS status; 7778 struct wlan_objmgr_psoc *psoc; 7779 struct wmi_unified *wmi_handle; 7780 struct spectral_capabilities_event_params event_params = {0}; 7781 struct spectral_scan_bw_capabilities *bw_caps; 7782 struct spectral_fft_size_capabilities *fft_size_caps; 7783 7784 if (!scn) { 7785 spectral_err("scn handle is null"); 7786 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7787 } 7788 7789 if (!data_buf) { 7790 spectral_err("WMI event buffer null"); 7791 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 7792 } 7793 7794 psoc = target_if_spectral_get_psoc_from_scn_handle(scn); 7795 if (!psoc) { 7796 spectral_err("psoc is null"); 7797 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7798 } 7799 7800 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 7801 if (!wmi_handle) { 7802 spectral_err("WMI handle is null"); 7803 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7804 } 7805 7806 status = target_if_wmi_extract_spectral_caps_fixed_param( 7807 psoc, data_buf, &event_params); 7808 if (QDF_IS_STATUS_ERROR(status)) { 7809 spectral_err("Failed to extract fixed parameters"); 7810 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 7811 } 7812 7813 /* There should be atleast one capability */ 7814 qdf_assert(event_params.num_sscan_bw_caps > 0); 7815 qdf_assert(event_params.num_fft_size_caps > 0); 7816 7817 bw_caps = qdf_mem_malloc( 7818 sizeof(*bw_caps) * event_params.num_sscan_bw_caps); 7819 if (!bw_caps) { 7820 spectral_err("memory allocation failed"); 7821 return qdf_status_to_os_return(QDF_STATUS_E_NOMEM); 7822 } 7823 7824 status = target_if_wmi_extract_spectral_scan_bw_caps(psoc, data_buf, 7825 bw_caps); 7826 if (QDF_IS_STATUS_ERROR(status)) { 7827 spectral_err("Failed to extract BW caps"); 7828 status = QDF_STATUS_E_FAILURE; 7829 goto free_bw_caps; 7830 } 7831 7832 fft_size_caps = qdf_mem_malloc( 7833 sizeof(*fft_size_caps) * event_params.num_fft_size_caps); 7834 if (!fft_size_caps) { 7835 spectral_err("memory allocation failed"); 7836 status = QDF_STATUS_E_NOMEM; 7837 goto free_bw_caps; 7838 } 7839 7840 status = target_if_wmi_extract_spectral_fft_size_caps(psoc, data_buf, 7841 fft_size_caps); 7842 if (QDF_IS_STATUS_ERROR(status)) { 7843 spectral_err("Failed to extract fft size caps"); 7844 status = QDF_STATUS_E_FAILURE; 7845 goto free_fft_size_caps; 7846 } 7847 7848 status = QDF_STATUS_SUCCESS; 7849 7850 free_fft_size_caps: 7851 qdf_mem_free(fft_size_caps); 7852 7853 free_bw_caps: 7854 qdf_mem_free(bw_caps); 7855 7856 return qdf_status_to_os_return(status); 7857 } 7858 7859 static QDF_STATUS 7860 target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc) 7861 { 7862 int ret; 7863 7864 if (!psoc) { 7865 spectral_err("psoc is null"); 7866 return QDF_STATUS_E_INVAL; 7867 } 7868 7869 ret = target_if_spectral_wmi_unified_register_event_handler( 7870 psoc, 7871 wmi_pdev_sscan_fw_param_eventid, 7872 target_if_spectral_fw_param_event_handler, 7873 WMI_RX_UMAC_CTX); 7874 7875 if (ret) 7876 spectral_debug("event handler not supported, ret=%d", ret); 7877 7878 ret = target_if_spectral_wmi_unified_register_event_handler( 7879 psoc, 7880 wmi_spectral_capabilities_eventid, 7881 target_if_spectral_capabilities_event_handler, 7882 WMI_RX_UMAC_CTX); 7883 if (ret) 7884 spectral_debug("event handler not supported, ret=%d", ret); 7885 7886 return QDF_STATUS_SUCCESS; 7887 } 7888 7889 static QDF_STATUS 7890 target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc) 7891 { 7892 int ret; 7893 7894 if (!psoc) { 7895 spectral_err("psoc is null"); 7896 return QDF_STATUS_E_INVAL; 7897 } 7898 7899 target_if_spectral_wmi_unified_unregister_event_handler( 7900 psoc, wmi_spectral_capabilities_eventid); 7901 7902 ret = target_if_spectral_wmi_unified_unregister_event_handler( 7903 psoc, wmi_pdev_sscan_fw_param_eventid); 7904 7905 if (ret) 7906 spectral_debug("Unregister WMI event handler failed, ret = %d", 7907 ret); 7908 7909 return QDF_STATUS_SUCCESS; 7910 } 7911 7912 void 7913 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 7914 { 7915 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 7916 target_if_pdev_spectral_init; 7917 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 7918 target_if_pdev_spectral_deinit; 7919 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init = 7920 target_if_psoc_spectral_init; 7921 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit = 7922 target_if_psoc_spectral_deinit; 7923 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 7924 target_if_set_spectral_config; 7925 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 7926 target_if_get_spectral_config; 7927 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 7928 target_if_start_spectral_scan; 7929 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 7930 target_if_stop_spectral_scan; 7931 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 7932 target_if_is_spectral_active; 7933 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 7934 target_if_is_spectral_enabled; 7935 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 7936 target_if_set_debug_level; 7937 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 7938 target_if_get_debug_level; 7939 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 7940 target_if_get_spectral_capinfo; 7941 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 7942 target_if_get_spectral_diagstats; 7943 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops = 7944 target_if_register_spectral_wmi_ops; 7945 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops = 7946 target_if_register_spectral_tgt_ops; 7947 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 7948 target_if_register_netlink_cb; 7949 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 7950 target_if_use_nl_bcast; 7951 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 7952 target_if_deregister_netlink_cb; 7953 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = 7954 target_if_process_spectral_report; 7955 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = 7956 target_if_spectral_direct_dma_support; 7957 tx_ops->sptrl_tx_ops.sptrlto_register_events = 7958 target_if_spectral_register_events; 7959 tx_ops->sptrl_tx_ops.sptrlto_unregister_events = 7960 target_if_spectral_unregister_events; 7961 tx_ops->sptrl_tx_ops.sptrlto_init_pdev_feature_caps = 7962 target_if_spectral_init_pdev_feature_caps; 7963 7964 target_if_sptrl_debug_register_tx_ops(tx_ops); 7965 } 7966 qdf_export_symbol(target_if_sptrl_register_tx_ops); 7967 7968 void 7969 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 7970 uint16_t cw_int, uint32_t dcs_enabled) 7971 { 7972 struct spectral_samp_msg *msg = NULL; 7973 struct target_if_spectral_ops *p_sops = NULL; 7974 struct target_if_spectral *spectral = NULL; 7975 7976 spectral = get_target_if_spectral_handle_from_pdev(pdev); 7977 7978 if (!spectral) { 7979 spectral_err("SPECTRAL : Module doesn't exist"); 7980 return; 7981 } 7982 7983 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 7984 if (!p_sops) { 7985 spectral_err("p_sops is null"); 7986 return; 7987 } 7988 7989 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( 7990 spectral->pdev_obj, 7991 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, 7992 SPECTRAL_MSG_BUF_NEW); 7993 7994 if (msg) { 7995 msg->int_type = cw_int ? 7996 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 7997 msg->dcs_enabled = dcs_enabled; 7998 msg->signature = SPECTRAL_SIGNATURE; 7999 p_sops->get_mac_address(spectral, msg->macaddr); 8000 if (spectral->send_phy_data 8001 (pdev, 8002 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0) 8003 spectral->spectral_sent_msg++; 8004 } 8005 } 8006 qdf_export_symbol(target_if_spectral_send_intf_found_msg); 8007 8008 QDF_STATUS 8009 target_if_spectral_is_finite_scan(struct target_if_spectral *spectral, 8010 enum spectral_scan_mode smode, 8011 bool *finite_spectral_scan) 8012 { 8013 struct target_if_finite_spectral_scan_params *finite_scan; 8014 8015 if (!spectral) { 8016 spectral_err_rl("target if spectral object is null"); 8017 return QDF_STATUS_E_INVAL; 8018 } 8019 8020 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 8021 spectral_err_rl("invalid spectral mode %d", smode); 8022 return QDF_STATUS_E_INVAL; 8023 } 8024 8025 if (!finite_spectral_scan) { 8026 spectral_err_rl("Invalid pointer"); 8027 return QDF_STATUS_E_INVAL; 8028 } 8029 8030 finite_scan = &spectral->finite_scan[smode]; 8031 *finite_spectral_scan = finite_scan->finite_spectral_scan; 8032 8033 return QDF_STATUS_SUCCESS; 8034 } 8035 8036 QDF_STATUS 8037 target_if_spectral_finite_scan_update(struct target_if_spectral *spectral, 8038 enum spectral_scan_mode smode) 8039 { 8040 struct target_if_finite_spectral_scan_params *finite_scan; 8041 8042 if (!spectral) { 8043 spectral_err_rl("target if spectral object is null"); 8044 return QDF_STATUS_E_INVAL; 8045 } 8046 8047 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 8048 spectral_err_rl("Invalid Spectral mode"); 8049 return QDF_STATUS_E_INVAL; 8050 } 8051 8052 finite_scan = &spectral->finite_scan[smode]; 8053 8054 if (!finite_scan->num_reports_expected) { 8055 spectral_err_rl("Error, No reports expected"); 8056 return QDF_STATUS_E_FAILURE; 8057 } 8058 8059 finite_scan->num_reports_expected--; 8060 if (!finite_scan->num_reports_expected) { 8061 QDF_STATUS status; 8062 enum spectral_cp_error_code err; 8063 8064 /* received expected number of reports from target, stop scan */ 8065 status = target_if_stop_spectral_scan(spectral->pdev_obj, smode, 8066 &err); 8067 if (QDF_IS_STATUS_ERROR(status)) { 8068 spectral_err_rl("Failed to stop finite Spectral scan"); 8069 return QDF_STATUS_E_FAILURE; 8070 } 8071 finite_scan->finite_spectral_scan = false; 8072 } 8073 8074 return QDF_STATUS_SUCCESS; 8075 } 8076