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