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