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