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