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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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(&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_QCA5018 || 1421 target_type == TARGET_TYPE_QCA6490) { 1422 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 1423 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 1424 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 1425 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 1426 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 1427 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 1428 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 1429 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 1430 } else { 1431 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 1432 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 1433 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 1434 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 1435 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 1436 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 1437 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 1438 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 1439 } 1440 break; 1441 1442 case SPECTRAL_GEN2: 1443 param_min_max->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; 1444 param_min_max->fft_size_max[CH_WIDTH_20MHZ] = 1445 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 1446 param_min_max->fft_size_max[CH_WIDTH_40MHZ] = 1447 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 1448 param_min_max->fft_size_max[CH_WIDTH_80MHZ] = 1449 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 1450 param_min_max->fft_size_max[CH_WIDTH_80P80MHZ] = 1451 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 1452 param_min_max->fft_size_max[CH_WIDTH_160MHZ] = 1453 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 1454 break; 1455 1456 default: 1457 spectral_err("Invalid spectral generation %d", gen); 1458 return QDF_STATUS_E_INVAL; 1459 } 1460 1461 return QDF_STATUS_SUCCESS; 1462 } 1463 1464 /** 1465 * target_if_init_spectral_param_properties() - Initialize Spectral parameter 1466 * properties 1467 * @spectral: Pointer to Spectral target_if internal private data 1468 * 1469 * Initialize Spectral parameter properties 1470 * 1471 * Return: QDF_STATUS 1472 */ 1473 static QDF_STATUS 1474 target_if_init_spectral_param_properties(struct target_if_spectral *spectral) 1475 { 1476 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 1477 int param; 1478 1479 /* Initialize default values for properties. 1480 * Default values are supported for all the parameters for all modes 1481 * and allows different values for each mode for all the parameters . 1482 */ 1483 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 1484 for (param = 0; param < SPECTRAL_PARAM_MAX; param++) { 1485 spectral->properties[smode][param].supported = true; 1486 spectral->properties[smode][param].common_all_modes = 1487 false; 1488 } 1489 } 1490 1491 /* Once FW advertisement is in place remove this hard coding */ 1492 smode = SPECTRAL_SCAN_MODE_NORMAL; 1493 spectral->properties[SPECTRAL_SCAN_MODE_NORMAL] 1494 [SPECTRAL_PARAM_FREQUENCY].supported = false; 1495 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 1496 spectral->properties[smode] 1497 [SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true; 1498 spectral->properties[smode] 1499 [SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true; 1500 spectral->properties[smode] 1501 [SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true; 1502 } 1503 1504 return QDF_STATUS_SUCCESS; 1505 } 1506 1507 QDF_STATUS 1508 target_if_init_spectral_capability(struct target_if_spectral *spectral, 1509 uint32_t target_type) 1510 { 1511 struct wlan_objmgr_psoc *psoc; 1512 struct wlan_objmgr_pdev *pdev; 1513 struct wlan_psoc_host_spectral_scaling_params *scaling_params; 1514 uint8_t num_bin_scaling_params, param_idx, pdev_id; 1515 struct target_psoc_info *tgt_psoc_info; 1516 struct wlan_psoc_host_service_ext_param *ext_svc_param; 1517 struct spectral_caps *pcap = &spectral->capability; 1518 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 1519 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 1520 struct wlan_psoc_host_chainmask_table *table; 1521 int j; 1522 uint32_t table_id; 1523 1524 pdev = spectral->pdev_obj; 1525 psoc = wlan_pdev_get_psoc(pdev); 1526 if (!psoc) { 1527 spectral_err("psoc is null"); 1528 return QDF_STATUS_E_FAILURE; 1529 } 1530 1531 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 1532 if (!tgt_psoc_info) { 1533 spectral_err("target_psoc_info is null"); 1534 return QDF_STATUS_E_FAILURE; 1535 } 1536 1537 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 1538 num_bin_scaling_params = ext_svc_param->num_bin_scaling_params; 1539 scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info); 1540 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1541 1542 /* XXX : Workaround: Set Spectral capability */ 1543 pcap = &spectral->capability; 1544 pcap->phydiag_cap = 1; 1545 pcap->radar_cap = 1; 1546 pcap->spectral_cap = 1; 1547 pcap->advncd_spectral_cap = 1; 1548 pcap->hw_gen = spectral->spectral_gen; 1549 if (spectral->spectral_gen >= SPECTRAL_GEN3) { 1550 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 1551 if (!mac_phy_cap_arr) { 1552 spectral_err("mac phy cap array is null"); 1553 return QDF_STATUS_E_FAILURE; 1554 } 1555 1556 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 1557 if (!mac_phy_cap) { 1558 spectral_err("mac phy cap is null"); 1559 return QDF_STATUS_E_FAILURE; 1560 } 1561 1562 table_id = mac_phy_cap->chainmask_table_id; 1563 table = &ext_svc_param->chainmask_table[table_id]; 1564 if (!table) { 1565 spectral_err("chainmask table not found"); 1566 return QDF_STATUS_E_FAILURE; 1567 } 1568 1569 for (j = 0; j < table->num_valid_chainmasks; j++) { 1570 pcap->agile_spectral_cap |= 1571 table->cap_list[j].supports_aSpectral; 1572 pcap->agile_spectral_cap_160 |= 1573 table->cap_list[j].supports_aSpectral_160; 1574 } 1575 pcap->agile_spectral_cap_80p80 = pcap->agile_spectral_cap_160; 1576 } else { 1577 pcap->agile_spectral_cap = false; 1578 pcap->agile_spectral_cap_160 = false; 1579 pcap->agile_spectral_cap_80p80 = false; 1580 } 1581 1582 if (scaling_params) { 1583 for (param_idx = 0; param_idx < num_bin_scaling_params; 1584 param_idx++) { 1585 if (scaling_params[param_idx].pdev_id == pdev_id) { 1586 pcap->is_scaling_params_populated = true; 1587 pcap->formula_id = 1588 scaling_params[param_idx].formula_id; 1589 pcap->low_level_offset = 1590 scaling_params[param_idx].low_level_offset; 1591 pcap->high_level_offset = 1592 scaling_params[param_idx].high_level_offset; 1593 pcap->rssi_thr = 1594 scaling_params[param_idx].rssi_thr; 1595 pcap->default_agc_max_gain = 1596 scaling_params[param_idx].default_agc_max_gain; 1597 break; 1598 } 1599 } 1600 } 1601 1602 pcap->num_detectors_20mhz = 1; 1603 pcap->num_detectors_40mhz = 1; 1604 pcap->num_detectors_80mhz = 1; 1605 if (target_type == TARGET_TYPE_QCN9000 || 1606 target_type == TARGET_TYPE_QCA6490) { 1607 pcap->num_detectors_160mhz = 1; 1608 pcap->num_detectors_80p80mhz = 1; 1609 } else { 1610 pcap->num_detectors_160mhz = 2; 1611 pcap->num_detectors_80p80mhz = 2; 1612 } 1613 1614 return QDF_STATUS_SUCCESS; 1615 } 1616 1617 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1618 /** 1619 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 1620 * internal operations with functions related to spectral simulation 1621 * @p_sops: spectral low level ops table 1622 * 1623 * Initialize spectral target_if internal operations with functions 1624 * related to spectral simulation 1625 * 1626 * Return: None 1627 */ 1628 static void 1629 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 1630 { 1631 /* 1632 * Spectral simulation is currently intended for platform transitions 1633 * where underlying HW support may not be available for some time. 1634 * Hence, we do not currently provide a runtime switch to turn the 1635 * simulation on or off. 1636 * In case of future requirements where runtime switches are required, 1637 * this can be added. But it is suggested to use application layer 1638 * simulation as far as possible in such cases, since the main 1639 * use of record and replay of samples would concern higher 1640 * level sample processing rather than lower level delivery. 1641 */ 1642 p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled; 1643 p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active; 1644 p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan; 1645 p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan; 1646 p_sops->configure_spectral = 1647 target_if_spectral_sops_sim_configure_params; 1648 p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params; 1649 } 1650 1651 #else 1652 /** 1653 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 1654 * internal operations 1655 * @p_sops: spectral low level ops table 1656 * 1657 * Return: None 1658 */ 1659 static void 1660 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 1661 { 1662 p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled; 1663 p_sops->is_spectral_active = target_if_sops_is_spectral_active; 1664 p_sops->start_spectral_scan = target_if_sops_start_spectral_scan; 1665 p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan; 1666 p_sops->configure_spectral = target_if_spectral_sops_configure_params; 1667 p_sops->get_spectral_config = target_if_spectral_sops_get_params; 1668 } 1669 #endif 1670 1671 /** 1672 * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal 1673 * operations common to all Spectral chipset generations 1674 * 1675 * Initializes target_if_spectral_ops common to all chipset generations 1676 * 1677 * Return: None 1678 */ 1679 static void 1680 target_if_init_spectral_ops_common(void) 1681 { 1682 struct target_if_spectral_ops *p_sops = &spectral_ops; 1683 1684 p_sops->get_tsf64 = target_if_spectral_get_tsf64; 1685 p_sops->get_capability = target_if_spectral_get_capability; 1686 p_sops->set_rxfilter = target_if_spectral_set_rxfilter; 1687 p_sops->get_rxfilter = target_if_spectral_get_rxfilter; 1688 1689 target_if_init_spectral_simulation_ops(p_sops); 1690 1691 p_sops->get_extension_channel = 1692 target_if_spectral_get_extension_channel; 1693 p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor; 1694 p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor; 1695 p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask; 1696 p_sops->get_mac_address = target_if_spectral_get_macaddr; 1697 p_sops->get_current_channel = target_if_spectral_get_current_channel; 1698 p_sops->reset_hw = target_if_spectral_reset_hw; 1699 p_sops->get_chain_noise_floor = 1700 target_if_spectral_get_chain_noise_floor; 1701 } 1702 1703 /** 1704 * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal 1705 * operations specific to Spectral chipset generation 2. 1706 * 1707 * Initializes target_if_spectral_ops specific to Spectral chipset generation 2. 1708 * 1709 * Return: None 1710 */ 1711 static void 1712 target_if_init_spectral_ops_gen2(void) 1713 { 1714 struct target_if_spectral_ops *p_sops = &spectral_ops; 1715 1716 p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2; 1717 } 1718 1719 /** 1720 * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal 1721 * operations specific to Spectral chipset generation 3. 1722 * 1723 * Initializes target_if_spectral_ops specific to Spectral chipset generation 3. 1724 * 1725 * Return: None 1726 */ 1727 static void 1728 target_if_init_spectral_ops_gen3(void) 1729 { 1730 struct target_if_spectral_ops *p_sops = &spectral_ops; 1731 1732 p_sops->process_spectral_report = 1733 target_if_spectral_process_report_gen3; 1734 return; 1735 } 1736 1737 /** 1738 * target_if_init_spectral_ops() - Initialize target_if internal Spectral 1739 * operations. 1740 * @spectral: Pointer to Spectral target_if internal private data 1741 * 1742 * Initializes all function pointers in target_if_spectral_ops for 1743 * all generations 1744 * 1745 * Return: None 1746 */ 1747 static void 1748 target_if_init_spectral_ops(struct target_if_spectral *spectral) 1749 { 1750 target_if_init_spectral_ops_common(); 1751 if (spectral->spectral_gen == SPECTRAL_GEN2) 1752 target_if_init_spectral_ops_gen2(); 1753 else if (spectral->spectral_gen == SPECTRAL_GEN3) 1754 target_if_init_spectral_ops_gen3(); 1755 else 1756 spectral_err("Invalid Spectral generation"); 1757 } 1758 1759 /* 1760 * Dummy Functions: 1761 * These functions are initially registered to avoid any crashes due to 1762 * invocation of spectral functions before they are registered. 1763 */ 1764 1765 static uint64_t 1766 null_get_tsf64(void *arg) 1767 { 1768 spectral_ops_not_registered("get_tsf64"); 1769 return 0; 1770 } 1771 1772 static uint32_t 1773 null_get_capability(void *arg, enum spectral_capability_type type) 1774 { 1775 /* 1776 * TODO : We should have conditional compilation to get the capability 1777 * : We have not yet attahced ATH layer here, so there is no 1778 * : way to check the HAL capbalities 1779 */ 1780 spectral_ops_not_registered("get_capability"); 1781 1782 /* TODO : For the time being, we are returning TRUE */ 1783 return true; 1784 } 1785 1786 static uint32_t 1787 null_set_rxfilter(void *arg, int rxfilter) 1788 { 1789 spectral_ops_not_registered("set_rxfilter"); 1790 return 1; 1791 } 1792 1793 static uint32_t 1794 null_get_rxfilter(void *arg) 1795 { 1796 spectral_ops_not_registered("get_rxfilter"); 1797 return 0; 1798 } 1799 1800 static uint32_t 1801 null_is_spectral_active(void *arg, enum spectral_scan_mode smode) 1802 { 1803 spectral_ops_not_registered("is_spectral_active"); 1804 return 1; 1805 } 1806 1807 static uint32_t 1808 null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode) 1809 { 1810 spectral_ops_not_registered("is_spectral_enabled"); 1811 return 1; 1812 } 1813 1814 static uint32_t 1815 null_start_spectral_scan(void *arg, enum spectral_scan_mode smode, 1816 enum spectral_cp_error_code *err) 1817 { 1818 spectral_ops_not_registered("start_spectral_scan"); 1819 return 1; 1820 } 1821 1822 static uint32_t 1823 null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode) 1824 { 1825 spectral_ops_not_registered("stop_spectral_scan"); 1826 return 1; 1827 } 1828 1829 static uint32_t 1830 null_get_extension_channel(void *arg, enum spectral_scan_mode smode) 1831 { 1832 spectral_ops_not_registered("get_extension_channel"); 1833 return 1; 1834 } 1835 1836 static int8_t 1837 null_get_ctl_noisefloor(void *arg) 1838 { 1839 spectral_ops_not_registered("get_ctl_noisefloor"); 1840 return 1; 1841 } 1842 1843 static int8_t 1844 null_get_ext_noisefloor(void *arg) 1845 { 1846 spectral_ops_not_registered("get_ext_noisefloor"); 1847 return 0; 1848 } 1849 1850 static uint32_t 1851 null_configure_spectral(void *arg, struct spectral_config *params, 1852 enum spectral_scan_mode smode) 1853 { 1854 spectral_ops_not_registered("configure_spectral"); 1855 return 0; 1856 } 1857 1858 static uint32_t 1859 null_get_spectral_config(void *arg, struct spectral_config *params, 1860 enum spectral_scan_mode smode) 1861 { 1862 spectral_ops_not_registered("get_spectral_config"); 1863 return 0; 1864 } 1865 1866 static uint32_t 1867 null_get_ent_spectral_mask(void *arg) 1868 { 1869 spectral_ops_not_registered("get_ent_spectral_mask"); 1870 return 0; 1871 } 1872 1873 static uint32_t 1874 null_get_mac_address(void *arg, char *addr) 1875 { 1876 spectral_ops_not_registered("get_mac_address"); 1877 return 0; 1878 } 1879 1880 static uint32_t 1881 null_get_current_channel(void *arg, enum spectral_scan_mode smode) 1882 { 1883 spectral_ops_not_registered("get_current_channel"); 1884 return 0; 1885 } 1886 1887 static uint32_t 1888 null_reset_hw(void *arg) 1889 { 1890 spectral_ops_not_registered("get_current_channel"); 1891 return 0; 1892 } 1893 1894 static uint32_t 1895 null_get_chain_noise_floor(void *arg, int16_t *nf_buf) 1896 { 1897 spectral_ops_not_registered("get_chain_noise_floor"); 1898 return 0; 1899 } 1900 1901 static int 1902 null_spectral_process_phyerr(struct target_if_spectral *spectral, 1903 uint8_t *data, 1904 uint32_t datalen, 1905 struct target_if_spectral_rfqual_info *p_rfqual, 1906 struct target_if_spectral_chan_info *p_chaninfo, 1907 uint64_t tsf64, 1908 struct target_if_spectral_acs_stats *acs_stats) 1909 { 1910 spectral_ops_not_registered("spectral_process_phyerr"); 1911 return 0; 1912 } 1913 1914 static int 1915 null_process_spectral_report(struct wlan_objmgr_pdev *pdev, 1916 void *payload) 1917 { 1918 spectral_ops_not_registered("process_spectral_report"); 1919 return 0; 1920 } 1921 /** 1922 * target_if_spectral_init_dummy_function_table() - 1923 * Initialize target_if internal 1924 * Spectral operations to dummy functions 1925 * @ps: Pointer to Spectral target_if internal private data 1926 * 1927 * Initialize all the function pointers in target_if_spectral_ops with 1928 * dummy functions. 1929 * 1930 * Return: None 1931 */ 1932 static void 1933 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps) 1934 { 1935 struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps); 1936 1937 p_sops->get_tsf64 = null_get_tsf64; 1938 p_sops->get_capability = null_get_capability; 1939 p_sops->set_rxfilter = null_set_rxfilter; 1940 p_sops->get_rxfilter = null_get_rxfilter; 1941 p_sops->is_spectral_enabled = null_is_spectral_enabled; 1942 p_sops->is_spectral_active = null_is_spectral_active; 1943 p_sops->start_spectral_scan = null_start_spectral_scan; 1944 p_sops->stop_spectral_scan = null_stop_spectral_scan; 1945 p_sops->get_extension_channel = null_get_extension_channel; 1946 p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor; 1947 p_sops->get_ext_noisefloor = null_get_ext_noisefloor; 1948 p_sops->configure_spectral = null_configure_spectral; 1949 p_sops->get_spectral_config = null_get_spectral_config; 1950 p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask; 1951 p_sops->get_mac_address = null_get_mac_address; 1952 p_sops->get_current_channel = null_get_current_channel; 1953 p_sops->reset_hw = null_reset_hw; 1954 p_sops->get_chain_noise_floor = null_get_chain_noise_floor; 1955 p_sops->spectral_process_phyerr = null_spectral_process_phyerr; 1956 p_sops->process_spectral_report = null_process_spectral_report; 1957 } 1958 1959 /** 1960 * target_if_spectral_register_funcs() - Initialize target_if internal Spectral 1961 * operations 1962 * @spectral: Pointer to Spectral target_if internal private data 1963 * @p: Pointer to Spectral function table 1964 * 1965 * Return: None 1966 */ 1967 static void 1968 target_if_spectral_register_funcs(struct target_if_spectral *spectral, 1969 struct target_if_spectral_ops *p) 1970 { 1971 struct target_if_spectral_ops *p_sops = 1972 GET_TARGET_IF_SPECTRAL_OPS(spectral); 1973 1974 p_sops->get_tsf64 = p->get_tsf64; 1975 p_sops->get_capability = p->get_capability; 1976 p_sops->set_rxfilter = p->set_rxfilter; 1977 p_sops->get_rxfilter = p->get_rxfilter; 1978 p_sops->is_spectral_enabled = p->is_spectral_enabled; 1979 p_sops->is_spectral_active = p->is_spectral_active; 1980 p_sops->start_spectral_scan = p->start_spectral_scan; 1981 p_sops->stop_spectral_scan = p->stop_spectral_scan; 1982 p_sops->get_extension_channel = p->get_extension_channel; 1983 p_sops->get_ctl_noisefloor = p->get_ctl_noisefloor; 1984 p_sops->get_ext_noisefloor = p->get_ext_noisefloor; 1985 p_sops->configure_spectral = p->configure_spectral; 1986 p_sops->get_spectral_config = p->get_spectral_config; 1987 p_sops->get_ent_spectral_mask = p->get_ent_spectral_mask; 1988 p_sops->get_mac_address = p->get_mac_address; 1989 p_sops->get_current_channel = p->get_current_channel; 1990 p_sops->reset_hw = p->reset_hw; 1991 p_sops->get_chain_noise_floor = p->get_chain_noise_floor; 1992 p_sops->spectral_process_phyerr = p->spectral_process_phyerr; 1993 p_sops->process_spectral_report = p->process_spectral_report; 1994 } 1995 1996 /** 1997 * target_if_spectral_clear_stats() - Clear Spectral stats 1998 * @spectral: Pointer to Spectral target_if internal private data 1999 * 2000 * Function to clear spectral stats 2001 * 2002 * Return: None 2003 */ 2004 static void 2005 target_if_spectral_clear_stats(struct target_if_spectral *spectral) 2006 { 2007 struct target_if_spectral_ops *p_sops = 2008 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2009 2010 qdf_mem_zero(&spectral->spectral_stats, 2011 sizeof(struct target_if_spectral_stats)); 2012 spectral->spectral_stats.last_reset_tstamp = 2013 p_sops->get_tsf64(spectral); 2014 } 2015 2016 /** 2017 * target_if_spectral_check_hw_capability() - Check whether HW supports spectral 2018 * @spectral: Pointer to Spectral target_if internal private data 2019 * 2020 * Function to check whether hardware supports spectral 2021 * 2022 * Return: True if HW supports Spectral, false if HW does not support Spectral 2023 */ 2024 static int 2025 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral) 2026 { 2027 struct target_if_spectral_ops *p_sops = NULL; 2028 struct spectral_caps *pcap = NULL; 2029 int is_spectral_supported = true; 2030 2031 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2032 pcap = &spectral->capability; 2033 2034 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) { 2035 is_spectral_supported = false; 2036 spectral_info("SPECTRAL : No PHYDIAG support"); 2037 return is_spectral_supported; 2038 } 2039 pcap->phydiag_cap = 1; 2040 2041 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) { 2042 is_spectral_supported = false; 2043 spectral_info("SPECTRAL : No RADAR support"); 2044 return is_spectral_supported; 2045 } 2046 pcap->radar_cap = 1; 2047 2048 if (p_sops->get_capability(spectral, 2049 SPECTRAL_CAP_SPECTRAL_SCAN) == false) { 2050 is_spectral_supported = false; 2051 spectral_info("SPECTRAL : No SPECTRAL SUPPORT"); 2052 return is_spectral_supported; 2053 } 2054 pcap->spectral_cap = 1; 2055 2056 if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN) 2057 == false) { 2058 spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT"); 2059 } else { 2060 pcap->advncd_spectral_cap = 1; 2061 } 2062 2063 return is_spectral_supported; 2064 } 2065 2066 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 2067 /** 2068 * target_if_spectral_detach_simulation() - De-initialize Spectral 2069 * Simulation functionality 2070 * @spectral: Pointer to Spectral target_if internal private data 2071 * 2072 * Function to de-initialize Spectral Simulation functionality 2073 * 2074 * Return: None 2075 */ 2076 static void 2077 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 2078 { 2079 target_if_spectral_sim_detach(spectral); 2080 } 2081 2082 #else 2083 static void 2084 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 2085 { 2086 } 2087 #endif 2088 2089 /** 2090 * target_if_spectral_detach() - De-initialize target_if Spectral 2091 * @pdev: Pointer to pdev object 2092 * 2093 * Function to detach target_if spectral 2094 * 2095 * Return: None 2096 */ 2097 static void 2098 target_if_spectral_detach(struct target_if_spectral *spectral) 2099 { 2100 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2101 spectral_info("spectral detach"); 2102 2103 if (spectral) { 2104 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 2105 qdf_spinlock_destroy 2106 (&spectral->param_info[smode].osps_lock); 2107 2108 target_if_spectral_detach_simulation(spectral); 2109 2110 qdf_spinlock_destroy(&spectral->spectral_lock); 2111 qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock); 2112 2113 qdf_mem_free(spectral); 2114 spectral = NULL; 2115 } 2116 } 2117 2118 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 2119 /** 2120 * target_if_spectral_attach_simulation() - Initialize Spectral Simulation 2121 * functionality 2122 * @spectral: Pointer to Spectral target_if internal private data 2123 * 2124 * Function to initialize spectral simulation functionality 2125 * 2126 * Return: 0 on success, negative error code on failure 2127 */ 2128 static int 2129 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 2130 { 2131 if (target_if_spectral_sim_attach(spectral)) { 2132 qdf_mem_free(spectral); 2133 return -EPERM; 2134 } 2135 return 0; 2136 } 2137 2138 #else 2139 static int 2140 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 2141 { 2142 return 0; 2143 } 2144 #endif 2145 2146 /** 2147 * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment 2148 * related info 2149 * @swar: Pointer to Spectral FFT bin length adjustment SWAR params 2150 * @target_type: Target type 2151 * 2152 * Function to Initialize parameters related to Spectral FFT bin 2153 * length adjustment SWARs. 2154 * 2155 * Return: void 2156 */ 2157 static void 2158 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar, 2159 uint32_t target_type) 2160 { 2161 if (target_type == TARGET_TYPE_QCA8074V2 || 2162 target_type == TARGET_TYPE_QCN9000 || 2163 target_type == TARGET_TYPE_QCN9100 || 2164 target_type == TARGET_TYPE_QCA5018 || 2165 target_type == TARGET_TYPE_QCA6750 || 2166 target_type == TARGET_TYPE_QCA6490) 2167 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; 2168 else if (target_type == TARGET_TYPE_QCA8074 || 2169 target_type == TARGET_TYPE_QCA6018 || 2170 target_type == TARGET_TYPE_QCA6390) 2171 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; 2172 else 2173 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; 2174 2175 if (target_type == TARGET_TYPE_QCA8074 || 2176 target_type == TARGET_TYPE_QCA8074V2 || 2177 target_type == TARGET_TYPE_QCA6018 || 2178 target_type == TARGET_TYPE_QCN9100 || 2179 target_type == TARGET_TYPE_QCA5018 || 2180 target_type == TARGET_TYPE_QCN9000 || 2181 target_type == TARGET_TYPE_QCA6490) { 2182 swar->inband_fftbin_size_adj = 1; 2183 swar->null_fftbin_adj = 1; 2184 } else { 2185 swar->inband_fftbin_size_adj = 0; 2186 swar->null_fftbin_adj = 0; 2187 } 2188 2189 if ((target_type == TARGET_TYPE_QCA8074V2) || 2190 (target_type == TARGET_TYPE_QCN9100)) 2191 swar->packmode_fftbin_size_adj = 1; 2192 else 2193 swar->packmode_fftbin_size_adj = 0; 2194 } 2195 2196 /** 2197 * target_if_spectral_report_params_init() - Initialize parameters which 2198 * describes the structure of Spectral reports 2199 * 2200 * @rparams: Pointer to Spectral report parameter object 2201 * @target_type: target type 2202 * 2203 * Function to Initialize parameters related to the structure of Spectral 2204 * reports. 2205 * 2206 * Return: void 2207 */ 2208 static void 2209 target_if_spectral_report_params_init( 2210 struct spectral_report_params *rparams, 2211 uint32_t target_type) 2212 { 2213 enum spectral_scan_mode smode; 2214 2215 /* This entries are currently used by gen3 chipsets only. Hence 2216 * initialization is done for gen3 alone. In future if other generations 2217 * needs to use them they have to add proper initial values. 2218 */ 2219 if (target_type == TARGET_TYPE_QCN9000 || 2220 target_type == TARGET_TYPE_QCA5018 || 2221 target_type == TARGET_TYPE_QCA6750 || 2222 target_type == TARGET_TYPE_QCA6490) { 2223 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2; 2224 rparams->num_spectral_detectors = 2225 NUM_SPECTRAL_DETECTORS_GEN3_V2; 2226 smode = SPECTRAL_SCAN_MODE_NORMAL; 2227 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 2228 rparams->fragmentation_160[smode] = false; 2229 rparams->max_agile_ch_width = CH_WIDTH_80P80MHZ; 2230 } else { 2231 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1; 2232 rparams->num_spectral_detectors = 2233 NUM_SPECTRAL_DETECTORS_GEN3_V1; 2234 smode = SPECTRAL_SCAN_MODE_NORMAL; 2235 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 2236 rparams->fragmentation_160[smode] = true; 2237 rparams->max_agile_ch_width = CH_WIDTH_80MHZ; 2238 } 2239 2240 switch (rparams->version) { 2241 case SPECTRAL_REPORT_FORMAT_VERSION_1: 2242 rparams->ssumaary_padding_bytes = 2243 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1; 2244 rparams->fft_report_hdr_len = 2245 FFT_REPORT_HEADER_LENGTH_GEN3_V1; 2246 break; 2247 case SPECTRAL_REPORT_FORMAT_VERSION_2: 2248 rparams->ssumaary_padding_bytes = 2249 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2; 2250 rparams->fft_report_hdr_len = 2251 FFT_REPORT_HEADER_LENGTH_GEN3_V2; 2252 break; 2253 default: 2254 qdf_assert_always(0); 2255 } 2256 2257 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] = 2258 SPECTRAL_SCAN_MODE_NORMAL; 2259 if (target_type == TARGET_TYPE_QCN9000 || 2260 target_type == TARGET_TYPE_QCA6490) { 2261 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 2262 SPECTRAL_SCAN_MODE_AGILE; 2263 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 2264 SPECTRAL_SCAN_MODE_INVALID; 2265 } else { 2266 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 2267 SPECTRAL_SCAN_MODE_NORMAL; 2268 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 2269 SPECTRAL_SCAN_MODE_AGILE; 2270 } 2271 } 2272 2273 /** 2274 * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR 2275 * related info 2276 * @twar: Pointer to Spectral timstamp WAR related info 2277 * 2278 * Function to Initialize parameters related to Spectral timestamp WAR 2279 * 2280 * Return: void 2281 */ 2282 static void 2283 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar) 2284 { 2285 enum spectral_scan_mode smode; 2286 2287 smode = SPECTRAL_SCAN_MODE_NORMAL; 2288 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2289 twar->last_fft_timestamp[smode] = 0; 2290 twar->timestamp_war_offset[smode] = 0; 2291 } 2292 twar->target_reset_count = 0; 2293 } 2294 2295 /** 2296 * target_if_pdev_spectral_init() - Initialize target_if Spectral 2297 * functionality for the given pdev 2298 * @pdev: Pointer to pdev object 2299 * 2300 * Function to initialize pointer to spectral target_if internal private data 2301 * 2302 * Return: On success, pointer to Spectral target_if internal private data, on 2303 * failure, NULL 2304 */ 2305 void * 2306 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 2307 { 2308 struct target_if_spectral_ops *p_sops = NULL; 2309 struct target_if_spectral *spectral = NULL; 2310 uint32_t target_type; 2311 uint32_t target_revision; 2312 struct wlan_objmgr_psoc *psoc; 2313 struct wlan_lmac_if_target_tx_ops *tgt_tx_ops; 2314 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2315 QDF_STATUS status; 2316 struct wlan_lmac_if_tx_ops *tx_ops; 2317 2318 if (!pdev) { 2319 spectral_err("SPECTRAL: pdev is NULL!"); 2320 return NULL; 2321 } 2322 spectral = (struct target_if_spectral *)qdf_mem_malloc( 2323 sizeof(struct target_if_spectral)); 2324 if (!spectral) 2325 return spectral; 2326 2327 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 2328 /* Store pdev in Spectral */ 2329 spectral->pdev_obj = pdev; 2330 spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID; 2331 spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID; 2332 2333 psoc = wlan_pdev_get_psoc(pdev); 2334 2335 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 2336 if (!tx_ops) { 2337 spectral_err("tx_ops is NULL"); 2338 qdf_mem_free(spectral); 2339 return NULL; 2340 } 2341 2342 tgt_tx_ops = &tx_ops->target_tx_ops; 2343 2344 if (tgt_tx_ops->tgt_get_tgt_type) { 2345 target_type = tgt_tx_ops->tgt_get_tgt_type(psoc); 2346 } else { 2347 qdf_mem_free(spectral); 2348 return NULL; 2349 } 2350 2351 if (tgt_tx_ops->tgt_get_tgt_revision) { 2352 target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc); 2353 } else { 2354 qdf_mem_free(spectral); 2355 return NULL; 2356 } 2357 2358 /* init the function ptr table */ 2359 target_if_spectral_init_dummy_function_table(spectral); 2360 2361 /* get spectral function table */ 2362 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2363 /* TODO : Should this be called here of after ath_attach ? */ 2364 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 2365 spectral_info("HAL_CAP_PHYDIAG : Capable"); 2366 2367 /* TODO: Need to fix the capablity check for RADAR */ 2368 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 2369 spectral_info("HAL_CAP_RADAR : Capable"); 2370 2371 /* TODO : Need to fix the capablity check for SPECTRAL */ 2372 /* TODO : Should this be called here of after ath_attach ? */ 2373 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 2374 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 2375 2376 qdf_spinlock_create(&spectral->spectral_lock); 2377 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 2378 target_if_spectral_clear_stats(spectral); 2379 2380 if (target_type == TARGET_TYPE_QCA8074 || 2381 target_type == TARGET_TYPE_QCA8074V2 || 2382 target_type == TARGET_TYPE_QCA6018 || 2383 target_type == TARGET_TYPE_QCA5018 || 2384 target_type == TARGET_TYPE_QCA6390 || 2385 target_type == TARGET_TYPE_QCN9100 || 2386 target_type == TARGET_TYPE_QCA6490 || 2387 target_type == TARGET_TYPE_QCN9000 || 2388 target_type == TARGET_TYPE_QCA6750) 2389 spectral->direct_dma_support = true; 2390 2391 target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar, 2392 target_type); 2393 target_if_spectral_report_params_init(&spectral->rparams, target_type); 2394 2395 if ((target_type == TARGET_TYPE_QCA8074) || 2396 (target_type == TARGET_TYPE_QCA8074V2) || 2397 (target_type == TARGET_TYPE_QCA6018) || 2398 (target_type == TARGET_TYPE_QCA5018) || 2399 (target_type == TARGET_TYPE_QCN9100) || 2400 (target_type == TARGET_TYPE_QCN9000) || 2401 (target_type == TARGET_TYPE_QCA6290) || 2402 (target_type == TARGET_TYPE_QCA6390) || 2403 (target_type == TARGET_TYPE_QCA6490) || 2404 (target_type == TARGET_TYPE_QCA6750)) { 2405 spectral->spectral_gen = SPECTRAL_GEN3; 2406 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 2407 spectral->tag_sscan_summary_exp = 2408 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 2409 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 2410 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 2411 } else { 2412 spectral->spectral_gen = SPECTRAL_GEN2; 2413 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 2414 spectral->tag_sscan_summary_exp = 2415 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 2416 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 2417 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 2418 } 2419 2420 status = target_if_init_spectral_param_min_max( 2421 &spectral->param_min_max, 2422 spectral->spectral_gen, target_type); 2423 if (QDF_IS_STATUS_ERROR(status)) { 2424 spectral_err("Failed to initialize parameter min max values"); 2425 goto fail; 2426 } 2427 2428 target_if_init_spectral_param_properties(spectral); 2429 /* Init spectral capability */ 2430 if (target_if_init_spectral_capability(spectral, target_type) != 2431 QDF_STATUS_SUCCESS) { 2432 qdf_mem_free(spectral); 2433 return NULL; 2434 } 2435 if (target_if_spectral_attach_simulation(spectral) < 0) 2436 return NULL; 2437 2438 target_if_init_spectral_ops(spectral); 2439 target_if_spectral_timestamp_war_init(&spectral->timestamp_war); 2440 2441 /* Spectral mode specific init */ 2442 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2443 spectral->params_valid[smode] = false; 2444 qdf_spinlock_create(&spectral->param_info[smode].osps_lock); 2445 spectral->param_info[smode].osps_cache.osc_is_valid = 0; 2446 } 2447 2448 target_if_spectral_register_funcs(spectral, &spectral_ops); 2449 2450 if (target_if_spectral_check_hw_capability(spectral) == false) { 2451 goto fail; 2452 } else { 2453 /* 2454 * TODO: Once the driver architecture transitions to chipset 2455 * versioning based checks, reflect this here. 2456 */ 2457 spectral->is_160_format = false; 2458 spectral->is_lb_edge_extrabins_format = false; 2459 spectral->is_rb_edge_extrabins_format = false; 2460 2461 if (target_type == TARGET_TYPE_QCA9984 || 2462 target_type == TARGET_TYPE_QCA9888) { 2463 spectral->is_160_format = true; 2464 spectral->is_lb_edge_extrabins_format = true; 2465 spectral->is_rb_edge_extrabins_format = true; 2466 } else if ((target_type == TARGET_TYPE_AR900B) && 2467 (target_revision == AR900B_REV_2)) { 2468 spectral->is_rb_edge_extrabins_format = true; 2469 } 2470 2471 if (target_type == TARGET_TYPE_QCA9984 || 2472 target_type == TARGET_TYPE_QCA9888) 2473 spectral->is_sec80_rssi_war_required = true; 2474 2475 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST; 2476 2477 if (spectral->spectral_gen == SPECTRAL_GEN3) 2478 init_160mhz_delivery_state_machine(spectral); 2479 } 2480 2481 return spectral; 2482 2483 fail: 2484 target_if_spectral_detach(spectral); 2485 return NULL; 2486 } 2487 2488 /** 2489 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 2490 * functionality for the given pdev 2491 * @pdev: Pointer to pdev object 2492 * 2493 * Function to de-initialize pointer to spectral target_if internal private data 2494 * 2495 * Return: None 2496 */ 2497 void 2498 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 2499 { 2500 struct target_if_spectral *spectral = NULL; 2501 2502 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2503 if (!spectral) { 2504 spectral_err("SPECTRAL : Module doesn't exist"); 2505 return; 2506 } 2507 target_if_spectral_detach(spectral); 2508 2509 return; 2510 } 2511 2512 /** 2513 * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral 2514 * functionality for the given psoc 2515 * @psoc: Pointer to psoc object 2516 * 2517 * Function to de-initialize pointer to psoc spectral target_if internal 2518 * private data 2519 * 2520 * Return: None 2521 */ 2522 static void 2523 target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc) 2524 { 2525 struct target_if_psoc_spectral *psoc_spectral; 2526 2527 if (!psoc) { 2528 spectral_err("psoc is null"); 2529 return; 2530 } 2531 2532 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 2533 if (!psoc_spectral) { 2534 spectral_err("Spectral target_if psoc object is null"); 2535 return; 2536 } 2537 2538 qdf_mem_free(psoc_spectral); 2539 } 2540 2541 /** 2542 * target_if_psoc_spectral_init() - Initialize target_if Spectral 2543 * functionality for the given psoc 2544 * @psoc: Pointer to psoc object 2545 * 2546 * Function to initialize pointer to psoc spectral target_if internal 2547 * private data 2548 * 2549 * Return: On success, pointer to Spectral psoc target_if internal 2550 * private data, on failure, NULL 2551 */ 2552 static void * 2553 target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc) 2554 { 2555 struct target_if_psoc_spectral *psoc_spectral = NULL; 2556 2557 if (!psoc) { 2558 spectral_err("psoc is null"); 2559 goto fail; 2560 } 2561 2562 psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc( 2563 sizeof(struct target_if_psoc_spectral)); 2564 if (!psoc_spectral) { 2565 spectral_err("Spectral lmac psoc object allocation failed"); 2566 goto fail; 2567 } 2568 2569 psoc_spectral->psoc_obj = psoc; 2570 2571 return psoc_spectral; 2572 2573 fail: 2574 if (psoc_spectral) 2575 target_if_psoc_spectral_deinit(psoc); 2576 2577 return psoc_spectral; 2578 } 2579 2580 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the 2581 * corresponding translation for Agile channel width. 2582 * @spectral: pointer to Spectral object 2583 * @chwidth: operating channel width 2584 * @is_80_80_agile: Indicates an 80+80 agile Scan request 2585 * 2586 * Return: The translated channel width enum. 2587 */ 2588 static enum phy_ch_width 2589 target_if_spectral_find_agile_width(struct target_if_spectral *spectral, 2590 enum phy_ch_width chwidth, 2591 bool is_80_80_agile) 2592 { 2593 enum phy_ch_width agile_width; 2594 struct wlan_objmgr_pdev *pdev; 2595 struct wlan_objmgr_psoc *psoc; 2596 2597 if (!spectral) { 2598 spectral_err("Spectral object is null"); 2599 return CH_WIDTH_INVALID; 2600 } 2601 2602 pdev = spectral->pdev_obj; 2603 if (!pdev) { 2604 spectral_err("pdev is null"); 2605 return CH_WIDTH_INVALID; 2606 } 2607 2608 psoc = wlan_pdev_get_psoc(pdev); 2609 if (!psoc) { 2610 spectral_err("psoc is null"); 2611 return CH_WIDTH_INVALID; 2612 } 2613 2614 switch (chwidth) { 2615 case CH_WIDTH_20MHZ: 2616 agile_width = CH_WIDTH_20MHZ; 2617 break; 2618 2619 case CH_WIDTH_40MHZ: 2620 agile_width = CH_WIDTH_40MHZ; 2621 break; 2622 2623 case CH_WIDTH_80MHZ: 2624 agile_width = CH_WIDTH_80MHZ; 2625 break; 2626 2627 case CH_WIDTH_80P80MHZ: 2628 if (wlan_psoc_nif_fw_ext_cap_get(psoc, 2629 WLAN_SOC_RESTRICTED_80P80_SUPPORT) && !is_80_80_agile) 2630 agile_width = CH_WIDTH_160MHZ; 2631 else 2632 agile_width = CH_WIDTH_80P80MHZ; 2633 2634 if (agile_width > spectral->rparams.max_agile_ch_width) 2635 agile_width = spectral->rparams.max_agile_ch_width; 2636 break; 2637 2638 case CH_WIDTH_160MHZ: 2639 if (wlan_psoc_nif_fw_ext_cap_get(psoc, 2640 WLAN_SOC_RESTRICTED_80P80_SUPPORT) && is_80_80_agile) 2641 agile_width = CH_WIDTH_80P80MHZ; 2642 else 2643 agile_width = CH_WIDTH_160MHZ; 2644 2645 if (agile_width > spectral->rparams.max_agile_ch_width) 2646 agile_width = spectral->rparams.max_agile_ch_width; 2647 break; 2648 2649 default: 2650 spectral_err("Invalid channel width %d", chwidth); 2651 agile_width = CH_WIDTH_INVALID; 2652 break; 2653 } 2654 2655 return agile_width; 2656 } 2657 2658 /** 2659 * target_if_calculate_center_freq() - Helper routine to 2660 * check whether given frequency is center frequency of a 2661 * WLAN channel 2662 * 2663 * @spectral: Pointer to Spectral object 2664 * @chan_freq: Center frequency of a WLAN channel 2665 * @is_valid: Indicates whether given frequency is valid 2666 * 2667 * Return: QDF_STATUS 2668 */ 2669 static QDF_STATUS 2670 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, 2671 uint32_t chan_freq, 2672 bool *is_valid) 2673 { 2674 struct regulatory_channel *cur_chan_list; 2675 int i; 2676 2677 if (!pdev) { 2678 spectral_err("pdev object is null"); 2679 return QDF_STATUS_E_FAILURE; 2680 } 2681 2682 if (!is_valid) { 2683 spectral_err("is valid argument is null"); 2684 return QDF_STATUS_E_FAILURE; 2685 } 2686 2687 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); 2688 if (!cur_chan_list) 2689 return QDF_STATUS_E_FAILURE; 2690 2691 if (wlan_reg_get_current_chan_list( 2692 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 2693 spectral_err("Failed to get cur_chan list"); 2694 qdf_mem_free(cur_chan_list); 2695 return QDF_STATUS_E_FAILURE; 2696 } 2697 2698 *is_valid = false; 2699 for (i = 0; i < NUM_CHANNELS; i++) { 2700 uint32_t flags; 2701 uint32_t center_freq; 2702 2703 flags = cur_chan_list[i].chan_flags; 2704 center_freq = cur_chan_list[i].center_freq; 2705 2706 if (!(flags & REGULATORY_CHAN_DISABLED) && 2707 (center_freq == chan_freq)) { 2708 *is_valid = true; 2709 break; 2710 } 2711 } 2712 2713 qdf_mem_free(cur_chan_list); 2714 2715 return QDF_STATUS_SUCCESS; 2716 } 2717 2718 /** 2719 * target_if_calculate_center_freq() - Helper routine to 2720 * find the center frequency of the agile span from a 2721 * WLAN channel center frequency 2722 * 2723 * @spectral: Pointer to Spectral object 2724 * @ch_width: Channel width array 2725 * @chan_freq: Center frequency of a WLAN channel 2726 * @center_freq: Pointer to center frequency 2727 * 2728 * Return: QDF_STATUS 2729 */ 2730 static QDF_STATUS 2731 target_if_calculate_center_freq(struct target_if_spectral *spectral, 2732 enum phy_ch_width *ch_width, 2733 uint16_t chan_freq, 2734 uint16_t *center_freq) 2735 { 2736 enum phy_ch_width agile_ch_width; 2737 2738 if (!spectral) { 2739 spectral_err("spectral target if object is null"); 2740 return QDF_STATUS_E_FAILURE; 2741 } 2742 2743 if (!ch_width) { 2744 spectral_err("Channel width array is null"); 2745 return QDF_STATUS_E_INVAL; 2746 } 2747 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 2748 2749 if (!center_freq) { 2750 spectral_err("center_freq argument is null"); 2751 return QDF_STATUS_E_FAILURE; 2752 } 2753 2754 if (agile_ch_width == CH_WIDTH_20MHZ) { 2755 *center_freq = chan_freq; 2756 } else { 2757 uint16_t start_freq; 2758 uint16_t end_freq; 2759 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2760 enum channel_state state; 2761 2762 state = wlan_reg_get_5g_bonded_channel_and_state_for_freq 2763 (spectral->pdev_obj, chan_freq, agile_ch_width, 2764 &bonded_chan_ptr); 2765 if (state == CHANNEL_STATE_DISABLE || 2766 state == CHANNEL_STATE_INVALID) { 2767 spectral_err("Channel state is disable or invalid"); 2768 return QDF_STATUS_E_FAILURE; 2769 } 2770 if (!bonded_chan_ptr) { 2771 spectral_err("Bonded channel is not found"); 2772 return QDF_STATUS_E_FAILURE; 2773 } 2774 start_freq = bonded_chan_ptr->start_freq; 2775 end_freq = bonded_chan_ptr->end_freq; 2776 *center_freq = (start_freq + end_freq) >> 1; 2777 } 2778 2779 return QDF_STATUS_SUCCESS; 2780 } 2781 2782 /** 2783 * target_if_validate_center_freq() - Helper routine to 2784 * validate user provided agile center frequency 2785 * 2786 * @spectral: Pointer to Spectral object 2787 * @ch_width: Channel width array 2788 * @center_freq: User provided agile span center frequency 2789 * @is_valid: Indicates whether agile span center frequency is valid 2790 * 2791 * Return: QDF_STATUS 2792 */ 2793 static QDF_STATUS 2794 target_if_validate_center_freq(struct target_if_spectral *spectral, 2795 enum phy_ch_width *ch_width, 2796 uint16_t center_freq, 2797 bool *is_valid) 2798 { 2799 enum phy_ch_width agile_ch_width; 2800 struct wlan_objmgr_pdev *pdev; 2801 QDF_STATUS status; 2802 2803 if (!spectral) { 2804 spectral_err("spectral target if object is null"); 2805 return QDF_STATUS_E_FAILURE; 2806 } 2807 2808 if (!ch_width) { 2809 spectral_err("channel width array is null"); 2810 return QDF_STATUS_E_INVAL; 2811 } 2812 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 2813 2814 if (!is_valid) { 2815 spectral_err("is_valid argument is null"); 2816 return QDF_STATUS_E_FAILURE; 2817 } 2818 2819 pdev = spectral->pdev_obj; 2820 2821 if (agile_ch_width == CH_WIDTH_20MHZ) { 2822 status = target_if_is_center_freq_of_any_chan 2823 (pdev, center_freq, is_valid); 2824 if (QDF_IS_STATUS_ERROR(status)) 2825 return QDF_STATUS_E_FAILURE; 2826 } else { 2827 uint16_t start_freq; 2828 uint16_t end_freq; 2829 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2830 bool is_chan; 2831 2832 status = target_if_is_center_freq_of_any_chan 2833 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2834 &is_chan); 2835 if (QDF_IS_STATUS_ERROR(status)) 2836 return QDF_STATUS_E_FAILURE; 2837 2838 if (is_chan) { 2839 uint32_t calulated_center_freq; 2840 enum channel_state st; 2841 2842 st = wlan_reg_get_5g_bonded_channel_and_state_for_freq 2843 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2844 agile_ch_width, 2845 &bonded_chan_ptr); 2846 if (st == CHANNEL_STATE_DISABLE || 2847 st == CHANNEL_STATE_INVALID) { 2848 spectral_err("Channel state disable/invalid"); 2849 return QDF_STATUS_E_FAILURE; 2850 } 2851 if (!bonded_chan_ptr) { 2852 spectral_err("Bonded channel is not found"); 2853 return QDF_STATUS_E_FAILURE; 2854 } 2855 start_freq = bonded_chan_ptr->start_freq; 2856 end_freq = bonded_chan_ptr->end_freq; 2857 calulated_center_freq = (start_freq + end_freq) >> 1; 2858 *is_valid = (center_freq == calulated_center_freq); 2859 } else { 2860 *is_valid = false; 2861 } 2862 } 2863 2864 return QDF_STATUS_SUCCESS; 2865 } 2866 2867 /** 2868 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to 2869 * check whether agile span overlaps with current operating band. 2870 * 2871 * @spectral: Pointer to Spectral object 2872 * @ch_width: Channel width array 2873 * @center_freq: Agile span center frequency 2874 * @is_overlapping: Indicates whether Agile span overlaps with operating span 2875 * 2876 * Helper routine to check whether agile span overlaps with current 2877 * operating band. 2878 * 2879 * Return: QDF_STATUS 2880 */ 2881 static QDF_STATUS 2882 target_if_is_agile_span_overlap_with_operating_span 2883 (struct target_if_spectral *spectral, 2884 enum phy_ch_width *ch_width, 2885 struct spectral_config_frequency *center_freq, 2886 bool *is_overlapping) 2887 { 2888 enum phy_ch_width op_ch_width; 2889 enum phy_ch_width agile_ch_width; 2890 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2891 struct wlan_objmgr_vdev *vdev; 2892 struct wlan_objmgr_pdev *pdev; 2893 int16_t chan_freq; 2894 uint32_t op_start_freq; 2895 uint32_t op_end_freq; 2896 uint32_t agile_start_freq; 2897 uint32_t agile_end_freq; 2898 uint32_t cfreq2; 2899 2900 if (!spectral) { 2901 spectral_err("Spectral object is NULL"); 2902 return QDF_STATUS_E_FAILURE; 2903 } 2904 2905 pdev = spectral->pdev_obj; 2906 if (!pdev) { 2907 spectral_err("pdev object is NULL"); 2908 return QDF_STATUS_E_FAILURE; 2909 } 2910 2911 if (!ch_width) { 2912 spectral_err("channel width array is null"); 2913 return QDF_STATUS_E_FAILURE; 2914 } 2915 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 2916 if (op_ch_width == CH_WIDTH_INVALID) { 2917 spectral_err("Invalid channel width"); 2918 return QDF_STATUS_E_INVAL; 2919 } 2920 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 2921 if (agile_ch_width == CH_WIDTH_INVALID) { 2922 spectral_err("Invalid channel width"); 2923 return QDF_STATUS_E_INVAL; 2924 } 2925 2926 if (!is_overlapping) { 2927 spectral_err("Argument(is_overlapping) is NULL"); 2928 return QDF_STATUS_E_FAILURE; 2929 } 2930 *is_overlapping = false; 2931 2932 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 2933 if (!vdev) { 2934 spectral_err("vdev is NULL"); 2935 return QDF_STATUS_E_FAILURE; 2936 } 2937 chan_freq = target_if_vdev_get_chan_freq(vdev); 2938 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); 2939 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2940 if (cfreq2 < 0) { 2941 spectral_err("cfreq2 is invalid"); 2942 return QDF_STATUS_E_FAILURE; 2943 } 2944 2945 if (op_ch_width == CH_WIDTH_20MHZ) { 2946 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; 2947 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; 2948 } else { 2949 enum channel_state state; 2950 2951 state = wlan_reg_get_5g_bonded_channel_and_state_for_freq 2952 (pdev, chan_freq, op_ch_width, &bonded_chan_ptr); 2953 if (state == CHANNEL_STATE_DISABLE || 2954 state == CHANNEL_STATE_INVALID) { 2955 spectral_err("Channel state is disable or invalid"); 2956 return QDF_STATUS_E_FAILURE; 2957 } 2958 if (!bonded_chan_ptr) { 2959 spectral_err("Bonded channel is not found"); 2960 return QDF_STATUS_E_FAILURE; 2961 } 2962 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; 2963 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; 2964 } 2965 2966 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 2967 agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 2968 agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 2969 if (agile_end_freq > op_start_freq && 2970 op_end_freq > agile_start_freq) 2971 *is_overlapping = true; 2972 2973 agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 2974 agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 2975 if (agile_end_freq > op_start_freq && 2976 op_end_freq > agile_start_freq) 2977 *is_overlapping = true; 2978 } else { 2979 agile_start_freq = center_freq->cfreq1 - 2980 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2981 agile_end_freq = center_freq->cfreq1 + 2982 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2983 if (agile_end_freq > op_start_freq && 2984 op_end_freq > agile_start_freq) 2985 *is_overlapping = true; 2986 } 2987 2988 if (op_ch_width == CH_WIDTH_80P80MHZ) { 2989 uint32_t sec80_start_feq; 2990 uint32_t sec80_end_freq; 2991 2992 sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ; 2993 sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ; 2994 2995 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 2996 agile_start_freq = 2997 center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 2998 agile_end_freq = 2999 center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 3000 if (agile_end_freq > sec80_start_feq && 3001 sec80_end_freq > agile_start_freq) 3002 *is_overlapping = true; 3003 3004 agile_start_freq = 3005 center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 3006 agile_end_freq = 3007 center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 3008 if (agile_end_freq > sec80_start_feq && 3009 sec80_end_freq > agile_start_freq) 3010 *is_overlapping = true; 3011 } else { 3012 agile_start_freq = center_freq->cfreq1 - 3013 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 3014 agile_end_freq = center_freq->cfreq1 + 3015 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 3016 if (agile_end_freq > sec80_start_feq && 3017 sec80_end_freq > agile_start_freq) 3018 *is_overlapping = true; 3019 } 3020 } 3021 3022 return QDF_STATUS_SUCCESS; 3023 } 3024 3025 /** 3026 * target_if_spectral_populate_chwidth() - Helper routine to 3027 * populate channel width for different Spectral modes 3028 * 3029 * @spectral: Pointer to Spectral object 3030 * @ch_width: Channel width array 3031 * @is_80_80_agile: Indicates whether 80+80 agile scan is requested 3032 * 3033 * Helper routine to populate channel width for different Spectral modes 3034 * 3035 * Return: QDF_STATUS 3036 */ 3037 static QDF_STATUS 3038 target_if_spectral_populate_chwidth(struct target_if_spectral *spectral, 3039 enum phy_ch_width *ch_width, 3040 bool is_80_80_agile) { 3041 struct wlan_objmgr_vdev *vdev; 3042 enum spectral_scan_mode smode; 3043 enum phy_ch_width vdev_ch_width; 3044 3045 smode = SPECTRAL_SCAN_MODE_NORMAL; 3046 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3047 ch_width[smode] = CH_WIDTH_INVALID; 3048 3049 if (!spectral) { 3050 spectral_err("Spectral object is null"); 3051 return QDF_STATUS_E_INVAL; 3052 } 3053 3054 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_NORMAL); 3055 if (!vdev) { 3056 spectral_err("vdev is null"); 3057 return QDF_STATUS_E_FAILURE; 3058 } 3059 3060 vdev_ch_width = target_if_vdev_get_ch_width(vdev); 3061 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3062 if (vdev_ch_width == CH_WIDTH_INVALID) { 3063 spectral_err("Invalid channel width %d", vdev_ch_width); 3064 return QDF_STATUS_E_FAILURE; 3065 } 3066 3067 ch_width[SPECTRAL_SCAN_MODE_NORMAL] = vdev_ch_width; 3068 ch_width[SPECTRAL_SCAN_MODE_AGILE] = 3069 target_if_spectral_find_agile_width(spectral, vdev_ch_width, 3070 is_80_80_agile); 3071 3072 return QDF_STATUS_SUCCESS; 3073 } 3074 3075 /** 3076 * target_if_spectral_is_valid_80p80_freq() - API to check whether given 3077 * (cfreq1, cfreq2) pair forms a valid 80+80 combination 3078 * @pdev: pointer to pdev 3079 * @cfreq1: center frequency 1 3080 * @cfreq2: center frequency 2 3081 * 3082 * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80 3083 * combination 3084 * 3085 * Return: true or false 3086 */ 3087 static bool 3088 target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev, 3089 uint32_t cfreq1, uint32_t cfreq2) 3090 { 3091 struct ch_params ch_params; 3092 enum channel_state chan_state1; 3093 enum channel_state chan_state2; 3094 struct wlan_objmgr_psoc *psoc; 3095 3096 qdf_assert_always(pdev); 3097 psoc = wlan_pdev_get_psoc(pdev); 3098 qdf_assert_always(psoc); 3099 3100 /* In restricted 80P80 MHz enabled, only one 80+80 MHz 3101 * channel is supported with cfreq=5690 and cfreq=5775. 3102 */ 3103 if (wlan_psoc_nif_fw_ext_cap_get( 3104 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) 3105 return CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2); 3106 3107 ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2); 3108 ch_params.mhz_freq_seg1 = cfreq2; 3109 ch_params.ch_width = CH_WIDTH_80P80MHZ; 3110 wlan_reg_set_channel_params_for_freq(pdev, cfreq1 - FREQ_OFFSET_10MHZ, 3111 0, &ch_params); 3112 3113 if (ch_params.ch_width != CH_WIDTH_80P80MHZ) 3114 return false; 3115 3116 if (ch_params.mhz_freq_seg0 != cfreq1 || 3117 ch_params.mhz_freq_seg1 != cfreq2) 3118 return false; 3119 3120 chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_freq( 3121 pdev, 3122 ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ, 3123 CH_WIDTH_80MHZ); 3124 if ((chan_state1 == CHANNEL_STATE_DISABLE) || 3125 (chan_state1 == CHANNEL_STATE_INVALID)) 3126 return false; 3127 3128 chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_freq( 3129 pdev, 3130 ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ, 3131 CH_WIDTH_80MHZ); 3132 if ((chan_state2 == CHANNEL_STATE_DISABLE) || 3133 (chan_state2 == CHANNEL_STATE_INVALID)) 3134 return false; 3135 3136 if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <= 3137 FREQ_OFFSET_80MHZ) 3138 return false; 3139 3140 return true; 3141 } 3142 3143 /** 3144 * _target_if_set_spectral_config() - Set spectral config 3145 * @spectral: Pointer to spectral object 3146 * @param: Spectral parameter id and value 3147 * @smode: Spectral scan mode 3148 * @err: Spectral error code 3149 * 3150 * API to set spectral configurations 3151 * 3152 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3153 */ 3154 static QDF_STATUS 3155 _target_if_set_spectral_config(struct target_if_spectral *spectral, 3156 const struct spectral_cp_param *param, 3157 const enum spectral_scan_mode smode, 3158 enum spectral_cp_error_code *err) 3159 { 3160 struct spectral_config params; 3161 struct target_if_spectral_ops *p_sops; 3162 struct spectral_config *sparams; 3163 QDF_STATUS status; 3164 bool is_overlapping; 3165 uint16_t agile_cfreq; 3166 bool is_valid_chan; 3167 struct spectral_param_min_max *param_min_max; 3168 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 3169 enum spectral_scan_mode m; 3170 struct spectral_config_frequency center_freq = {0}; 3171 3172 if (!err) { 3173 spectral_err("Error code argument is null"); 3174 QDF_ASSERT(0); 3175 return QDF_STATUS_E_FAILURE; 3176 } 3177 *err = SPECTRAL_SCAN_ERR_INVALID; 3178 3179 if (!param) { 3180 spectral_err("Parameter object is null"); 3181 return QDF_STATUS_E_FAILURE; 3182 } 3183 3184 if (!spectral) { 3185 spectral_err("spectral object is NULL"); 3186 return QDF_STATUS_E_FAILURE; 3187 } 3188 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3189 param_min_max = &spectral->param_min_max; 3190 3191 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3192 spectral_err("Invalid Spectral mode %u", smode); 3193 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3194 return QDF_STATUS_E_FAILURE; 3195 } 3196 3197 sparams = &spectral->params[smode]; 3198 m = SPECTRAL_SCAN_MODE_NORMAL; 3199 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 3200 ch_width[m] = CH_WIDTH_INVALID; 3201 3202 if (!spectral->params_valid[smode]) { 3203 target_if_spectral_info_read(spectral, 3204 smode, 3205 TARGET_IF_SPECTRAL_INFO_PARAMS, 3206 &spectral->params[smode], 3207 sizeof(spectral->params[smode])); 3208 spectral->params_valid[smode] = true; 3209 } 3210 3211 switch (param->id) { 3212 case SPECTRAL_PARAM_FFT_PERIOD: 3213 sparams->ss_fft_period = param->value; 3214 break; 3215 case SPECTRAL_PARAM_SCAN_PERIOD: 3216 sparams->ss_period = param->value; 3217 break; 3218 case SPECTRAL_PARAM_SCAN_COUNT: 3219 sparams->ss_count = param->value; 3220 break; 3221 case SPECTRAL_PARAM_SHORT_REPORT: 3222 sparams->ss_short_report = (!!param->value) ? true : false; 3223 break; 3224 case SPECTRAL_PARAM_SPECT_PRI: 3225 sparams->ss_spectral_pri = (!!param->value) ? true : false; 3226 break; 3227 case SPECTRAL_PARAM_FFT_SIZE: 3228 status = target_if_spectral_populate_chwidth 3229 (spectral, ch_width, spectral->params 3230 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 3231 if (QDF_IS_STATUS_ERROR(status)) 3232 return QDF_STATUS_E_FAILURE; 3233 if ((param->value < param_min_max->fft_size_min) || 3234 (param->value > param_min_max->fft_size_max 3235 [ch_width[smode]])) { 3236 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3237 return QDF_STATUS_E_FAILURE; 3238 } 3239 sparams->ss_fft_size = param->value; 3240 break; 3241 case SPECTRAL_PARAM_GC_ENA: 3242 sparams->ss_gc_ena = !!param->value; 3243 break; 3244 case SPECTRAL_PARAM_RESTART_ENA: 3245 sparams->ss_restart_ena = !!param->value; 3246 break; 3247 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 3248 sparams->ss_noise_floor_ref = param->value; 3249 break; 3250 case SPECTRAL_PARAM_INIT_DELAY: 3251 sparams->ss_init_delay = param->value; 3252 break; 3253 case SPECTRAL_PARAM_NB_TONE_THR: 3254 sparams->ss_nb_tone_thr = param->value; 3255 break; 3256 case SPECTRAL_PARAM_STR_BIN_THR: 3257 sparams->ss_str_bin_thr = param->value; 3258 break; 3259 case SPECTRAL_PARAM_WB_RPT_MODE: 3260 sparams->ss_wb_rpt_mode = !!param->value; 3261 break; 3262 case SPECTRAL_PARAM_RSSI_RPT_MODE: 3263 sparams->ss_rssi_rpt_mode = !!param->value; 3264 break; 3265 case SPECTRAL_PARAM_RSSI_THR: 3266 sparams->ss_rssi_thr = param->value; 3267 break; 3268 case SPECTRAL_PARAM_PWR_FORMAT: 3269 sparams->ss_pwr_format = !!param->value; 3270 break; 3271 case SPECTRAL_PARAM_RPT_MODE: 3272 if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) || 3273 (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) { 3274 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3275 return QDF_STATUS_E_FAILURE; 3276 } 3277 sparams->ss_rpt_mode = param->value; 3278 break; 3279 case SPECTRAL_PARAM_BIN_SCALE: 3280 sparams->ss_bin_scale = param->value; 3281 break; 3282 case SPECTRAL_PARAM_DBM_ADJ: 3283 sparams->ss_dbm_adj = !!param->value; 3284 break; 3285 case SPECTRAL_PARAM_CHN_MASK: 3286 sparams->ss_chn_mask = param->value; 3287 break; 3288 case SPECTRAL_PARAM_FREQUENCY: 3289 status = target_if_spectral_populate_chwidth( 3290 spectral, ch_width, param->freq.cfreq2 > 0); 3291 if (QDF_IS_STATUS_ERROR(status)) { 3292 spectral_err("Failed to populate channel width"); 3293 return QDF_STATUS_E_FAILURE; 3294 } 3295 3296 if (ch_width[smode] != CH_WIDTH_80P80MHZ && 3297 param->freq.cfreq2) { 3298 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3299 spectral_err("Non zero cfreq2 expected for 80p80 only"); 3300 return QDF_STATUS_E_INVAL; 3301 } 3302 3303 if (ch_width[smode] == CH_WIDTH_80P80MHZ && 3304 !param->freq.cfreq2) { 3305 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3306 spectral_err("Non zero cfreq2 expected for 80p80"); 3307 return QDF_STATUS_E_INVAL; 3308 } 3309 3310 status = target_if_is_center_freq_of_any_chan 3311 (spectral->pdev_obj, param->freq.cfreq1, 3312 &is_valid_chan); 3313 if (QDF_IS_STATUS_ERROR(status)) 3314 return QDF_STATUS_E_FAILURE; 3315 3316 if (is_valid_chan) { 3317 status = target_if_calculate_center_freq( 3318 spectral, ch_width, 3319 param->freq.cfreq1, 3320 &agile_cfreq); 3321 if (QDF_IS_STATUS_ERROR(status)) { 3322 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3323 return QDF_STATUS_E_FAILURE; 3324 } 3325 } else { 3326 bool is_valid_agile_cfreq; 3327 3328 status = target_if_validate_center_freq 3329 (spectral, ch_width, param->freq.cfreq1, 3330 &is_valid_agile_cfreq); 3331 if (QDF_IS_STATUS_ERROR(status)) 3332 return QDF_STATUS_E_FAILURE; 3333 3334 if (!is_valid_agile_cfreq) { 3335 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3336 spectral_err("Invalid agile center frequency"); 3337 return QDF_STATUS_E_FAILURE; 3338 } 3339 3340 agile_cfreq = param->freq.cfreq1; 3341 } 3342 center_freq.cfreq1 = agile_cfreq; 3343 3344 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 3345 status = target_if_is_center_freq_of_any_chan 3346 (spectral->pdev_obj, param->freq.cfreq2, 3347 &is_valid_chan); 3348 if (QDF_IS_STATUS_ERROR(status)) 3349 return QDF_STATUS_E_FAILURE; 3350 3351 if (is_valid_chan) { 3352 status = target_if_calculate_center_freq( 3353 spectral, ch_width, 3354 param->freq.cfreq2, 3355 &agile_cfreq); 3356 if (QDF_IS_STATUS_ERROR(status)) { 3357 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3358 return QDF_STATUS_E_FAILURE; 3359 } 3360 } else { 3361 bool is_valid_agile_cfreq; 3362 3363 status = target_if_validate_center_freq 3364 (spectral, ch_width, param->freq.cfreq2, 3365 &is_valid_agile_cfreq); 3366 if (QDF_IS_STATUS_ERROR(status)) 3367 return QDF_STATUS_E_FAILURE; 3368 3369 if (!is_valid_agile_cfreq) { 3370 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3371 spectral_err("Invalid agile center frequency"); 3372 return QDF_STATUS_E_FAILURE; 3373 } 3374 3375 agile_cfreq = param->freq.cfreq2; 3376 } 3377 center_freq.cfreq2 = agile_cfreq; 3378 } 3379 3380 status = target_if_is_agile_span_overlap_with_operating_span 3381 (spectral, ch_width, 3382 ¢er_freq, &is_overlapping); 3383 if (QDF_IS_STATUS_ERROR(status)) 3384 return QDF_STATUS_E_FAILURE; 3385 3386 if (is_overlapping) { 3387 spectral_err("Agile freq %u, %u overlaps with operating span", 3388 center_freq.cfreq1, center_freq.cfreq2); 3389 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3390 return QDF_STATUS_E_FAILURE; 3391 } 3392 3393 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 3394 bool is_valid_80p80; 3395 3396 is_valid_80p80 = target_if_spectral_is_valid_80p80_freq( 3397 spectral->pdev_obj, 3398 center_freq.cfreq1, 3399 center_freq.cfreq2); 3400 3401 if (!is_valid_80p80) { 3402 spectral_err("Agile freq %u, %u is invalid 80+80 combination", 3403 center_freq.cfreq1, 3404 center_freq.cfreq2); 3405 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3406 return QDF_STATUS_E_FAILURE; 3407 } 3408 } 3409 3410 sparams->ss_frequency.cfreq1 = center_freq.cfreq1; 3411 sparams->ss_frequency.cfreq2 = center_freq.cfreq2; 3412 3413 break; 3414 } 3415 3416 p_sops->configure_spectral(spectral, sparams, smode); 3417 /* only to validate the writes */ 3418 p_sops->get_spectral_config(spectral, ¶ms, smode); 3419 return QDF_STATUS_SUCCESS; 3420 } 3421 3422 QDF_STATUS 3423 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 3424 const struct spectral_cp_param *param, 3425 const enum spectral_scan_mode smode, 3426 enum spectral_cp_error_code *err) 3427 { 3428 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; 3429 struct target_if_spectral *spectral; 3430 QDF_STATUS status; 3431 3432 if (!err) { 3433 spectral_err("Error code argument is null"); 3434 QDF_ASSERT(0); 3435 return QDF_STATUS_E_FAILURE; 3436 } 3437 *err = SPECTRAL_SCAN_ERR_INVALID; 3438 3439 if (!pdev) { 3440 spectral_err("pdev object is NULL"); 3441 return QDF_STATUS_E_FAILURE; 3442 } 3443 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3444 if (!spectral) { 3445 spectral_err("spectral object is NULL"); 3446 return QDF_STATUS_E_FAILURE; 3447 } 3448 3449 if (!param) { 3450 spectral_err("parameter object is NULL"); 3451 return QDF_STATUS_E_FAILURE; 3452 } 3453 3454 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3455 spectral_err("Invalid Spectral mode %u", smode); 3456 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3457 return QDF_STATUS_E_FAILURE; 3458 } 3459 3460 if (!spectral->properties[smode][param->id].supported) { 3461 spectral_err("Spectral parameter(%u) unsupported for mode %u", 3462 param->id, smode); 3463 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 3464 return QDF_STATUS_E_FAILURE; 3465 } 3466 3467 if (spectral->properties[smode][param->id].common_all_modes) { 3468 spectral_warn("Setting Spectral parameter %u for all modes", 3469 param->id); 3470 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { 3471 status = _target_if_set_spectral_config 3472 (spectral, param, mode, err); 3473 if (QDF_IS_STATUS_ERROR(status)) 3474 return QDF_STATUS_E_FAILURE; 3475 } 3476 return QDF_STATUS_SUCCESS; 3477 } 3478 3479 return _target_if_set_spectral_config(spectral, param, smode, err); 3480 } 3481 3482 /** 3483 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 3484 * @fft_len: FFT length 3485 * @pdev: Pointer to pdev object 3486 * 3487 * API to get fft bin count for a given fft length 3488 * 3489 * Return: FFt bin count 3490 */ 3491 static int 3492 target_if_get_fft_bin_count(int fft_len) 3493 { 3494 int bin_count = 0; 3495 3496 switch (fft_len) { 3497 case 5: 3498 bin_count = 16; 3499 break; 3500 case 6: 3501 bin_count = 32; 3502 break; 3503 case 7: 3504 bin_count = 64; 3505 break; 3506 case 8: 3507 bin_count = 128; 3508 break; 3509 case 9: 3510 bin_count = 256; 3511 break; 3512 default: 3513 break; 3514 } 3515 3516 return bin_count; 3517 } 3518 3519 /** 3520 * target_if_init_upper_lower_flags() - Initializes control and extension 3521 * segment flags 3522 * @spectral: pointer to target if spectral object 3523 * @smode: Spectral scan mode 3524 * 3525 * API to initialize the control and extension flags with the lower/upper 3526 * segment based on the HT mode 3527 * 3528 * Return: FFt bin count 3529 */ 3530 static void 3531 target_if_init_upper_lower_flags(struct target_if_spectral *spectral, 3532 enum spectral_scan_mode smode) 3533 { 3534 int current_channel = 0; 3535 int ext_channel = 0; 3536 struct target_if_spectral_ops *p_sops = 3537 GET_TARGET_IF_SPECTRAL_OPS(spectral); 3538 3539 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3540 spectral_err("Invalid Spectral mode %u", smode); 3541 return; 3542 } 3543 current_channel = p_sops->get_current_channel(spectral, smode); 3544 ext_channel = p_sops->get_extension_channel(spectral, smode); 3545 3546 if ((current_channel == 0) || (ext_channel == 0)) 3547 return; 3548 3549 if (spectral->sc_spectral_20_40_mode) { 3550 /* HT40 mode */ 3551 if (ext_channel < current_channel) { 3552 spectral->lower_is_extension = 1; 3553 spectral->upper_is_control = 1; 3554 spectral->lower_is_control = 0; 3555 spectral->upper_is_extension = 0; 3556 } else { 3557 spectral->lower_is_extension = 0; 3558 spectral->upper_is_control = 0; 3559 spectral->lower_is_control = 1; 3560 spectral->upper_is_extension = 1; 3561 } 3562 } else { 3563 /* HT20 mode, lower is always control */ 3564 spectral->lower_is_extension = 0; 3565 spectral->upper_is_control = 0; 3566 spectral->lower_is_control = 1; 3567 spectral->upper_is_extension = 0; 3568 } 3569 } 3570 3571 /** 3572 * target_if_get_spectral_config() - Get spectral configuration 3573 * @pdev: Pointer to pdev object 3574 * @param: Pointer to spectral_config structure in which the configuration 3575 * should be returned 3576 * @smode: Spectral scan mode 3577 * 3578 * API to get the current spectral configuration 3579 * 3580 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3581 */ 3582 QDF_STATUS 3583 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 3584 struct spectral_config *param, 3585 enum spectral_scan_mode smode) 3586 { 3587 struct target_if_spectral_ops *p_sops = NULL; 3588 struct target_if_spectral *spectral = NULL; 3589 3590 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3591 3592 if (!spectral) { 3593 spectral_err("SPECTRAL : Module doesn't exist"); 3594 return QDF_STATUS_E_FAILURE; 3595 } 3596 3597 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3598 3599 if (!p_sops) { 3600 spectral_err("p_sops is null"); 3601 return QDF_STATUS_E_FAILURE; 3602 } 3603 3604 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3605 spectral_err("Invalid Spectral mode %u", smode); 3606 return QDF_STATUS_E_FAILURE; 3607 } 3608 3609 qdf_mem_zero(param, sizeof(struct spectral_config)); 3610 p_sops->get_spectral_config(spectral, param, smode); 3611 3612 return QDF_STATUS_SUCCESS; 3613 } 3614 3615 /** 3616 * target_if_spectral_get_num_detectors() - Get number of Spectral detectors 3617 * @spectral: Pointer to target if Spectral object 3618 * @ch_width: channel width 3619 * @num_detectors: Pointer to the variable to store number of Spectral detectors 3620 * 3621 * API to get number of Spectral detectors used for scan in the given channel 3622 * width. 3623 * 3624 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_INVAL on failure 3625 */ 3626 static QDF_STATUS 3627 target_if_spectral_get_num_detectors(struct target_if_spectral *spectral, 3628 enum phy_ch_width ch_width, 3629 uint32_t *num_detectors) 3630 { 3631 if (!spectral) { 3632 spectral_err("target if spectral object is null"); 3633 return QDF_STATUS_E_INVAL; 3634 } 3635 3636 if (ch_width >= CH_WIDTH_INVALID) { 3637 spectral_err("Invalid channel width %d", ch_width); 3638 return QDF_STATUS_E_INVAL; 3639 } 3640 3641 if (!num_detectors) { 3642 spectral_err("Invalid argument, number of detectors"); 3643 return QDF_STATUS_E_INVAL; 3644 } 3645 3646 switch (ch_width) { 3647 case CH_WIDTH_20MHZ: 3648 *num_detectors = spectral->capability.num_detectors_20mhz; 3649 break; 3650 3651 case CH_WIDTH_40MHZ: 3652 *num_detectors = spectral->capability.num_detectors_40mhz; 3653 break; 3654 3655 case CH_WIDTH_80MHZ: 3656 *num_detectors = spectral->capability.num_detectors_80mhz; 3657 break; 3658 3659 case CH_WIDTH_160MHZ: 3660 *num_detectors = spectral->capability.num_detectors_160mhz; 3661 break; 3662 3663 case CH_WIDTH_80P80MHZ: 3664 *num_detectors = spectral->capability.num_detectors_80p80mhz; 3665 break; 3666 3667 default: 3668 spectral_err("Unsupported channel width %d", ch_width); 3669 return QDF_STATUS_E_INVAL; 3670 } 3671 3672 return QDF_STATUS_SUCCESS; 3673 } 3674 3675 /** 3676 * target_if_spectral_finite_scan_init() - Initializations required for finite 3677 * Spectral scan 3678 * @spectral: Pointer to target of Spctral object 3679 * @smode: Spectral scan mode 3680 * 3681 * This routine initializes the finite Spectral scan. Finite Spectral scan is 3682 * triggered by configuring a non zero scan count. 3683 * 3684 * Return: QDF_STATUS_SUCCESS on success 3685 */ 3686 static QDF_STATUS 3687 target_if_spectral_finite_scan_init(struct target_if_spectral *spectral, 3688 enum spectral_scan_mode smode) 3689 { 3690 struct target_if_finite_spectral_scan_params *finite_scan; 3691 enum phy_ch_width ch_width; 3692 uint32_t num_detectors; 3693 QDF_STATUS status; 3694 uint16_t sscan_count; 3695 3696 if (!spectral) { 3697 spectral_err("target if spectral object is null"); 3698 return QDF_STATUS_E_INVAL; 3699 } 3700 3701 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3702 spectral_err("Invalid Spectral mode"); 3703 return QDF_STATUS_E_INVAL; 3704 } 3705 3706 ch_width = spectral->ch_width[smode]; 3707 status = target_if_spectral_get_num_detectors(spectral, ch_width, 3708 &num_detectors); 3709 3710 if (QDF_IS_STATUS_ERROR(status)) { 3711 spectral_err("Failed to get number of detectors"); 3712 return QDF_STATUS_E_FAILURE; 3713 } 3714 3715 finite_scan = &spectral->finite_scan[smode]; 3716 sscan_count = spectral->params[smode].ss_count; 3717 3718 finite_scan->finite_spectral_scan = true; 3719 finite_scan->num_reports_expected = num_detectors * sscan_count; 3720 3721 return QDF_STATUS_SUCCESS; 3722 } 3723 3724 /** 3725 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 3726 * parameters 3727 * @spectral: Pointer to Spectral target_if internal private data 3728 * @spectral_params: Pointer to Spectral parameters 3729 * @smode: Spectral scan mode 3730 * @err: Spectral error code 3731 * 3732 * Enable use of desired Spectral parameters by configuring them into HW, and 3733 * starting Spectral scan 3734 * 3735 * Return: 0 on success, 1 on failure 3736 */ 3737 int 3738 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 3739 struct spectral_config *spectral_params, 3740 enum spectral_scan_mode smode, 3741 enum spectral_cp_error_code *err) 3742 { 3743 int extension_channel = 0; 3744 int current_channel = 0; 3745 struct target_if_spectral_ops *p_sops = NULL; 3746 QDF_STATUS status; 3747 struct wlan_objmgr_pdev *pdev; 3748 struct wlan_objmgr_psoc *psoc; 3749 3750 if (!spectral) { 3751 spectral_err("Spectral LMAC object is NULL"); 3752 return 1; 3753 } 3754 3755 pdev = spectral->pdev_obj; 3756 if (!pdev) { 3757 spectral_err("pdev is null"); 3758 return QDF_STATUS_E_INVAL; 3759 } 3760 3761 psoc = wlan_pdev_get_psoc(pdev); 3762 if (!psoc) { 3763 spectral_err("psoc is null"); 3764 return QDF_STATUS_E_INVAL; 3765 } 3766 3767 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3768 spectral_err("Invalid Spectral mode %u", smode); 3769 return 1; 3770 } 3771 3772 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3773 3774 if (!p_sops) { 3775 spectral_err("p_sops is NULL"); 3776 return 1; 3777 } 3778 3779 spectral->sc_spectral_noise_pwr_cal = 3780 spectral_params->ss_spectral_pri ? 1 : 0; 3781 3782 /* check if extension channel is present */ 3783 extension_channel = p_sops->get_extension_channel(spectral, smode); 3784 current_channel = p_sops->get_current_channel(spectral, smode); 3785 3786 status = target_if_spectral_populate_chwidth( 3787 spectral, spectral->ch_width, 3788 spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 3789 ss_frequency.cfreq2 > 0); 3790 if (QDF_IS_STATUS_ERROR(status)) { 3791 spectral_err("Failed to get channel widths"); 3792 return 1; 3793 } 3794 3795 if (spectral->capability.advncd_spectral_cap) { 3796 spectral->lb_edge_extrabins = 0; 3797 spectral->rb_edge_extrabins = 0; 3798 3799 if (spectral->is_lb_edge_extrabins_format && 3800 spectral->params[smode].ss_rpt_mode == 2) { 3801 spectral->lb_edge_extrabins = 4; 3802 } 3803 3804 if (spectral->is_rb_edge_extrabins_format && 3805 spectral->params[smode].ss_rpt_mode == 2) { 3806 spectral->rb_edge_extrabins = 4; 3807 } 3808 3809 if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) { 3810 spectral->sc_spectral_20_40_mode = 0; 3811 3812 spectral->spectral_numbins = 3813 target_if_get_fft_bin_count( 3814 spectral->params[smode].ss_fft_size); 3815 spectral->spectral_fft_len = 3816 target_if_get_fft_bin_count( 3817 spectral->params[smode].ss_fft_size); 3818 spectral->spectral_data_len = 3819 target_if_get_fft_bin_count( 3820 spectral->params[smode].ss_fft_size); 3821 /* 3822 * Initialize classifier params to be sent to user 3823 * space classifier 3824 */ 3825 spectral->classifier_params.lower_chan_in_mhz = 3826 current_channel; 3827 spectral->classifier_params.upper_chan_in_mhz = 0; 3828 3829 } else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) { 3830 /* TODO : Remove this variable */ 3831 spectral->sc_spectral_20_40_mode = 1; 3832 spectral->spectral_numbins = 3833 target_if_get_fft_bin_count( 3834 spectral->params[smode].ss_fft_size); 3835 spectral->spectral_fft_len = 3836 target_if_get_fft_bin_count( 3837 spectral->params[smode].ss_fft_size); 3838 spectral->spectral_data_len = 3839 target_if_get_fft_bin_count( 3840 spectral->params[smode].ss_fft_size); 3841 3842 /* 3843 * Initialize classifier params to be sent to user 3844 * space classifier 3845 */ 3846 if (extension_channel < current_channel) { 3847 spectral->classifier_params.lower_chan_in_mhz = 3848 extension_channel; 3849 spectral->classifier_params.upper_chan_in_mhz = 3850 current_channel; 3851 } else { 3852 spectral->classifier_params.lower_chan_in_mhz = 3853 current_channel; 3854 spectral->classifier_params.upper_chan_in_mhz = 3855 extension_channel; 3856 } 3857 3858 } else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) { 3859 /* Set the FFT Size */ 3860 /* TODO : Remove this variable */ 3861 spectral->sc_spectral_20_40_mode = 0; 3862 spectral->spectral_numbins = 3863 target_if_get_fft_bin_count( 3864 spectral->params[smode].ss_fft_size); 3865 spectral->spectral_fft_len = 3866 target_if_get_fft_bin_count( 3867 spectral->params[smode].ss_fft_size); 3868 spectral->spectral_data_len = 3869 target_if_get_fft_bin_count( 3870 spectral->params[smode].ss_fft_size); 3871 3872 /* 3873 * Initialize classifier params to be sent to user 3874 * space classifier 3875 */ 3876 spectral->classifier_params.lower_chan_in_mhz = 3877 current_channel; 3878 spectral->classifier_params.upper_chan_in_mhz = 0; 3879 3880 /* 3881 * Initialize classifier params to be sent to user 3882 * space classifier 3883 */ 3884 if (extension_channel < current_channel) { 3885 spectral->classifier_params.lower_chan_in_mhz = 3886 extension_channel; 3887 spectral->classifier_params.upper_chan_in_mhz = 3888 current_channel; 3889 } else { 3890 spectral->classifier_params.lower_chan_in_mhz = 3891 current_channel; 3892 spectral->classifier_params.upper_chan_in_mhz = 3893 extension_channel; 3894 } 3895 3896 } else if (is_ch_width_160_or_80p80( 3897 spectral->ch_width[smode])) { 3898 /* Set the FFT Size */ 3899 3900 /* The below applies to both 160 and 80+80 cases */ 3901 3902 /* TODO : Remove this variable */ 3903 spectral->sc_spectral_20_40_mode = 0; 3904 spectral->spectral_numbins = 3905 target_if_get_fft_bin_count( 3906 spectral->params[smode].ss_fft_size); 3907 spectral->spectral_fft_len = 3908 target_if_get_fft_bin_count( 3909 spectral->params[smode].ss_fft_size); 3910 spectral->spectral_data_len = 3911 target_if_get_fft_bin_count( 3912 spectral->params[smode].ss_fft_size); 3913 3914 /* 3915 * Initialize classifier params to be sent to user 3916 * space classifier 3917 */ 3918 spectral->classifier_params.lower_chan_in_mhz = 3919 current_channel; 3920 spectral->classifier_params.upper_chan_in_mhz = 0; 3921 3922 /* 3923 * Initialize classifier params to be sent to user 3924 * space classifier 3925 */ 3926 if (extension_channel < current_channel) { 3927 spectral->classifier_params.lower_chan_in_mhz = 3928 extension_channel; 3929 spectral->classifier_params.upper_chan_in_mhz = 3930 current_channel; 3931 } else { 3932 spectral->classifier_params.lower_chan_in_mhz = 3933 current_channel; 3934 spectral->classifier_params.upper_chan_in_mhz = 3935 extension_channel; 3936 } 3937 } 3938 3939 if (spectral->spectral_numbins) { 3940 spectral->spectral_numbins += 3941 spectral->lb_edge_extrabins; 3942 spectral->spectral_numbins += 3943 spectral->rb_edge_extrabins; 3944 } 3945 3946 if (spectral->spectral_fft_len) { 3947 spectral->spectral_fft_len += 3948 spectral->lb_edge_extrabins; 3949 spectral->spectral_fft_len += 3950 spectral->rb_edge_extrabins; 3951 } 3952 3953 if (spectral->spectral_data_len) { 3954 spectral->spectral_data_len += 3955 spectral->lb_edge_extrabins; 3956 spectral->spectral_data_len += 3957 spectral->rb_edge_extrabins; 3958 } 3959 } else { 3960 /* 3961 * The decision to find 20/40 mode is found based on the 3962 * presence of extension channel 3963 * instead of channel width, as the channel width can 3964 * dynamically change 3965 */ 3966 3967 if (extension_channel == 0) { 3968 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 3969 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 3970 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 3971 spectral->spectral_data_len = 3972 SPECTRAL_HT20_TOTAL_DATA_LEN; 3973 /* only valid in 20-40 mode */ 3974 spectral->spectral_lower_max_index_offset = -1; 3975 /* only valid in 20-40 mode */ 3976 spectral->spectral_upper_max_index_offset = -1; 3977 spectral->spectral_max_index_offset = 3978 spectral->spectral_fft_len + 2; 3979 spectral->sc_spectral_20_40_mode = 0; 3980 3981 /* 3982 * Initialize classifier params to be sent to user 3983 * space classifier 3984 */ 3985 spectral->classifier_params.lower_chan_in_mhz = 3986 current_channel; 3987 spectral->classifier_params.upper_chan_in_mhz = 0; 3988 3989 } else { 3990 spectral->spectral_numbins = 3991 SPECTRAL_HT40_TOTAL_NUM_BINS; 3992 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 3993 spectral->spectral_data_len = 3994 SPECTRAL_HT40_TOTAL_DATA_LEN; 3995 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 3996 /* only valid in 20 mode */ 3997 spectral->spectral_max_index_offset = -1; 3998 spectral->spectral_lower_max_index_offset = 3999 spectral->spectral_fft_len + 2; 4000 spectral->spectral_upper_max_index_offset = 4001 spectral->spectral_fft_len + 5; 4002 spectral->sc_spectral_20_40_mode = 1; 4003 4004 /* 4005 * Initialize classifier params to be sent to user 4006 * space classifier 4007 */ 4008 if (extension_channel < current_channel) { 4009 spectral->classifier_params.lower_chan_in_mhz = 4010 extension_channel; 4011 spectral->classifier_params.upper_chan_in_mhz = 4012 current_channel; 4013 } else { 4014 spectral->classifier_params.lower_chan_in_mhz = 4015 current_channel; 4016 spectral->classifier_params.upper_chan_in_mhz = 4017 extension_channel; 4018 } 4019 } 4020 } 4021 4022 spectral->send_single_packet = 0; 4023 spectral->classifier_params.spectral_20_40_mode = 4024 spectral->sc_spectral_20_40_mode; 4025 spectral->classifier_params.spectral_dc_index = 4026 spectral->spectral_dc_index; 4027 spectral->spectral_sent_msg = 0; 4028 spectral->classify_scan = 0; 4029 spectral->num_spectral_data = 0; 4030 4031 if (!p_sops->is_spectral_active(spectral, smode)) { 4032 p_sops->configure_spectral(spectral, spectral_params, smode); 4033 spectral->rparams.marker[smode].is_valid = false; 4034 4035 if (spectral->params[smode].ss_count) { 4036 status = target_if_spectral_finite_scan_init(spectral, 4037 smode); 4038 if (QDF_IS_STATUS_ERROR(status)) { 4039 spectral_err("Failed to init finite scan"); 4040 return 1; 4041 } 4042 } 4043 p_sops->start_spectral_scan(spectral, smode, err); 4044 spectral->timestamp_war.timestamp_war_offset[smode] = 0; 4045 spectral->timestamp_war.last_fft_timestamp[smode] = 0; 4046 } 4047 4048 /* get current spectral configuration */ 4049 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode); 4050 4051 target_if_init_upper_lower_flags(spectral, smode); 4052 4053 return 0; 4054 } 4055 4056 /** 4057 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by 4058 * Agile DFS 4059 * @psoc: Pointer to psoc 4060 * @object: Pointer to pdev 4061 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited 4062 * 4063 * This API checks whether Agile DFS is running on any of the pdevs. If so, it 4064 * indicates that Agile Spectral scan is prohibited by Agile DFS. 4065 * 4066 * Return: void 4067 */ 4068 static void 4069 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, 4070 void *object, void *arg) 4071 { 4072 bool *is_aspectral_prohibited = arg; 4073 struct wlan_objmgr_pdev *cur_pdev = object; 4074 bool is_agile_dfs_enabled_cur_pdev = false; 4075 QDF_STATUS status; 4076 4077 qdf_assert_always(is_aspectral_prohibited); 4078 if (*is_aspectral_prohibited) 4079 return; 4080 4081 qdf_assert_always(psoc); 4082 qdf_assert_always(cur_pdev); 4083 4084 status = ucfg_dfs_get_agile_precac_enable 4085 (cur_pdev, 4086 &is_agile_dfs_enabled_cur_pdev); 4087 if (QDF_IS_STATUS_ERROR(status)) { 4088 spectral_err("Get agile precac failed, prohibiting aSpectral"); 4089 *is_aspectral_prohibited = true; 4090 return; 4091 } 4092 4093 if (is_agile_dfs_enabled_cur_pdev) { 4094 spectral_err("aDFS is in progress on one of the pdevs"); 4095 *is_aspectral_prohibited = true; 4096 } 4097 } 4098 4099 /** 4100 * target_if_get_curr_band() - Get current operating band of pdev 4101 * 4102 * @pdev: pointer to pdev object 4103 * 4104 * API to get current operating band of a given pdev. 4105 * 4106 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure 4107 */ 4108 static enum reg_wifi_band 4109 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 4110 { 4111 struct wlan_objmgr_vdev *vdev; 4112 int16_t chan_freq; 4113 enum reg_wifi_band cur_band; 4114 4115 if (!pdev) { 4116 spectral_err("pdev is NULL"); 4117 return REG_BAND_UNKNOWN; 4118 } 4119 4120 if (vdev_id == WLAN_INVALID_VDEV_ID) 4121 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); 4122 else 4123 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 4124 WLAN_SPECTRAL_ID); 4125 if (!vdev) { 4126 spectral_debug("vdev is NULL"); 4127 return REG_BAND_UNKNOWN; 4128 } 4129 chan_freq = target_if_vdev_get_chan_freq(vdev); 4130 cur_band = wlan_reg_freq_to_band(chan_freq); 4131 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4132 4133 return cur_band; 4134 } 4135 4136 /** 4137 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on 4138 * any of the 5G pdevs 4139 * @psoc: Pointer to psoc 4140 * @object: Pointer to pdev 4141 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in 4142 * progress in any 5G pdevs 4143 * 4144 * Return: void 4145 */ 4146 static void 4147 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, 4148 void *object, void *arg) 4149 { 4150 enum reg_wifi_band band; 4151 bool *is_agile_scan_inprog_5g_pdev = arg; 4152 struct target_if_spectral *spectral; 4153 struct wlan_objmgr_pdev *cur_pdev = object; 4154 struct target_if_spectral_ops *p_sops; 4155 4156 if (*is_agile_scan_inprog_5g_pdev) 4157 return; 4158 4159 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); 4160 if (!spectral) { 4161 spectral_err("target if spectral handle is NULL"); 4162 return; 4163 } 4164 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4165 4166 band = target_if_get_curr_band( 4167 cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]); 4168 if (band == REG_BAND_UNKNOWN) { 4169 spectral_debug("Failed to get current band"); 4170 return; 4171 } 4172 4173 if (band == REG_BAND_5G && 4174 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) 4175 *is_agile_scan_inprog_5g_pdev = true; 4176 } 4177 4178 /** 4179 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported 4180 * for current vdev rx chainmask. 4181 * 4182 * @spectral: Pointer to Spectral object 4183 * @is_supported: Pointer to is_supported 4184 * 4185 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4186 */ 4187 static QDF_STATUS 4188 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, 4189 bool *is_supported) 4190 { 4191 struct wlan_objmgr_vdev *vdev; 4192 uint8_t vdev_rxchainmask; 4193 struct wlan_objmgr_psoc *psoc; 4194 struct wlan_objmgr_pdev *pdev; 4195 struct target_psoc_info *tgt_psoc_info; 4196 struct wlan_psoc_host_service_ext_param *ext_svc_param; 4197 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 4198 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 4199 struct wlan_psoc_host_chainmask_table *table; 4200 int j; 4201 uint32_t table_id; 4202 enum phy_ch_width ch_width; 4203 uint8_t pdev_id; 4204 4205 if (!spectral) { 4206 spectral_err("spectral target if object is null"); 4207 return QDF_STATUS_E_FAILURE; 4208 } 4209 4210 if (!is_supported) { 4211 spectral_err("is supported argument is null"); 4212 return QDF_STATUS_E_FAILURE; 4213 } 4214 4215 if (spectral->spectral_gen <= SPECTRAL_GEN2) { 4216 spectral_err("HW Agile mode is not supported up to gen 2"); 4217 return QDF_STATUS_E_FAILURE; 4218 } 4219 4220 pdev = spectral->pdev_obj; 4221 if (!pdev) { 4222 spectral_err("pdev is null"); 4223 return QDF_STATUS_E_FAILURE; 4224 } 4225 4226 psoc = wlan_pdev_get_psoc(pdev); 4227 if (!psoc) { 4228 spectral_err("psoc is null"); 4229 return QDF_STATUS_E_FAILURE; 4230 } 4231 4232 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 4233 if (!vdev) { 4234 spectral_err("First vdev is NULL"); 4235 return QDF_STATUS_E_FAILURE; 4236 } 4237 4238 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 4239 if (!vdev_rxchainmask) { 4240 spectral_err("vdev rx chainmask is zero"); 4241 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4242 return QDF_STATUS_E_FAILURE; 4243 } 4244 4245 ch_width = target_if_vdev_get_ch_width(vdev); 4246 if (ch_width == CH_WIDTH_INVALID) { 4247 spectral_err("Invalid channel width"); 4248 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4249 return QDF_STATUS_E_FAILURE; 4250 } 4251 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4252 4253 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 4254 if (!tgt_psoc_info) { 4255 spectral_err("target_psoc_info is null"); 4256 return QDF_STATUS_E_FAILURE; 4257 } 4258 4259 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 4260 if (!ext_svc_param) { 4261 spectral_err("Extended service ready param null"); 4262 return QDF_STATUS_E_FAILURE; 4263 } 4264 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 4265 4266 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 4267 if (!mac_phy_cap_arr) { 4268 spectral_err("mac phy cap array is null"); 4269 return QDF_STATUS_E_FAILURE; 4270 } 4271 4272 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 4273 if (!mac_phy_cap) { 4274 spectral_err("mac phy cap is null"); 4275 return QDF_STATUS_E_FAILURE; 4276 } 4277 4278 table_id = mac_phy_cap->chainmask_table_id; 4279 table = &ext_svc_param->chainmask_table[table_id]; 4280 if (!table) { 4281 spectral_err("chainmask table not found"); 4282 return QDF_STATUS_E_FAILURE; 4283 } 4284 4285 for (j = 0; j < table->num_valid_chainmasks; j++) { 4286 if (table->cap_list[j].chainmask == vdev_rxchainmask) { 4287 if (ch_width <= CH_WIDTH_80MHZ) 4288 *is_supported = 4289 table->cap_list[j].supports_aSpectral; 4290 else 4291 *is_supported = 4292 table->cap_list[j].supports_aSpectral_160; 4293 break; 4294 } 4295 } 4296 4297 if (j == table->num_valid_chainmasks) { 4298 spectral_err("vdev rx chainmask %u not found in table id = %u", 4299 vdev_rxchainmask, table_id); 4300 return QDF_STATUS_E_FAILURE; 4301 } 4302 4303 return QDF_STATUS_SUCCESS; 4304 } 4305 4306 QDF_STATUS 4307 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, 4308 uint8_t vdev_id, 4309 const enum spectral_scan_mode smode, 4310 enum spectral_cp_error_code *err) 4311 { 4312 struct target_if_spectral_ops *p_sops; 4313 struct target_if_spectral *spectral; 4314 struct wlan_objmgr_psoc *psoc; 4315 enum reg_wifi_band band; 4316 4317 if (!err) { 4318 spectral_err("Error code argument is null"); 4319 QDF_ASSERT(0); 4320 return QDF_STATUS_E_FAILURE; 4321 } 4322 *err = SPECTRAL_SCAN_ERR_INVALID; 4323 4324 if (!pdev) { 4325 spectral_err("pdev object is NUll"); 4326 return QDF_STATUS_E_FAILURE; 4327 } 4328 4329 psoc = wlan_pdev_get_psoc(pdev); 4330 if (!psoc) { 4331 spectral_err("psoc is null"); 4332 return QDF_STATUS_E_FAILURE; 4333 } 4334 4335 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4336 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4337 spectral_err("Invalid Spectral mode %u", smode); 4338 return QDF_STATUS_E_FAILURE; 4339 } 4340 4341 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4342 if (!spectral) { 4343 spectral_err("Spectral LMAC object is NUll"); 4344 return QDF_STATUS_E_FAILURE; 4345 } 4346 4347 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4348 if (!p_sops) { 4349 spectral_err("p_sops is null"); 4350 return QDF_STATUS_E_FAILURE; 4351 } 4352 4353 if (p_sops->is_spectral_active(spectral, smode)) { 4354 spectral_err("spectral in progress in current pdev, mode %d", 4355 smode); 4356 return QDF_STATUS_E_FAILURE; 4357 } 4358 spectral->vdev_id[smode] = vdev_id; 4359 4360 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 4361 QDF_STATUS status; 4362 bool is_supported = false; 4363 4364 status = target_if_is_agile_supported_cur_chmask(spectral, 4365 &is_supported); 4366 if (QDF_IS_STATUS_ERROR(status)) { 4367 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4368 return QDF_STATUS_E_FAILURE; 4369 } 4370 4371 if (!is_supported) { 4372 spectral_err("aSpectral unsupported for cur chainmask"); 4373 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4374 return QDF_STATUS_E_FAILURE; 4375 } 4376 } 4377 4378 band = target_if_get_curr_band(spectral->pdev_obj, vdev_id); 4379 if (band == REG_BAND_UNKNOWN) { 4380 spectral_err("Failed to get current band"); 4381 return QDF_STATUS_E_FAILURE; 4382 } 4383 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { 4384 struct target_psoc_info *tgt_hdl; 4385 enum wmi_host_hw_mode_config_type mode; 4386 bool is_agile_scan_inprog_5g_pdev; 4387 4388 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 4389 if (!tgt_hdl) { 4390 target_if_err("target_psoc_info is null"); 4391 return QDF_STATUS_E_FAILURE; 4392 } 4393 4394 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 4395 switch (mode) { 4396 case WMI_HOST_HW_MODE_SBS_PASSIVE: 4397 case WMI_HOST_HW_MODE_SBS: 4398 case WMI_HOST_HW_MODE_DBS_SBS: 4399 case WMI_HOST_HW_MODE_DBS_OR_SBS: 4400 is_agile_scan_inprog_5g_pdev = false; 4401 wlan_objmgr_iterate_obj_list 4402 (psoc, WLAN_PDEV_OP, 4403 target_if_is_agile_scan_active_in_5g, 4404 &is_agile_scan_inprog_5g_pdev, 0, 4405 WLAN_SPECTRAL_ID); 4406 break; 4407 default: 4408 is_agile_scan_inprog_5g_pdev = false; 4409 break; 4410 } 4411 4412 if (is_agile_scan_inprog_5g_pdev) { 4413 spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); 4414 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4415 return QDF_STATUS_E_FAILURE; 4416 } 4417 } 4418 4419 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 4420 bool is_aspectral_prohibited = false; 4421 QDF_STATUS status; 4422 4423 status = wlan_objmgr_iterate_obj_list 4424 (psoc, WLAN_PDEV_OP, 4425 target_if_is_aspectral_prohibited_by_adfs, 4426 &is_aspectral_prohibited, 0, 4427 WLAN_SPECTRAL_ID); 4428 if (QDF_IS_STATUS_ERROR(status)) { 4429 spectral_err("Failed to iterate over pdevs"); 4430 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4431 return QDF_STATUS_E_FAILURE; 4432 } 4433 4434 if (is_aspectral_prohibited) { 4435 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4436 return QDF_STATUS_E_FAILURE; 4437 } 4438 } 4439 4440 if (!spectral->params_valid[smode]) { 4441 target_if_spectral_info_read(spectral, 4442 smode, 4443 TARGET_IF_SPECTRAL_INFO_PARAMS, 4444 &spectral->params[smode], 4445 sizeof(spectral->params[smode])); 4446 spectral->params_valid[smode] = true; 4447 } 4448 4449 qdf_spin_lock(&spectral->spectral_lock); 4450 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 4451 QDF_STATUS status; 4452 bool is_overlapping; 4453 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 4454 enum spectral_scan_mode m; 4455 enum phy_ch_width op_ch_width; 4456 enum phy_ch_width agile_ch_width; 4457 4458 m = SPECTRAL_SCAN_MODE_NORMAL; 4459 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 4460 ch_width[m] = CH_WIDTH_INVALID; 4461 status = target_if_spectral_populate_chwidth 4462 (spectral, ch_width, spectral->params 4463 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 4464 if (QDF_IS_STATUS_ERROR(status)) { 4465 qdf_spin_unlock(&spectral->spectral_lock); 4466 spectral_err("Failed to populate channel width"); 4467 return QDF_STATUS_E_FAILURE; 4468 } 4469 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 4470 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 4471 4472 if (!spectral->params[smode].ss_frequency.cfreq1 || 4473 (agile_ch_width == CH_WIDTH_80P80MHZ && 4474 !spectral->params[smode].ss_frequency.cfreq2)) { 4475 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 4476 qdf_spin_unlock(&spectral->spectral_lock); 4477 return QDF_STATUS_E_FAILURE; 4478 } 4479 4480 status = target_if_is_agile_span_overlap_with_operating_span 4481 (spectral, ch_width, 4482 &spectral->params[smode].ss_frequency, 4483 &is_overlapping); 4484 if (QDF_IS_STATUS_ERROR(status)) { 4485 qdf_spin_unlock(&spectral->spectral_lock); 4486 return QDF_STATUS_E_FAILURE; 4487 } 4488 4489 if (is_overlapping) { 4490 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4491 qdf_spin_unlock(&spectral->spectral_lock); 4492 return QDF_STATUS_E_FAILURE; 4493 } 4494 } 4495 4496 target_if_spectral_scan_enable_params(spectral, 4497 &spectral->params[smode], smode, 4498 err); 4499 qdf_spin_unlock(&spectral->spectral_lock); 4500 4501 return QDF_STATUS_SUCCESS; 4502 } 4503 4504 QDF_STATUS 4505 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, 4506 const enum spectral_scan_mode smode, 4507 enum spectral_cp_error_code *err) 4508 { 4509 struct target_if_spectral_ops *p_sops; 4510 struct target_if_spectral *spectral; 4511 4512 if (!err) { 4513 spectral_err("Error code argument is null"); 4514 QDF_ASSERT(0); 4515 return QDF_STATUS_E_FAILURE; 4516 } 4517 *err = SPECTRAL_SCAN_ERR_INVALID; 4518 4519 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4520 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4521 spectral_err("Invalid Spectral mode %u", smode); 4522 return QDF_STATUS_E_FAILURE; 4523 } 4524 4525 if (!pdev) { 4526 spectral_err("pdev object is NUll "); 4527 return QDF_STATUS_E_FAILURE; 4528 } 4529 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4530 if (!spectral) { 4531 spectral_err("Spectral LMAC object is NUll "); 4532 return QDF_STATUS_E_FAILURE; 4533 } 4534 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4535 4536 qdf_spin_lock(&spectral->spectral_lock); 4537 p_sops->stop_spectral_scan(spectral, smode); 4538 if (spectral->classify_scan) { 4539 /* TODO : Check if this logic is necessary */ 4540 spectral->detects_control_channel = 0; 4541 spectral->detects_extension_channel = 0; 4542 spectral->detects_above_dc = 0; 4543 spectral->detects_below_dc = 0; 4544 spectral->classify_scan = 0; 4545 } 4546 4547 spectral->send_single_packet = 0; 4548 spectral->sc_spectral_scan = 0; 4549 spectral->vdev_id[smode] = WLAN_INVALID_VDEV_ID; 4550 4551 qdf_spin_unlock(&spectral->spectral_lock); 4552 4553 return QDF_STATUS_SUCCESS; 4554 } 4555 4556 /** 4557 * target_if_is_spectral_active() - Get whether Spectral is active 4558 * @pdev: Pointer to pdev object 4559 * @smode: Spectral scan mode 4560 * 4561 * API to get whether Spectral is active 4562 * 4563 * Return: True if Spectral is active, false if Spectral is not active 4564 */ 4565 bool 4566 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, 4567 const enum spectral_scan_mode smode) 4568 { 4569 struct target_if_spectral *spectral = NULL; 4570 struct target_if_spectral_ops *p_sops = NULL; 4571 4572 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4573 4574 if (!spectral) { 4575 spectral_err("SPECTRAL : Module doesn't exist"); 4576 return QDF_STATUS_E_FAILURE; 4577 } 4578 4579 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4580 4581 if (!p_sops) { 4582 spectral_err("p_sops is null"); 4583 return QDF_STATUS_E_FAILURE; 4584 } 4585 4586 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4587 spectral_err("Invalid Spectral mode %u", smode); 4588 return QDF_STATUS_E_FAILURE; 4589 } 4590 4591 return p_sops->is_spectral_active(spectral, smode); 4592 } 4593 4594 /** 4595 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 4596 * @pdev: Pointer to pdev object 4597 * @smode: Spectral scan mode 4598 * 4599 * API to get whether Spectral is enabled 4600 * 4601 * Return: True if Spectral is enabled, false if Spectral is not enabled 4602 */ 4603 bool 4604 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, 4605 enum spectral_scan_mode smode) 4606 { 4607 struct target_if_spectral *spectral = NULL; 4608 struct target_if_spectral_ops *p_sops = NULL; 4609 4610 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4611 4612 if (!spectral) { 4613 spectral_err("SPECTRAL : Module doesn't exist"); 4614 return QDF_STATUS_E_FAILURE; 4615 } 4616 4617 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4618 4619 if (!p_sops) { 4620 spectral_err("p_sops is null"); 4621 return QDF_STATUS_E_FAILURE; 4622 } 4623 4624 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4625 spectral_err("Invalid Spectral mode %u", smode); 4626 return QDF_STATUS_E_FAILURE; 4627 } 4628 4629 return p_sops->is_spectral_enabled(spectral, smode); 4630 } 4631 4632 #ifdef DIRECT_BUF_RX_DEBUG 4633 /** 4634 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug 4635 * @pdev: Pointer to pdev object 4636 * @enable: Enable/Disable Spectral DMA ring debug 4637 * 4638 * Start/stop Spectral DMA ring debug based on @enable. 4639 * Also save the state for future use. 4640 * 4641 * Return: QDF_STATUS of operation 4642 */ 4643 static QDF_STATUS 4644 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) 4645 { 4646 struct target_if_spectral *spectral; 4647 struct wlan_lmac_if_tx_ops *tx_ops; 4648 struct wlan_objmgr_psoc *psoc; 4649 4650 if (!pdev) 4651 return QDF_STATUS_E_FAILURE; 4652 4653 psoc = wlan_pdev_get_psoc(pdev); 4654 if (!psoc) { 4655 spectral_err("psoc is null"); 4656 return QDF_STATUS_E_INVAL; 4657 } 4658 4659 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 4660 if (!tx_ops) { 4661 spectral_err("tx_ops is NULL"); 4662 return QDF_STATUS_E_INVAL; 4663 } 4664 4665 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4666 if (!spectral) { 4667 spectral_err("Spectal LMAC object is NULL"); 4668 return QDF_STATUS_E_INVAL; 4669 } 4670 4671 /* Save the state */ 4672 spectral->dbr_ring_debug = enable; 4673 4674 if (enable) 4675 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( 4676 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); 4677 else 4678 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( 4679 pdev, 0); 4680 4681 return QDF_STATUS_SUCCESS; 4682 } 4683 4684 /** 4685 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug 4686 * @pdev: Pointer to pdev object 4687 * @enable: Enable/Disable Spectral DMA buffer debug 4688 * 4689 * Start/stop Spectral DMA buffer debug based on @enable. 4690 * Also save the state for future use. 4691 * 4692 * Return: QDF_STATUS of operation 4693 */ 4694 static QDF_STATUS 4695 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) 4696 { 4697 struct target_if_spectral *spectral; 4698 struct wlan_lmac_if_tx_ops *tx_ops; 4699 struct wlan_objmgr_psoc *psoc; 4700 4701 if (!pdev) 4702 return QDF_STATUS_E_FAILURE; 4703 4704 psoc = wlan_pdev_get_psoc(pdev); 4705 if (!psoc) { 4706 spectral_err("psoc is null"); 4707 return QDF_STATUS_E_INVAL; 4708 } 4709 4710 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 4711 if (!tx_ops) { 4712 spectral_err("tx_ops is NULL"); 4713 return QDF_STATUS_E_INVAL; 4714 } 4715 4716 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4717 if (!spectral) { 4718 spectral_err("Spectal LMAC object is NULL"); 4719 return QDF_STATUS_E_INVAL; 4720 } 4721 4722 /* Save the state */ 4723 spectral->dbr_buff_debug = enable; 4724 4725 if (enable) 4726 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( 4727 pdev, 0, MEM_POISON_SIGNATURE); 4728 else 4729 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( 4730 pdev, 0); 4731 } 4732 4733 /** 4734 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer 4735 * debug based on the previous state 4736 * @pdev: Pointer to pdev object 4737 * 4738 * Return: QDF_STATUS of operation 4739 */ 4740 static QDF_STATUS 4741 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) 4742 { 4743 struct target_if_spectral *spectral; 4744 4745 if (!pdev) { 4746 spectral_err("pdev is NULL!"); 4747 return QDF_STATUS_E_FAILURE; 4748 } 4749 4750 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4751 if (!spectral) { 4752 spectral_err("Spectal LMAC object is NULL"); 4753 return QDF_STATUS_E_INVAL; 4754 } 4755 4756 if (spectral->dbr_buff_debug) 4757 return target_if_spectral_do_dbr_buff_debug(pdev, true); 4758 else 4759 return target_if_spectral_do_dbr_buff_debug(pdev, false); 4760 } 4761 4762 /** 4763 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring 4764 * debug based on the previous state 4765 * @pdev: Pointer to pdev object 4766 * 4767 * Return: QDF_STATUS of operation 4768 */ 4769 static QDF_STATUS 4770 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) 4771 { 4772 struct target_if_spectral *spectral; 4773 4774 if (!pdev) { 4775 spectral_err("pdev is NULL!"); 4776 return QDF_STATUS_E_FAILURE; 4777 } 4778 4779 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4780 if (!spectral) { 4781 spectral_err("Spectal LMAC object is NULL"); 4782 return QDF_STATUS_E_INVAL; 4783 } 4784 4785 if (spectral->dbr_ring_debug) 4786 return target_if_spectral_do_dbr_ring_debug(pdev, true); 4787 else 4788 return target_if_spectral_do_dbr_ring_debug(pdev, false); 4789 } 4790 4791 /** 4792 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral 4793 * @pdev: Pointer to pdev object 4794 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug 4795 * @debug_value: Value to be set for @dma_debug_type 4796 * 4797 * Set DMA debug for Spectral and start/stop Spectral DMA debug function 4798 * based on @debug_value 4799 * 4800 * Return: QDF_STATUS of operation 4801 */ 4802 static QDF_STATUS 4803 target_if_spectral_set_dma_debug( 4804 struct wlan_objmgr_pdev *pdev, 4805 enum spectral_dma_debug dma_debug_type, 4806 bool debug_value) 4807 { 4808 struct target_if_spectral_ops *p_sops; 4809 struct wlan_objmgr_psoc *psoc; 4810 struct wlan_lmac_if_tx_ops *tx_ops; 4811 struct target_if_spectral *spectral; 4812 4813 if (!pdev) 4814 return QDF_STATUS_E_FAILURE; 4815 4816 psoc = wlan_pdev_get_psoc(pdev); 4817 if (!psoc) { 4818 spectral_err("psoc is null"); 4819 return QDF_STATUS_E_INVAL; 4820 } 4821 4822 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 4823 if (!tx_ops) { 4824 spectral_err("tx_ops is NULL"); 4825 return QDF_STATUS_E_FAILURE; 4826 } 4827 4828 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { 4829 spectral_err("Unable to fetch target type"); 4830 return QDF_STATUS_E_FAILURE; 4831 } 4832 4833 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4834 if (!spectral) { 4835 spectral_err("Spectal LMAC object is NULL"); 4836 return QDF_STATUS_E_INVAL; 4837 } 4838 4839 if (spectral->direct_dma_support) { 4840 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4841 if (p_sops->is_spectral_active(spectral, 4842 SPECTRAL_SCAN_MODE_NORMAL) || 4843 p_sops->is_spectral_active(spectral, 4844 SPECTRAL_SCAN_MODE_AGILE)) { 4845 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); 4846 return QDF_STATUS_E_FAILURE; 4847 } 4848 4849 switch (dma_debug_type) { 4850 case SPECTRAL_DMA_RING_DEBUG: 4851 target_if_spectral_do_dbr_ring_debug(pdev, debug_value); 4852 break; 4853 4854 case SPECTRAL_DMA_BUFFER_DEBUG: 4855 target_if_spectral_do_dbr_buff_debug(pdev, debug_value); 4856 break; 4857 4858 default: 4859 spectral_err("Unsupported DMA debug type : %d", 4860 dma_debug_type); 4861 return QDF_STATUS_E_FAILURE; 4862 } 4863 } 4864 return QDF_STATUS_SUCCESS; 4865 } 4866 #endif /* DIRECT_BUF_RX_DEBUG */ 4867 4868 /** 4869 * target_if_spectral_direct_dma_support() - Get Direct-DMA support 4870 * @pdev: Pointer to pdev object 4871 * 4872 * Return: Whether Direct-DMA is supported on this radio 4873 */ 4874 static bool 4875 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) 4876 { 4877 struct target_if_spectral *spectral; 4878 4879 if (!pdev) { 4880 spectral_err("pdev is NULL!"); 4881 return false; 4882 } 4883 4884 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4885 if (!spectral) { 4886 spectral_err("Spectral LMAC object is NULL"); 4887 return false; 4888 } 4889 4890 return spectral->direct_dma_support; 4891 } 4892 4893 /** 4894 * target_if_set_debug_level() - Set debug level for Spectral 4895 * @pdev: Pointer to pdev object 4896 * @debug_level: Debug level 4897 * 4898 * API to set the debug level for Spectral 4899 * 4900 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4901 */ 4902 QDF_STATUS 4903 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 4904 { 4905 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 4906 4907 return QDF_STATUS_SUCCESS; 4908 } 4909 4910 /** 4911 * target_if_get_debug_level() - Get debug level for Spectral 4912 * @pdev: Pointer to pdev object 4913 * 4914 * API to get the debug level for Spectral 4915 * 4916 * Return: Current debug level 4917 */ 4918 uint32_t 4919 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 4920 { 4921 return spectral_debug_level; 4922 } 4923 4924 /** 4925 * target_if_get_spectral_capinfo() - Get Spectral capability information 4926 * @pdev: Pointer to pdev object 4927 * @scaps: Buffer into which data should be copied 4928 * 4929 * API to get the spectral capability information 4930 * 4931 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4932 */ 4933 QDF_STATUS 4934 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, 4935 struct spectral_caps *scaps) 4936 { 4937 struct target_if_spectral *spectral = NULL; 4938 4939 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4940 if (!spectral) { 4941 spectral_err("SPECTRAL : Module doesn't exist"); 4942 return QDF_STATUS_E_FAILURE; 4943 } 4944 4945 qdf_mem_copy(scaps, &spectral->capability, 4946 sizeof(struct spectral_caps)); 4947 4948 return QDF_STATUS_SUCCESS; 4949 } 4950 4951 /** 4952 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 4953 * @pdev: Pointer to pdev object 4954 * @stats: Buffer into which data should be copied 4955 * 4956 * API to get the spectral diagnostic statistics 4957 * 4958 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4959 */ 4960 QDF_STATUS 4961 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, 4962 struct spectral_diag_stats *stats) 4963 { 4964 struct target_if_spectral *spectral = NULL; 4965 4966 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4967 if (!spectral) { 4968 spectral_err("SPECTRAL : Module doesn't exist"); 4969 return QDF_STATUS_E_FAILURE; 4970 } 4971 4972 qdf_mem_copy(stats, &spectral->diag_stats, 4973 sizeof(struct spectral_diag_stats)); 4974 4975 return QDF_STATUS_SUCCESS; 4976 } 4977 4978 /** 4979 * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations 4980 * @psoc: Pointer to psoc object 4981 * @wmi_ops: Pointer to the structure having Spectral WMI operations 4982 * 4983 * API for registering Spectral WMI operations in 4984 * spectral internal data structure 4985 * 4986 * Return: QDF_STATUS 4987 */ 4988 static QDF_STATUS 4989 target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 4990 struct spectral_wmi_ops *wmi_ops) 4991 { 4992 struct target_if_psoc_spectral *psoc_spectral; 4993 4994 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 4995 if (!psoc_spectral) { 4996 spectral_err("Spectral LMAC object is null"); 4997 return QDF_STATUS_E_INVAL; 4998 } 4999 5000 psoc_spectral->wmi_ops = *wmi_ops; 5001 5002 return QDF_STATUS_SUCCESS; 5003 } 5004 5005 /** 5006 * target_if_register_spectral_tgt_ops() - Register Spectral target operations 5007 * @psoc: Pointer to psoc object 5008 * @tgt_ops: Pointer to the structure having Spectral target operations 5009 * 5010 * API for registering Spectral target operations in 5011 * spectral internal data structure 5012 * 5013 * Return: QDF_STATUS 5014 */ 5015 static QDF_STATUS 5016 target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 5017 struct spectral_tgt_ops *tgt_ops) 5018 { 5019 if (!psoc) { 5020 spectral_err("psoc is null"); 5021 return QDF_STATUS_E_INVAL; 5022 } 5023 5024 ops_tgt = *tgt_ops; 5025 5026 return QDF_STATUS_SUCCESS; 5027 } 5028 5029 /** 5030 * target_if_register_netlink_cb() - Register Netlink callbacks 5031 * @pdev: Pointer to pdev object 5032 * @nl_cb: Netlink callbacks to register 5033 * 5034 * Return: void 5035 */ 5036 static void 5037 target_if_register_netlink_cb( 5038 struct wlan_objmgr_pdev *pdev, 5039 struct spectral_nl_cb *nl_cb) 5040 { 5041 struct target_if_spectral *spectral = NULL; 5042 5043 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5044 5045 if (!spectral) { 5046 spectral_err("SPECTRAL : Module doesn't exist"); 5047 return; 5048 } 5049 5050 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 5051 5052 if (spectral->use_nl_bcast) 5053 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 5054 else 5055 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 5056 } 5057 5058 /** 5059 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 5060 * Netlink messages to the application layer 5061 * @pdev: Pointer to pdev object 5062 * 5063 * Return: true for broadcast, false for unicast 5064 */ 5065 static bool 5066 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 5067 { 5068 struct target_if_spectral *spectral = NULL; 5069 5070 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5071 5072 if (!spectral) { 5073 spectral_err("SPECTRAL : Module doesn't exist"); 5074 return false; 5075 } 5076 5077 return spectral->use_nl_bcast; 5078 } 5079 5080 /** 5081 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 5082 * @pdev: Pointer to pdev object 5083 * 5084 * Return: void 5085 */ 5086 static void 5087 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 5088 { 5089 struct target_if_spectral *spectral = NULL; 5090 5091 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5092 if (!spectral) { 5093 spectral_err("SPECTRAL : Module doesn't exist"); 5094 return; 5095 } 5096 5097 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 5098 } 5099 5100 static int 5101 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, 5102 void *payload) 5103 { 5104 struct target_if_spectral *spectral = NULL; 5105 struct target_if_spectral_ops *p_sops = NULL; 5106 5107 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5108 if (!spectral) { 5109 spectral_err("SPECTRAL : Module doesn't exist"); 5110 return -EPERM; 5111 } 5112 5113 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5114 5115 if (!p_sops) { 5116 spectral_err("p_sops is null"); 5117 return -EPERM; 5118 } 5119 5120 return p_sops->process_spectral_report(pdev, payload); 5121 } 5122 5123 #ifdef DIRECT_BUF_RX_DEBUG 5124 static inline void 5125 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 5126 { 5127 if (!tx_ops) { 5128 spectral_err("tx_ops is NULL"); 5129 return; 5130 } 5131 5132 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = 5133 target_if_spectral_set_dma_debug; 5134 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = 5135 target_if_spectral_check_and_do_dbr_ring_debug; 5136 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = 5137 target_if_spectral_check_and_do_dbr_buff_debug; 5138 } 5139 #else 5140 static inline void 5141 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 5142 { 5143 } 5144 #endif 5145 5146 #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE) 5147 /** 5148 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 5149 * register WMI event handler 5150 * @psoc: Pointer to psoc object 5151 * @event_id: Event id 5152 * @handler_func: Handler function 5153 * @rx_ctx: Context of WMI event processing 5154 * 5155 * Wrapper function to register WMI event handler 5156 * 5157 * Return: 0 for success else failure 5158 */ 5159 static int 5160 target_if_spectral_wmi_unified_register_event_handler( 5161 struct wlan_objmgr_psoc *psoc, 5162 wmi_conv_event_id event_id, 5163 wmi_unified_event_handler handler_func, 5164 uint8_t rx_ctx) 5165 { 5166 wmi_unified_t wmi_handle; 5167 struct target_if_psoc_spectral *psoc_spectral; 5168 QDF_STATUS ret; 5169 5170 if (!psoc) { 5171 spectral_err("psoc is null"); 5172 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5173 } 5174 5175 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5176 if (!wmi_handle) { 5177 spectral_err("WMI handle is null"); 5178 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5179 } 5180 5181 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5182 if (!psoc_spectral) { 5183 spectral_err("spectral object is null"); 5184 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5185 } 5186 5187 ret = psoc_spectral->wmi_ops.wmi_unified_register_event_handler( 5188 wmi_handle, event_id, handler_func, rx_ctx); 5189 5190 return qdf_status_to_os_return(ret); 5191 } 5192 5193 /** 5194 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 5195 * to unregister WMI event handler 5196 * @psoc: Pointer to psoc object 5197 * @event_id: Event id 5198 * 5199 * Wrapper function to unregister WMI event handler 5200 * 5201 * Return: 0 for success else failure 5202 */ 5203 static int 5204 target_if_spectral_wmi_unified_unregister_event_handler( 5205 struct wlan_objmgr_psoc *psoc, 5206 wmi_conv_event_id event_id) 5207 { 5208 wmi_unified_t wmi_handle; 5209 struct target_if_psoc_spectral *psoc_spectral; 5210 QDF_STATUS ret; 5211 5212 if (!psoc) { 5213 spectral_err("psoc is null"); 5214 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5215 } 5216 5217 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5218 if (!wmi_handle) { 5219 spectral_err("WMI handle is null"); 5220 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5221 } 5222 5223 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5224 if (!psoc_spectral) { 5225 spectral_err("spectral object is null"); 5226 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5227 } 5228 5229 ret = psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler( 5230 wmi_handle, event_id); 5231 5232 return qdf_status_to_os_return(ret); 5233 } 5234 5235 /** 5236 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 5237 * function to extract fixed parameters from start scan response event 5238 * @psoc: Pointer to psoc object 5239 * @evt_buf: Event buffer 5240 * @param: Start scan response parameters 5241 * 5242 * Wrapper function to extract fixed parameters from start scan response event 5243 * 5244 * Return: QDF_STATUS 5245 */ 5246 static QDF_STATUS 5247 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5248 struct wlan_objmgr_psoc *psoc, 5249 uint8_t *evt_buf, 5250 struct spectral_startscan_resp_params *param) 5251 { 5252 wmi_unified_t wmi_handle; 5253 struct target_if_psoc_spectral *psoc_spectral; 5254 5255 if (!psoc) { 5256 spectral_err("psoc is null"); 5257 return QDF_STATUS_E_INVAL; 5258 } 5259 5260 if (!evt_buf) { 5261 spectral_err("WMI event buffer is null"); 5262 return QDF_STATUS_E_INVAL; 5263 } 5264 5265 if (!param) { 5266 spectral_err("Spectral startscan response parameters is null"); 5267 return QDF_STATUS_E_INVAL; 5268 } 5269 5270 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5271 if (!wmi_handle) { 5272 spectral_err("WMI handle is null"); 5273 return QDF_STATUS_E_INVAL; 5274 } 5275 5276 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5277 if (!psoc_spectral) { 5278 spectral_err("spectral object is null"); 5279 return QDF_STATUS_E_FAILURE; 5280 } 5281 5282 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5283 wmi_handle, evt_buf, param); 5284 } 5285 5286 /** 5287 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 5288 * function to extract start and end indices of primary 80 MHz, 5 MHz and 5289 * secondary 80 MHz FFT bins 5290 * @psoc: Pointer to psoc object 5291 * @evt_buf: Event buffer 5292 * @param: FFT bin start and end indices 5293 * 5294 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 5295 * and secondary 80 MHz FFT bins 5296 * 5297 * Return: QDF_STATUS 5298 */ 5299 static QDF_STATUS 5300 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 5301 struct wlan_objmgr_psoc *psoc, 5302 uint8_t *evt_buf, 5303 struct spectral_fft_bin_markers_160_165mhz *param) 5304 { 5305 wmi_unified_t wmi_handle; 5306 struct target_if_psoc_spectral *psoc_spectral; 5307 5308 if (!psoc) { 5309 spectral_err("psoc is null"); 5310 return QDF_STATUS_E_INVAL; 5311 } 5312 5313 if (!evt_buf) { 5314 spectral_err("WMI event buffer is null"); 5315 return QDF_STATUS_E_INVAL; 5316 } 5317 5318 if (!param) { 5319 spectral_err("Spectral FFT bin markers is null"); 5320 return QDF_STATUS_E_INVAL; 5321 } 5322 5323 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5324 if (!wmi_handle) { 5325 spectral_err("WMI handle is null"); 5326 return QDF_STATUS_E_INVAL; 5327 } 5328 5329 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5330 if (!psoc_spectral) { 5331 spectral_err("spectral object is null"); 5332 return QDF_STATUS_E_FAILURE; 5333 } 5334 5335 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index( 5336 wmi_handle, evt_buf, param); 5337 } 5338 5339 /** 5340 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 5341 * object from scn handle 5342 * @scn: scn handle 5343 * 5344 * Wrapper function to get psoc object from scn handle 5345 * 5346 * Return: Pointer to psoc object 5347 */ 5348 static struct wlan_objmgr_psoc * 5349 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 5350 { 5351 if (!scn) { 5352 spectral_err("scn is null"); 5353 return NULL; 5354 } 5355 5356 return ops_tgt.tgt_get_psoc_from_scn_hdl(scn); 5357 } 5358 #else 5359 /** 5360 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 5361 * register WMI event handler 5362 * @psoc: Pointer to psoc object 5363 * @event_id: Event id 5364 * @handler_func: Handler function 5365 * @rx_ctx: Context of WMI event processing 5366 * 5367 * Wrapper function to register WMI event handler 5368 * 5369 * Return: 0 for success else failure 5370 */ 5371 static int 5372 target_if_spectral_wmi_unified_register_event_handler( 5373 struct wlan_objmgr_psoc *psoc, 5374 wmi_conv_event_id event_id, 5375 wmi_unified_event_handler handler_func, 5376 uint8_t rx_ctx) 5377 { 5378 wmi_unified_t wmi_handle; 5379 QDF_STATUS ret; 5380 5381 if (!psoc) { 5382 spectral_err("psoc is null"); 5383 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5384 } 5385 5386 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5387 if (!wmi_handle) { 5388 spectral_err("WMI handle is null"); 5389 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5390 } 5391 5392 ret = wmi_unified_register_event_handler(wmi_handle, event_id, 5393 handler_func, rx_ctx); 5394 5395 return qdf_status_to_os_return(ret); 5396 } 5397 5398 /** 5399 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 5400 * to unregister WMI event handler 5401 * @psoc: Pointer to psoc object 5402 * @event_id: Event id 5403 * 5404 * Wrapper function to unregister WMI event handler 5405 * 5406 * Return: 0 for success else failure 5407 */ 5408 static int 5409 target_if_spectral_wmi_unified_unregister_event_handler( 5410 struct wlan_objmgr_psoc *psoc, 5411 wmi_conv_event_id event_id) 5412 { 5413 wmi_unified_t wmi_handle; 5414 QDF_STATUS ret; 5415 5416 if (!psoc) { 5417 spectral_err("psoc is null"); 5418 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5419 } 5420 5421 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5422 if (!wmi_handle) { 5423 spectral_err("WMI handle is null"); 5424 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5425 } 5426 5427 ret = wmi_unified_unregister_event_handler(wmi_handle, event_id); 5428 5429 return qdf_status_to_os_return(ret); 5430 } 5431 5432 /** 5433 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 5434 * function to extract fixed parameters from start scan response event 5435 * @psoc: Pointer to psoc object 5436 * @evt_buf: Event buffer 5437 * @param: Start scan response parameters 5438 * 5439 * Wrapper function to extract fixed parameters from start scan response event 5440 * 5441 * Return: QDF_STATUS 5442 */ 5443 static QDF_STATUS 5444 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5445 struct wlan_objmgr_psoc *psoc, 5446 uint8_t *evt_buf, 5447 struct spectral_startscan_resp_params *param) 5448 { 5449 wmi_unified_t wmi_handle; 5450 5451 if (!psoc) { 5452 spectral_err("psoc is null"); 5453 return QDF_STATUS_E_INVAL; 5454 } 5455 5456 if (!evt_buf) { 5457 spectral_err("WMI event buffer is null"); 5458 return QDF_STATUS_E_INVAL; 5459 } 5460 5461 if (!param) { 5462 spectral_err("Spectral startscan response parameters is null"); 5463 return QDF_STATUS_E_INVAL; 5464 } 5465 5466 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5467 if (!wmi_handle) { 5468 spectral_err("WMI handle is null"); 5469 return QDF_STATUS_E_INVAL; 5470 } 5471 5472 return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf, 5473 param); 5474 } 5475 5476 /** 5477 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 5478 * function to extract start and end indices of primary 80 MHz, 5 MHz and 5479 * secondary 80 MHz FFT bins 5480 * @psoc: Pointer to psoc object 5481 * @evt_buf: Event buffer 5482 * @param: FFT bin start and end indices 5483 * 5484 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 5485 * and secondary 80 MHz FFT bins 5486 * 5487 * Return: QDF_STATUS 5488 */ 5489 static QDF_STATUS 5490 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 5491 struct wlan_objmgr_psoc *psoc, 5492 uint8_t *evt_buf, 5493 struct spectral_fft_bin_markers_160_165mhz *param) 5494 { 5495 wmi_unified_t wmi_handle; 5496 5497 if (!psoc) { 5498 spectral_err("psoc is null"); 5499 return QDF_STATUS_E_INVAL; 5500 } 5501 5502 if (!evt_buf) { 5503 spectral_err("WMI event buffer is null"); 5504 return QDF_STATUS_E_INVAL; 5505 } 5506 5507 if (!param) { 5508 spectral_err("Spectral FFT bin markers is null"); 5509 return QDF_STATUS_E_INVAL; 5510 } 5511 5512 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5513 if (!wmi_handle) { 5514 spectral_err("WMI handle is null"); 5515 return QDF_STATUS_E_INVAL; 5516 } 5517 5518 return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param); 5519 } 5520 5521 /** 5522 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 5523 * object from scn handle 5524 * @scn: scn handle 5525 * 5526 * Wrapper function to get psoc object from scn handle 5527 * 5528 * Return: Pointer to psoc object 5529 */ 5530 static struct wlan_objmgr_psoc * 5531 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 5532 { 5533 if (!scn) { 5534 spectral_err("scn is null"); 5535 return NULL; 5536 } 5537 5538 return target_if_get_psoc_from_scn_hdl(scn); 5539 } 5540 #endif 5541 5542 /** 5543 * target_if_spectral_fw_param_event_handler() - WMI event handler to 5544 * process start scan response event 5545 * @scn: Pointer to scn object 5546 * @data_buf: Pointer to event buffer 5547 * @data_len: Length of event buffer 5548 * 5549 * Return: 0 for success, else failure 5550 */ 5551 static int 5552 target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf, 5553 uint32_t data_len) 5554 { 5555 QDF_STATUS status; 5556 struct wlan_objmgr_psoc *psoc; 5557 struct wlan_objmgr_pdev *pdev; 5558 struct wmi_unified *wmi_handle; 5559 struct spectral_startscan_resp_params event_params = {0}; 5560 struct target_if_psoc_spectral *psoc_spectral; 5561 struct target_if_spectral *spectral; 5562 5563 if (!scn) { 5564 spectral_err("scn handle is null"); 5565 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5566 } 5567 5568 if (!data_buf) { 5569 spectral_err("WMI event buffer null"); 5570 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5571 } 5572 5573 psoc = target_if_spectral_get_psoc_from_scn_handle(scn); 5574 if (!psoc) { 5575 spectral_err("psoc is null"); 5576 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5577 } 5578 5579 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5580 if (!psoc_spectral) { 5581 spectral_err("spectral object is null"); 5582 return QDF_STATUS_E_FAILURE; 5583 } 5584 5585 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5586 if (!wmi_handle) { 5587 spectral_err("WMI handle is null"); 5588 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5589 } 5590 5591 status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5592 psoc, data_buf, &event_params); 5593 if (QDF_IS_STATUS_ERROR(status)) { 5594 spectral_err("unable to extract sscan fw fixed params"); 5595 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5596 } 5597 5598 pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id, 5599 WLAN_SPECTRAL_ID); 5600 if (!pdev) { 5601 spectral_err("pdev is null"); 5602 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5603 } 5604 5605 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5606 if (!spectral) { 5607 spectral_err("spectral object is null"); 5608 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 5609 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5610 } 5611 5612 if (event_params.num_fft_bin_index == 1) { 5613 status = 5614 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 5615 psoc, data_buf, 5616 &spectral->rparams.marker[event_params.smode]); 5617 if (QDF_IS_STATUS_ERROR(status)) { 5618 spectral_err("unable to extract sscan fw fixed params"); 5619 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 5620 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5621 } 5622 } else { 5623 spectral->rparams.marker[event_params.smode].is_valid = false; 5624 } 5625 5626 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 5627 5628 return qdf_status_to_os_return(QDF_STATUS_SUCCESS); 5629 } 5630 5631 static QDF_STATUS 5632 target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc) 5633 { 5634 int ret; 5635 5636 if (!psoc) { 5637 spectral_err("psoc is null"); 5638 return QDF_STATUS_E_INVAL; 5639 } 5640 5641 ret = target_if_spectral_wmi_unified_register_event_handler( 5642 psoc, 5643 wmi_pdev_sscan_fw_param_eventid, 5644 target_if_spectral_fw_param_event_handler, 5645 WMI_RX_UMAC_CTX); 5646 5647 if (ret) 5648 spectral_debug("event handler not supported, ret=%d", ret); 5649 5650 return QDF_STATUS_SUCCESS; 5651 } 5652 5653 static QDF_STATUS 5654 target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc) 5655 { 5656 int ret; 5657 5658 if (!psoc) { 5659 spectral_err("psoc is null"); 5660 return QDF_STATUS_E_INVAL; 5661 } 5662 5663 ret = target_if_spectral_wmi_unified_unregister_event_handler( 5664 psoc, wmi_pdev_sscan_fw_param_eventid); 5665 5666 if (ret) 5667 spectral_debug("Unregister WMI event handler failed, ret = %d", 5668 ret); 5669 5670 return QDF_STATUS_SUCCESS; 5671 } 5672 5673 void 5674 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 5675 { 5676 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 5677 target_if_pdev_spectral_init; 5678 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 5679 target_if_pdev_spectral_deinit; 5680 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init = 5681 target_if_psoc_spectral_init; 5682 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit = 5683 target_if_psoc_spectral_deinit; 5684 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 5685 target_if_set_spectral_config; 5686 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 5687 target_if_get_spectral_config; 5688 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 5689 target_if_start_spectral_scan; 5690 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 5691 target_if_stop_spectral_scan; 5692 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 5693 target_if_is_spectral_active; 5694 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 5695 target_if_is_spectral_enabled; 5696 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 5697 target_if_set_debug_level; 5698 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 5699 target_if_get_debug_level; 5700 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 5701 target_if_get_spectral_capinfo; 5702 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 5703 target_if_get_spectral_diagstats; 5704 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops = 5705 target_if_register_spectral_wmi_ops; 5706 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops = 5707 target_if_register_spectral_tgt_ops; 5708 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 5709 target_if_register_netlink_cb; 5710 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 5711 target_if_use_nl_bcast; 5712 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 5713 target_if_deregister_netlink_cb; 5714 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = 5715 target_if_process_spectral_report; 5716 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = 5717 target_if_spectral_direct_dma_support; 5718 tx_ops->sptrl_tx_ops.sptrlto_register_events = 5719 target_if_spectral_register_events; 5720 tx_ops->sptrl_tx_ops.sptrlto_unregister_events = 5721 target_if_spectral_unregister_events; 5722 5723 target_if_sptrl_debug_register_tx_ops(tx_ops); 5724 } 5725 qdf_export_symbol(target_if_sptrl_register_tx_ops); 5726 5727 void 5728 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 5729 uint16_t cw_int, uint32_t dcs_enabled) 5730 { 5731 struct spectral_samp_msg *msg = NULL; 5732 struct target_if_spectral_ops *p_sops = NULL; 5733 struct target_if_spectral *spectral = NULL; 5734 5735 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5736 5737 if (!spectral) { 5738 spectral_err("SPECTRAL : Module doesn't exist"); 5739 return; 5740 } 5741 5742 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5743 if (!p_sops) { 5744 spectral_err("p_sops is null"); 5745 return; 5746 } 5747 5748 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( 5749 spectral->pdev_obj, 5750 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, 5751 SPECTRAL_MSG_BUF_NEW); 5752 5753 if (msg) { 5754 msg->int_type = cw_int ? 5755 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 5756 msg->dcs_enabled = dcs_enabled; 5757 msg->signature = SPECTRAL_SIGNATURE; 5758 p_sops->get_mac_address(spectral, msg->macaddr); 5759 if (spectral->send_phy_data 5760 (pdev, 5761 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0) 5762 spectral->spectral_sent_msg++; 5763 } 5764 } 5765 qdf_export_symbol(target_if_spectral_send_intf_found_msg); 5766 5767 QDF_STATUS 5768 target_if_spectral_is_finite_scan(struct target_if_spectral *spectral, 5769 enum spectral_scan_mode smode, 5770 bool *finite_spectral_scan) 5771 { 5772 struct target_if_finite_spectral_scan_params *finite_scan; 5773 5774 if (!spectral) { 5775 spectral_err_rl("target if spectral object is null"); 5776 return QDF_STATUS_E_INVAL; 5777 } 5778 5779 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5780 spectral_err_rl("invalid spectral mode %d", smode); 5781 return QDF_STATUS_E_INVAL; 5782 } 5783 5784 if (!finite_spectral_scan) { 5785 spectral_err_rl("Invalid pointer"); 5786 return QDF_STATUS_E_INVAL; 5787 } 5788 5789 finite_scan = &spectral->finite_scan[smode]; 5790 *finite_spectral_scan = finite_scan->finite_spectral_scan; 5791 5792 return QDF_STATUS_SUCCESS; 5793 } 5794 5795 QDF_STATUS 5796 target_if_spectral_finite_scan_update(struct target_if_spectral *spectral, 5797 enum spectral_scan_mode smode) 5798 { 5799 struct target_if_finite_spectral_scan_params *finite_scan; 5800 5801 if (!spectral) { 5802 spectral_err_rl("target if spectral object is null"); 5803 return QDF_STATUS_E_INVAL; 5804 } 5805 5806 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 5807 spectral_err_rl("Invalid Spectral mode"); 5808 return QDF_STATUS_E_INVAL; 5809 } 5810 5811 finite_scan = &spectral->finite_scan[smode]; 5812 5813 if (!finite_scan->num_reports_expected) { 5814 spectral_err_rl("Error, No reports expected"); 5815 return QDF_STATUS_E_FAILURE; 5816 } 5817 5818 finite_scan->num_reports_expected--; 5819 if (!finite_scan->num_reports_expected) { 5820 QDF_STATUS status; 5821 enum spectral_cp_error_code err; 5822 5823 /* received expected number of reports from target, stop scan */ 5824 status = target_if_stop_spectral_scan(spectral->pdev_obj, smode, 5825 &err); 5826 if (QDF_IS_STATUS_ERROR(status)) { 5827 spectral_err_rl("Failed to stop finite Spectral scan"); 5828 return QDF_STATUS_E_FAILURE; 5829 } 5830 finite_scan->finite_spectral_scan = false; 5831 } 5832 5833 return QDF_STATUS_SUCCESS; 5834 } 5835