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