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