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