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_QCA5018 || 2164 target_type == TARGET_TYPE_QCA6750 || 2165 target_type == TARGET_TYPE_QCA6490) 2166 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; 2167 else if (target_type == TARGET_TYPE_QCA8074 || 2168 target_type == TARGET_TYPE_QCA6018 || 2169 target_type == TARGET_TYPE_QCA6390) 2170 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; 2171 else 2172 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; 2173 2174 if (target_type == TARGET_TYPE_QCA8074 || 2175 target_type == TARGET_TYPE_QCA8074V2 || 2176 target_type == TARGET_TYPE_QCA6018 || 2177 target_type == TARGET_TYPE_QCA5018 || 2178 target_type == TARGET_TYPE_QCN9000 || 2179 target_type == TARGET_TYPE_QCA6490) { 2180 swar->inband_fftbin_size_adj = 1; 2181 swar->null_fftbin_adj = 1; 2182 } else { 2183 swar->inband_fftbin_size_adj = 0; 2184 swar->null_fftbin_adj = 0; 2185 } 2186 2187 if (target_type == TARGET_TYPE_QCA8074V2) 2188 swar->packmode_fftbin_size_adj = 1; 2189 else 2190 swar->packmode_fftbin_size_adj = 0; 2191 } 2192 2193 /** 2194 * target_if_spectral_report_params_init() - Initialize parameters which 2195 * describes the structure of Spectral reports 2196 * 2197 * @rparams: Pointer to Spectral report parameter object 2198 * @target_type: target type 2199 * 2200 * Function to Initialize parameters related to the structure of Spectral 2201 * reports. 2202 * 2203 * Return: void 2204 */ 2205 static void 2206 target_if_spectral_report_params_init( 2207 struct spectral_report_params *rparams, 2208 uint32_t target_type) 2209 { 2210 enum spectral_scan_mode smode; 2211 2212 /* This entries are currently used by gen3 chipsets only. Hence 2213 * initialization is done for gen3 alone. In future if other generations 2214 * needs to use them they have to add proper initial values. 2215 */ 2216 if (target_type == TARGET_TYPE_QCN9000 || 2217 target_type == TARGET_TYPE_QCA5018 || 2218 target_type == TARGET_TYPE_QCA6750 || 2219 target_type == TARGET_TYPE_QCA6490) { 2220 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2; 2221 rparams->num_spectral_detectors = 2222 NUM_SPECTRAL_DETECTORS_GEN3_V2; 2223 smode = SPECTRAL_SCAN_MODE_NORMAL; 2224 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 2225 rparams->fragmentation_160[smode] = false; 2226 rparams->max_agile_ch_width = CH_WIDTH_80P80MHZ; 2227 } else { 2228 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1; 2229 rparams->num_spectral_detectors = 2230 NUM_SPECTRAL_DETECTORS_GEN3_V1; 2231 smode = SPECTRAL_SCAN_MODE_NORMAL; 2232 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 2233 rparams->fragmentation_160[smode] = true; 2234 rparams->max_agile_ch_width = CH_WIDTH_80MHZ; 2235 } 2236 2237 switch (rparams->version) { 2238 case SPECTRAL_REPORT_FORMAT_VERSION_1: 2239 rparams->ssumaary_padding_bytes = 2240 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1; 2241 rparams->fft_report_hdr_len = 2242 FFT_REPORT_HEADER_LENGTH_GEN3_V1; 2243 break; 2244 case SPECTRAL_REPORT_FORMAT_VERSION_2: 2245 rparams->ssumaary_padding_bytes = 2246 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2; 2247 rparams->fft_report_hdr_len = 2248 FFT_REPORT_HEADER_LENGTH_GEN3_V2; 2249 break; 2250 default: 2251 qdf_assert_always(0); 2252 } 2253 2254 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_0] = 2255 SPECTRAL_SCAN_MODE_NORMAL; 2256 if (target_type == TARGET_TYPE_QCN9000 || 2257 target_type == TARGET_TYPE_QCA6490) { 2258 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 2259 SPECTRAL_SCAN_MODE_AGILE; 2260 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 2261 SPECTRAL_SCAN_MODE_INVALID; 2262 } else { 2263 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_1] = 2264 SPECTRAL_SCAN_MODE_NORMAL; 2265 rparams->detid_mode_table[SPECTRAL_DETECTOR_ID_2] = 2266 SPECTRAL_SCAN_MODE_AGILE; 2267 } 2268 } 2269 2270 /** 2271 * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR 2272 * related info 2273 * @twar: Pointer to Spectral timstamp WAR related info 2274 * 2275 * Function to Initialize parameters related to Spectral timestamp WAR 2276 * 2277 * Return: void 2278 */ 2279 static void 2280 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar) 2281 { 2282 enum spectral_scan_mode smode; 2283 2284 smode = SPECTRAL_SCAN_MODE_NORMAL; 2285 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2286 twar->last_fft_timestamp[smode] = 0; 2287 twar->timestamp_war_offset[smode] = 0; 2288 } 2289 twar->target_reset_count = 0; 2290 } 2291 2292 /** 2293 * target_if_pdev_spectral_init() - Initialize target_if Spectral 2294 * functionality for the given pdev 2295 * @pdev: Pointer to pdev object 2296 * 2297 * Function to initialize pointer to spectral target_if internal private data 2298 * 2299 * Return: On success, pointer to Spectral target_if internal private data, on 2300 * failure, NULL 2301 */ 2302 void * 2303 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 2304 { 2305 struct target_if_spectral_ops *p_sops = NULL; 2306 struct target_if_spectral *spectral = NULL; 2307 uint32_t target_type; 2308 uint32_t target_revision; 2309 struct wlan_objmgr_psoc *psoc; 2310 struct wlan_lmac_if_target_tx_ops *tgt_tx_ops; 2311 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2312 QDF_STATUS status; 2313 struct wlan_lmac_if_tx_ops *tx_ops; 2314 2315 if (!pdev) { 2316 spectral_err("SPECTRAL: pdev is NULL!"); 2317 return NULL; 2318 } 2319 spectral = (struct target_if_spectral *)qdf_mem_malloc( 2320 sizeof(struct target_if_spectral)); 2321 if (!spectral) 2322 return spectral; 2323 2324 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 2325 /* Store pdev in Spectral */ 2326 spectral->pdev_obj = pdev; 2327 spectral->vdev_id[SPECTRAL_SCAN_MODE_NORMAL] = WLAN_INVALID_VDEV_ID; 2328 spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE] = WLAN_INVALID_VDEV_ID; 2329 2330 psoc = wlan_pdev_get_psoc(pdev); 2331 2332 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 2333 if (!tx_ops) { 2334 spectral_err("tx_ops is NULL"); 2335 qdf_mem_free(spectral); 2336 return NULL; 2337 } 2338 2339 tgt_tx_ops = &tx_ops->target_tx_ops; 2340 2341 if (tgt_tx_ops->tgt_get_tgt_type) { 2342 target_type = tgt_tx_ops->tgt_get_tgt_type(psoc); 2343 } else { 2344 qdf_mem_free(spectral); 2345 return NULL; 2346 } 2347 2348 if (tgt_tx_ops->tgt_get_tgt_revision) { 2349 target_revision = tgt_tx_ops->tgt_get_tgt_revision(psoc); 2350 } else { 2351 qdf_mem_free(spectral); 2352 return NULL; 2353 } 2354 2355 /* init the function ptr table */ 2356 target_if_spectral_init_dummy_function_table(spectral); 2357 2358 /* get spectral function table */ 2359 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2360 /* TODO : Should this be called here of after ath_attach ? */ 2361 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 2362 spectral_info("HAL_CAP_PHYDIAG : Capable"); 2363 2364 /* TODO: Need to fix the capablity check for RADAR */ 2365 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 2366 spectral_info("HAL_CAP_RADAR : Capable"); 2367 2368 /* TODO : Need to fix the capablity check for SPECTRAL */ 2369 /* TODO : Should this be called here of after ath_attach ? */ 2370 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 2371 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 2372 2373 qdf_spinlock_create(&spectral->spectral_lock); 2374 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 2375 target_if_spectral_clear_stats(spectral); 2376 2377 if (target_type == TARGET_TYPE_QCA8074 || 2378 target_type == TARGET_TYPE_QCA8074V2 || 2379 target_type == TARGET_TYPE_QCA6018 || 2380 target_type == TARGET_TYPE_QCA5018 || 2381 target_type == TARGET_TYPE_QCA6390 || 2382 target_type == TARGET_TYPE_QCA6490 || 2383 target_type == TARGET_TYPE_QCN9000 || 2384 target_type == TARGET_TYPE_QCA6750) 2385 spectral->direct_dma_support = true; 2386 2387 target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar, 2388 target_type); 2389 target_if_spectral_report_params_init(&spectral->rparams, target_type); 2390 2391 if ((target_type == TARGET_TYPE_QCA8074) || 2392 (target_type == TARGET_TYPE_QCA8074V2) || 2393 (target_type == TARGET_TYPE_QCA6018) || 2394 (target_type == TARGET_TYPE_QCA5018) || 2395 (target_type == TARGET_TYPE_QCN9000) || 2396 (target_type == TARGET_TYPE_QCA6290) || 2397 (target_type == TARGET_TYPE_QCA6390) || 2398 (target_type == TARGET_TYPE_QCA6490) || 2399 (target_type == TARGET_TYPE_QCA6750)) { 2400 spectral->spectral_gen = SPECTRAL_GEN3; 2401 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 2402 spectral->tag_sscan_summary_exp = 2403 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 2404 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 2405 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 2406 } else { 2407 spectral->spectral_gen = SPECTRAL_GEN2; 2408 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 2409 spectral->tag_sscan_summary_exp = 2410 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 2411 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 2412 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 2413 } 2414 2415 status = target_if_init_spectral_param_min_max( 2416 &spectral->param_min_max, 2417 spectral->spectral_gen, target_type); 2418 if (QDF_IS_STATUS_ERROR(status)) { 2419 spectral_err("Failed to initialize parameter min max values"); 2420 goto fail; 2421 } 2422 2423 target_if_init_spectral_param_properties(spectral); 2424 /* Init spectral capability */ 2425 if (target_if_init_spectral_capability(spectral, target_type) != 2426 QDF_STATUS_SUCCESS) { 2427 qdf_mem_free(spectral); 2428 return NULL; 2429 } 2430 if (target_if_spectral_attach_simulation(spectral) < 0) 2431 return NULL; 2432 2433 target_if_init_spectral_ops(spectral); 2434 target_if_spectral_timestamp_war_init(&spectral->timestamp_war); 2435 2436 /* Spectral mode specific init */ 2437 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2438 spectral->params_valid[smode] = false; 2439 qdf_spinlock_create(&spectral->param_info[smode].osps_lock); 2440 spectral->param_info[smode].osps_cache.osc_is_valid = 0; 2441 } 2442 2443 target_if_spectral_register_funcs(spectral, &spectral_ops); 2444 2445 if (target_if_spectral_check_hw_capability(spectral) == false) { 2446 goto fail; 2447 } else { 2448 /* 2449 * TODO: Once the driver architecture transitions to chipset 2450 * versioning based checks, reflect this here. 2451 */ 2452 spectral->is_160_format = false; 2453 spectral->is_lb_edge_extrabins_format = false; 2454 spectral->is_rb_edge_extrabins_format = false; 2455 2456 if (target_type == TARGET_TYPE_QCA9984 || 2457 target_type == TARGET_TYPE_QCA9888) { 2458 spectral->is_160_format = true; 2459 spectral->is_lb_edge_extrabins_format = true; 2460 spectral->is_rb_edge_extrabins_format = true; 2461 } else if ((target_type == TARGET_TYPE_AR900B) && 2462 (target_revision == AR900B_REV_2)) { 2463 spectral->is_rb_edge_extrabins_format = true; 2464 } 2465 2466 if (target_type == TARGET_TYPE_QCA9984 || 2467 target_type == TARGET_TYPE_QCA9888) 2468 spectral->is_sec80_rssi_war_required = true; 2469 2470 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST; 2471 2472 if (spectral->spectral_gen == SPECTRAL_GEN3) 2473 init_160mhz_delivery_state_machine(spectral); 2474 } 2475 2476 return spectral; 2477 2478 fail: 2479 target_if_spectral_detach(spectral); 2480 return NULL; 2481 } 2482 2483 /** 2484 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 2485 * functionality for the given pdev 2486 * @pdev: Pointer to pdev object 2487 * 2488 * Function to de-initialize pointer to spectral target_if internal private data 2489 * 2490 * Return: None 2491 */ 2492 void 2493 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 2494 { 2495 struct target_if_spectral *spectral = NULL; 2496 2497 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2498 if (!spectral) { 2499 spectral_err("SPECTRAL : Module doesn't exist"); 2500 return; 2501 } 2502 target_if_spectral_detach(spectral); 2503 2504 return; 2505 } 2506 2507 /** 2508 * target_if_psoc_spectral_deinit() - De-initialize target_if Spectral 2509 * functionality for the given psoc 2510 * @psoc: Pointer to psoc object 2511 * 2512 * Function to de-initialize pointer to psoc spectral target_if internal 2513 * private data 2514 * 2515 * Return: None 2516 */ 2517 static void 2518 target_if_psoc_spectral_deinit(struct wlan_objmgr_psoc *psoc) 2519 { 2520 struct target_if_psoc_spectral *psoc_spectral; 2521 2522 if (!psoc) { 2523 spectral_err("psoc is null"); 2524 return; 2525 } 2526 2527 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 2528 if (!psoc_spectral) { 2529 spectral_err("Spectral target_if psoc object is null"); 2530 return; 2531 } 2532 2533 qdf_mem_free(psoc_spectral); 2534 } 2535 2536 /** 2537 * target_if_psoc_spectral_init() - Initialize target_if Spectral 2538 * functionality for the given psoc 2539 * @psoc: Pointer to psoc object 2540 * 2541 * Function to initialize pointer to psoc spectral target_if internal 2542 * private data 2543 * 2544 * Return: On success, pointer to Spectral psoc target_if internal 2545 * private data, on failure, NULL 2546 */ 2547 static void * 2548 target_if_psoc_spectral_init(struct wlan_objmgr_psoc *psoc) 2549 { 2550 struct target_if_psoc_spectral *psoc_spectral = NULL; 2551 2552 if (!psoc) { 2553 spectral_err("psoc is null"); 2554 goto fail; 2555 } 2556 2557 psoc_spectral = (struct target_if_psoc_spectral *)qdf_mem_malloc( 2558 sizeof(struct target_if_psoc_spectral)); 2559 if (!psoc_spectral) { 2560 spectral_err("Spectral lmac psoc object allocation failed"); 2561 goto fail; 2562 } 2563 2564 psoc_spectral->psoc_obj = psoc; 2565 2566 return psoc_spectral; 2567 2568 fail: 2569 if (psoc_spectral) 2570 target_if_psoc_spectral_deinit(psoc); 2571 2572 return psoc_spectral; 2573 } 2574 2575 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the 2576 * corresponding translation for Agile channel width. 2577 * @spectral: pointer to Spectral object 2578 * @chwidth: operating channel width 2579 * @is_80_80_agile: Indicates an 80+80 agile Scan request 2580 * 2581 * Return: The translated channel width enum. 2582 */ 2583 static enum phy_ch_width 2584 target_if_spectral_find_agile_width(struct target_if_spectral *spectral, 2585 enum phy_ch_width chwidth, 2586 bool is_80_80_agile) 2587 { 2588 enum phy_ch_width agile_width; 2589 struct wlan_objmgr_pdev *pdev; 2590 struct wlan_objmgr_psoc *psoc; 2591 2592 if (!spectral) { 2593 spectral_err("Spectral object is null"); 2594 return CH_WIDTH_INVALID; 2595 } 2596 2597 pdev = spectral->pdev_obj; 2598 if (!pdev) { 2599 spectral_err("pdev is null"); 2600 return CH_WIDTH_INVALID; 2601 } 2602 2603 psoc = wlan_pdev_get_psoc(pdev); 2604 if (!psoc) { 2605 spectral_err("psoc is null"); 2606 return CH_WIDTH_INVALID; 2607 } 2608 2609 switch (chwidth) { 2610 case CH_WIDTH_20MHZ: 2611 agile_width = CH_WIDTH_20MHZ; 2612 break; 2613 2614 case CH_WIDTH_40MHZ: 2615 agile_width = CH_WIDTH_40MHZ; 2616 break; 2617 2618 case CH_WIDTH_80MHZ: 2619 agile_width = CH_WIDTH_80MHZ; 2620 break; 2621 2622 case CH_WIDTH_80P80MHZ: 2623 if (wlan_psoc_nif_fw_ext_cap_get(psoc, 2624 WLAN_SOC_RESTRICTED_80P80_SUPPORT) && !is_80_80_agile) 2625 agile_width = CH_WIDTH_160MHZ; 2626 else 2627 agile_width = CH_WIDTH_80P80MHZ; 2628 2629 if (agile_width > spectral->rparams.max_agile_ch_width) 2630 agile_width = spectral->rparams.max_agile_ch_width; 2631 break; 2632 2633 case CH_WIDTH_160MHZ: 2634 if (wlan_psoc_nif_fw_ext_cap_get(psoc, 2635 WLAN_SOC_RESTRICTED_80P80_SUPPORT) && is_80_80_agile) 2636 agile_width = CH_WIDTH_80P80MHZ; 2637 else 2638 agile_width = CH_WIDTH_160MHZ; 2639 2640 if (agile_width > spectral->rparams.max_agile_ch_width) 2641 agile_width = spectral->rparams.max_agile_ch_width; 2642 break; 2643 2644 default: 2645 spectral_err("Invalid channel width %d", chwidth); 2646 agile_width = CH_WIDTH_INVALID; 2647 break; 2648 } 2649 2650 return agile_width; 2651 } 2652 2653 /** 2654 * target_if_calculate_center_freq() - Helper routine to 2655 * check whether given frequency is center frequency of a 2656 * WLAN channel 2657 * 2658 * @spectral: Pointer to Spectral object 2659 * @chan_freq: Center frequency of a WLAN channel 2660 * @is_valid: Indicates whether given frequency is valid 2661 * 2662 * Return: QDF_STATUS 2663 */ 2664 static QDF_STATUS 2665 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, 2666 uint32_t chan_freq, 2667 bool *is_valid) 2668 { 2669 struct regulatory_channel *cur_chan_list; 2670 int i; 2671 2672 if (!pdev) { 2673 spectral_err("pdev object is null"); 2674 return QDF_STATUS_E_FAILURE; 2675 } 2676 2677 if (!is_valid) { 2678 spectral_err("is valid argument is null"); 2679 return QDF_STATUS_E_FAILURE; 2680 } 2681 2682 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); 2683 if (!cur_chan_list) 2684 return QDF_STATUS_E_FAILURE; 2685 2686 if (wlan_reg_get_current_chan_list( 2687 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 2688 spectral_err("Failed to get cur_chan list"); 2689 qdf_mem_free(cur_chan_list); 2690 return QDF_STATUS_E_FAILURE; 2691 } 2692 2693 *is_valid = false; 2694 for (i = 0; i < NUM_CHANNELS; i++) { 2695 uint32_t flags; 2696 uint32_t center_freq; 2697 2698 flags = cur_chan_list[i].chan_flags; 2699 center_freq = cur_chan_list[i].center_freq; 2700 2701 if (!(flags & REGULATORY_CHAN_DISABLED) && 2702 (center_freq == chan_freq)) { 2703 *is_valid = true; 2704 break; 2705 } 2706 } 2707 2708 qdf_mem_free(cur_chan_list); 2709 2710 return QDF_STATUS_SUCCESS; 2711 } 2712 2713 /** 2714 * target_if_calculate_center_freq() - Helper routine to 2715 * find the center frequency of the agile span from a 2716 * WLAN channel center frequency 2717 * 2718 * @spectral: Pointer to Spectral object 2719 * @ch_width: Channel width array 2720 * @chan_freq: Center frequency of a WLAN channel 2721 * @center_freq: Pointer to center frequency 2722 * 2723 * Return: QDF_STATUS 2724 */ 2725 static QDF_STATUS 2726 target_if_calculate_center_freq(struct target_if_spectral *spectral, 2727 enum phy_ch_width *ch_width, 2728 uint16_t chan_freq, 2729 uint16_t *center_freq) 2730 { 2731 enum phy_ch_width agile_ch_width; 2732 2733 if (!spectral) { 2734 spectral_err("spectral target if object is null"); 2735 return QDF_STATUS_E_FAILURE; 2736 } 2737 2738 if (!ch_width) { 2739 spectral_err("Channel width array is null"); 2740 return QDF_STATUS_E_INVAL; 2741 } 2742 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 2743 2744 if (!center_freq) { 2745 spectral_err("center_freq argument is null"); 2746 return QDF_STATUS_E_FAILURE; 2747 } 2748 2749 if (agile_ch_width == CH_WIDTH_20MHZ) { 2750 *center_freq = chan_freq; 2751 } else { 2752 uint16_t start_freq; 2753 uint16_t end_freq; 2754 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2755 enum channel_state state; 2756 2757 state = wlan_reg_get_5g_bonded_channel_and_state_for_freq 2758 (spectral->pdev_obj, chan_freq, agile_ch_width, 2759 &bonded_chan_ptr); 2760 if (state == CHANNEL_STATE_DISABLE || 2761 state == CHANNEL_STATE_INVALID) { 2762 spectral_err("Channel state is disable or invalid"); 2763 return QDF_STATUS_E_FAILURE; 2764 } 2765 if (!bonded_chan_ptr) { 2766 spectral_err("Bonded channel is not found"); 2767 return QDF_STATUS_E_FAILURE; 2768 } 2769 start_freq = bonded_chan_ptr->start_freq; 2770 end_freq = bonded_chan_ptr->end_freq; 2771 *center_freq = (start_freq + end_freq) >> 1; 2772 } 2773 2774 return QDF_STATUS_SUCCESS; 2775 } 2776 2777 /** 2778 * target_if_validate_center_freq() - Helper routine to 2779 * validate user provided agile center frequency 2780 * 2781 * @spectral: Pointer to Spectral object 2782 * @ch_width: Channel width array 2783 * @center_freq: User provided agile span center frequency 2784 * @is_valid: Indicates whether agile span center frequency is valid 2785 * 2786 * Return: QDF_STATUS 2787 */ 2788 static QDF_STATUS 2789 target_if_validate_center_freq(struct target_if_spectral *spectral, 2790 enum phy_ch_width *ch_width, 2791 uint16_t center_freq, 2792 bool *is_valid) 2793 { 2794 enum phy_ch_width agile_ch_width; 2795 struct wlan_objmgr_pdev *pdev; 2796 QDF_STATUS status; 2797 2798 if (!spectral) { 2799 spectral_err("spectral target if object is null"); 2800 return QDF_STATUS_E_FAILURE; 2801 } 2802 2803 if (!ch_width) { 2804 spectral_err("channel width array is null"); 2805 return QDF_STATUS_E_INVAL; 2806 } 2807 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 2808 2809 if (!is_valid) { 2810 spectral_err("is_valid argument is null"); 2811 return QDF_STATUS_E_FAILURE; 2812 } 2813 2814 pdev = spectral->pdev_obj; 2815 2816 if (agile_ch_width == CH_WIDTH_20MHZ) { 2817 status = target_if_is_center_freq_of_any_chan 2818 (pdev, center_freq, is_valid); 2819 if (QDF_IS_STATUS_ERROR(status)) 2820 return QDF_STATUS_E_FAILURE; 2821 } else { 2822 uint16_t start_freq; 2823 uint16_t end_freq; 2824 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2825 bool is_chan; 2826 2827 status = target_if_is_center_freq_of_any_chan 2828 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2829 &is_chan); 2830 if (QDF_IS_STATUS_ERROR(status)) 2831 return QDF_STATUS_E_FAILURE; 2832 2833 if (is_chan) { 2834 uint32_t calulated_center_freq; 2835 enum channel_state st; 2836 2837 st = wlan_reg_get_5g_bonded_channel_and_state_for_freq 2838 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2839 agile_ch_width, 2840 &bonded_chan_ptr); 2841 if (st == CHANNEL_STATE_DISABLE || 2842 st == CHANNEL_STATE_INVALID) { 2843 spectral_err("Channel state disable/invalid"); 2844 return QDF_STATUS_E_FAILURE; 2845 } 2846 if (!bonded_chan_ptr) { 2847 spectral_err("Bonded channel is not found"); 2848 return QDF_STATUS_E_FAILURE; 2849 } 2850 start_freq = bonded_chan_ptr->start_freq; 2851 end_freq = bonded_chan_ptr->end_freq; 2852 calulated_center_freq = (start_freq + end_freq) >> 1; 2853 *is_valid = (center_freq == calulated_center_freq); 2854 } else { 2855 *is_valid = false; 2856 } 2857 } 2858 2859 return QDF_STATUS_SUCCESS; 2860 } 2861 2862 /** 2863 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to 2864 * check whether agile span overlaps with current operating band. 2865 * 2866 * @spectral: Pointer to Spectral object 2867 * @ch_width: Channel width array 2868 * @center_freq: Agile span center frequency 2869 * @is_overlapping: Indicates whether Agile span overlaps with operating span 2870 * 2871 * Helper routine to check whether agile span overlaps with current 2872 * operating band. 2873 * 2874 * Return: QDF_STATUS 2875 */ 2876 static QDF_STATUS 2877 target_if_is_agile_span_overlap_with_operating_span 2878 (struct target_if_spectral *spectral, 2879 enum phy_ch_width *ch_width, 2880 struct spectral_config_frequency *center_freq, 2881 bool *is_overlapping) 2882 { 2883 enum phy_ch_width op_ch_width; 2884 enum phy_ch_width agile_ch_width; 2885 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2886 struct wlan_objmgr_vdev *vdev; 2887 struct wlan_objmgr_pdev *pdev; 2888 int16_t chan_freq; 2889 uint32_t op_start_freq; 2890 uint32_t op_end_freq; 2891 uint32_t agile_start_freq; 2892 uint32_t agile_end_freq; 2893 uint32_t cfreq2; 2894 2895 if (!spectral) { 2896 spectral_err("Spectral object is NULL"); 2897 return QDF_STATUS_E_FAILURE; 2898 } 2899 2900 pdev = spectral->pdev_obj; 2901 if (!pdev) { 2902 spectral_err("pdev object is NULL"); 2903 return QDF_STATUS_E_FAILURE; 2904 } 2905 2906 if (!ch_width) { 2907 spectral_err("channel width array is null"); 2908 return QDF_STATUS_E_FAILURE; 2909 } 2910 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 2911 if (op_ch_width == CH_WIDTH_INVALID) { 2912 spectral_err("Invalid channel width"); 2913 return QDF_STATUS_E_INVAL; 2914 } 2915 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 2916 if (agile_ch_width == CH_WIDTH_INVALID) { 2917 spectral_err("Invalid channel width"); 2918 return QDF_STATUS_E_INVAL; 2919 } 2920 2921 if (!is_overlapping) { 2922 spectral_err("Argument(is_overlapping) is NULL"); 2923 return QDF_STATUS_E_FAILURE; 2924 } 2925 *is_overlapping = false; 2926 2927 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 2928 if (!vdev) { 2929 spectral_err("vdev is NULL"); 2930 return QDF_STATUS_E_FAILURE; 2931 } 2932 chan_freq = target_if_vdev_get_chan_freq(vdev); 2933 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); 2934 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2935 if (cfreq2 < 0) { 2936 spectral_err("cfreq2 is invalid"); 2937 return QDF_STATUS_E_FAILURE; 2938 } 2939 2940 if (op_ch_width == CH_WIDTH_20MHZ) { 2941 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; 2942 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; 2943 } else { 2944 enum channel_state state; 2945 2946 state = wlan_reg_get_5g_bonded_channel_and_state_for_freq 2947 (pdev, chan_freq, op_ch_width, &bonded_chan_ptr); 2948 if (state == CHANNEL_STATE_DISABLE || 2949 state == CHANNEL_STATE_INVALID) { 2950 spectral_err("Channel state is disable or invalid"); 2951 return QDF_STATUS_E_FAILURE; 2952 } 2953 if (!bonded_chan_ptr) { 2954 spectral_err("Bonded channel is not found"); 2955 return QDF_STATUS_E_FAILURE; 2956 } 2957 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; 2958 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; 2959 } 2960 2961 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 2962 agile_start_freq = center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 2963 agile_end_freq = center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 2964 if (agile_end_freq > op_start_freq && 2965 op_end_freq > agile_start_freq) 2966 *is_overlapping = true; 2967 2968 agile_start_freq = center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 2969 agile_end_freq = center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 2970 if (agile_end_freq > op_start_freq && 2971 op_end_freq > agile_start_freq) 2972 *is_overlapping = true; 2973 } else { 2974 agile_start_freq = center_freq->cfreq1 - 2975 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2976 agile_end_freq = center_freq->cfreq1 + 2977 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2978 if (agile_end_freq > op_start_freq && 2979 op_end_freq > agile_start_freq) 2980 *is_overlapping = true; 2981 } 2982 2983 if (op_ch_width == CH_WIDTH_80P80MHZ) { 2984 uint32_t sec80_start_feq; 2985 uint32_t sec80_end_freq; 2986 2987 sec80_start_feq = cfreq2 - FREQ_OFFSET_40MHZ; 2988 sec80_end_freq = cfreq2 + FREQ_OFFSET_40MHZ; 2989 2990 if (agile_ch_width == CH_WIDTH_80P80MHZ) { 2991 agile_start_freq = 2992 center_freq->cfreq1 - FREQ_OFFSET_40MHZ; 2993 agile_end_freq = 2994 center_freq->cfreq1 + FREQ_OFFSET_40MHZ; 2995 if (agile_end_freq > sec80_start_feq && 2996 sec80_end_freq > agile_start_freq) 2997 *is_overlapping = true; 2998 2999 agile_start_freq = 3000 center_freq->cfreq2 - FREQ_OFFSET_40MHZ; 3001 agile_end_freq = 3002 center_freq->cfreq2 + FREQ_OFFSET_40MHZ; 3003 if (agile_end_freq > sec80_start_feq && 3004 sec80_end_freq > agile_start_freq) 3005 *is_overlapping = true; 3006 } else { 3007 agile_start_freq = center_freq->cfreq1 - 3008 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 3009 agile_end_freq = center_freq->cfreq1 + 3010 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 3011 if (agile_end_freq > sec80_start_feq && 3012 sec80_end_freq > agile_start_freq) 3013 *is_overlapping = true; 3014 } 3015 } 3016 3017 return QDF_STATUS_SUCCESS; 3018 } 3019 3020 /** 3021 * target_if_spectral_populate_chwidth() - Helper routine to 3022 * populate channel width for different Spectral modes 3023 * 3024 * @spectral: Pointer to Spectral object 3025 * @ch_width: Channel width array 3026 * @is_80_80_agile: Indicates whether 80+80 agile scan is requested 3027 * 3028 * Helper routine to populate channel width for different Spectral modes 3029 * 3030 * Return: QDF_STATUS 3031 */ 3032 static QDF_STATUS 3033 target_if_spectral_populate_chwidth(struct target_if_spectral *spectral, 3034 enum phy_ch_width *ch_width, 3035 bool is_80_80_agile) { 3036 struct wlan_objmgr_vdev *vdev; 3037 enum spectral_scan_mode smode; 3038 enum phy_ch_width vdev_ch_width; 3039 3040 smode = SPECTRAL_SCAN_MODE_NORMAL; 3041 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 3042 ch_width[smode] = CH_WIDTH_INVALID; 3043 3044 if (!spectral) { 3045 spectral_err("Spectral object is null"); 3046 return QDF_STATUS_E_INVAL; 3047 } 3048 3049 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_NORMAL); 3050 if (!vdev) { 3051 spectral_err("vdev is null"); 3052 return QDF_STATUS_E_FAILURE; 3053 } 3054 3055 vdev_ch_width = target_if_vdev_get_ch_width(vdev); 3056 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3057 if (vdev_ch_width == CH_WIDTH_INVALID) { 3058 spectral_err("Invalid channel width %d", vdev_ch_width); 3059 return QDF_STATUS_E_FAILURE; 3060 } 3061 3062 ch_width[SPECTRAL_SCAN_MODE_NORMAL] = vdev_ch_width; 3063 ch_width[SPECTRAL_SCAN_MODE_AGILE] = 3064 target_if_spectral_find_agile_width(spectral, vdev_ch_width, 3065 is_80_80_agile); 3066 3067 return QDF_STATUS_SUCCESS; 3068 } 3069 3070 /** 3071 * target_if_spectral_is_valid_80p80_freq() - API to check whether given 3072 * (cfreq1, cfreq2) pair forms a valid 80+80 combination 3073 * @pdev: pointer to pdev 3074 * @cfreq1: center frequency 1 3075 * @cfreq2: center frequency 2 3076 * 3077 * API to check whether given (cfreq1, cfreq2) pair forms a valid 80+80 3078 * combination 3079 * 3080 * Return: true or false 3081 */ 3082 static bool 3083 target_if_spectral_is_valid_80p80_freq(struct wlan_objmgr_pdev *pdev, 3084 uint32_t cfreq1, uint32_t cfreq2) 3085 { 3086 struct ch_params ch_params; 3087 enum channel_state chan_state1; 3088 enum channel_state chan_state2; 3089 struct wlan_objmgr_psoc *psoc; 3090 3091 qdf_assert_always(pdev); 3092 psoc = wlan_pdev_get_psoc(pdev); 3093 qdf_assert_always(psoc); 3094 3095 /* In restricted 80P80 MHz enabled, only one 80+80 MHz 3096 * channel is supported with cfreq=5690 and cfreq=5775. 3097 */ 3098 if (wlan_psoc_nif_fw_ext_cap_get( 3099 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) 3100 return CHAN_WITHIN_RESTRICTED_80P80(cfreq1, cfreq2); 3101 3102 ch_params.center_freq_seg1 = wlan_reg_freq_to_chan(pdev, cfreq2); 3103 ch_params.mhz_freq_seg1 = cfreq2; 3104 ch_params.ch_width = CH_WIDTH_80P80MHZ; 3105 wlan_reg_set_channel_params_for_freq(pdev, cfreq1 - FREQ_OFFSET_10MHZ, 3106 0, &ch_params); 3107 3108 if (ch_params.ch_width != CH_WIDTH_80P80MHZ) 3109 return false; 3110 3111 if (ch_params.mhz_freq_seg0 != cfreq1 || 3112 ch_params.mhz_freq_seg1 != cfreq2) 3113 return false; 3114 3115 chan_state1 = wlan_reg_get_5g_bonded_channel_state_for_freq( 3116 pdev, 3117 ch_params.mhz_freq_seg0 - FREQ_OFFSET_10MHZ, 3118 CH_WIDTH_80MHZ); 3119 if ((chan_state1 == CHANNEL_STATE_DISABLE) || 3120 (chan_state1 == CHANNEL_STATE_INVALID)) 3121 return false; 3122 3123 chan_state2 = wlan_reg_get_5g_bonded_channel_state_for_freq( 3124 pdev, 3125 ch_params.mhz_freq_seg1 - FREQ_OFFSET_10MHZ, 3126 CH_WIDTH_80MHZ); 3127 if ((chan_state2 == CHANNEL_STATE_DISABLE) || 3128 (chan_state2 == CHANNEL_STATE_INVALID)) 3129 return false; 3130 3131 if (abs(ch_params.mhz_freq_seg0 - ch_params.mhz_freq_seg1) <= 3132 FREQ_OFFSET_80MHZ) 3133 return false; 3134 3135 return true; 3136 } 3137 3138 /** 3139 * _target_if_set_spectral_config() - Set spectral config 3140 * @spectral: Pointer to spectral object 3141 * @param: Spectral parameter id and value 3142 * @smode: Spectral scan mode 3143 * @err: Spectral error code 3144 * 3145 * API to set spectral configurations 3146 * 3147 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3148 */ 3149 static QDF_STATUS 3150 _target_if_set_spectral_config(struct target_if_spectral *spectral, 3151 const struct spectral_cp_param *param, 3152 const enum spectral_scan_mode smode, 3153 enum spectral_cp_error_code *err) 3154 { 3155 struct spectral_config params; 3156 struct target_if_spectral_ops *p_sops; 3157 struct spectral_config *sparams; 3158 QDF_STATUS status; 3159 bool is_overlapping; 3160 uint16_t agile_cfreq; 3161 bool is_valid_chan; 3162 struct spectral_param_min_max *param_min_max; 3163 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 3164 enum spectral_scan_mode m; 3165 struct spectral_config_frequency center_freq = {0}; 3166 3167 if (!err) { 3168 spectral_err("Error code argument is null"); 3169 QDF_ASSERT(0); 3170 return QDF_STATUS_E_FAILURE; 3171 } 3172 *err = SPECTRAL_SCAN_ERR_INVALID; 3173 3174 if (!param) { 3175 spectral_err("Parameter object is null"); 3176 return QDF_STATUS_E_FAILURE; 3177 } 3178 3179 if (!spectral) { 3180 spectral_err("spectral object is NULL"); 3181 return QDF_STATUS_E_FAILURE; 3182 } 3183 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3184 param_min_max = &spectral->param_min_max; 3185 3186 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3187 spectral_err("Invalid Spectral mode %u", smode); 3188 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3189 return QDF_STATUS_E_FAILURE; 3190 } 3191 3192 sparams = &spectral->params[smode]; 3193 m = SPECTRAL_SCAN_MODE_NORMAL; 3194 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 3195 ch_width[m] = CH_WIDTH_INVALID; 3196 3197 if (!spectral->params_valid[smode]) { 3198 target_if_spectral_info_read(spectral, 3199 smode, 3200 TARGET_IF_SPECTRAL_INFO_PARAMS, 3201 &spectral->params[smode], 3202 sizeof(spectral->params[smode])); 3203 spectral->params_valid[smode] = true; 3204 } 3205 3206 switch (param->id) { 3207 case SPECTRAL_PARAM_FFT_PERIOD: 3208 sparams->ss_fft_period = param->value; 3209 break; 3210 case SPECTRAL_PARAM_SCAN_PERIOD: 3211 sparams->ss_period = param->value; 3212 break; 3213 case SPECTRAL_PARAM_SCAN_COUNT: 3214 sparams->ss_count = param->value; 3215 break; 3216 case SPECTRAL_PARAM_SHORT_REPORT: 3217 sparams->ss_short_report = (!!param->value) ? true : false; 3218 break; 3219 case SPECTRAL_PARAM_SPECT_PRI: 3220 sparams->ss_spectral_pri = (!!param->value) ? true : false; 3221 break; 3222 case SPECTRAL_PARAM_FFT_SIZE: 3223 status = target_if_spectral_populate_chwidth 3224 (spectral, ch_width, spectral->params 3225 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 3226 if (QDF_IS_STATUS_ERROR(status)) 3227 return QDF_STATUS_E_FAILURE; 3228 if ((param->value < param_min_max->fft_size_min) || 3229 (param->value > param_min_max->fft_size_max 3230 [ch_width[smode]])) { 3231 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3232 return QDF_STATUS_E_FAILURE; 3233 } 3234 sparams->ss_fft_size = param->value; 3235 break; 3236 case SPECTRAL_PARAM_GC_ENA: 3237 sparams->ss_gc_ena = !!param->value; 3238 break; 3239 case SPECTRAL_PARAM_RESTART_ENA: 3240 sparams->ss_restart_ena = !!param->value; 3241 break; 3242 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 3243 sparams->ss_noise_floor_ref = param->value; 3244 break; 3245 case SPECTRAL_PARAM_INIT_DELAY: 3246 sparams->ss_init_delay = param->value; 3247 break; 3248 case SPECTRAL_PARAM_NB_TONE_THR: 3249 sparams->ss_nb_tone_thr = param->value; 3250 break; 3251 case SPECTRAL_PARAM_STR_BIN_THR: 3252 sparams->ss_str_bin_thr = param->value; 3253 break; 3254 case SPECTRAL_PARAM_WB_RPT_MODE: 3255 sparams->ss_wb_rpt_mode = !!param->value; 3256 break; 3257 case SPECTRAL_PARAM_RSSI_RPT_MODE: 3258 sparams->ss_rssi_rpt_mode = !!param->value; 3259 break; 3260 case SPECTRAL_PARAM_RSSI_THR: 3261 sparams->ss_rssi_thr = param->value; 3262 break; 3263 case SPECTRAL_PARAM_PWR_FORMAT: 3264 sparams->ss_pwr_format = !!param->value; 3265 break; 3266 case SPECTRAL_PARAM_RPT_MODE: 3267 if ((param->value < SPECTRAL_PARAM_RPT_MODE_MIN) || 3268 (param->value > SPECTRAL_PARAM_RPT_MODE_MAX)) { 3269 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3270 return QDF_STATUS_E_FAILURE; 3271 } 3272 sparams->ss_rpt_mode = param->value; 3273 break; 3274 case SPECTRAL_PARAM_BIN_SCALE: 3275 sparams->ss_bin_scale = param->value; 3276 break; 3277 case SPECTRAL_PARAM_DBM_ADJ: 3278 sparams->ss_dbm_adj = !!param->value; 3279 break; 3280 case SPECTRAL_PARAM_CHN_MASK: 3281 sparams->ss_chn_mask = param->value; 3282 break; 3283 case SPECTRAL_PARAM_FREQUENCY: 3284 status = target_if_spectral_populate_chwidth( 3285 spectral, ch_width, param->freq.cfreq2 > 0); 3286 if (QDF_IS_STATUS_ERROR(status)) { 3287 spectral_err("Failed to populate channel width"); 3288 return QDF_STATUS_E_FAILURE; 3289 } 3290 3291 if (ch_width[smode] != CH_WIDTH_80P80MHZ && 3292 param->freq.cfreq2) { 3293 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3294 spectral_err("Non zero cfreq2 expected for 80p80 only"); 3295 return QDF_STATUS_E_INVAL; 3296 } 3297 3298 if (ch_width[smode] == CH_WIDTH_80P80MHZ && 3299 !param->freq.cfreq2) { 3300 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3301 spectral_err("Non zero cfreq2 expected for 80p80"); 3302 return QDF_STATUS_E_INVAL; 3303 } 3304 3305 status = target_if_is_center_freq_of_any_chan 3306 (spectral->pdev_obj, param->freq.cfreq1, 3307 &is_valid_chan); 3308 if (QDF_IS_STATUS_ERROR(status)) 3309 return QDF_STATUS_E_FAILURE; 3310 3311 if (is_valid_chan) { 3312 status = target_if_calculate_center_freq( 3313 spectral, ch_width, 3314 param->freq.cfreq1, 3315 &agile_cfreq); 3316 if (QDF_IS_STATUS_ERROR(status)) { 3317 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3318 return QDF_STATUS_E_FAILURE; 3319 } 3320 } else { 3321 bool is_valid_agile_cfreq; 3322 3323 status = target_if_validate_center_freq 3324 (spectral, ch_width, param->freq.cfreq1, 3325 &is_valid_agile_cfreq); 3326 if (QDF_IS_STATUS_ERROR(status)) 3327 return QDF_STATUS_E_FAILURE; 3328 3329 if (!is_valid_agile_cfreq) { 3330 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3331 spectral_err("Invalid agile center frequency"); 3332 return QDF_STATUS_E_FAILURE; 3333 } 3334 3335 agile_cfreq = param->freq.cfreq1; 3336 } 3337 center_freq.cfreq1 = agile_cfreq; 3338 3339 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 3340 status = target_if_is_center_freq_of_any_chan 3341 (spectral->pdev_obj, param->freq.cfreq2, 3342 &is_valid_chan); 3343 if (QDF_IS_STATUS_ERROR(status)) 3344 return QDF_STATUS_E_FAILURE; 3345 3346 if (is_valid_chan) { 3347 status = target_if_calculate_center_freq( 3348 spectral, ch_width, 3349 param->freq.cfreq2, 3350 &agile_cfreq); 3351 if (QDF_IS_STATUS_ERROR(status)) { 3352 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3353 return QDF_STATUS_E_FAILURE; 3354 } 3355 } else { 3356 bool is_valid_agile_cfreq; 3357 3358 status = target_if_validate_center_freq 3359 (spectral, ch_width, param->freq.cfreq2, 3360 &is_valid_agile_cfreq); 3361 if (QDF_IS_STATUS_ERROR(status)) 3362 return QDF_STATUS_E_FAILURE; 3363 3364 if (!is_valid_agile_cfreq) { 3365 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3366 spectral_err("Invalid agile center frequency"); 3367 return QDF_STATUS_E_FAILURE; 3368 } 3369 3370 agile_cfreq = param->freq.cfreq2; 3371 } 3372 center_freq.cfreq2 = agile_cfreq; 3373 } 3374 3375 status = target_if_is_agile_span_overlap_with_operating_span 3376 (spectral, ch_width, 3377 ¢er_freq, &is_overlapping); 3378 if (QDF_IS_STATUS_ERROR(status)) 3379 return QDF_STATUS_E_FAILURE; 3380 3381 if (is_overlapping) { 3382 spectral_err("Agile freq %u, %u overlaps with operating span", 3383 center_freq.cfreq1, center_freq.cfreq2); 3384 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3385 return QDF_STATUS_E_FAILURE; 3386 } 3387 3388 if (ch_width[smode] == CH_WIDTH_80P80MHZ) { 3389 bool is_valid_80p80; 3390 3391 is_valid_80p80 = target_if_spectral_is_valid_80p80_freq( 3392 spectral->pdev_obj, 3393 center_freq.cfreq1, 3394 center_freq.cfreq2); 3395 3396 if (!is_valid_80p80) { 3397 spectral_err("Agile freq %u, %u is invalid 80+80 combination", 3398 center_freq.cfreq1, 3399 center_freq.cfreq2); 3400 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3401 return QDF_STATUS_E_FAILURE; 3402 } 3403 } 3404 3405 sparams->ss_frequency.cfreq1 = center_freq.cfreq1; 3406 sparams->ss_frequency.cfreq2 = center_freq.cfreq2; 3407 3408 break; 3409 } 3410 3411 p_sops->configure_spectral(spectral, sparams, smode); 3412 /* only to validate the writes */ 3413 p_sops->get_spectral_config(spectral, ¶ms, smode); 3414 return QDF_STATUS_SUCCESS; 3415 } 3416 3417 QDF_STATUS 3418 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 3419 const struct spectral_cp_param *param, 3420 const enum spectral_scan_mode smode, 3421 enum spectral_cp_error_code *err) 3422 { 3423 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; 3424 struct target_if_spectral *spectral; 3425 QDF_STATUS status; 3426 3427 if (!err) { 3428 spectral_err("Error code argument is null"); 3429 QDF_ASSERT(0); 3430 return QDF_STATUS_E_FAILURE; 3431 } 3432 *err = SPECTRAL_SCAN_ERR_INVALID; 3433 3434 if (!pdev) { 3435 spectral_err("pdev object is NULL"); 3436 return QDF_STATUS_E_FAILURE; 3437 } 3438 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3439 if (!spectral) { 3440 spectral_err("spectral object is NULL"); 3441 return QDF_STATUS_E_FAILURE; 3442 } 3443 3444 if (!param) { 3445 spectral_err("parameter object is NULL"); 3446 return QDF_STATUS_E_FAILURE; 3447 } 3448 3449 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3450 spectral_err("Invalid Spectral mode %u", smode); 3451 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3452 return QDF_STATUS_E_FAILURE; 3453 } 3454 3455 if (!spectral->properties[smode][param->id].supported) { 3456 spectral_err("Spectral parameter(%u) unsupported for mode %u", 3457 param->id, smode); 3458 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 3459 return QDF_STATUS_E_FAILURE; 3460 } 3461 3462 if (spectral->properties[smode][param->id].common_all_modes) { 3463 spectral_warn("Setting Spectral parameter %u for all modes", 3464 param->id); 3465 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { 3466 status = _target_if_set_spectral_config 3467 (spectral, param, mode, err); 3468 if (QDF_IS_STATUS_ERROR(status)) 3469 return QDF_STATUS_E_FAILURE; 3470 } 3471 return QDF_STATUS_SUCCESS; 3472 } 3473 3474 return _target_if_set_spectral_config(spectral, param, smode, err); 3475 } 3476 3477 /** 3478 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 3479 * @fft_len: FFT length 3480 * @pdev: Pointer to pdev object 3481 * 3482 * API to get fft bin count for a given fft length 3483 * 3484 * Return: FFt bin count 3485 */ 3486 static int 3487 target_if_get_fft_bin_count(int fft_len) 3488 { 3489 int bin_count = 0; 3490 3491 switch (fft_len) { 3492 case 5: 3493 bin_count = 16; 3494 break; 3495 case 6: 3496 bin_count = 32; 3497 break; 3498 case 7: 3499 bin_count = 64; 3500 break; 3501 case 8: 3502 bin_count = 128; 3503 break; 3504 case 9: 3505 bin_count = 256; 3506 break; 3507 default: 3508 break; 3509 } 3510 3511 return bin_count; 3512 } 3513 3514 /** 3515 * target_if_init_upper_lower_flags() - Initializes control and extension 3516 * segment flags 3517 * @spectral: pointer to target if spectral object 3518 * @smode: Spectral scan mode 3519 * 3520 * API to initialize the control and extension flags with the lower/upper 3521 * segment based on the HT mode 3522 * 3523 * Return: FFt bin count 3524 */ 3525 static void 3526 target_if_init_upper_lower_flags(struct target_if_spectral *spectral, 3527 enum spectral_scan_mode smode) 3528 { 3529 int current_channel = 0; 3530 int ext_channel = 0; 3531 struct target_if_spectral_ops *p_sops = 3532 GET_TARGET_IF_SPECTRAL_OPS(spectral); 3533 3534 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3535 spectral_err("Invalid Spectral mode %u", smode); 3536 return; 3537 } 3538 current_channel = p_sops->get_current_channel(spectral, smode); 3539 ext_channel = p_sops->get_extension_channel(spectral, smode); 3540 3541 if ((current_channel == 0) || (ext_channel == 0)) 3542 return; 3543 3544 if (spectral->sc_spectral_20_40_mode) { 3545 /* HT40 mode */ 3546 if (ext_channel < current_channel) { 3547 spectral->lower_is_extension = 1; 3548 spectral->upper_is_control = 1; 3549 spectral->lower_is_control = 0; 3550 spectral->upper_is_extension = 0; 3551 } else { 3552 spectral->lower_is_extension = 0; 3553 spectral->upper_is_control = 0; 3554 spectral->lower_is_control = 1; 3555 spectral->upper_is_extension = 1; 3556 } 3557 } else { 3558 /* HT20 mode, lower is always control */ 3559 spectral->lower_is_extension = 0; 3560 spectral->upper_is_control = 0; 3561 spectral->lower_is_control = 1; 3562 spectral->upper_is_extension = 0; 3563 } 3564 } 3565 3566 /** 3567 * target_if_get_spectral_config() - Get spectral configuration 3568 * @pdev: Pointer to pdev object 3569 * @param: Pointer to spectral_config structure in which the configuration 3570 * should be returned 3571 * @smode: Spectral scan mode 3572 * 3573 * API to get the current spectral configuration 3574 * 3575 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3576 */ 3577 QDF_STATUS 3578 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 3579 struct spectral_config *param, 3580 enum spectral_scan_mode smode) 3581 { 3582 struct target_if_spectral_ops *p_sops = NULL; 3583 struct target_if_spectral *spectral = NULL; 3584 3585 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3586 3587 if (!spectral) { 3588 spectral_err("SPECTRAL : Module doesn't exist"); 3589 return QDF_STATUS_E_FAILURE; 3590 } 3591 3592 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3593 3594 if (!p_sops) { 3595 spectral_err("p_sops is null"); 3596 return QDF_STATUS_E_FAILURE; 3597 } 3598 3599 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3600 spectral_err("Invalid Spectral mode %u", smode); 3601 return QDF_STATUS_E_FAILURE; 3602 } 3603 3604 qdf_mem_zero(param, sizeof(struct spectral_config)); 3605 p_sops->get_spectral_config(spectral, param, smode); 3606 3607 return QDF_STATUS_SUCCESS; 3608 } 3609 3610 /** 3611 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 3612 * parameters 3613 * @spectral: Pointer to Spectral target_if internal private data 3614 * @spectral_params: Pointer to Spectral parameters 3615 * @smode: Spectral scan mode 3616 * @err: Spectral error code 3617 * 3618 * Enable use of desired Spectral parameters by configuring them into HW, and 3619 * starting Spectral scan 3620 * 3621 * Return: 0 on success, 1 on failure 3622 */ 3623 int 3624 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 3625 struct spectral_config *spectral_params, 3626 enum spectral_scan_mode smode, 3627 enum spectral_cp_error_code *err) 3628 { 3629 int extension_channel = 0; 3630 int current_channel = 0; 3631 struct target_if_spectral_ops *p_sops = NULL; 3632 QDF_STATUS status; 3633 struct wlan_objmgr_pdev *pdev; 3634 struct wlan_objmgr_psoc *psoc; 3635 3636 if (!spectral) { 3637 spectral_err("Spectral LMAC object is NULL"); 3638 return 1; 3639 } 3640 3641 pdev = spectral->pdev_obj; 3642 if (!pdev) { 3643 spectral_err("pdev is null"); 3644 return QDF_STATUS_E_INVAL; 3645 } 3646 3647 psoc = wlan_pdev_get_psoc(pdev); 3648 if (!psoc) { 3649 spectral_err("psoc is null"); 3650 return QDF_STATUS_E_INVAL; 3651 } 3652 3653 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3654 spectral_err("Invalid Spectral mode %u", smode); 3655 return 1; 3656 } 3657 3658 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3659 3660 if (!p_sops) { 3661 spectral_err("p_sops is NULL"); 3662 return 1; 3663 } 3664 3665 spectral->sc_spectral_noise_pwr_cal = 3666 spectral_params->ss_spectral_pri ? 1 : 0; 3667 3668 /* check if extension channel is present */ 3669 extension_channel = p_sops->get_extension_channel(spectral, smode); 3670 current_channel = p_sops->get_current_channel(spectral, smode); 3671 3672 status = target_if_spectral_populate_chwidth( 3673 spectral, spectral->ch_width, 3674 spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 3675 ss_frequency.cfreq2 > 0); 3676 if (QDF_IS_STATUS_ERROR(status)) { 3677 spectral_err("Failed to get channel widths"); 3678 return 1; 3679 } 3680 3681 if (spectral->capability.advncd_spectral_cap) { 3682 spectral->lb_edge_extrabins = 0; 3683 spectral->rb_edge_extrabins = 0; 3684 3685 if (spectral->is_lb_edge_extrabins_format && 3686 spectral->params[smode].ss_rpt_mode == 2) { 3687 spectral->lb_edge_extrabins = 4; 3688 } 3689 3690 if (spectral->is_rb_edge_extrabins_format && 3691 spectral->params[smode].ss_rpt_mode == 2) { 3692 spectral->rb_edge_extrabins = 4; 3693 } 3694 3695 if (spectral->ch_width[smode] == CH_WIDTH_20MHZ) { 3696 spectral->sc_spectral_20_40_mode = 0; 3697 3698 spectral->spectral_numbins = 3699 target_if_get_fft_bin_count( 3700 spectral->params[smode].ss_fft_size); 3701 spectral->spectral_fft_len = 3702 target_if_get_fft_bin_count( 3703 spectral->params[smode].ss_fft_size); 3704 spectral->spectral_data_len = 3705 target_if_get_fft_bin_count( 3706 spectral->params[smode].ss_fft_size); 3707 /* 3708 * Initialize classifier params to be sent to user 3709 * space classifier 3710 */ 3711 spectral->classifier_params.lower_chan_in_mhz = 3712 current_channel; 3713 spectral->classifier_params.upper_chan_in_mhz = 0; 3714 3715 } else if (spectral->ch_width[smode] == CH_WIDTH_40MHZ) { 3716 /* TODO : Remove this variable */ 3717 spectral->sc_spectral_20_40_mode = 1; 3718 spectral->spectral_numbins = 3719 target_if_get_fft_bin_count( 3720 spectral->params[smode].ss_fft_size); 3721 spectral->spectral_fft_len = 3722 target_if_get_fft_bin_count( 3723 spectral->params[smode].ss_fft_size); 3724 spectral->spectral_data_len = 3725 target_if_get_fft_bin_count( 3726 spectral->params[smode].ss_fft_size); 3727 3728 /* 3729 * Initialize classifier params to be sent to user 3730 * space classifier 3731 */ 3732 if (extension_channel < current_channel) { 3733 spectral->classifier_params.lower_chan_in_mhz = 3734 extension_channel; 3735 spectral->classifier_params.upper_chan_in_mhz = 3736 current_channel; 3737 } else { 3738 spectral->classifier_params.lower_chan_in_mhz = 3739 current_channel; 3740 spectral->classifier_params.upper_chan_in_mhz = 3741 extension_channel; 3742 } 3743 3744 } else if (spectral->ch_width[smode] == CH_WIDTH_80MHZ) { 3745 /* Set the FFT Size */ 3746 /* TODO : Remove this variable */ 3747 spectral->sc_spectral_20_40_mode = 0; 3748 spectral->spectral_numbins = 3749 target_if_get_fft_bin_count( 3750 spectral->params[smode].ss_fft_size); 3751 spectral->spectral_fft_len = 3752 target_if_get_fft_bin_count( 3753 spectral->params[smode].ss_fft_size); 3754 spectral->spectral_data_len = 3755 target_if_get_fft_bin_count( 3756 spectral->params[smode].ss_fft_size); 3757 3758 /* 3759 * Initialize classifier params to be sent to user 3760 * space classifier 3761 */ 3762 spectral->classifier_params.lower_chan_in_mhz = 3763 current_channel; 3764 spectral->classifier_params.upper_chan_in_mhz = 0; 3765 3766 /* 3767 * Initialize classifier params to be sent to user 3768 * space classifier 3769 */ 3770 if (extension_channel < current_channel) { 3771 spectral->classifier_params.lower_chan_in_mhz = 3772 extension_channel; 3773 spectral->classifier_params.upper_chan_in_mhz = 3774 current_channel; 3775 } else { 3776 spectral->classifier_params.lower_chan_in_mhz = 3777 current_channel; 3778 spectral->classifier_params.upper_chan_in_mhz = 3779 extension_channel; 3780 } 3781 3782 } else if (is_ch_width_160_or_80p80( 3783 spectral->ch_width[smode])) { 3784 /* Set the FFT Size */ 3785 3786 /* The below applies to both 160 and 80+80 cases */ 3787 3788 /* TODO : Remove this variable */ 3789 spectral->sc_spectral_20_40_mode = 0; 3790 spectral->spectral_numbins = 3791 target_if_get_fft_bin_count( 3792 spectral->params[smode].ss_fft_size); 3793 spectral->spectral_fft_len = 3794 target_if_get_fft_bin_count( 3795 spectral->params[smode].ss_fft_size); 3796 spectral->spectral_data_len = 3797 target_if_get_fft_bin_count( 3798 spectral->params[smode].ss_fft_size); 3799 3800 /* 3801 * Initialize classifier params to be sent to user 3802 * space classifier 3803 */ 3804 spectral->classifier_params.lower_chan_in_mhz = 3805 current_channel; 3806 spectral->classifier_params.upper_chan_in_mhz = 0; 3807 3808 /* 3809 * Initialize classifier params to be sent to user 3810 * space classifier 3811 */ 3812 if (extension_channel < current_channel) { 3813 spectral->classifier_params.lower_chan_in_mhz = 3814 extension_channel; 3815 spectral->classifier_params.upper_chan_in_mhz = 3816 current_channel; 3817 } else { 3818 spectral->classifier_params.lower_chan_in_mhz = 3819 current_channel; 3820 spectral->classifier_params.upper_chan_in_mhz = 3821 extension_channel; 3822 } 3823 } 3824 3825 if (spectral->spectral_numbins) { 3826 spectral->spectral_numbins += 3827 spectral->lb_edge_extrabins; 3828 spectral->spectral_numbins += 3829 spectral->rb_edge_extrabins; 3830 } 3831 3832 if (spectral->spectral_fft_len) { 3833 spectral->spectral_fft_len += 3834 spectral->lb_edge_extrabins; 3835 spectral->spectral_fft_len += 3836 spectral->rb_edge_extrabins; 3837 } 3838 3839 if (spectral->spectral_data_len) { 3840 spectral->spectral_data_len += 3841 spectral->lb_edge_extrabins; 3842 spectral->spectral_data_len += 3843 spectral->rb_edge_extrabins; 3844 } 3845 } else { 3846 /* 3847 * The decision to find 20/40 mode is found based on the 3848 * presence of extension channel 3849 * instead of channel width, as the channel width can 3850 * dynamically change 3851 */ 3852 3853 if (extension_channel == 0) { 3854 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 3855 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 3856 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 3857 spectral->spectral_data_len = 3858 SPECTRAL_HT20_TOTAL_DATA_LEN; 3859 /* only valid in 20-40 mode */ 3860 spectral->spectral_lower_max_index_offset = -1; 3861 /* only valid in 20-40 mode */ 3862 spectral->spectral_upper_max_index_offset = -1; 3863 spectral->spectral_max_index_offset = 3864 spectral->spectral_fft_len + 2; 3865 spectral->sc_spectral_20_40_mode = 0; 3866 3867 /* 3868 * Initialize classifier params to be sent to user 3869 * space classifier 3870 */ 3871 spectral->classifier_params.lower_chan_in_mhz = 3872 current_channel; 3873 spectral->classifier_params.upper_chan_in_mhz = 0; 3874 3875 } else { 3876 spectral->spectral_numbins = 3877 SPECTRAL_HT40_TOTAL_NUM_BINS; 3878 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 3879 spectral->spectral_data_len = 3880 SPECTRAL_HT40_TOTAL_DATA_LEN; 3881 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 3882 /* only valid in 20 mode */ 3883 spectral->spectral_max_index_offset = -1; 3884 spectral->spectral_lower_max_index_offset = 3885 spectral->spectral_fft_len + 2; 3886 spectral->spectral_upper_max_index_offset = 3887 spectral->spectral_fft_len + 5; 3888 spectral->sc_spectral_20_40_mode = 1; 3889 3890 /* 3891 * Initialize classifier params to be sent to user 3892 * space classifier 3893 */ 3894 if (extension_channel < current_channel) { 3895 spectral->classifier_params.lower_chan_in_mhz = 3896 extension_channel; 3897 spectral->classifier_params.upper_chan_in_mhz = 3898 current_channel; 3899 } else { 3900 spectral->classifier_params.lower_chan_in_mhz = 3901 current_channel; 3902 spectral->classifier_params.upper_chan_in_mhz = 3903 extension_channel; 3904 } 3905 } 3906 } 3907 3908 spectral->send_single_packet = 0; 3909 spectral->classifier_params.spectral_20_40_mode = 3910 spectral->sc_spectral_20_40_mode; 3911 spectral->classifier_params.spectral_dc_index = 3912 spectral->spectral_dc_index; 3913 spectral->spectral_sent_msg = 0; 3914 spectral->classify_scan = 0; 3915 spectral->num_spectral_data = 0; 3916 3917 if (!p_sops->is_spectral_active(spectral, smode)) { 3918 p_sops->configure_spectral(spectral, spectral_params, smode); 3919 spectral->rparams.marker[smode].is_valid = false; 3920 p_sops->start_spectral_scan(spectral, smode, err); 3921 spectral->timestamp_war.timestamp_war_offset[smode] = 0; 3922 spectral->timestamp_war.last_fft_timestamp[smode] = 0; 3923 } 3924 3925 /* get current spectral configuration */ 3926 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode); 3927 3928 target_if_init_upper_lower_flags(spectral, smode); 3929 3930 return 0; 3931 } 3932 3933 /** 3934 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by 3935 * Agile DFS 3936 * @psoc: Pointer to psoc 3937 * @object: Pointer to pdev 3938 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited 3939 * 3940 * This API checks whether Agile DFS is running on any of the pdevs. If so, it 3941 * indicates that Agile Spectral scan is prohibited by Agile DFS. 3942 * 3943 * Return: void 3944 */ 3945 static void 3946 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, 3947 void *object, void *arg) 3948 { 3949 bool *is_aspectral_prohibited = arg; 3950 struct wlan_objmgr_pdev *cur_pdev = object; 3951 bool is_agile_dfs_enabled_cur_pdev = false; 3952 QDF_STATUS status; 3953 3954 qdf_assert_always(is_aspectral_prohibited); 3955 if (*is_aspectral_prohibited) 3956 return; 3957 3958 qdf_assert_always(psoc); 3959 qdf_assert_always(cur_pdev); 3960 3961 status = ucfg_dfs_get_agile_precac_enable 3962 (cur_pdev, 3963 &is_agile_dfs_enabled_cur_pdev); 3964 if (QDF_IS_STATUS_ERROR(status)) { 3965 spectral_err("Get agile precac failed, prohibiting aSpectral"); 3966 *is_aspectral_prohibited = true; 3967 return; 3968 } 3969 3970 if (is_agile_dfs_enabled_cur_pdev) { 3971 spectral_err("aDFS is in progress on one of the pdevs"); 3972 *is_aspectral_prohibited = true; 3973 } 3974 } 3975 3976 /** 3977 * target_if_get_curr_band() - Get current operating band of pdev 3978 * 3979 * @pdev: pointer to pdev object 3980 * 3981 * API to get current operating band of a given pdev. 3982 * 3983 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure 3984 */ 3985 static enum reg_wifi_band 3986 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) 3987 { 3988 struct wlan_objmgr_vdev *vdev; 3989 int16_t chan_freq; 3990 enum reg_wifi_band cur_band; 3991 3992 if (!pdev) { 3993 spectral_err("pdev is NULL"); 3994 return REG_BAND_UNKNOWN; 3995 } 3996 3997 if (vdev_id == WLAN_INVALID_VDEV_ID) 3998 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); 3999 else 4000 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 4001 WLAN_SPECTRAL_ID); 4002 if (!vdev) { 4003 spectral_debug("vdev is NULL"); 4004 return REG_BAND_UNKNOWN; 4005 } 4006 chan_freq = target_if_vdev_get_chan_freq(vdev); 4007 cur_band = wlan_reg_freq_to_band(chan_freq); 4008 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4009 4010 return cur_band; 4011 } 4012 4013 /** 4014 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on 4015 * any of the 5G pdevs 4016 * @psoc: Pointer to psoc 4017 * @object: Pointer to pdev 4018 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in 4019 * progress in any 5G pdevs 4020 * 4021 * Return: void 4022 */ 4023 static void 4024 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, 4025 void *object, void *arg) 4026 { 4027 enum reg_wifi_band band; 4028 bool *is_agile_scan_inprog_5g_pdev = arg; 4029 struct target_if_spectral *spectral; 4030 struct wlan_objmgr_pdev *cur_pdev = object; 4031 struct target_if_spectral_ops *p_sops; 4032 4033 if (*is_agile_scan_inprog_5g_pdev) 4034 return; 4035 4036 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); 4037 if (!spectral) { 4038 spectral_err("target if spectral handle is NULL"); 4039 return; 4040 } 4041 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4042 4043 band = target_if_get_curr_band( 4044 cur_pdev, spectral->vdev_id[SPECTRAL_SCAN_MODE_AGILE]); 4045 if (band == REG_BAND_UNKNOWN) { 4046 spectral_debug("Failed to get current band"); 4047 return; 4048 } 4049 4050 if (band == REG_BAND_5G && 4051 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) 4052 *is_agile_scan_inprog_5g_pdev = true; 4053 } 4054 4055 /** 4056 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported 4057 * for current vdev rx chainmask. 4058 * 4059 * @spectral: Pointer to Spectral object 4060 * @is_supported: Pointer to is_supported 4061 * 4062 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4063 */ 4064 static QDF_STATUS 4065 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, 4066 bool *is_supported) 4067 { 4068 struct wlan_objmgr_vdev *vdev; 4069 uint8_t vdev_rxchainmask; 4070 struct wlan_objmgr_psoc *psoc; 4071 struct wlan_objmgr_pdev *pdev; 4072 struct target_psoc_info *tgt_psoc_info; 4073 struct wlan_psoc_host_service_ext_param *ext_svc_param; 4074 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 4075 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 4076 struct wlan_psoc_host_chainmask_table *table; 4077 int j; 4078 uint32_t table_id; 4079 enum phy_ch_width ch_width; 4080 uint8_t pdev_id; 4081 4082 if (!spectral) { 4083 spectral_err("spectral target if object is null"); 4084 return QDF_STATUS_E_FAILURE; 4085 } 4086 4087 if (!is_supported) { 4088 spectral_err("is supported argument is null"); 4089 return QDF_STATUS_E_FAILURE; 4090 } 4091 4092 if (spectral->spectral_gen <= SPECTRAL_GEN2) { 4093 spectral_err("HW Agile mode is not supported up to gen 2"); 4094 return QDF_STATUS_E_FAILURE; 4095 } 4096 4097 pdev = spectral->pdev_obj; 4098 if (!pdev) { 4099 spectral_err("pdev is null"); 4100 return QDF_STATUS_E_FAILURE; 4101 } 4102 4103 psoc = wlan_pdev_get_psoc(pdev); 4104 if (!psoc) { 4105 spectral_err("psoc is null"); 4106 return QDF_STATUS_E_FAILURE; 4107 } 4108 4109 vdev = target_if_spectral_get_vdev(spectral, SPECTRAL_SCAN_MODE_AGILE); 4110 if (!vdev) { 4111 spectral_err("First vdev is NULL"); 4112 return QDF_STATUS_E_FAILURE; 4113 } 4114 4115 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 4116 if (!vdev_rxchainmask) { 4117 spectral_err("vdev rx chainmask is zero"); 4118 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4119 return QDF_STATUS_E_FAILURE; 4120 } 4121 4122 ch_width = target_if_vdev_get_ch_width(vdev); 4123 if (ch_width == CH_WIDTH_INVALID) { 4124 spectral_err("Invalid channel width"); 4125 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4126 return QDF_STATUS_E_FAILURE; 4127 } 4128 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 4129 4130 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 4131 if (!tgt_psoc_info) { 4132 spectral_err("target_psoc_info is null"); 4133 return QDF_STATUS_E_FAILURE; 4134 } 4135 4136 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 4137 if (!ext_svc_param) { 4138 spectral_err("Extended service ready param null"); 4139 return QDF_STATUS_E_FAILURE; 4140 } 4141 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 4142 4143 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 4144 if (!mac_phy_cap_arr) { 4145 spectral_err("mac phy cap array is null"); 4146 return QDF_STATUS_E_FAILURE; 4147 } 4148 4149 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 4150 if (!mac_phy_cap) { 4151 spectral_err("mac phy cap is null"); 4152 return QDF_STATUS_E_FAILURE; 4153 } 4154 4155 table_id = mac_phy_cap->chainmask_table_id; 4156 table = &ext_svc_param->chainmask_table[table_id]; 4157 if (!table) { 4158 spectral_err("chainmask table not found"); 4159 return QDF_STATUS_E_FAILURE; 4160 } 4161 4162 for (j = 0; j < table->num_valid_chainmasks; j++) { 4163 if (table->cap_list[j].chainmask == vdev_rxchainmask) { 4164 if (ch_width <= CH_WIDTH_80MHZ) 4165 *is_supported = 4166 table->cap_list[j].supports_aSpectral; 4167 else 4168 *is_supported = 4169 table->cap_list[j].supports_aSpectral_160; 4170 break; 4171 } 4172 } 4173 4174 if (j == table->num_valid_chainmasks) { 4175 spectral_err("vdev rx chainmask %u not found in table id = %u", 4176 vdev_rxchainmask, table_id); 4177 return QDF_STATUS_E_FAILURE; 4178 } 4179 4180 return QDF_STATUS_SUCCESS; 4181 } 4182 4183 QDF_STATUS 4184 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, 4185 uint8_t vdev_id, 4186 const enum spectral_scan_mode smode, 4187 enum spectral_cp_error_code *err) 4188 { 4189 struct target_if_spectral_ops *p_sops; 4190 struct target_if_spectral *spectral; 4191 struct wlan_objmgr_psoc *psoc; 4192 enum reg_wifi_band band; 4193 4194 if (!err) { 4195 spectral_err("Error code argument is null"); 4196 QDF_ASSERT(0); 4197 return QDF_STATUS_E_FAILURE; 4198 } 4199 *err = SPECTRAL_SCAN_ERR_INVALID; 4200 4201 if (!pdev) { 4202 spectral_err("pdev object is NUll"); 4203 return QDF_STATUS_E_FAILURE; 4204 } 4205 4206 psoc = wlan_pdev_get_psoc(pdev); 4207 if (!psoc) { 4208 spectral_err("psoc is null"); 4209 return QDF_STATUS_E_FAILURE; 4210 } 4211 4212 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4213 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4214 spectral_err("Invalid Spectral mode %u", smode); 4215 return QDF_STATUS_E_FAILURE; 4216 } 4217 4218 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4219 if (!spectral) { 4220 spectral_err("Spectral LMAC object is NUll"); 4221 return QDF_STATUS_E_FAILURE; 4222 } 4223 4224 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4225 if (!p_sops) { 4226 spectral_err("p_sops is null"); 4227 return QDF_STATUS_E_FAILURE; 4228 } 4229 4230 if (p_sops->is_spectral_active(spectral, smode)) { 4231 spectral_err("spectral in progress in current pdev, mode %d", 4232 smode); 4233 return QDF_STATUS_E_FAILURE; 4234 } 4235 spectral->vdev_id[smode] = vdev_id; 4236 4237 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 4238 QDF_STATUS status; 4239 bool is_supported = false; 4240 4241 status = target_if_is_agile_supported_cur_chmask(spectral, 4242 &is_supported); 4243 if (QDF_IS_STATUS_ERROR(status)) { 4244 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4245 return QDF_STATUS_E_FAILURE; 4246 } 4247 4248 if (!is_supported) { 4249 spectral_err("aSpectral unsupported for cur chainmask"); 4250 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4251 return QDF_STATUS_E_FAILURE; 4252 } 4253 } 4254 4255 band = target_if_get_curr_band(spectral->pdev_obj, vdev_id); 4256 if (band == REG_BAND_UNKNOWN) { 4257 spectral_err("Failed to get current band"); 4258 return QDF_STATUS_E_FAILURE; 4259 } 4260 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { 4261 struct target_psoc_info *tgt_hdl; 4262 enum wmi_host_hw_mode_config_type mode; 4263 bool is_agile_scan_inprog_5g_pdev; 4264 4265 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 4266 if (!tgt_hdl) { 4267 target_if_err("target_psoc_info is null"); 4268 return QDF_STATUS_E_FAILURE; 4269 } 4270 4271 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 4272 switch (mode) { 4273 case WMI_HOST_HW_MODE_SBS_PASSIVE: 4274 case WMI_HOST_HW_MODE_SBS: 4275 case WMI_HOST_HW_MODE_DBS_SBS: 4276 case WMI_HOST_HW_MODE_DBS_OR_SBS: 4277 is_agile_scan_inprog_5g_pdev = false; 4278 wlan_objmgr_iterate_obj_list 4279 (psoc, WLAN_PDEV_OP, 4280 target_if_is_agile_scan_active_in_5g, 4281 &is_agile_scan_inprog_5g_pdev, 0, 4282 WLAN_SPECTRAL_ID); 4283 break; 4284 default: 4285 is_agile_scan_inprog_5g_pdev = false; 4286 break; 4287 } 4288 4289 if (is_agile_scan_inprog_5g_pdev) { 4290 spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); 4291 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4292 return QDF_STATUS_E_FAILURE; 4293 } 4294 } 4295 4296 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 4297 bool is_aspectral_prohibited = false; 4298 QDF_STATUS status; 4299 4300 status = wlan_objmgr_iterate_obj_list 4301 (psoc, WLAN_PDEV_OP, 4302 target_if_is_aspectral_prohibited_by_adfs, 4303 &is_aspectral_prohibited, 0, 4304 WLAN_SPECTRAL_ID); 4305 if (QDF_IS_STATUS_ERROR(status)) { 4306 spectral_err("Failed to iterate over pdevs"); 4307 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4308 return QDF_STATUS_E_FAILURE; 4309 } 4310 4311 if (is_aspectral_prohibited) { 4312 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4313 return QDF_STATUS_E_FAILURE; 4314 } 4315 } 4316 4317 if (!spectral->params_valid[smode]) { 4318 target_if_spectral_info_read(spectral, 4319 smode, 4320 TARGET_IF_SPECTRAL_INFO_PARAMS, 4321 &spectral->params[smode], 4322 sizeof(spectral->params[smode])); 4323 spectral->params_valid[smode] = true; 4324 } 4325 4326 qdf_spin_lock(&spectral->spectral_lock); 4327 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 4328 QDF_STATUS status; 4329 bool is_overlapping; 4330 enum phy_ch_width ch_width[SPECTRAL_SCAN_MODE_MAX]; 4331 enum spectral_scan_mode m; 4332 enum phy_ch_width op_ch_width; 4333 enum phy_ch_width agile_ch_width; 4334 4335 m = SPECTRAL_SCAN_MODE_NORMAL; 4336 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 4337 ch_width[m] = CH_WIDTH_INVALID; 4338 status = target_if_spectral_populate_chwidth 4339 (spectral, ch_width, spectral->params 4340 [SPECTRAL_SCAN_MODE_AGILE].ss_frequency.cfreq2 > 0); 4341 if (QDF_IS_STATUS_ERROR(status)) { 4342 qdf_spin_unlock(&spectral->spectral_lock); 4343 spectral_err("Failed to populate channel width"); 4344 return QDF_STATUS_E_FAILURE; 4345 } 4346 op_ch_width = ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 4347 agile_ch_width = ch_width[SPECTRAL_SCAN_MODE_AGILE]; 4348 4349 if (!spectral->params[smode].ss_frequency.cfreq1 || 4350 (agile_ch_width == CH_WIDTH_80P80MHZ && 4351 !spectral->params[smode].ss_frequency.cfreq2)) { 4352 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 4353 qdf_spin_unlock(&spectral->spectral_lock); 4354 return QDF_STATUS_E_FAILURE; 4355 } 4356 4357 status = target_if_is_agile_span_overlap_with_operating_span 4358 (spectral, ch_width, 4359 &spectral->params[smode].ss_frequency, 4360 &is_overlapping); 4361 if (QDF_IS_STATUS_ERROR(status)) { 4362 qdf_spin_unlock(&spectral->spectral_lock); 4363 return QDF_STATUS_E_FAILURE; 4364 } 4365 4366 if (is_overlapping) { 4367 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 4368 qdf_spin_unlock(&spectral->spectral_lock); 4369 return QDF_STATUS_E_FAILURE; 4370 } 4371 } 4372 4373 target_if_spectral_scan_enable_params(spectral, 4374 &spectral->params[smode], smode, 4375 err); 4376 qdf_spin_unlock(&spectral->spectral_lock); 4377 4378 return QDF_STATUS_SUCCESS; 4379 } 4380 4381 QDF_STATUS 4382 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, 4383 const enum spectral_scan_mode smode, 4384 enum spectral_cp_error_code *err) 4385 { 4386 struct target_if_spectral_ops *p_sops; 4387 struct target_if_spectral *spectral; 4388 4389 if (!err) { 4390 spectral_err("Error code argument is null"); 4391 QDF_ASSERT(0); 4392 return QDF_STATUS_E_FAILURE; 4393 } 4394 *err = SPECTRAL_SCAN_ERR_INVALID; 4395 4396 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4397 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 4398 spectral_err("Invalid Spectral mode %u", smode); 4399 return QDF_STATUS_E_FAILURE; 4400 } 4401 4402 if (!pdev) { 4403 spectral_err("pdev object is NUll "); 4404 return QDF_STATUS_E_FAILURE; 4405 } 4406 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4407 if (!spectral) { 4408 spectral_err("Spectral LMAC object is NUll "); 4409 return QDF_STATUS_E_FAILURE; 4410 } 4411 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4412 4413 qdf_spin_lock(&spectral->spectral_lock); 4414 p_sops->stop_spectral_scan(spectral, smode); 4415 if (spectral->classify_scan) { 4416 /* TODO : Check if this logic is necessary */ 4417 spectral->detects_control_channel = 0; 4418 spectral->detects_extension_channel = 0; 4419 spectral->detects_above_dc = 0; 4420 spectral->detects_below_dc = 0; 4421 spectral->classify_scan = 0; 4422 } 4423 4424 spectral->send_single_packet = 0; 4425 spectral->sc_spectral_scan = 0; 4426 spectral->vdev_id[smode] = WLAN_INVALID_VDEV_ID; 4427 4428 qdf_spin_unlock(&spectral->spectral_lock); 4429 4430 return QDF_STATUS_SUCCESS; 4431 } 4432 4433 /** 4434 * target_if_is_spectral_active() - Get whether Spectral is active 4435 * @pdev: Pointer to pdev object 4436 * @smode: Spectral scan mode 4437 * 4438 * API to get whether Spectral is active 4439 * 4440 * Return: True if Spectral is active, false if Spectral is not active 4441 */ 4442 bool 4443 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, 4444 const enum spectral_scan_mode smode) 4445 { 4446 struct target_if_spectral *spectral = NULL; 4447 struct target_if_spectral_ops *p_sops = NULL; 4448 4449 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4450 4451 if (!spectral) { 4452 spectral_err("SPECTRAL : Module doesn't exist"); 4453 return QDF_STATUS_E_FAILURE; 4454 } 4455 4456 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4457 4458 if (!p_sops) { 4459 spectral_err("p_sops is null"); 4460 return QDF_STATUS_E_FAILURE; 4461 } 4462 4463 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4464 spectral_err("Invalid Spectral mode %u", smode); 4465 return QDF_STATUS_E_FAILURE; 4466 } 4467 4468 return p_sops->is_spectral_active(spectral, smode); 4469 } 4470 4471 /** 4472 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 4473 * @pdev: Pointer to pdev object 4474 * @smode: Spectral scan mode 4475 * 4476 * API to get whether Spectral is enabled 4477 * 4478 * Return: True if Spectral is enabled, false if Spectral is not enabled 4479 */ 4480 bool 4481 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, 4482 enum spectral_scan_mode smode) 4483 { 4484 struct target_if_spectral *spectral = NULL; 4485 struct target_if_spectral_ops *p_sops = NULL; 4486 4487 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4488 4489 if (!spectral) { 4490 spectral_err("SPECTRAL : Module doesn't exist"); 4491 return QDF_STATUS_E_FAILURE; 4492 } 4493 4494 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4495 4496 if (!p_sops) { 4497 spectral_err("p_sops is null"); 4498 return QDF_STATUS_E_FAILURE; 4499 } 4500 4501 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 4502 spectral_err("Invalid Spectral mode %u", smode); 4503 return QDF_STATUS_E_FAILURE; 4504 } 4505 4506 return p_sops->is_spectral_enabled(spectral, smode); 4507 } 4508 4509 #ifdef DIRECT_BUF_RX_DEBUG 4510 /** 4511 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug 4512 * @pdev: Pointer to pdev object 4513 * @enable: Enable/Disable Spectral DMA ring debug 4514 * 4515 * Start/stop Spectral DMA ring debug based on @enable. 4516 * Also save the state for future use. 4517 * 4518 * Return: QDF_STATUS of operation 4519 */ 4520 static QDF_STATUS 4521 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) 4522 { 4523 struct target_if_spectral *spectral; 4524 struct wlan_lmac_if_tx_ops *tx_ops; 4525 struct wlan_objmgr_psoc *psoc; 4526 4527 if (!pdev) 4528 return QDF_STATUS_E_FAILURE; 4529 4530 psoc = wlan_pdev_get_psoc(pdev); 4531 if (!psoc) { 4532 spectral_err("psoc is null"); 4533 return QDF_STATUS_E_INVAL; 4534 } 4535 4536 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 4537 if (!tx_ops) { 4538 spectral_err("tx_ops is NULL"); 4539 return QDF_STATUS_E_INVAL; 4540 } 4541 4542 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4543 if (!spectral) { 4544 spectral_err("Spectal LMAC object is NULL"); 4545 return QDF_STATUS_E_INVAL; 4546 } 4547 4548 /* Save the state */ 4549 spectral->dbr_ring_debug = enable; 4550 4551 if (enable) 4552 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( 4553 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); 4554 else 4555 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( 4556 pdev, 0); 4557 4558 return QDF_STATUS_SUCCESS; 4559 } 4560 4561 /** 4562 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug 4563 * @pdev: Pointer to pdev object 4564 * @enable: Enable/Disable Spectral DMA buffer debug 4565 * 4566 * Start/stop Spectral DMA buffer debug based on @enable. 4567 * Also save the state for future use. 4568 * 4569 * Return: QDF_STATUS of operation 4570 */ 4571 static QDF_STATUS 4572 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) 4573 { 4574 struct target_if_spectral *spectral; 4575 struct wlan_lmac_if_tx_ops *tx_ops; 4576 struct wlan_objmgr_psoc *psoc; 4577 4578 if (!pdev) 4579 return QDF_STATUS_E_FAILURE; 4580 4581 psoc = wlan_pdev_get_psoc(pdev); 4582 if (!psoc) { 4583 spectral_err("psoc is null"); 4584 return QDF_STATUS_E_INVAL; 4585 } 4586 4587 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 4588 if (!tx_ops) { 4589 spectral_err("tx_ops is NULL"); 4590 return QDF_STATUS_E_INVAL; 4591 } 4592 4593 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4594 if (!spectral) { 4595 spectral_err("Spectal LMAC object is NULL"); 4596 return QDF_STATUS_E_INVAL; 4597 } 4598 4599 /* Save the state */ 4600 spectral->dbr_buff_debug = enable; 4601 4602 if (enable) 4603 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( 4604 pdev, 0, MEM_POISON_SIGNATURE); 4605 else 4606 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( 4607 pdev, 0); 4608 } 4609 4610 /** 4611 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer 4612 * debug based on the previous state 4613 * @pdev: Pointer to pdev object 4614 * 4615 * Return: QDF_STATUS of operation 4616 */ 4617 static QDF_STATUS 4618 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) 4619 { 4620 struct target_if_spectral *spectral; 4621 4622 if (!pdev) { 4623 spectral_err("pdev is NULL!"); 4624 return QDF_STATUS_E_FAILURE; 4625 } 4626 4627 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4628 if (!spectral) { 4629 spectral_err("Spectal LMAC object is NULL"); 4630 return QDF_STATUS_E_INVAL; 4631 } 4632 4633 if (spectral->dbr_buff_debug) 4634 return target_if_spectral_do_dbr_buff_debug(pdev, true); 4635 else 4636 return target_if_spectral_do_dbr_buff_debug(pdev, false); 4637 } 4638 4639 /** 4640 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring 4641 * debug based on the previous state 4642 * @pdev: Pointer to pdev object 4643 * 4644 * Return: QDF_STATUS of operation 4645 */ 4646 static QDF_STATUS 4647 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) 4648 { 4649 struct target_if_spectral *spectral; 4650 4651 if (!pdev) { 4652 spectral_err("pdev is NULL!"); 4653 return QDF_STATUS_E_FAILURE; 4654 } 4655 4656 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4657 if (!spectral) { 4658 spectral_err("Spectal LMAC object is NULL"); 4659 return QDF_STATUS_E_INVAL; 4660 } 4661 4662 if (spectral->dbr_ring_debug) 4663 return target_if_spectral_do_dbr_ring_debug(pdev, true); 4664 else 4665 return target_if_spectral_do_dbr_ring_debug(pdev, false); 4666 } 4667 4668 /** 4669 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral 4670 * @pdev: Pointer to pdev object 4671 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug 4672 * @debug_value: Value to be set for @dma_debug_type 4673 * 4674 * Set DMA debug for Spectral and start/stop Spectral DMA debug function 4675 * based on @debug_value 4676 * 4677 * Return: QDF_STATUS of operation 4678 */ 4679 static QDF_STATUS 4680 target_if_spectral_set_dma_debug( 4681 struct wlan_objmgr_pdev *pdev, 4682 enum spectral_dma_debug dma_debug_type, 4683 bool debug_value) 4684 { 4685 struct target_if_spectral_ops *p_sops; 4686 struct wlan_objmgr_psoc *psoc; 4687 struct wlan_lmac_if_tx_ops *tx_ops; 4688 struct target_if_spectral *spectral; 4689 4690 if (!pdev) 4691 return QDF_STATUS_E_FAILURE; 4692 4693 psoc = wlan_pdev_get_psoc(pdev); 4694 if (!psoc) { 4695 spectral_err("psoc is null"); 4696 return QDF_STATUS_E_INVAL; 4697 } 4698 4699 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 4700 if (!tx_ops) { 4701 spectral_err("tx_ops is NULL"); 4702 return QDF_STATUS_E_FAILURE; 4703 } 4704 4705 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { 4706 spectral_err("Unable to fetch target type"); 4707 return QDF_STATUS_E_FAILURE; 4708 } 4709 4710 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4711 if (!spectral) { 4712 spectral_err("Spectal LMAC object is NULL"); 4713 return QDF_STATUS_E_INVAL; 4714 } 4715 4716 if (spectral->direct_dma_support) { 4717 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4718 if (p_sops->is_spectral_active(spectral, 4719 SPECTRAL_SCAN_MODE_NORMAL) || 4720 p_sops->is_spectral_active(spectral, 4721 SPECTRAL_SCAN_MODE_AGILE)) { 4722 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); 4723 return QDF_STATUS_E_FAILURE; 4724 } 4725 4726 switch (dma_debug_type) { 4727 case SPECTRAL_DMA_RING_DEBUG: 4728 target_if_spectral_do_dbr_ring_debug(pdev, debug_value); 4729 break; 4730 4731 case SPECTRAL_DMA_BUFFER_DEBUG: 4732 target_if_spectral_do_dbr_buff_debug(pdev, debug_value); 4733 break; 4734 4735 default: 4736 spectral_err("Unsupported DMA debug type : %d", 4737 dma_debug_type); 4738 return QDF_STATUS_E_FAILURE; 4739 } 4740 } 4741 return QDF_STATUS_SUCCESS; 4742 } 4743 #endif /* DIRECT_BUF_RX_DEBUG */ 4744 4745 /** 4746 * target_if_spectral_direct_dma_support() - Get Direct-DMA support 4747 * @pdev: Pointer to pdev object 4748 * 4749 * Return: Whether Direct-DMA is supported on this radio 4750 */ 4751 static bool 4752 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) 4753 { 4754 struct target_if_spectral *spectral; 4755 4756 if (!pdev) { 4757 spectral_err("pdev is NULL!"); 4758 return false; 4759 } 4760 4761 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4762 if (!spectral) { 4763 spectral_err("Spectral LMAC object is NULL"); 4764 return false; 4765 } 4766 4767 return spectral->direct_dma_support; 4768 } 4769 4770 /** 4771 * target_if_set_debug_level() - Set debug level for Spectral 4772 * @pdev: Pointer to pdev object 4773 * @debug_level: Debug level 4774 * 4775 * API to set the debug level for Spectral 4776 * 4777 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4778 */ 4779 QDF_STATUS 4780 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 4781 { 4782 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 4783 4784 return QDF_STATUS_SUCCESS; 4785 } 4786 4787 /** 4788 * target_if_get_debug_level() - Get debug level for Spectral 4789 * @pdev: Pointer to pdev object 4790 * 4791 * API to get the debug level for Spectral 4792 * 4793 * Return: Current debug level 4794 */ 4795 uint32_t 4796 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 4797 { 4798 return spectral_debug_level; 4799 } 4800 4801 /** 4802 * target_if_get_spectral_capinfo() - Get Spectral capability information 4803 * @pdev: Pointer to pdev object 4804 * @scaps: Buffer into which data should be copied 4805 * 4806 * API to get the spectral capability information 4807 * 4808 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4809 */ 4810 QDF_STATUS 4811 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, 4812 struct spectral_caps *scaps) 4813 { 4814 struct target_if_spectral *spectral = NULL; 4815 4816 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4817 if (!spectral) { 4818 spectral_err("SPECTRAL : Module doesn't exist"); 4819 return QDF_STATUS_E_FAILURE; 4820 } 4821 4822 qdf_mem_copy(scaps, &spectral->capability, 4823 sizeof(struct spectral_caps)); 4824 4825 return QDF_STATUS_SUCCESS; 4826 } 4827 4828 /** 4829 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 4830 * @pdev: Pointer to pdev object 4831 * @stats: Buffer into which data should be copied 4832 * 4833 * API to get the spectral diagnostic statistics 4834 * 4835 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4836 */ 4837 QDF_STATUS 4838 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, 4839 struct spectral_diag_stats *stats) 4840 { 4841 struct target_if_spectral *spectral = NULL; 4842 4843 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4844 if (!spectral) { 4845 spectral_err("SPECTRAL : Module doesn't exist"); 4846 return QDF_STATUS_E_FAILURE; 4847 } 4848 4849 qdf_mem_copy(stats, &spectral->diag_stats, 4850 sizeof(struct spectral_diag_stats)); 4851 4852 return QDF_STATUS_SUCCESS; 4853 } 4854 4855 /** 4856 * target_if_register_spectral_wmi_ops() - Register Spectral WMI operations 4857 * @psoc: Pointer to psoc object 4858 * @wmi_ops: Pointer to the structure having Spectral WMI operations 4859 * 4860 * API for registering Spectral WMI operations in 4861 * spectral internal data structure 4862 * 4863 * Return: QDF_STATUS 4864 */ 4865 static QDF_STATUS 4866 target_if_register_spectral_wmi_ops(struct wlan_objmgr_psoc *psoc, 4867 struct spectral_wmi_ops *wmi_ops) 4868 { 4869 struct target_if_psoc_spectral *psoc_spectral; 4870 4871 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 4872 if (!psoc_spectral) { 4873 spectral_err("Spectral LMAC object is null"); 4874 return QDF_STATUS_E_INVAL; 4875 } 4876 4877 psoc_spectral->wmi_ops = *wmi_ops; 4878 4879 return QDF_STATUS_SUCCESS; 4880 } 4881 4882 /** 4883 * target_if_register_spectral_tgt_ops() - Register Spectral target operations 4884 * @psoc: Pointer to psoc object 4885 * @tgt_ops: Pointer to the structure having Spectral target operations 4886 * 4887 * API for registering Spectral target operations in 4888 * spectral internal data structure 4889 * 4890 * Return: QDF_STATUS 4891 */ 4892 static QDF_STATUS 4893 target_if_register_spectral_tgt_ops(struct wlan_objmgr_psoc *psoc, 4894 struct spectral_tgt_ops *tgt_ops) 4895 { 4896 if (!psoc) { 4897 spectral_err("psoc is null"); 4898 return QDF_STATUS_E_INVAL; 4899 } 4900 4901 ops_tgt = *tgt_ops; 4902 4903 return QDF_STATUS_SUCCESS; 4904 } 4905 4906 /** 4907 * target_if_register_netlink_cb() - Register Netlink callbacks 4908 * @pdev: Pointer to pdev object 4909 * @nl_cb: Netlink callbacks to register 4910 * 4911 * Return: void 4912 */ 4913 static void 4914 target_if_register_netlink_cb( 4915 struct wlan_objmgr_pdev *pdev, 4916 struct spectral_nl_cb *nl_cb) 4917 { 4918 struct target_if_spectral *spectral = NULL; 4919 4920 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4921 4922 if (!spectral) { 4923 spectral_err("SPECTRAL : Module doesn't exist"); 4924 return; 4925 } 4926 4927 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 4928 4929 if (spectral->use_nl_bcast) 4930 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 4931 else 4932 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 4933 } 4934 4935 /** 4936 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 4937 * Netlink messages to the application layer 4938 * @pdev: Pointer to pdev object 4939 * 4940 * Return: true for broadcast, false for unicast 4941 */ 4942 static bool 4943 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 4944 { 4945 struct target_if_spectral *spectral = NULL; 4946 4947 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4948 4949 if (!spectral) { 4950 spectral_err("SPECTRAL : Module doesn't exist"); 4951 return false; 4952 } 4953 4954 return spectral->use_nl_bcast; 4955 } 4956 4957 /** 4958 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 4959 * @pdev: Pointer to pdev object 4960 * 4961 * Return: void 4962 */ 4963 static void 4964 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 4965 { 4966 struct target_if_spectral *spectral = NULL; 4967 4968 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4969 if (!spectral) { 4970 spectral_err("SPECTRAL : Module doesn't exist"); 4971 return; 4972 } 4973 4974 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 4975 } 4976 4977 static int 4978 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, 4979 void *payload) 4980 { 4981 struct target_if_spectral *spectral = NULL; 4982 struct target_if_spectral_ops *p_sops = NULL; 4983 4984 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4985 if (!spectral) { 4986 spectral_err("SPECTRAL : Module doesn't exist"); 4987 return -EPERM; 4988 } 4989 4990 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4991 4992 if (!p_sops) { 4993 spectral_err("p_sops is null"); 4994 return -EPERM; 4995 } 4996 4997 return p_sops->process_spectral_report(pdev, payload); 4998 } 4999 5000 #ifdef DIRECT_BUF_RX_DEBUG 5001 static inline void 5002 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 5003 { 5004 if (!tx_ops) { 5005 spectral_err("tx_ops is NULL"); 5006 return; 5007 } 5008 5009 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = 5010 target_if_spectral_set_dma_debug; 5011 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = 5012 target_if_spectral_check_and_do_dbr_ring_debug; 5013 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = 5014 target_if_spectral_check_and_do_dbr_buff_debug; 5015 } 5016 #else 5017 static inline void 5018 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 5019 { 5020 } 5021 #endif 5022 5023 #if defined(WLAN_CONV_SPECTRAL_ENABLE) && defined(SPECTRAL_MODULIZED_ENABLE) 5024 /** 5025 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 5026 * register WMI event handler 5027 * @psoc: Pointer to psoc object 5028 * @event_id: Event id 5029 * @handler_func: Handler function 5030 * @rx_ctx: Context of WMI event processing 5031 * 5032 * Wrapper function to register WMI event handler 5033 * 5034 * Return: 0 for success else failure 5035 */ 5036 static int 5037 target_if_spectral_wmi_unified_register_event_handler( 5038 struct wlan_objmgr_psoc *psoc, 5039 wmi_conv_event_id event_id, 5040 wmi_unified_event_handler handler_func, 5041 uint8_t rx_ctx) 5042 { 5043 wmi_unified_t wmi_handle; 5044 struct target_if_psoc_spectral *psoc_spectral; 5045 5046 if (!psoc) { 5047 spectral_err("psoc is null"); 5048 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5049 } 5050 5051 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5052 if (!wmi_handle) { 5053 spectral_err("WMI handle is null"); 5054 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5055 } 5056 5057 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5058 if (!psoc_spectral) { 5059 spectral_err("spectral object is null"); 5060 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5061 } 5062 5063 return psoc_spectral->wmi_ops.wmi_unified_register_event_handler( 5064 wmi_handle, event_id, handler_func, rx_ctx); 5065 } 5066 5067 /** 5068 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 5069 * to unregister WMI event handler 5070 * @psoc: Pointer to psoc object 5071 * @event_id: Event id 5072 * 5073 * Wrapper function to unregister WMI event handler 5074 * 5075 * Return: 0 for success else failure 5076 */ 5077 static int 5078 target_if_spectral_wmi_unified_unregister_event_handler( 5079 struct wlan_objmgr_psoc *psoc, 5080 wmi_conv_event_id event_id) 5081 { 5082 wmi_unified_t wmi_handle; 5083 struct target_if_psoc_spectral *psoc_spectral; 5084 5085 if (!psoc) { 5086 spectral_err("psoc is null"); 5087 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5088 } 5089 5090 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5091 if (!wmi_handle) { 5092 spectral_err("WMI handle is null"); 5093 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5094 } 5095 5096 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5097 if (!psoc_spectral) { 5098 spectral_err("spectral object is null"); 5099 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5100 } 5101 5102 return psoc_spectral->wmi_ops.wmi_unified_unregister_event_handler( 5103 wmi_handle, event_id); 5104 } 5105 5106 /** 5107 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 5108 * function to extract fixed parameters from start scan response event 5109 * @psoc: Pointer to psoc object 5110 * @evt_buf: Event buffer 5111 * @param: Start scan response parameters 5112 * 5113 * Wrapper function to extract fixed parameters from start scan response event 5114 * 5115 * Return: QDF_STATUS 5116 */ 5117 static QDF_STATUS 5118 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5119 struct wlan_objmgr_psoc *psoc, 5120 uint8_t *evt_buf, 5121 struct spectral_startscan_resp_params *param) 5122 { 5123 wmi_unified_t wmi_handle; 5124 struct target_if_psoc_spectral *psoc_spectral; 5125 5126 if (!psoc) { 5127 spectral_err("psoc is null"); 5128 return QDF_STATUS_E_INVAL; 5129 } 5130 5131 if (!evt_buf) { 5132 spectral_err("WMI event buffer is null"); 5133 return QDF_STATUS_E_INVAL; 5134 } 5135 5136 if (!param) { 5137 spectral_err("Spectral startscan response parameters is null"); 5138 return QDF_STATUS_E_INVAL; 5139 } 5140 5141 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5142 if (!wmi_handle) { 5143 spectral_err("WMI handle is null"); 5144 return QDF_STATUS_E_INVAL; 5145 } 5146 5147 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5148 if (!psoc_spectral) { 5149 spectral_err("spectral object is null"); 5150 return QDF_STATUS_E_FAILURE; 5151 } 5152 5153 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5154 wmi_handle, evt_buf, param); 5155 } 5156 5157 /** 5158 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 5159 * function to extract start and end indices of primary 80 MHz, 5 MHz and 5160 * secondary 80 MHz FFT bins 5161 * @psoc: Pointer to psoc object 5162 * @evt_buf: Event buffer 5163 * @param: FFT bin start and end indices 5164 * 5165 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 5166 * and secondary 80 MHz FFT bins 5167 * 5168 * Return: QDF_STATUS 5169 */ 5170 static QDF_STATUS 5171 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 5172 struct wlan_objmgr_psoc *psoc, 5173 uint8_t *evt_buf, 5174 struct spectral_fft_bin_markers_160_165mhz *param) 5175 { 5176 wmi_unified_t wmi_handle; 5177 struct target_if_psoc_spectral *psoc_spectral; 5178 5179 if (!psoc) { 5180 spectral_err("psoc is null"); 5181 return QDF_STATUS_E_INVAL; 5182 } 5183 5184 if (!evt_buf) { 5185 spectral_err("WMI event buffer is null"); 5186 return QDF_STATUS_E_INVAL; 5187 } 5188 5189 if (!param) { 5190 spectral_err("Spectral FFT bin markers is null"); 5191 return QDF_STATUS_E_INVAL; 5192 } 5193 5194 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5195 if (!wmi_handle) { 5196 spectral_err("WMI handle is null"); 5197 return QDF_STATUS_E_INVAL; 5198 } 5199 5200 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5201 if (!psoc_spectral) { 5202 spectral_err("spectral object is null"); 5203 return QDF_STATUS_E_FAILURE; 5204 } 5205 5206 return psoc_spectral->wmi_ops.wmi_extract_pdev_sscan_fft_bin_index( 5207 wmi_handle, evt_buf, param); 5208 } 5209 5210 /** 5211 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 5212 * object from scn handle 5213 * @scn: scn handle 5214 * 5215 * Wrapper function to get psoc object from scn handle 5216 * 5217 * Return: Pointer to psoc object 5218 */ 5219 static struct wlan_objmgr_psoc * 5220 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 5221 { 5222 if (!scn) { 5223 spectral_err("scn is null"); 5224 return NULL; 5225 } 5226 5227 return ops_tgt.tgt_get_psoc_from_scn_hdl(scn); 5228 } 5229 #else 5230 /** 5231 * target_if_spectral_wmi_unified_register_event_handler() - Wrapper function to 5232 * register WMI event handler 5233 * @psoc: Pointer to psoc object 5234 * @event_id: Event id 5235 * @handler_func: Handler function 5236 * @rx_ctx: Context of WMI event processing 5237 * 5238 * Wrapper function to register WMI event handler 5239 * 5240 * Return: 0 for success else failure 5241 */ 5242 static int 5243 target_if_spectral_wmi_unified_register_event_handler( 5244 struct wlan_objmgr_psoc *psoc, 5245 wmi_conv_event_id event_id, 5246 wmi_unified_event_handler handler_func, 5247 uint8_t rx_ctx) 5248 { 5249 wmi_unified_t wmi_handle; 5250 5251 if (!psoc) { 5252 spectral_err("psoc is null"); 5253 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5254 } 5255 5256 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5257 if (!wmi_handle) { 5258 spectral_err("WMI handle is null"); 5259 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5260 } 5261 5262 return wmi_unified_register_event_handler(wmi_handle, event_id, 5263 handler_func, rx_ctx); 5264 } 5265 5266 /** 5267 * target_if_spectral_wmi_unified_unregister_event_handler() - Wrapper function 5268 * to unregister WMI event handler 5269 * @psoc: Pointer to psoc object 5270 * @event_id: Event id 5271 * 5272 * Wrapper function to unregister WMI event handler 5273 * 5274 * Return: 0 for success else failure 5275 */ 5276 static int 5277 target_if_spectral_wmi_unified_unregister_event_handler( 5278 struct wlan_objmgr_psoc *psoc, 5279 wmi_conv_event_id event_id) 5280 { 5281 wmi_unified_t wmi_handle; 5282 5283 if (!psoc) { 5284 spectral_err("psoc is null"); 5285 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5286 } 5287 5288 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5289 if (!wmi_handle) { 5290 spectral_err("WMI handle is null"); 5291 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5292 } 5293 5294 return wmi_unified_unregister_event_handler(wmi_handle, event_id); 5295 } 5296 5297 /** 5298 * target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param() - Wrapper 5299 * function to extract fixed parameters from start scan response event 5300 * @psoc: Pointer to psoc object 5301 * @evt_buf: Event buffer 5302 * @param: Start scan response parameters 5303 * 5304 * Wrapper function to extract fixed parameters from start scan response event 5305 * 5306 * Return: QDF_STATUS 5307 */ 5308 static QDF_STATUS 5309 target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5310 struct wlan_objmgr_psoc *psoc, 5311 uint8_t *evt_buf, 5312 struct spectral_startscan_resp_params *param) 5313 { 5314 wmi_unified_t wmi_handle; 5315 5316 if (!psoc) { 5317 spectral_err("psoc is null"); 5318 return QDF_STATUS_E_INVAL; 5319 } 5320 5321 if (!evt_buf) { 5322 spectral_err("WMI event buffer is null"); 5323 return QDF_STATUS_E_INVAL; 5324 } 5325 5326 if (!param) { 5327 spectral_err("Spectral startscan response parameters is null"); 5328 return QDF_STATUS_E_INVAL; 5329 } 5330 5331 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5332 if (!wmi_handle) { 5333 spectral_err("WMI handle is null"); 5334 return QDF_STATUS_E_INVAL; 5335 } 5336 5337 return wmi_extract_pdev_sscan_fw_cmd_fixed_param(wmi_handle, evt_buf, 5338 param); 5339 } 5340 5341 /** 5342 * target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index() - Wrapper 5343 * function to extract start and end indices of primary 80 MHz, 5 MHz and 5344 * secondary 80 MHz FFT bins 5345 * @psoc: Pointer to psoc object 5346 * @evt_buf: Event buffer 5347 * @param: FFT bin start and end indices 5348 * 5349 * Wrapper function to extract start and end indices of primary 80 MHz, 5 MHz 5350 * and secondary 80 MHz FFT bins 5351 * 5352 * Return: QDF_STATUS 5353 */ 5354 static QDF_STATUS 5355 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 5356 struct wlan_objmgr_psoc *psoc, 5357 uint8_t *evt_buf, 5358 struct spectral_fft_bin_markers_160_165mhz *param) 5359 { 5360 wmi_unified_t wmi_handle; 5361 5362 if (!psoc) { 5363 spectral_err("psoc is null"); 5364 return QDF_STATUS_E_INVAL; 5365 } 5366 5367 if (!evt_buf) { 5368 spectral_err("WMI event buffer is null"); 5369 return QDF_STATUS_E_INVAL; 5370 } 5371 5372 if (!param) { 5373 spectral_err("Spectral FFT bin markers is null"); 5374 return QDF_STATUS_E_INVAL; 5375 } 5376 5377 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5378 if (!wmi_handle) { 5379 spectral_err("WMI handle is null"); 5380 return QDF_STATUS_E_INVAL; 5381 } 5382 5383 return wmi_extract_pdev_sscan_fft_bin_index(wmi_handle, evt_buf, param); 5384 } 5385 5386 /** 5387 * target_if_spectral_get_psoc_from_scn_handle() - Wrapper function to get psoc 5388 * object from scn handle 5389 * @scn: scn handle 5390 * 5391 * Wrapper function to get psoc object from scn handle 5392 * 5393 * Return: Pointer to psoc object 5394 */ 5395 static struct wlan_objmgr_psoc * 5396 target_if_spectral_get_psoc_from_scn_handle(ol_scn_t scn) 5397 { 5398 if (!scn) { 5399 spectral_err("scn is null"); 5400 return NULL; 5401 } 5402 5403 return target_if_get_psoc_from_scn_hdl(scn); 5404 } 5405 #endif 5406 5407 /** 5408 * target_if_spectral_fw_param_event_handler() - WMI event handler to 5409 * process start scan response event 5410 * @scn: Pointer to scn object 5411 * @data_buf: Pointer to event buffer 5412 * @data_len: Length of event buffer 5413 * 5414 * Return: 0 for success, else failure 5415 */ 5416 static int 5417 target_if_spectral_fw_param_event_handler(ol_scn_t scn, uint8_t *data_buf, 5418 uint32_t data_len) 5419 { 5420 QDF_STATUS status; 5421 struct wlan_objmgr_psoc *psoc; 5422 struct wlan_objmgr_pdev *pdev; 5423 struct wmi_unified *wmi_handle; 5424 struct spectral_startscan_resp_params event_params = {0}; 5425 struct target_if_psoc_spectral *psoc_spectral; 5426 struct target_if_spectral *spectral; 5427 5428 if (!scn) { 5429 spectral_err("scn handle is null"); 5430 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5431 } 5432 5433 if (!data_buf) { 5434 spectral_err("WMI event buffer null"); 5435 return qdf_status_to_os_return(QDF_STATUS_E_INVAL); 5436 } 5437 5438 psoc = target_if_spectral_get_psoc_from_scn_handle(scn); 5439 if (!psoc) { 5440 spectral_err("psoc is null"); 5441 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5442 } 5443 5444 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 5445 if (!psoc_spectral) { 5446 spectral_err("spectral object is null"); 5447 return QDF_STATUS_E_FAILURE; 5448 } 5449 5450 wmi_handle = GET_WMI_HDL_FROM_PSOC(psoc); 5451 if (!wmi_handle) { 5452 spectral_err("WMI handle is null"); 5453 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5454 } 5455 5456 status = target_if_spectral_wmi_extract_pdev_sscan_fw_cmd_fixed_param( 5457 psoc, data_buf, &event_params); 5458 if (QDF_IS_STATUS_ERROR(status)) { 5459 spectral_err("unable to extract sscan fw fixed params"); 5460 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5461 } 5462 5463 pdev = wlan_objmgr_get_pdev_by_id(psoc, event_params.pdev_id, 5464 WLAN_SPECTRAL_ID); 5465 if (!pdev) { 5466 spectral_err("pdev is null"); 5467 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5468 } 5469 5470 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5471 if (!spectral) { 5472 spectral_err("spectral object is null"); 5473 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 5474 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5475 } 5476 5477 if (event_params.num_fft_bin_index == 1) { 5478 status = 5479 target_if_spectral_wmi_extract_pdev_sscan_fft_bin_index( 5480 psoc, data_buf, 5481 &spectral->rparams.marker[event_params.smode]); 5482 if (QDF_IS_STATUS_ERROR(status)) { 5483 spectral_err("unable to extract sscan fw fixed params"); 5484 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 5485 return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); 5486 } 5487 } else { 5488 spectral->rparams.marker[event_params.smode].is_valid = false; 5489 } 5490 5491 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 5492 5493 return qdf_status_to_os_return(QDF_STATUS_SUCCESS); 5494 } 5495 5496 static QDF_STATUS 5497 target_if_spectral_register_events(struct wlan_objmgr_psoc *psoc) 5498 { 5499 int ret; 5500 5501 if (!psoc) { 5502 spectral_err("psoc is null"); 5503 return QDF_STATUS_E_INVAL; 5504 } 5505 5506 ret = target_if_spectral_wmi_unified_register_event_handler( 5507 psoc, 5508 wmi_pdev_sscan_fw_param_eventid, 5509 target_if_spectral_fw_param_event_handler, 5510 WMI_RX_UMAC_CTX); 5511 5512 if (ret) 5513 spectral_debug("event handler not supported, ret=%d", ret); 5514 5515 return QDF_STATUS_SUCCESS; 5516 } 5517 5518 static QDF_STATUS 5519 target_if_spectral_unregister_events(struct wlan_objmgr_psoc *psoc) 5520 { 5521 int ret; 5522 5523 if (!psoc) { 5524 spectral_err("psoc is null"); 5525 return QDF_STATUS_E_INVAL; 5526 } 5527 5528 ret = target_if_spectral_wmi_unified_unregister_event_handler( 5529 psoc, wmi_pdev_sscan_fw_param_eventid); 5530 5531 if (ret) 5532 spectral_debug("Unregister WMI event handler failed, ret = %d", 5533 ret); 5534 5535 return QDF_STATUS_SUCCESS; 5536 } 5537 5538 void 5539 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 5540 { 5541 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 5542 target_if_pdev_spectral_init; 5543 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 5544 target_if_pdev_spectral_deinit; 5545 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_init = 5546 target_if_psoc_spectral_init; 5547 tx_ops->sptrl_tx_ops.sptrlto_psoc_spectral_deinit = 5548 target_if_psoc_spectral_deinit; 5549 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 5550 target_if_set_spectral_config; 5551 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 5552 target_if_get_spectral_config; 5553 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 5554 target_if_start_spectral_scan; 5555 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 5556 target_if_stop_spectral_scan; 5557 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 5558 target_if_is_spectral_active; 5559 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 5560 target_if_is_spectral_enabled; 5561 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 5562 target_if_set_debug_level; 5563 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 5564 target_if_get_debug_level; 5565 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 5566 target_if_get_spectral_capinfo; 5567 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 5568 target_if_get_spectral_diagstats; 5569 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_wmi_ops = 5570 target_if_register_spectral_wmi_ops; 5571 tx_ops->sptrl_tx_ops.sptrlto_register_spectral_tgt_ops = 5572 target_if_register_spectral_tgt_ops; 5573 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 5574 target_if_register_netlink_cb; 5575 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 5576 target_if_use_nl_bcast; 5577 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 5578 target_if_deregister_netlink_cb; 5579 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = 5580 target_if_process_spectral_report; 5581 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = 5582 target_if_spectral_direct_dma_support; 5583 tx_ops->sptrl_tx_ops.sptrlto_register_events = 5584 target_if_spectral_register_events; 5585 tx_ops->sptrl_tx_ops.sptrlto_unregister_events = 5586 target_if_spectral_unregister_events; 5587 5588 target_if_sptrl_debug_register_tx_ops(tx_ops); 5589 } 5590 qdf_export_symbol(target_if_sptrl_register_tx_ops); 5591 5592 void 5593 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 5594 uint16_t cw_int, uint32_t dcs_enabled) 5595 { 5596 struct spectral_samp_msg *msg = NULL; 5597 struct target_if_spectral_ops *p_sops = NULL; 5598 struct target_if_spectral *spectral = NULL; 5599 5600 spectral = get_target_if_spectral_handle_from_pdev(pdev); 5601 5602 if (!spectral) { 5603 spectral_err("SPECTRAL : Module doesn't exist"); 5604 return; 5605 } 5606 5607 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 5608 if (!p_sops) { 5609 spectral_err("p_sops is null"); 5610 return; 5611 } 5612 5613 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( 5614 spectral->pdev_obj, 5615 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, 5616 SPECTRAL_MSG_BUF_NEW); 5617 5618 if (msg) { 5619 msg->int_type = cw_int ? 5620 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 5621 msg->dcs_enabled = dcs_enabled; 5622 msg->signature = SPECTRAL_SIGNATURE; 5623 p_sops->get_mac_address(spectral, msg->macaddr); 5624 if (spectral->send_phy_data 5625 (pdev, 5626 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0) 5627 spectral->spectral_sent_msg++; 5628 } 5629 } 5630 qdf_export_symbol(target_if_spectral_send_intf_found_msg); 5631