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