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 45 static void target_if_spectral_get_firstvdev_pdev(struct wlan_objmgr_pdev *pdev, 46 void *obj, void *arg) 47 { 48 struct wlan_objmgr_vdev *vdev = obj; 49 struct wlan_objmgr_vdev **first_vdev = arg; 50 51 if (!(*first_vdev)) 52 *first_vdev = vdev; 53 } 54 55 struct wlan_objmgr_vdev * 56 target_if_spectral_get_vdev(struct target_if_spectral *spectral) 57 { 58 struct wlan_objmgr_pdev *pdev = NULL; 59 struct wlan_objmgr_vdev *first_vdev = NULL; 60 61 qdf_assert_always(spectral); 62 pdev = spectral->pdev_obj; 63 qdf_assert_always(pdev); 64 65 if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) != 66 QDF_STATUS_SUCCESS) { 67 spectral_err("Unable to get pdev reference."); 68 return NULL; 69 } 70 71 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 72 target_if_spectral_get_firstvdev_pdev, 73 &first_vdev, 0, WLAN_SPECTRAL_ID); 74 75 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 76 77 if (!first_vdev) 78 return NULL; 79 80 if (wlan_objmgr_vdev_try_get_ref(first_vdev, WLAN_SPECTRAL_ID) != 81 QDF_STATUS_SUCCESS) 82 first_vdev = NULL; 83 84 85 return first_vdev; 86 } 87 88 /** 89 * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure 90 * spectral parameters 91 * @spectral: Pointer to Spectral target_if internal private data 92 * @smode: Spectral scan mode 93 * @param: Pointer to spectral_config giving the Spectral configuration 94 * 95 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 96 */ 97 static int 98 target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, 99 enum spectral_scan_mode smode, 100 struct spectral_config *param) 101 { 102 struct vdev_spectral_configure_params sparam; 103 struct wlan_objmgr_pdev *pdev = NULL; 104 struct wlan_objmgr_vdev *vdev = NULL; 105 106 qdf_assert_always(spectral && param); 107 108 pdev = spectral->pdev_obj; 109 110 qdf_assert_always(pdev); 111 112 vdev = target_if_spectral_get_vdev(spectral); 113 if (!vdev) 114 return QDF_STATUS_E_NOENT; 115 116 qdf_mem_zero(&sparam, sizeof(sparam)); 117 118 sparam.vdev_id = wlan_vdev_get_id(vdev); 119 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 120 121 sparam.count = param->ss_count; 122 sparam.period = param->ss_period; 123 sparam.spectral_pri = param->ss_spectral_pri; 124 sparam.fft_size = param->ss_fft_size; 125 sparam.gc_enable = param->ss_gc_ena; 126 sparam.restart_enable = param->ss_restart_ena; 127 sparam.noise_floor_ref = param->ss_noise_floor_ref; 128 sparam.init_delay = param->ss_init_delay; 129 sparam.nb_tone_thr = param->ss_nb_tone_thr; 130 sparam.str_bin_thr = param->ss_str_bin_thr; 131 sparam.wb_rpt_mode = param->ss_wb_rpt_mode; 132 sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode; 133 sparam.rssi_thr = param->ss_rssi_thr; 134 sparam.pwr_format = param->ss_pwr_format; 135 sparam.rpt_mode = param->ss_rpt_mode; 136 sparam.bin_scale = param->ss_bin_scale; 137 sparam.dbm_adj = param->ss_dbm_adj; 138 sparam.chn_mask = param->ss_chn_mask; 139 sparam.mode = smode; 140 sparam.center_freq = param->ss_frequency; 141 142 return spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send( 143 GET_WMI_HDL_FROM_PDEV(pdev), &sparam); 144 } 145 146 /** 147 * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to 148 * enable/disable Spectral 149 * @spectral: Pointer to Spectral target_if internal private data 150 * @smode: Spectral scan mode 151 * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is 152 * valid 153 * @is_spectral_active: Value of spectral activate 154 * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid 155 * @is_spectral_enabled: Value of spectral enable 156 * 157 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 158 */ 159 static int 160 target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral, 161 enum spectral_scan_mode smode, 162 uint8_t is_spectral_active_valid, 163 uint8_t is_spectral_active, 164 uint8_t is_spectral_enabled_valid, 165 uint8_t is_spectral_enabled) 166 { 167 struct vdev_spectral_enable_params param; 168 struct wlan_objmgr_pdev *pdev = NULL; 169 struct wlan_objmgr_vdev *vdev = NULL; 170 171 qdf_assert_always(spectral); 172 173 pdev = spectral->pdev_obj; 174 175 qdf_assert_always(pdev); 176 177 vdev = target_if_spectral_get_vdev(spectral); 178 if (!vdev) 179 return QDF_STATUS_E_NOENT; 180 181 qdf_mem_zero(¶m, sizeof(param)); 182 183 param.vdev_id = wlan_vdev_get_id(vdev); 184 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 185 186 param.active_valid = is_spectral_active_valid; 187 param.enabled_valid = is_spectral_enabled_valid; 188 param.active = is_spectral_active; 189 param.enabled = is_spectral_enabled; 190 param.mode = smode; 191 192 return spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send( 193 GET_WMI_HDL_FROM_PDEV(pdev), ¶m); 194 } 195 196 /** 197 * target_if_spectral_info_init_defaults() - Helper function to load defaults 198 * for Spectral information (parameters and state) into cache. 199 * @spectral: Pointer to Spectral target_if internal private data 200 * @smode: Spectral scan mode 201 * 202 * It is assumed that the caller has obtained the requisite lock if applicable. 203 * Note that this is currently treated as a temporary function. Ideally, we 204 * would like to get defaults from the firmware. 205 * 206 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 207 */ 208 static QDF_STATUS 209 target_if_spectral_info_init_defaults(struct target_if_spectral *spectral, 210 enum spectral_scan_mode smode) 211 { 212 struct target_if_spectral_param_state_info *info; 213 struct wlan_objmgr_vdev *vdev = NULL; 214 215 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 216 spectral_err("Invalid Spectral mode %u", smode); 217 return QDF_STATUS_E_FAILURE; 218 } 219 220 info = &spectral->param_info[smode]; 221 222 /* State */ 223 info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT; 224 225 info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT; 226 227 /* Parameters */ 228 info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT; 229 230 if (spectral->spectral_gen == SPECTRAL_GEN3) 231 info->osps_cache.osc_params.ss_period = 232 SPECTRAL_SCAN_PERIOD_GEN_III_DEFAULT; 233 else 234 info->osps_cache.osc_params.ss_period = 235 SPECTRAL_SCAN_PERIOD_GEN_II_DEFAULT; 236 237 info->osps_cache.osc_params.ss_spectral_pri = 238 SPECTRAL_SCAN_PRIORITY_DEFAULT; 239 240 info->osps_cache.osc_params.ss_fft_size = 241 SPECTRAL_SCAN_FFT_SIZE_DEFAULT; 242 243 info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT; 244 245 info->osps_cache.osc_params.ss_restart_ena = 246 SPECTRAL_SCAN_RESTART_ENA_DEFAULT; 247 248 info->osps_cache.osc_params.ss_noise_floor_ref = 249 SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT; 250 251 info->osps_cache.osc_params.ss_init_delay = 252 SPECTRAL_SCAN_INIT_DELAY_DEFAULT; 253 254 info->osps_cache.osc_params.ss_nb_tone_thr = 255 SPECTRAL_SCAN_NB_TONE_THR_DEFAULT; 256 257 info->osps_cache.osc_params.ss_str_bin_thr = 258 SPECTRAL_SCAN_STR_BIN_THR_DEFAULT; 259 260 info->osps_cache.osc_params.ss_wb_rpt_mode = 261 SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT; 262 263 info->osps_cache.osc_params.ss_rssi_rpt_mode = 264 SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT; 265 266 info->osps_cache.osc_params.ss_rssi_thr = 267 SPECTRAL_SCAN_RSSI_THR_DEFAULT; 268 269 info->osps_cache.osc_params.ss_pwr_format = 270 SPECTRAL_SCAN_PWR_FORMAT_DEFAULT; 271 272 info->osps_cache.osc_params.ss_rpt_mode = 273 SPECTRAL_SCAN_RPT_MODE_DEFAULT; 274 275 info->osps_cache.osc_params.ss_bin_scale = 276 SPECTRAL_SCAN_BIN_SCALE_DEFAULT; 277 278 info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT; 279 280 vdev = target_if_spectral_get_vdev(spectral); 281 if (!vdev) 282 return QDF_STATUS_E_NOENT; 283 284 info->osps_cache.osc_params.ss_chn_mask = 285 wlan_vdev_mlme_get_rxchainmask(vdev); 286 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 287 288 info->osps_cache.osc_params.ss_short_report = 289 SPECTRAL_SCAN_SHORT_REPORT_DEFAULT; 290 291 info->osps_cache.osc_params.ss_fft_period = 292 SPECTRAL_SCAN_FFT_PERIOD_DEFAULT; 293 294 info->osps_cache.osc_params.ss_frequency = 295 SPECTRAL_SCAN_FREQUENCY_DEFAULT; 296 297 /* The cache is now valid */ 298 info->osps_cache.osc_is_valid = 1; 299 300 return QDF_STATUS_SUCCESS; 301 } 302 303 /** 304 * target_if_log_read_spectral_active() - Helper function to log whether 305 * spectral is active after reading cache 306 * @function_name: Function name 307 * @output: whether spectral is active or not 308 * 309 * Helper function to log whether spectral is active after reading cache 310 * 311 * Return: none 312 */ 313 static void 314 target_if_log_read_spectral_active( 315 const char *function_name, 316 unsigned char output) 317 { 318 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u", 319 function_name, output); 320 } 321 322 /** 323 * target_if_log_read_spectral_enabled() - Helper function to log whether 324 * spectral is enabled after reading cache 325 * @function_name: Function name 326 * @output: whether spectral is enabled or not 327 * 328 * Helper function to log whether spectral is enabled after reading cache 329 * 330 * Return: none 331 */ 332 static void 333 target_if_log_read_spectral_enabled( 334 const char *function_name, 335 unsigned char output) 336 { 337 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u", 338 function_name, output); 339 } 340 341 /** 342 * target_if_log_read_spectral_enabled() - Helper function to log spectral 343 * parameters after reading cache 344 * @function_name: Function name 345 * @pparam: Spectral parameters 346 * 347 * Helper function to log spectral parameters after reading cache 348 * 349 * Return: none 350 */ 351 static void 352 target_if_log_read_spectral_params( 353 const char *function_name, 354 struct spectral_config *pparam) 355 { 356 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_frequency=%u\n", 357 function_name, 358 pparam->ss_count, 359 pparam->ss_period, 360 pparam->ss_spectral_pri, 361 pparam->ss_fft_size, 362 pparam->ss_gc_ena, 363 pparam->ss_restart_ena, 364 (int8_t)pparam->ss_noise_floor_ref, 365 pparam->ss_init_delay, 366 pparam->ss_nb_tone_thr, 367 pparam->ss_str_bin_thr, 368 pparam->ss_wb_rpt_mode, 369 pparam->ss_rssi_rpt_mode, 370 (int8_t)pparam->ss_rssi_thr, 371 pparam->ss_pwr_format, 372 pparam->ss_rpt_mode, 373 pparam->ss_bin_scale, 374 pparam->ss_dbm_adj, 375 pparam->ss_chn_mask, 376 pparam->ss_frequency); 377 } 378 379 /** 380 * target_if_log_read_spectral_active_catch_validate() - Helper function to 381 * log whether spectral is active after intializing the cache 382 * @function_name: Function name 383 * @output: whether spectral is active or not 384 * 385 * Helper function to log whether spectral is active after intializing cache 386 * 387 * Return: none 388 */ 389 static void 390 target_if_log_read_spectral_active_catch_validate( 391 const char *function_name, 392 unsigned char output) 393 { 394 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u", 395 function_name, output); 396 } 397 398 /** 399 * target_if_log_read_spectral_enabled_catch_validate() - Helper function to 400 * log whether spectral is enabled after intializing the cache 401 * @function_name: Function name 402 * @output: whether spectral is enabled or not 403 * 404 * Helper function to log whether spectral is enabled after intializing cache 405 * 406 * Return: none 407 */ 408 static void 409 target_if_log_read_spectral_enabled_catch_validate( 410 const char *function_name, 411 unsigned char output) 412 { 413 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n", 414 function_name, output); 415 } 416 417 /** 418 * target_if_log_read_spectral_params_catch_validate() - Helper function to 419 * log spectral parameters after intializing the cache 420 * @function_name: Function name 421 * @pparam: Spectral parameters 422 * 423 * Helper function to log spectral parameters after intializing the cache 424 * 425 * Return: none 426 */ 427 static void 428 target_if_log_read_spectral_params_catch_validate( 429 const char *function_name, 430 struct spectral_config *pparam) 431 { 432 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", 433 function_name, 434 pparam->ss_count, 435 pparam->ss_period, 436 pparam->ss_spectral_pri, 437 pparam->ss_fft_size, 438 pparam->ss_gc_ena, 439 pparam->ss_restart_ena, 440 (int8_t)pparam->ss_noise_floor_ref, 441 pparam->ss_init_delay, 442 pparam->ss_nb_tone_thr, 443 pparam->ss_str_bin_thr, 444 pparam->ss_wb_rpt_mode, 445 pparam->ss_rssi_rpt_mode, 446 (int8_t)pparam->ss_rssi_thr, 447 pparam->ss_pwr_format, 448 pparam->ss_rpt_mode, 449 pparam->ss_bin_scale, 450 pparam->ss_dbm_adj, pparam->ss_chn_mask); 451 } 452 453 /** 454 * target_if_spectral_info_read() - Read spectral information from the cache. 455 * @spectral: Pointer to Spectral target_if internal private data 456 * @smode: Spectral scan mode 457 * @specifier: target_if_spectral_info enumeration specifying which 458 * information is required 459 * @output: Void output pointer into which the information will be read 460 * @output_len: size of object pointed to by output pointer 461 * 462 * Read spectral parameters or the desired state information from the cache. 463 * 464 * Return: 0 on success, negative error code on failure 465 */ 466 static int 467 target_if_spectral_info_read( 468 struct target_if_spectral *spectral, 469 enum spectral_scan_mode smode, 470 enum target_if_spectral_info specifier, 471 void *output, int output_len) 472 { 473 /* 474 * Note: This function is designed to be able to accommodate 475 * WMI reads for defaults, non-cacheable information, etc 476 * if required. 477 */ 478 struct target_if_spectral_param_state_info *info; 479 int is_cacheable = 0; 480 int init_def_retval = 0; 481 482 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 483 spectral_err("Invalid Spectral mode %u", smode); 484 return -EINVAL; 485 } 486 info = &spectral->param_info[smode]; 487 488 if (!output) 489 return -EINVAL; 490 491 switch (specifier) { 492 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 493 if (output_len != sizeof(info->osps_cache.osc_spectral_active)) 494 return -EINVAL; 495 is_cacheable = 1; 496 break; 497 498 case TARGET_IF_SPECTRAL_INFO_ENABLED: 499 if (output_len != sizeof(info->osps_cache.osc_spectral_enabled)) 500 return -EINVAL; 501 is_cacheable = 1; 502 break; 503 504 case TARGET_IF_SPECTRAL_INFO_PARAMS: 505 if (output_len != sizeof(info->osps_cache.osc_params)) 506 return -EINVAL; 507 is_cacheable = 1; 508 break; 509 510 default: 511 spectral_err("Unknown target_if_spectral_info specifier"); 512 return -EINVAL; 513 } 514 515 qdf_spin_lock(&info->osps_lock); 516 517 if (is_cacheable) { 518 if (info->osps_cache.osc_is_valid) { 519 switch (specifier) { 520 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 521 qdf_mem_copy( 522 output, 523 &info->osps_cache.osc_spectral_active, 524 sizeof(info->osps_cache.osc_spectral_active)); 525 526 target_if_log_read_spectral_active( 527 __func__, 528 *((unsigned char *)output)); 529 break; 530 531 case TARGET_IF_SPECTRAL_INFO_ENABLED: 532 qdf_mem_copy( 533 output, 534 &info->osps_cache.osc_spectral_enabled, 535 sizeof( 536 info->osps_cache.osc_spectral_enabled)); 537 538 target_if_log_read_spectral_enabled( 539 __func__, 540 *((unsigned char *)output)); 541 break; 542 543 case TARGET_IF_SPECTRAL_INFO_PARAMS: 544 qdf_mem_copy( 545 output, 546 &info->osps_cache.osc_params, 547 sizeof(info->osps_cache.osc_params)); 548 549 target_if_log_read_spectral_params( 550 __func__, 551 (struct spectral_config *)output); 552 break; 553 554 default: 555 /* We can't reach this point */ 556 break; 557 } 558 qdf_spin_unlock(&info->osps_lock); 559 return 0; 560 } 561 } 562 563 /* Cache is invalid */ 564 565 /* 566 * If WMI Reads are implemented to fetch defaults/non-cacheable info, 567 * then the below implementation will change 568 */ 569 init_def_retval = 570 target_if_spectral_info_init_defaults(spectral, smode); 571 if (init_def_retval != QDF_STATUS_SUCCESS) { 572 qdf_spin_unlock(&info->osps_lock); 573 if (init_def_retval == QDF_STATUS_E_NOENT) 574 return -ENOENT; 575 else 576 return -EINVAL; 577 } 578 /* target_if_spectral_info_init_defaults() has set cache to valid */ 579 580 switch (specifier) { 581 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 582 qdf_mem_copy(output, 583 &info->osps_cache.osc_spectral_active, 584 sizeof(info->osps_cache.osc_spectral_active)); 585 586 target_if_log_read_spectral_active_catch_validate( 587 __func__, 588 *((unsigned char *)output)); 589 break; 590 591 case TARGET_IF_SPECTRAL_INFO_ENABLED: 592 qdf_mem_copy(output, 593 &info->osps_cache.osc_spectral_enabled, 594 sizeof(info->osps_cache.osc_spectral_enabled)); 595 596 target_if_log_read_spectral_enabled_catch_validate( 597 __func__, 598 *((unsigned char *)output)); 599 break; 600 601 case TARGET_IF_SPECTRAL_INFO_PARAMS: 602 qdf_mem_copy(output, 603 &info->osps_cache.osc_params, 604 sizeof(info->osps_cache.osc_params)); 605 606 target_if_log_read_spectral_params_catch_validate( 607 __func__, 608 (struct spectral_config *)output); 609 610 break; 611 612 default: 613 /* We can't reach this point */ 614 break; 615 } 616 617 qdf_spin_unlock(&info->osps_lock); 618 619 return 0; 620 } 621 622 /** 623 * target_if_log_write_spectral_active() - Helper function to log inputs and 624 * return value of call to configure the Spectral 'active' configuration, 625 * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware 626 * @function_name: Function name in which this is called 627 * @pval: whether spectral is active or not 628 * @ret: return value of the firmware write function 629 * 630 * Return: none 631 */ 632 static void 633 target_if_log_write_spectral_active( 634 const char *function_name, 635 uint8_t pval, 636 int ret) 637 { 638 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d", 639 function_name, pval, ret); 640 } 641 642 /** 643 * target_if_log_write_spectral_enabled() - Helper function to log inputs and 644 * return value of call to configure the Spectral 'enabled' configuration, 645 * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware 646 * @function_name: Function name in which this is called 647 * @pval: whether spectral is enabled or not 648 * @ret: return value of the firmware write function 649 * 650 * Return: none 651 */ 652 static void 653 target_if_log_write_spectral_enabled( 654 const char *function_name, 655 uint8_t pval, 656 int ret) 657 { 658 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d", 659 function_name, pval, ret); 660 } 661 662 /** 663 * target_if_log_write_spectral_params() - Helper function to log inputs and 664 * return value of call to configure Spectral parameters, 665 * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware 666 * @param: Spectral parameters 667 * @function_name: Function name in which this is called 668 * @ret: return value of the firmware write function 669 * 670 * Return: none 671 */ 672 static void 673 target_if_log_write_spectral_params( 674 struct spectral_config *param, 675 const char *function_name, 676 int ret) 677 { 678 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_frequency=%u\nstatus = %d", 679 function_name, 680 param->ss_count, 681 param->ss_period, 682 param->ss_spectral_pri, 683 param->ss_fft_size, 684 param->ss_gc_ena, 685 param->ss_restart_ena, 686 (int8_t)param->ss_noise_floor_ref, 687 param->ss_init_delay, 688 param->ss_nb_tone_thr, 689 param->ss_str_bin_thr, 690 param->ss_wb_rpt_mode, 691 param->ss_rssi_rpt_mode, 692 (int8_t)param->ss_rssi_thr, 693 param->ss_pwr_format, 694 param->ss_rpt_mode, 695 param->ss_bin_scale, 696 param->ss_dbm_adj, 697 param->ss_chn_mask, 698 param->ss_frequency, 699 ret); 700 } 701 702 /** 703 * target_if_spectral_info_write() - Write Spectral information to the 704 * firmware, and update cache 705 * @spectral: Pointer to Spectral target_if internal private data 706 * @smode: Spectral scan mode 707 * @specifier: target_if_spectral_info enumeration specifying which 708 * information is involved 709 * @input: void input pointer containing the information to be written 710 * @input_len: size of object pointed to by input pointer 711 * 712 * Write Spectral parameters or the desired state information to 713 * the firmware, and update cache 714 * 715 * Return: 0 on success, negative error code on failure 716 */ 717 static int 718 target_if_spectral_info_write( 719 struct target_if_spectral *spectral, 720 enum spectral_scan_mode smode, 721 enum target_if_spectral_info specifier, 722 void *input, int input_len) 723 { 724 struct target_if_spectral_param_state_info *info; 725 int ret; 726 uint8_t *pval = NULL; 727 struct spectral_config *param = NULL; 728 729 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 730 spectral_err("Invalid Spectral mode %u", smode); 731 return -EINVAL; 732 } 733 info = &spectral->param_info[smode]; 734 735 if (!input) 736 return -EINVAL; 737 738 switch (specifier) { 739 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 740 if (input_len != sizeof(info->osps_cache.osc_spectral_active)) 741 return -EINVAL; 742 743 pval = (uint8_t *)input; 744 745 qdf_spin_lock(&info->osps_lock); 746 ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode, 747 1, *pval, 0, 0); 748 749 target_if_log_write_spectral_active( 750 __func__, 751 *pval, 752 ret); 753 754 if (ret < 0) { 755 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d", 756 ret); 757 qdf_spin_unlock(&info->osps_lock); 758 return ret; 759 } 760 761 info->osps_cache.osc_spectral_active = *pval; 762 763 /* The cache is now valid */ 764 info->osps_cache.osc_is_valid = 1; 765 766 qdf_spin_unlock(&info->osps_lock); 767 break; 768 769 case TARGET_IF_SPECTRAL_INFO_ENABLED: 770 if (input_len != sizeof(info->osps_cache.osc_spectral_enabled)) 771 return -EINVAL; 772 773 pval = (uint8_t *)input; 774 775 qdf_spin_lock(&info->osps_lock); 776 ret = target_if_send_vdev_spectral_enable_cmd(spectral, smode, 777 0, 0, 1, *pval); 778 779 target_if_log_write_spectral_enabled( 780 __func__, 781 *pval, 782 ret); 783 784 if (ret < 0) { 785 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d", 786 ret); 787 qdf_spin_unlock(&info->osps_lock); 788 return ret; 789 } 790 791 info->osps_cache.osc_spectral_enabled = *pval; 792 793 /* The cache is now valid */ 794 info->osps_cache.osc_is_valid = 1; 795 796 qdf_spin_unlock(&info->osps_lock); 797 break; 798 799 case TARGET_IF_SPECTRAL_INFO_PARAMS: 800 if (input_len != sizeof(info->osps_cache.osc_params)) 801 return -EINVAL; 802 803 param = (struct spectral_config *)input; 804 805 qdf_spin_lock(&info->osps_lock); 806 ret = target_if_send_vdev_spectral_configure_cmd(spectral, 807 smode, param); 808 809 target_if_log_write_spectral_params( 810 param, 811 __func__, 812 ret); 813 814 if (ret < 0) { 815 spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d", 816 ret); 817 qdf_spin_unlock(&info->osps_lock); 818 return ret; 819 } 820 821 qdf_mem_copy(&info->osps_cache.osc_params, 822 param, sizeof(info->osps_cache.osc_params)); 823 824 /* The cache is now valid */ 825 info->osps_cache.osc_is_valid = 1; 826 827 qdf_spin_unlock(&info->osps_lock); 828 break; 829 830 default: 831 spectral_err("Unknown target_if_spectral_info specifier"); 832 return -EINVAL; 833 } 834 835 return 0; 836 } 837 838 /** 839 * target_if_spectral_get_tsf64() - Function to get the TSF value 840 * @arg: Pointer to handle for Spectral target_if internal private data 841 * 842 * Get the last TSF received in WMI buffer 843 * 844 * Return: TSF value 845 */ 846 static uint64_t 847 target_if_spectral_get_tsf64(void *arg) 848 { 849 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 850 851 return spectral->tsf64; 852 } 853 854 /** 855 * target_if_spectral_get_capability() - Function to get whether a 856 * given Spectral hardware capability is available 857 * @arg: Pointer to handle for Spectral target_if internal private data 858 * @type: Spectral hardware capability type 859 * 860 * Get whether a given Spectral hardware capability is available 861 * 862 * Return: True if the capability is available, false if the capability is not 863 * available 864 */ 865 uint32_t 866 target_if_spectral_get_capability(void *arg, enum spectral_capability_type type) 867 { 868 int status = STATUS_FAIL; 869 870 switch (type) { 871 case SPECTRAL_CAP_PHYDIAG: 872 case SPECTRAL_CAP_RADAR: 873 case SPECTRAL_CAP_SPECTRAL_SCAN: 874 case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN: 875 status = STATUS_PASS; 876 break; 877 default: 878 status = STATUS_FAIL; 879 } 880 return status; 881 } 882 883 /** 884 * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start 885 * @arg: Pointer to handle for Spectral target_if internal private data 886 * @rxfilter: Rx filter to be used 887 * 888 * Note: This is only a placeholder function. It is not currently required since 889 * FW should be taking care of setting the required filters. 890 * 891 * Return: 0 892 */ 893 uint32_t 894 target_if_spectral_set_rxfilter(void *arg, int rxfilter) 895 { 896 /* 897 * Will not be required since enabling of spectral in firmware 898 * will take care of this 899 */ 900 return 0; 901 } 902 903 /** 904 * target_if_spectral_get_rxfilter() - Get the current RX Filter settings 905 * @arg: Pointer to handle for Spectral target_if internal private data 906 * 907 * Note: This is only a placeholder function. It is not currently required since 908 * FW should be taking care of setting the required filters. 909 * 910 * Return: 0 911 */ 912 uint32_t 913 target_if_spectral_get_rxfilter(void *arg) 914 { 915 /* 916 * Will not be required since enabling of spectral in firmware 917 * will take care of this 918 */ 919 return 0; 920 } 921 922 /** 923 * target_if_sops_is_spectral_active() - Get whether Spectral is active 924 * @arg: Pointer to handle for Spectral target_if internal private data 925 * @smode: Spectral scan mode 926 * 927 * Function to check whether Spectral is active 928 * 929 * Return: True if Spectral is active, false if Spectral is not active 930 */ 931 uint32_t 932 target_if_sops_is_spectral_active(void *arg, enum spectral_scan_mode smode) 933 { 934 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 935 uint8_t val = 0; 936 int ret; 937 938 ret = target_if_spectral_info_read( 939 spectral, 940 smode, 941 TARGET_IF_SPECTRAL_INFO_ACTIVE, 942 &val, sizeof(val)); 943 944 if (ret != 0) { 945 /* 946 * Could not determine if Spectral is active. 947 * Return false as a safe value. 948 * XXX: Consider changing the function prototype 949 * to be able to indicate failure to fetch value. 950 */ 951 return 0; 952 } 953 954 return val; 955 } 956 957 /** 958 * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled 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 enabled 963 * 964 * Return: True if Spectral is enabled, false if Spectral is not enabled 965 */ 966 uint32_t 967 target_if_sops_is_spectral_enabled(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_ENABLED, 977 &val, sizeof(val)); 978 979 if (ret != 0) { 980 /* 981 * Could not determine if Spectral is enabled. 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_start_spectral_scan() - Start Spectral scan 994 * @arg: Pointer to handle for Spectral target_if internal private data 995 * @smode: Spectral scan mode 996 * @err: Spectral error code 997 * 998 * Function to start spectral scan 999 * 1000 * Return: 0 on success else failure 1001 */ 1002 uint32_t 1003 target_if_sops_start_spectral_scan(void *arg, enum spectral_scan_mode smode, 1004 enum spectral_cp_error_code *err) 1005 { 1006 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1007 uint8_t val = 1; 1008 uint8_t enabled = 0; 1009 int ret; 1010 1011 ret = target_if_spectral_info_read( 1012 spectral, 1013 smode, 1014 TARGET_IF_SPECTRAL_INFO_ENABLED, 1015 &enabled, sizeof(enabled)); 1016 1017 if (ret != 0) { 1018 /* 1019 * Could not determine if Spectral is enabled. Assume we need 1020 * to enable it 1021 */ 1022 enabled = 0; 1023 } 1024 1025 if (!enabled) { 1026 ret = target_if_spectral_info_write( 1027 spectral, 1028 smode, 1029 TARGET_IF_SPECTRAL_INFO_ENABLED, 1030 &val, sizeof(val)); 1031 1032 if (ret != 0) 1033 return ret; 1034 } 1035 1036 ret = target_if_spectral_info_write( 1037 spectral, 1038 smode, 1039 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1040 &val, sizeof(val)); 1041 1042 if (ret != 0) 1043 return ret; 1044 1045 return 0; 1046 } 1047 1048 /** 1049 * target_if_sops_stop_spectral_scan() - Stop Spectral scan 1050 * @arg: Pointer to handle for Spectral target_if internal private data 1051 * @smode: Spectral scan mode 1052 * 1053 * Function to stop spectral scan 1054 * 1055 * Return: 0 on success else failure 1056 */ 1057 uint32_t 1058 target_if_sops_stop_spectral_scan(void *arg, enum spectral_scan_mode smode) 1059 { 1060 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1061 uint8_t val = 0; 1062 int tempret, ret = 0; 1063 uint8_t enabled = 0; 1064 1065 tempret = target_if_spectral_info_read( 1066 spectral, 1067 smode, 1068 TARGET_IF_SPECTRAL_INFO_ENABLED, 1069 &enabled, sizeof(enabled)); 1070 1071 if (tempret) 1072 /* 1073 * Could not determine if Spectral is enabled. Assume scan is 1074 * not in progress 1075 */ 1076 enabled = 0; 1077 1078 /* if scan is not enabled, no need to send stop to FW */ 1079 if (!enabled) 1080 return -EPERM; 1081 1082 tempret = target_if_spectral_info_write( 1083 spectral, 1084 smode, 1085 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1086 &val, sizeof(val)); 1087 1088 if (tempret != 0) 1089 ret = tempret; 1090 1091 tempret = target_if_spectral_info_write( 1092 spectral, 1093 smode, 1094 TARGET_IF_SPECTRAL_INFO_ENABLED, 1095 &val, sizeof(val)); 1096 1097 if (tempret != 0) 1098 ret = tempret; 1099 1100 return ret; 1101 } 1102 1103 /** 1104 * target_if_spectral_get_extension_channel() - Get the Extension channel 1105 * @arg: Pointer to handle for Spectral target_if internal private data 1106 * 1107 * Function to get the current Extension channel (in MHz) 1108 * 1109 * Return: Current Extension channel (in MHz) on success, 0 on failure or if 1110 * extension channel is not present. 1111 */ 1112 uint32_t 1113 target_if_spectral_get_extension_channel(void *arg) 1114 { 1115 /* 1116 * XXX: Once we expand to use cases where Spectral could be activated 1117 * without a channel being set to VDEV, we need to consider returning a 1118 * negative value in case of failure and having all callers handle this. 1119 */ 1120 1121 struct target_if_spectral *spectral = NULL; 1122 struct wlan_objmgr_vdev *vdev = NULL; 1123 uint16_t sec20chan_freq = 0; 1124 1125 qdf_assert_always(arg); 1126 spectral = (struct target_if_spectral *)arg; 1127 1128 vdev = target_if_spectral_get_vdev(spectral); 1129 if (!vdev) 1130 return 0; 1131 1132 if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) { 1133 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1134 return 0; 1135 } 1136 1137 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1138 1139 return sec20chan_freq; 1140 } 1141 1142 /** 1143 * target_if_spectral_get_current_channel() - Get the current channel 1144 * @arg: Pointer to handle for Spectral target_if internal private data 1145 * 1146 * Function to get the current channel (in MHz) 1147 * 1148 * Return: Current channel (in MHz) on success, 0 on failure 1149 */ 1150 uint32_t 1151 target_if_spectral_get_current_channel(void *arg) 1152 { 1153 /* 1154 * XXX: Once we expand to use cases where Spectral could be activated 1155 * without a channel being set to VDEV, we need to consider returning a 1156 * negative value in case of failure and having all callers handle this. 1157 */ 1158 1159 struct target_if_spectral *spectral = NULL; 1160 int16_t chan_freq = 0; 1161 struct wlan_objmgr_vdev *vdev = NULL; 1162 1163 qdf_assert_always(arg); 1164 spectral = (struct target_if_spectral *)arg; 1165 1166 vdev = target_if_spectral_get_vdev(spectral); 1167 if (!vdev) 1168 return 0; 1169 1170 chan_freq = target_if_vdev_get_chan_freq(vdev); 1171 if (chan_freq < 0) { 1172 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1173 return 0; 1174 } 1175 1176 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1177 1178 return chan_freq; 1179 } 1180 1181 /** 1182 * target_if_spectral_reset_hw() - Reset the hardware 1183 * @arg: Pointer to handle for Spectral target_if internal private data 1184 * 1185 * This is only a placeholder since it is not currently required in the offload 1186 * case. 1187 * 1188 * Return: 0 1189 */ 1190 uint32_t 1191 target_if_spectral_reset_hw(void *arg) 1192 { 1193 not_yet_implemented(); 1194 return 0; 1195 } 1196 1197 /** 1198 * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from 1199 * Noisefloor history buffer 1200 * @arg: Pointer to handle for Spectral target_if internal private data 1201 * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied 1202 * 1203 * This is only a placeholder since it is not currently required in the offload 1204 * case. 1205 * 1206 * Return: 0 1207 */ 1208 uint32_t 1209 target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf) 1210 { 1211 not_yet_implemented(); 1212 return 0; 1213 } 1214 1215 /** 1216 * target_if_spectral_get_ext_noisefloor() - Get the extension channel 1217 * noisefloor 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 int8_t 1226 target_if_spectral_get_ext_noisefloor(void *arg) 1227 { 1228 not_yet_implemented(); 1229 return 0; 1230 } 1231 1232 /** 1233 * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor 1234 * @arg: Pointer to handle for Spectral target_if internal private data 1235 * 1236 * This is only a placeholder since it is not currently required in the offload 1237 * case. 1238 * 1239 * Return: 0 1240 */ 1241 int8_t 1242 target_if_spectral_get_ctl_noisefloor(void *arg) 1243 { 1244 not_yet_implemented(); 1245 return 0; 1246 } 1247 1248 /** 1249 * target_if_spectral_sops_configure_params() - Configure user supplied Spectral 1250 * parameters 1251 * @arg: Pointer to handle for Spectral target_if internal private data 1252 * @params: Spectral parameters 1253 * @smode: Spectral scan mode 1254 * 1255 * Function to configure spectral parameters 1256 * 1257 * Return: 0 on success else failure 1258 */ 1259 uint32_t 1260 target_if_spectral_sops_configure_params( 1261 void *arg, struct spectral_config *params, 1262 enum spectral_scan_mode smode) 1263 { 1264 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1265 1266 return target_if_spectral_info_write( 1267 spectral, 1268 smode, 1269 TARGET_IF_SPECTRAL_INFO_PARAMS, 1270 params, sizeof(*params)); 1271 } 1272 1273 /** 1274 * target_if_spectral_sops_get_params() - Get user configured Spectral 1275 * parameters 1276 * @arg: Pointer to handle for Spectral target_if internal private data 1277 * @params: Pointer to buffer into which Spectral parameters should be copied 1278 * @smode: Spectral scan mode 1279 * 1280 * Function to get the configured spectral parameters 1281 * 1282 * Return: 0 on success else failure 1283 */ 1284 uint32_t 1285 target_if_spectral_sops_get_params(void *arg, struct spectral_config *params, 1286 enum spectral_scan_mode smode) 1287 { 1288 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1289 1290 return target_if_spectral_info_read( 1291 spectral, 1292 smode, 1293 TARGET_IF_SPECTRAL_INFO_PARAMS, 1294 params, sizeof(*params)); 1295 } 1296 1297 /** 1298 * target_if_spectral_get_ent_mask() - Get enterprise mask 1299 * @arg: Pointer to handle for Spectral target_if internal private data 1300 * 1301 * This is only a placeholder since it is not currently required in the offload 1302 * case. 1303 * 1304 * Return: 0 1305 */ 1306 static uint32_t 1307 target_if_spectral_get_ent_mask(void *arg) 1308 { 1309 not_yet_implemented(); 1310 return 0; 1311 } 1312 1313 /** 1314 * target_if_spectral_get_macaddr() - Get radio MAC address 1315 * @arg: Pointer to handle for Spectral target_if internal private data 1316 * @addr: Pointer to buffer into which MAC address should be copied 1317 * 1318 * Function to get the MAC address of the pdev 1319 * 1320 * Return: 0 on success, -1 on failure 1321 */ 1322 static uint32_t 1323 target_if_spectral_get_macaddr(void *arg, char *addr) 1324 { 1325 uint8_t *myaddr = NULL; 1326 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1327 struct wlan_objmgr_pdev *pdev = NULL; 1328 1329 pdev = spectral->pdev_obj; 1330 1331 wlan_pdev_obj_lock(pdev); 1332 myaddr = wlan_pdev_get_hw_macaddr(pdev); 1333 wlan_pdev_obj_unlock(pdev); 1334 qdf_mem_copy(addr, myaddr, QDF_MAC_ADDR_SIZE); 1335 1336 return 0; 1337 } 1338 1339 /** 1340 * target_if_init_spectral_param_properties() - Initialize Spectral parameter 1341 * properties 1342 * @spectral: Pointer to Spectral target_if internal private data 1343 * 1344 * Initialize Spectral parameter properties 1345 * 1346 * Return: QDF_STATUS 1347 */ 1348 static QDF_STATUS 1349 target_if_init_spectral_param_properties(struct target_if_spectral *spectral) 1350 { 1351 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 1352 int param; 1353 1354 /* Initialize default values for properties. 1355 * Default values are supported for all the parameters for all modes 1356 * and allows different values for each mode for all the parameters . 1357 */ 1358 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 1359 for (param = 0; param < SPECTRAL_PARAM_MAX; param++) { 1360 spectral->properties[smode][param].supported = true; 1361 spectral->properties[smode][param].common_all_modes = 1362 false; 1363 } 1364 } 1365 1366 /* Once FW advertisement is in place remove this hard coding */ 1367 smode = SPECTRAL_SCAN_MODE_NORMAL; 1368 spectral->properties[SPECTRAL_SCAN_MODE_NORMAL] 1369 [SPECTRAL_PARAM_FREQUENCY].supported = false; 1370 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 1371 spectral->properties[smode] 1372 [SPECTRAL_PARAM_SPECT_PRI].common_all_modes = true; 1373 spectral->properties[smode] 1374 [SPECTRAL_PARAM_SCAN_PERIOD].common_all_modes = true; 1375 spectral->properties[smode] 1376 [SPECTRAL_PARAM_INIT_DELAY].common_all_modes = true; 1377 } 1378 1379 return QDF_STATUS_SUCCESS; 1380 } 1381 1382 /** 1383 * target_if_init_spectral_capability() - Initialize Spectral capability 1384 * @spectral: Pointer to Spectral target_if internal private data 1385 * 1386 * This is a workaround. 1387 * 1388 * Return: QDF_STATUS 1389 */ 1390 QDF_STATUS 1391 target_if_init_spectral_capability(struct target_if_spectral *spectral) 1392 { 1393 struct wlan_objmgr_psoc *psoc; 1394 struct wlan_objmgr_pdev *pdev; 1395 struct wlan_psoc_host_spectral_scaling_params *scaling_params; 1396 uint8_t num_bin_scaling_params, param_idx, pdev_id; 1397 struct target_psoc_info *tgt_psoc_info; 1398 struct wlan_psoc_host_service_ext_param *ext_svc_param; 1399 struct spectral_caps *pcap = &spectral->capability; 1400 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 1401 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 1402 struct wlan_psoc_host_chainmask_table *table; 1403 int j; 1404 uint32_t table_id; 1405 1406 pdev = spectral->pdev_obj; 1407 psoc = wlan_pdev_get_psoc(pdev); 1408 if (!psoc) { 1409 spectral_err("psoc is null"); 1410 return QDF_STATUS_E_FAILURE; 1411 } 1412 1413 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 1414 if (!tgt_psoc_info) { 1415 spectral_err("target_psoc_info is null"); 1416 return QDF_STATUS_E_FAILURE; 1417 } 1418 1419 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 1420 num_bin_scaling_params = ext_svc_param->num_bin_scaling_params; 1421 scaling_params = target_psoc_get_spectral_scaling_params(tgt_psoc_info); 1422 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1423 1424 /* XXX : Workaround: Set Spectral capability */ 1425 pcap = &spectral->capability; 1426 pcap->phydiag_cap = 1; 1427 pcap->radar_cap = 1; 1428 pcap->spectral_cap = 1; 1429 pcap->advncd_spectral_cap = 1; 1430 pcap->hw_gen = spectral->spectral_gen; 1431 if (spectral->spectral_gen >= SPECTRAL_GEN3) { 1432 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 1433 if (!mac_phy_cap_arr) { 1434 spectral_err("mac phy cap array is null"); 1435 return QDF_STATUS_E_FAILURE; 1436 } 1437 1438 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 1439 if (!mac_phy_cap) { 1440 spectral_err("mac phy cap is null"); 1441 return QDF_STATUS_E_FAILURE; 1442 } 1443 1444 table_id = mac_phy_cap->chainmask_table_id; 1445 table = &ext_svc_param->chainmask_table[table_id]; 1446 if (!table) { 1447 spectral_err("chainmask table not found"); 1448 return QDF_STATUS_E_FAILURE; 1449 } 1450 1451 for (j = 0; j < table->num_valid_chainmasks; j++) { 1452 pcap->agile_spectral_cap |= 1453 table->cap_list[j].supports_aSpectral; 1454 pcap->agile_spectral_cap_160 |= 1455 table->cap_list[j].supports_aSpectral_160; 1456 } 1457 pcap->agile_spectral_cap_80p80 = pcap->agile_spectral_cap_160; 1458 } else { 1459 pcap->agile_spectral_cap = false; 1460 pcap->agile_spectral_cap_160 = false; 1461 pcap->agile_spectral_cap_80p80 = false; 1462 } 1463 1464 for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) { 1465 if (scaling_params[param_idx].pdev_id == pdev_id) { 1466 pcap->is_scaling_params_populated = true; 1467 pcap->formula_id = scaling_params[param_idx].formula_id; 1468 pcap->low_level_offset = 1469 scaling_params[param_idx].low_level_offset; 1470 pcap->high_level_offset = 1471 scaling_params[param_idx].high_level_offset; 1472 pcap->rssi_thr = scaling_params[param_idx].rssi_thr; 1473 pcap->default_agc_max_gain = 1474 scaling_params[param_idx].default_agc_max_gain; 1475 break; 1476 } 1477 } 1478 1479 return QDF_STATUS_SUCCESS; 1480 } 1481 1482 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1483 /** 1484 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 1485 * internal operations with functions related to spectral simulation 1486 * @p_sops: spectral low level ops table 1487 * 1488 * Initialize spectral target_if internal operations with functions 1489 * related to spectral simulation 1490 * 1491 * Return: None 1492 */ 1493 static void 1494 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 1495 { 1496 /* 1497 * Spectral simulation is currently intended for platform transitions 1498 * where underlying HW support may not be available for some time. 1499 * Hence, we do not currently provide a runtime switch to turn the 1500 * simulation on or off. 1501 * In case of future requirements where runtime switches are required, 1502 * this can be added. But it is suggested to use application layer 1503 * simulation as far as possible in such cases, since the main 1504 * use of record and replay of samples would concern higher 1505 * level sample processing rather than lower level delivery. 1506 */ 1507 p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled; 1508 p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active; 1509 p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan; 1510 p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan; 1511 p_sops->configure_spectral = 1512 target_if_spectral_sops_sim_configure_params; 1513 p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params; 1514 } 1515 1516 #else 1517 /** 1518 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 1519 * internal operations 1520 * @p_sops: spectral low level ops table 1521 * 1522 * Return: None 1523 */ 1524 static void 1525 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 1526 { 1527 p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled; 1528 p_sops->is_spectral_active = target_if_sops_is_spectral_active; 1529 p_sops->start_spectral_scan = target_if_sops_start_spectral_scan; 1530 p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan; 1531 p_sops->configure_spectral = target_if_spectral_sops_configure_params; 1532 p_sops->get_spectral_config = target_if_spectral_sops_get_params; 1533 } 1534 #endif 1535 1536 /** 1537 * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal 1538 * operations common to all Spectral chipset generations 1539 * 1540 * Initializes target_if_spectral_ops common to all chipset generations 1541 * 1542 * Return: None 1543 */ 1544 static void 1545 target_if_init_spectral_ops_common(void) 1546 { 1547 struct target_if_spectral_ops *p_sops = &spectral_ops; 1548 1549 p_sops->get_tsf64 = target_if_spectral_get_tsf64; 1550 p_sops->get_capability = target_if_spectral_get_capability; 1551 p_sops->set_rxfilter = target_if_spectral_set_rxfilter; 1552 p_sops->get_rxfilter = target_if_spectral_get_rxfilter; 1553 1554 target_if_init_spectral_simulation_ops(p_sops); 1555 1556 p_sops->get_extension_channel = 1557 target_if_spectral_get_extension_channel; 1558 p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor; 1559 p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor; 1560 p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask; 1561 p_sops->get_mac_address = target_if_spectral_get_macaddr; 1562 p_sops->get_current_channel = target_if_spectral_get_current_channel; 1563 p_sops->reset_hw = target_if_spectral_reset_hw; 1564 p_sops->get_chain_noise_floor = 1565 target_if_spectral_get_chain_noise_floor; 1566 } 1567 1568 /** 1569 * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal 1570 * operations specific to Spectral chipset generation 2. 1571 * 1572 * Initializes target_if_spectral_ops specific to Spectral chipset generation 2. 1573 * 1574 * Return: None 1575 */ 1576 static void 1577 target_if_init_spectral_ops_gen2(void) 1578 { 1579 struct target_if_spectral_ops *p_sops = &spectral_ops; 1580 1581 p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2; 1582 } 1583 1584 /** 1585 * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal 1586 * operations specific to Spectral chipset generation 3. 1587 * 1588 * Initializes target_if_spectral_ops specific to Spectral chipset generation 3. 1589 * 1590 * Return: None 1591 */ 1592 static void 1593 target_if_init_spectral_ops_gen3(void) 1594 { 1595 struct target_if_spectral_ops *p_sops = &spectral_ops; 1596 1597 p_sops->process_spectral_report = 1598 target_if_spectral_process_report_gen3; 1599 return; 1600 } 1601 1602 /** 1603 * target_if_init_spectral_ops() - Initialize target_if internal Spectral 1604 * operations. 1605 * @spectral: Pointer to Spectral target_if internal private data 1606 * 1607 * Initializes all function pointers in target_if_spectral_ops for 1608 * all generations 1609 * 1610 * Return: None 1611 */ 1612 static void 1613 target_if_init_spectral_ops(struct target_if_spectral *spectral) 1614 { 1615 target_if_init_spectral_ops_common(); 1616 if (spectral->spectral_gen == SPECTRAL_GEN2) 1617 target_if_init_spectral_ops_gen2(); 1618 else if (spectral->spectral_gen == SPECTRAL_GEN3) 1619 target_if_init_spectral_ops_gen3(); 1620 else 1621 spectral_err("Invalid Spectral generation"); 1622 } 1623 1624 /* 1625 * Dummy Functions: 1626 * These functions are initially registered to avoid any crashes due to 1627 * invocation of spectral functions before they are registered. 1628 */ 1629 1630 static uint64_t 1631 null_get_tsf64(void *arg) 1632 { 1633 spectral_ops_not_registered("get_tsf64"); 1634 return 0; 1635 } 1636 1637 static uint32_t 1638 null_get_capability(void *arg, enum spectral_capability_type type) 1639 { 1640 /* 1641 * TODO : We should have conditional compilation to get the capability 1642 * : We have not yet attahced ATH layer here, so there is no 1643 * : way to check the HAL capbalities 1644 */ 1645 spectral_ops_not_registered("get_capability"); 1646 1647 /* TODO : For the time being, we are returning TRUE */ 1648 return true; 1649 } 1650 1651 static uint32_t 1652 null_set_rxfilter(void *arg, int rxfilter) 1653 { 1654 spectral_ops_not_registered("set_rxfilter"); 1655 return 1; 1656 } 1657 1658 static uint32_t 1659 null_get_rxfilter(void *arg) 1660 { 1661 spectral_ops_not_registered("get_rxfilter"); 1662 return 0; 1663 } 1664 1665 static uint32_t 1666 null_is_spectral_active(void *arg, enum spectral_scan_mode smode) 1667 { 1668 spectral_ops_not_registered("is_spectral_active"); 1669 return 1; 1670 } 1671 1672 static uint32_t 1673 null_is_spectral_enabled(void *arg, enum spectral_scan_mode smode) 1674 { 1675 spectral_ops_not_registered("is_spectral_enabled"); 1676 return 1; 1677 } 1678 1679 static uint32_t 1680 null_start_spectral_scan(void *arg, enum spectral_scan_mode smode, 1681 enum spectral_cp_error_code *err) 1682 { 1683 spectral_ops_not_registered("start_spectral_scan"); 1684 return 1; 1685 } 1686 1687 static uint32_t 1688 null_stop_spectral_scan(void *arg, enum spectral_scan_mode smode) 1689 { 1690 spectral_ops_not_registered("stop_spectral_scan"); 1691 return 1; 1692 } 1693 1694 static uint32_t 1695 null_get_extension_channel(void *arg) 1696 { 1697 spectral_ops_not_registered("get_extension_channel"); 1698 return 1; 1699 } 1700 1701 static int8_t 1702 null_get_ctl_noisefloor(void *arg) 1703 { 1704 spectral_ops_not_registered("get_ctl_noisefloor"); 1705 return 1; 1706 } 1707 1708 static int8_t 1709 null_get_ext_noisefloor(void *arg) 1710 { 1711 spectral_ops_not_registered("get_ext_noisefloor"); 1712 return 0; 1713 } 1714 1715 static uint32_t 1716 null_configure_spectral(void *arg, struct spectral_config *params, 1717 enum spectral_scan_mode smode) 1718 { 1719 spectral_ops_not_registered("configure_spectral"); 1720 return 0; 1721 } 1722 1723 static uint32_t 1724 null_get_spectral_config(void *arg, struct spectral_config *params, 1725 enum spectral_scan_mode smode) 1726 { 1727 spectral_ops_not_registered("get_spectral_config"); 1728 return 0; 1729 } 1730 1731 static uint32_t 1732 null_get_ent_spectral_mask(void *arg) 1733 { 1734 spectral_ops_not_registered("get_ent_spectral_mask"); 1735 return 0; 1736 } 1737 1738 static uint32_t 1739 null_get_mac_address(void *arg, char *addr) 1740 { 1741 spectral_ops_not_registered("get_mac_address"); 1742 return 0; 1743 } 1744 1745 static uint32_t 1746 null_get_current_channel(void *arg) 1747 { 1748 spectral_ops_not_registered("get_current_channel"); 1749 return 0; 1750 } 1751 1752 static uint32_t 1753 null_reset_hw(void *arg) 1754 { 1755 spectral_ops_not_registered("get_current_channel"); 1756 return 0; 1757 } 1758 1759 static uint32_t 1760 null_get_chain_noise_floor(void *arg, int16_t *nf_buf) 1761 { 1762 spectral_ops_not_registered("get_chain_noise_floor"); 1763 return 0; 1764 } 1765 1766 static int 1767 null_spectral_process_phyerr(struct target_if_spectral *spectral, 1768 uint8_t *data, 1769 uint32_t datalen, 1770 struct target_if_spectral_rfqual_info *p_rfqual, 1771 struct target_if_spectral_chan_info *p_chaninfo, 1772 uint64_t tsf64, 1773 struct target_if_spectral_acs_stats *acs_stats) 1774 { 1775 spectral_ops_not_registered("spectral_process_phyerr"); 1776 return 0; 1777 } 1778 1779 static int 1780 null_process_spectral_report(struct wlan_objmgr_pdev *pdev, 1781 void *payload) 1782 { 1783 spectral_ops_not_registered("process_spectral_report"); 1784 return 0; 1785 } 1786 /** 1787 * target_if_spectral_init_dummy_function_table() - 1788 * Initialize target_if internal 1789 * Spectral operations to dummy functions 1790 * @ps: Pointer to Spectral target_if internal private data 1791 * 1792 * Initialize all the function pointers in target_if_spectral_ops with 1793 * dummy functions. 1794 * 1795 * Return: None 1796 */ 1797 static void 1798 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps) 1799 { 1800 struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps); 1801 1802 p_sops->get_tsf64 = null_get_tsf64; 1803 p_sops->get_capability = null_get_capability; 1804 p_sops->set_rxfilter = null_set_rxfilter; 1805 p_sops->get_rxfilter = null_get_rxfilter; 1806 p_sops->is_spectral_enabled = null_is_spectral_enabled; 1807 p_sops->is_spectral_active = null_is_spectral_active; 1808 p_sops->start_spectral_scan = null_start_spectral_scan; 1809 p_sops->stop_spectral_scan = null_stop_spectral_scan; 1810 p_sops->get_extension_channel = null_get_extension_channel; 1811 p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor; 1812 p_sops->get_ext_noisefloor = null_get_ext_noisefloor; 1813 p_sops->configure_spectral = null_configure_spectral; 1814 p_sops->get_spectral_config = null_get_spectral_config; 1815 p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask; 1816 p_sops->get_mac_address = null_get_mac_address; 1817 p_sops->get_current_channel = null_get_current_channel; 1818 p_sops->reset_hw = null_reset_hw; 1819 p_sops->get_chain_noise_floor = null_get_chain_noise_floor; 1820 p_sops->spectral_process_phyerr = null_spectral_process_phyerr; 1821 p_sops->process_spectral_report = null_process_spectral_report; 1822 } 1823 1824 /** 1825 * target_if_spectral_register_funcs() - Initialize target_if internal Spectral 1826 * operations 1827 * @spectral: Pointer to Spectral target_if internal private data 1828 * @p: Pointer to Spectral function table 1829 * 1830 * Return: None 1831 */ 1832 static void 1833 target_if_spectral_register_funcs(struct target_if_spectral *spectral, 1834 struct target_if_spectral_ops *p) 1835 { 1836 struct target_if_spectral_ops *p_sops = 1837 GET_TARGET_IF_SPECTRAL_OPS(spectral); 1838 1839 p_sops->get_tsf64 = p->get_tsf64; 1840 p_sops->get_capability = p->get_capability; 1841 p_sops->set_rxfilter = p->set_rxfilter; 1842 p_sops->get_rxfilter = p->get_rxfilter; 1843 p_sops->is_spectral_enabled = p->is_spectral_enabled; 1844 p_sops->is_spectral_active = p->is_spectral_active; 1845 p_sops->start_spectral_scan = p->start_spectral_scan; 1846 p_sops->stop_spectral_scan = p->stop_spectral_scan; 1847 p_sops->get_extension_channel = p->get_extension_channel; 1848 p_sops->get_ctl_noisefloor = p->get_ctl_noisefloor; 1849 p_sops->get_ext_noisefloor = p->get_ext_noisefloor; 1850 p_sops->configure_spectral = p->configure_spectral; 1851 p_sops->get_spectral_config = p->get_spectral_config; 1852 p_sops->get_ent_spectral_mask = p->get_ent_spectral_mask; 1853 p_sops->get_mac_address = p->get_mac_address; 1854 p_sops->get_current_channel = p->get_current_channel; 1855 p_sops->reset_hw = p->reset_hw; 1856 p_sops->get_chain_noise_floor = p->get_chain_noise_floor; 1857 p_sops->spectral_process_phyerr = p->spectral_process_phyerr; 1858 p_sops->process_spectral_report = p->process_spectral_report; 1859 } 1860 1861 /** 1862 * target_if_spectral_clear_stats() - Clear Spectral stats 1863 * @spectral: Pointer to Spectral target_if internal private data 1864 * 1865 * Function to clear spectral stats 1866 * 1867 * Return: None 1868 */ 1869 static void 1870 target_if_spectral_clear_stats(struct target_if_spectral *spectral) 1871 { 1872 struct target_if_spectral_ops *p_sops = 1873 GET_TARGET_IF_SPECTRAL_OPS(spectral); 1874 1875 qdf_mem_zero(&spectral->spectral_stats, 1876 sizeof(struct target_if_spectral_stats)); 1877 spectral->spectral_stats.last_reset_tstamp = 1878 p_sops->get_tsf64(spectral); 1879 } 1880 1881 /** 1882 * target_if_spectral_check_hw_capability() - Check whether HW supports spectral 1883 * @spectral: Pointer to Spectral target_if internal private data 1884 * 1885 * Function to check whether hardware supports spectral 1886 * 1887 * Return: True if HW supports Spectral, false if HW does not support Spectral 1888 */ 1889 static int 1890 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral) 1891 { 1892 struct target_if_spectral_ops *p_sops = NULL; 1893 struct spectral_caps *pcap = NULL; 1894 int is_spectral_supported = true; 1895 1896 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 1897 pcap = &spectral->capability; 1898 1899 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) { 1900 is_spectral_supported = false; 1901 spectral_info("SPECTRAL : No PHYDIAG support"); 1902 return is_spectral_supported; 1903 } 1904 pcap->phydiag_cap = 1; 1905 1906 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) { 1907 is_spectral_supported = false; 1908 spectral_info("SPECTRAL : No RADAR support"); 1909 return is_spectral_supported; 1910 } 1911 pcap->radar_cap = 1; 1912 1913 if (p_sops->get_capability(spectral, 1914 SPECTRAL_CAP_SPECTRAL_SCAN) == false) { 1915 is_spectral_supported = false; 1916 spectral_info("SPECTRAL : No SPECTRAL SUPPORT"); 1917 return is_spectral_supported; 1918 } 1919 pcap->spectral_cap = 1; 1920 1921 if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN) 1922 == false) { 1923 spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT"); 1924 } else { 1925 pcap->advncd_spectral_cap = 1; 1926 } 1927 1928 return is_spectral_supported; 1929 } 1930 1931 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1932 /** 1933 * target_if_spectral_detach_simulation() - De-initialize Spectral 1934 * Simulation functionality 1935 * @spectral: Pointer to Spectral target_if internal private data 1936 * 1937 * Function to de-initialize Spectral Simulation functionality 1938 * 1939 * Return: None 1940 */ 1941 static void 1942 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 1943 { 1944 target_if_spectral_sim_detach(spectral); 1945 } 1946 1947 #else 1948 static void 1949 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 1950 { 1951 } 1952 #endif 1953 1954 /** 1955 * target_if_spectral_detach() - De-initialize target_if Spectral 1956 * @pdev: Pointer to pdev object 1957 * 1958 * Function to detach target_if spectral 1959 * 1960 * Return: None 1961 */ 1962 static void 1963 target_if_spectral_detach(struct target_if_spectral *spectral) 1964 { 1965 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 1966 spectral_info("spectral detach"); 1967 1968 if (spectral) { 1969 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) 1970 qdf_spinlock_destroy 1971 (&spectral->param_info[smode].osps_lock); 1972 1973 target_if_spectral_detach_simulation(spectral); 1974 1975 qdf_spinlock_destroy(&spectral->spectral_lock); 1976 qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock); 1977 1978 qdf_mem_free(spectral); 1979 spectral = NULL; 1980 } 1981 } 1982 1983 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1984 /** 1985 * target_if_spectral_attach_simulation() - Initialize Spectral Simulation 1986 * functionality 1987 * @spectral: Pointer to Spectral target_if internal private data 1988 * 1989 * Function to initialize spectral simulation functionality 1990 * 1991 * Return: 0 on success, negative error code on failure 1992 */ 1993 static int 1994 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 1995 { 1996 if (target_if_spectral_sim_attach(spectral)) { 1997 qdf_mem_free(spectral); 1998 return -EPERM; 1999 } 2000 return 0; 2001 } 2002 2003 #else 2004 static int 2005 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 2006 { 2007 return 0; 2008 } 2009 #endif 2010 2011 /** 2012 * target_if_spectral_len_adj_swar_init() - Initialize FFT bin length adjustment 2013 * related info 2014 * @swar: Pointer to Spectral FFT bin length adjustment SWAR params 2015 * @target_type: Target type 2016 * 2017 * Function to Initialize parameters related to Spectral FFT bin 2018 * length adjustment SWARs. 2019 * 2020 * Return: void 2021 */ 2022 static void 2023 target_if_spectral_len_adj_swar_init(struct spectral_fft_bin_len_adj_swar *swar, 2024 uint32_t target_type) 2025 { 2026 if (target_type == TARGET_TYPE_QCA8074V2 || 2027 target_type == TARGET_TYPE_QCN9000) 2028 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; 2029 else if (target_type == TARGET_TYPE_QCA8074 || 2030 target_type == TARGET_TYPE_QCA6018 || 2031 target_type == TARGET_TYPE_QCA6390) 2032 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; 2033 else 2034 swar->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; 2035 2036 if (target_type == TARGET_TYPE_QCA8074 || 2037 target_type == TARGET_TYPE_QCA8074V2 || 2038 target_type == TARGET_TYPE_QCA6018 || 2039 target_type == TARGET_TYPE_QCN9000) { 2040 swar->inband_fftbin_size_adj = 1; 2041 swar->null_fftbin_adj = 1; 2042 } else { 2043 swar->inband_fftbin_size_adj = 0; 2044 swar->null_fftbin_adj = 0; 2045 } 2046 2047 if (target_type == TARGET_TYPE_QCA8074V2) 2048 swar->packmode_fftbin_size_adj = 1; 2049 else 2050 swar->packmode_fftbin_size_adj = 0; 2051 } 2052 2053 /** 2054 * target_if_spectral_report_params_init() - Initialize parameters which 2055 * describes the structure of Spectral reports 2056 * 2057 * @rparams: Pointer to Spectral report parameter object 2058 * @target_type: target type 2059 * 2060 * Function to Initialize parameters related to the structure of Spectral 2061 * reports. 2062 * 2063 * Return: void 2064 */ 2065 static void 2066 target_if_spectral_report_params_init( 2067 struct spectral_report_params *rparams, 2068 uint32_t target_type) 2069 { 2070 /* This entries are currently used by gen3 chipsets only. Hence 2071 * initialization is done for gen3 alone. In future if other generations 2072 * needs to use them they have to add proper initial values. 2073 */ 2074 if (target_type == TARGET_TYPE_QCN9000) 2075 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_2; 2076 else 2077 rparams->version = SPECTRAL_REPORT_FORMAT_VERSION_1; 2078 2079 switch (rparams->version) { 2080 case SPECTRAL_REPORT_FORMAT_VERSION_1: 2081 rparams->ssumaary_padding_bytes = 2082 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V1; 2083 rparams->fft_report_hdr_len = 2084 FFT_REPORT_HEADER_LENGTH_GEN3_V1; 2085 break; 2086 case SPECTRAL_REPORT_FORMAT_VERSION_2: 2087 rparams->ssumaary_padding_bytes = 2088 NUM_PADDING_BYTES_SSCAN_SUMARY_REPORT_GEN3_V2; 2089 rparams->fft_report_hdr_len = 2090 FFT_REPORT_HEADER_LENGTH_GEN3_V2; 2091 break; 2092 default: 2093 qdf_assert_always(0); 2094 } 2095 } 2096 2097 /** 2098 * target_if_spectral_timestamp_war_init() - Initialize Spectral timestamp WAR 2099 * related info 2100 * @twar: Pointer to Spectral timstamp WAR related info 2101 * 2102 * Function to Initialize parameters related to Spectral timestamp WAR 2103 * 2104 * Return: void 2105 */ 2106 static void 2107 target_if_spectral_timestamp_war_init(struct spectral_timestamp_war *twar) 2108 { 2109 enum spectral_scan_mode smode; 2110 2111 smode = SPECTRAL_SCAN_MODE_NORMAL; 2112 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2113 twar->last_fft_timestamp[smode] = 0; 2114 twar->timestamp_war_offset[smode] = 0; 2115 } 2116 twar->target_reset_count = 0; 2117 } 2118 2119 /** 2120 * target_if_pdev_spectral_init() - Initialize target_if Spectral 2121 * functionality for the given pdev 2122 * @pdev: Pointer to pdev object 2123 * 2124 * Function to initialize pointer to spectral target_if internal private data 2125 * 2126 * Return: On success, pointer to Spectral target_if internal private data, on 2127 * failure, NULL 2128 */ 2129 void * 2130 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 2131 { 2132 struct target_if_spectral_ops *p_sops = NULL; 2133 struct target_if_spectral *spectral = NULL; 2134 uint32_t target_type; 2135 uint32_t target_revision; 2136 struct wlan_objmgr_psoc *psoc; 2137 struct wlan_lmac_if_target_tx_ops *tx_ops; 2138 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2139 2140 if (!pdev) { 2141 spectral_err("SPECTRAL: pdev is NULL!"); 2142 return NULL; 2143 } 2144 spectral = (struct target_if_spectral *)qdf_mem_malloc( 2145 sizeof(struct target_if_spectral)); 2146 if (!spectral) 2147 return spectral; 2148 2149 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 2150 /* Store pdev in Spectral */ 2151 spectral->pdev_obj = pdev; 2152 2153 psoc = wlan_pdev_get_psoc(pdev); 2154 2155 tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; 2156 2157 if (tx_ops->tgt_get_tgt_type) { 2158 target_type = tx_ops->tgt_get_tgt_type(psoc); 2159 } else { 2160 qdf_mem_free(spectral); 2161 return NULL; 2162 } 2163 2164 if (tx_ops->tgt_get_tgt_revision) { 2165 target_revision = tx_ops->tgt_get_tgt_revision(psoc); 2166 } else { 2167 qdf_mem_free(spectral); 2168 return NULL; 2169 } 2170 2171 /* init the function ptr table */ 2172 target_if_spectral_init_dummy_function_table(spectral); 2173 2174 /* get spectral function table */ 2175 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2176 /* TODO : Should this be called here of after ath_attach ? */ 2177 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 2178 spectral_info("HAL_CAP_PHYDIAG : Capable"); 2179 2180 /* TODO: Need to fix the capablity check for RADAR */ 2181 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 2182 spectral_info("HAL_CAP_RADAR : Capable"); 2183 2184 /* TODO : Need to fix the capablity check for SPECTRAL */ 2185 /* TODO : Should this be called here of after ath_attach ? */ 2186 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 2187 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 2188 2189 qdf_spinlock_create(&spectral->spectral_lock); 2190 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 2191 target_if_spectral_clear_stats(spectral); 2192 2193 if (target_type == TARGET_TYPE_QCA8074 || 2194 target_type == TARGET_TYPE_QCA8074V2 || 2195 target_type == TARGET_TYPE_QCA6018 || 2196 target_type == TARGET_TYPE_QCA6390 || 2197 target_type == TARGET_TYPE_QCN9000) 2198 spectral->direct_dma_support = true; 2199 2200 target_if_spectral_len_adj_swar_init(&spectral->len_adj_swar, 2201 target_type); 2202 target_if_spectral_report_params_init(&spectral->rparams, target_type); 2203 2204 if ((target_type == TARGET_TYPE_QCA8074) || 2205 (target_type == TARGET_TYPE_QCA8074V2) || 2206 (target_type == TARGET_TYPE_QCA6018) || 2207 (target_type == TARGET_TYPE_QCN9000) || 2208 (target_type == TARGET_TYPE_QCA6290) || 2209 (target_type == TARGET_TYPE_QCA6390)) { 2210 spectral->spectral_gen = SPECTRAL_GEN3; 2211 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 2212 spectral->tag_sscan_summary_exp = 2213 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 2214 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 2215 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 2216 spectral->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3; 2217 spectral->fft_size_max = 2218 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_DEFAULT; 2219 if (target_type == TARGET_TYPE_QCN9000) 2220 spectral->fft_size_max = 2221 SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3_QCN9000; 2222 } else { 2223 spectral->spectral_gen = SPECTRAL_GEN2; 2224 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 2225 spectral->tag_sscan_summary_exp = 2226 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 2227 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 2228 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 2229 spectral->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; 2230 spectral->fft_size_max = SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2231 } 2232 2233 target_if_init_spectral_param_properties(spectral); 2234 /* Init spectral capability */ 2235 if (target_if_init_spectral_capability(spectral) != 2236 QDF_STATUS_SUCCESS) { 2237 qdf_mem_free(spectral); 2238 return NULL; 2239 } 2240 if (target_if_spectral_attach_simulation(spectral) < 0) 2241 return NULL; 2242 2243 target_if_init_spectral_ops(spectral); 2244 target_if_spectral_timestamp_war_init(&spectral->timestamp_war); 2245 2246 /* Spectral mode specific init */ 2247 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2248 spectral->params_valid[smode] = false; 2249 qdf_spinlock_create(&spectral->param_info[smode].osps_lock); 2250 spectral->param_info[smode].osps_cache.osc_is_valid = 0; 2251 } 2252 2253 target_if_spectral_register_funcs(spectral, &spectral_ops); 2254 2255 if (target_if_spectral_check_hw_capability(spectral) == false) { 2256 target_if_spectral_detach(spectral); 2257 spectral = NULL; 2258 } else { 2259 /* 2260 * TODO: Once the driver architecture transitions to chipset 2261 * versioning based checks, reflect this here. 2262 */ 2263 spectral->is_160_format = false; 2264 spectral->is_lb_edge_extrabins_format = false; 2265 spectral->is_rb_edge_extrabins_format = false; 2266 2267 if (target_type == TARGET_TYPE_QCA9984 || 2268 target_type == TARGET_TYPE_QCA9888) { 2269 spectral->is_160_format = true; 2270 spectral->is_lb_edge_extrabins_format = true; 2271 spectral->is_rb_edge_extrabins_format = true; 2272 } else if ((target_type == TARGET_TYPE_AR900B) && 2273 (target_revision == AR900B_REV_2)) { 2274 spectral->is_rb_edge_extrabins_format = true; 2275 } 2276 2277 if (target_type == TARGET_TYPE_QCA9984 || 2278 target_type == TARGET_TYPE_QCA9888) 2279 spectral->is_sec80_rssi_war_required = true; 2280 2281 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST; 2282 2283 if (spectral->spectral_gen == SPECTRAL_GEN3) 2284 init_160mhz_delivery_state_machine(spectral); 2285 } 2286 2287 return spectral; 2288 } 2289 2290 /** 2291 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 2292 * functionality for the given pdev 2293 * @pdev: Pointer to pdev object 2294 * 2295 * Function to de-initialize pointer to spectral target_if internal private data 2296 * 2297 * Return: None 2298 */ 2299 void 2300 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 2301 { 2302 struct target_if_spectral *spectral = NULL; 2303 2304 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2305 if (!spectral) { 2306 spectral_err("SPECTRAL : Module doesn't exist"); 2307 return; 2308 } 2309 target_if_spectral_detach(spectral); 2310 2311 return; 2312 } 2313 2314 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the 2315 * corresponding translation for Agile channel width. 2316 * Translation schema of different operating modes: 2317 * 20 -> 20, 40 -> 40, (80 & 160 & 80_80) -> 80. 2318 * @chwidth: Channel width enum. 2319 * 2320 * Return: The translated channel width enum. 2321 */ 2322 static enum phy_ch_width 2323 target_if_spectral_find_agile_width(enum phy_ch_width chwidth) 2324 { 2325 switch (chwidth) { 2326 case CH_WIDTH_20MHZ: 2327 return CH_WIDTH_20MHZ; 2328 case CH_WIDTH_40MHZ: 2329 return CH_WIDTH_40MHZ; 2330 case CH_WIDTH_80MHZ: 2331 case CH_WIDTH_80P80MHZ: 2332 case CH_WIDTH_160MHZ: 2333 return CH_WIDTH_80MHZ; 2334 default: 2335 spectral_err("Invalid chwidth enum %d", chwidth); 2336 return CH_WIDTH_INVALID; 2337 } 2338 } 2339 2340 /** 2341 * target_if_calculate_center_freq() - Helper routine to 2342 * check whether given frequency is center frequency of a 2343 * WLAN channel 2344 * 2345 * @spectral: Pointer to Spectral object 2346 * @chan_freq: Center frequency of a WLAN channel 2347 * @is_valid: Indicates whether given frequency is valid 2348 * 2349 * Return: QDF_STATUS 2350 */ 2351 static QDF_STATUS 2352 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, 2353 uint32_t chan_freq, 2354 bool *is_valid) 2355 { 2356 struct regulatory_channel *cur_chan_list; 2357 int i; 2358 2359 if (!pdev) { 2360 spectral_err("pdev object is null"); 2361 return QDF_STATUS_E_FAILURE; 2362 } 2363 2364 if (!is_valid) { 2365 spectral_err("is valid argument is null"); 2366 return QDF_STATUS_E_FAILURE; 2367 } 2368 2369 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); 2370 if (!cur_chan_list) 2371 return QDF_STATUS_E_FAILURE; 2372 2373 if (wlan_reg_get_current_chan_list( 2374 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 2375 spectral_err("Failed to get cur_chan list"); 2376 qdf_mem_free(cur_chan_list); 2377 return QDF_STATUS_E_FAILURE; 2378 } 2379 2380 *is_valid = false; 2381 for (i = 0; i < NUM_CHANNELS; i++) { 2382 uint32_t flags; 2383 uint32_t center_freq; 2384 2385 flags = cur_chan_list[i].chan_flags; 2386 center_freq = cur_chan_list[i].center_freq; 2387 2388 if (!(flags & REGULATORY_CHAN_DISABLED) && 2389 (center_freq == chan_freq)) { 2390 *is_valid = true; 2391 break; 2392 } 2393 } 2394 2395 qdf_mem_free(cur_chan_list); 2396 2397 return QDF_STATUS_SUCCESS; 2398 } 2399 2400 /** 2401 * target_if_calculate_center_freq() - Helper routine to 2402 * find the center frequency of the agile span from a 2403 * WLAN channel center frequency 2404 * 2405 * @spectral: Pointer to Spectral object 2406 * @chan_freq: Center frequency of a WLAN channel 2407 * @center_freq: Pointer to center frequency 2408 * 2409 * Return: QDF_STATUS 2410 */ 2411 static QDF_STATUS 2412 target_if_calculate_center_freq(struct target_if_spectral *spectral, 2413 uint16_t chan_freq, 2414 uint16_t *center_freq) 2415 { 2416 struct wlan_objmgr_vdev *vdev; 2417 enum phy_ch_width ch_width; 2418 enum phy_ch_width agile_ch_width; 2419 2420 if (!spectral) { 2421 spectral_err("spectral target if object is null"); 2422 return QDF_STATUS_E_FAILURE; 2423 } 2424 2425 if (!center_freq) { 2426 spectral_err("center_freq argument is null"); 2427 return QDF_STATUS_E_FAILURE; 2428 } 2429 2430 vdev = target_if_spectral_get_vdev(spectral); 2431 if (!vdev) { 2432 spectral_err("vdev is NULL"); 2433 return QDF_STATUS_E_FAILURE; 2434 } 2435 ch_width = target_if_vdev_get_ch_width(vdev); 2436 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2437 agile_ch_width = target_if_spectral_find_agile_width(ch_width); 2438 2439 if (agile_ch_width == CH_WIDTH_20MHZ) { 2440 *center_freq = chan_freq; 2441 } else { 2442 uint16_t start_freq; 2443 uint16_t end_freq; 2444 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2445 2446 wlan_reg_get_5g_bonded_channel_and_state_for_freq 2447 (spectral->pdev_obj, chan_freq, agile_ch_width, 2448 &bonded_chan_ptr); 2449 if (!bonded_chan_ptr) { 2450 spectral_err("Bonded channel is not found"); 2451 return QDF_STATUS_E_FAILURE; 2452 } 2453 start_freq = bonded_chan_ptr->start_freq; 2454 end_freq = bonded_chan_ptr->end_freq; 2455 *center_freq = (start_freq + end_freq) >> 1; 2456 } 2457 2458 return QDF_STATUS_SUCCESS; 2459 } 2460 2461 /** 2462 * target_if_validate_center_freq() - Helper routine to 2463 * validate user provided agile center frequency 2464 * 2465 * @spectral: Pointer to Spectral object 2466 * @center_freq: User provided agile span center frequency 2467 * @is_valid: Indicates whether agile span center frequency is valid 2468 * 2469 * Return: QDF_STATUS 2470 */ 2471 static QDF_STATUS 2472 target_if_validate_center_freq(struct target_if_spectral *spectral, 2473 uint16_t center_freq, 2474 bool *is_valid) 2475 { 2476 struct wlan_objmgr_vdev *vdev; 2477 enum phy_ch_width ch_width; 2478 enum phy_ch_width agile_ch_width; 2479 struct wlan_objmgr_pdev *pdev; 2480 QDF_STATUS status; 2481 2482 if (!spectral) { 2483 spectral_err("spectral target if object is null"); 2484 return QDF_STATUS_E_FAILURE; 2485 } 2486 2487 if (!is_valid) { 2488 spectral_err("is_valid argument is null"); 2489 return QDF_STATUS_E_FAILURE; 2490 } 2491 2492 pdev = spectral->pdev_obj; 2493 vdev = target_if_spectral_get_vdev(spectral); 2494 if (!vdev) { 2495 spectral_err("vdev is NULL"); 2496 return QDF_STATUS_E_FAILURE; 2497 } 2498 ch_width = target_if_vdev_get_ch_width(vdev); 2499 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2500 agile_ch_width = target_if_spectral_find_agile_width(ch_width); 2501 2502 if (agile_ch_width == CH_WIDTH_20MHZ) { 2503 status = target_if_is_center_freq_of_any_chan 2504 (pdev, center_freq, is_valid); 2505 if (QDF_IS_STATUS_ERROR(status)) 2506 return QDF_STATUS_E_FAILURE; 2507 } else { 2508 uint16_t start_freq; 2509 uint16_t end_freq; 2510 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2511 bool is_chan; 2512 2513 status = target_if_is_center_freq_of_any_chan 2514 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2515 &is_chan); 2516 if (QDF_IS_STATUS_ERROR(status)) 2517 return QDF_STATUS_E_FAILURE; 2518 2519 if (is_chan) { 2520 uint32_t calulated_center_freq; 2521 2522 wlan_reg_get_5g_bonded_channel_and_state_for_freq 2523 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2524 agile_ch_width, 2525 &bonded_chan_ptr); 2526 if (!bonded_chan_ptr) { 2527 spectral_err("Bonded channel is not found"); 2528 return QDF_STATUS_E_FAILURE; 2529 } 2530 start_freq = bonded_chan_ptr->start_freq; 2531 end_freq = bonded_chan_ptr->end_freq; 2532 calulated_center_freq = (start_freq + end_freq) >> 1; 2533 *is_valid = (center_freq == calulated_center_freq); 2534 } else { 2535 *is_valid = false; 2536 } 2537 } 2538 2539 return QDF_STATUS_SUCCESS; 2540 } 2541 2542 /** 2543 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to 2544 * check whether agile span overlaps with current operating band. 2545 * 2546 * @spectral: Pointer to Spectral object 2547 * @ss_frequency: Agile span center frequency 2548 * @is_overlapping: Indicates whether Agile span overlaps with operating span 2549 * 2550 * Helper routine to check whether agile span overlaps with current 2551 * operating band. 2552 * 2553 * Return: QDF_STATUS 2554 */ 2555 static QDF_STATUS 2556 target_if_is_agile_span_overlap_with_operating_span 2557 (struct target_if_spectral *spectral, 2558 uint32_t ss_frequency, 2559 bool *is_overlapping) 2560 { 2561 enum phy_ch_width ch_width; 2562 enum phy_ch_width agile_ch_width; 2563 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2564 struct wlan_objmgr_vdev *vdev; 2565 struct wlan_objmgr_pdev *pdev; 2566 int16_t chan_freq; 2567 uint32_t op_start_freq; 2568 uint32_t op_end_freq; 2569 uint32_t agile_start_freq; 2570 uint32_t agile_end_freq; 2571 uint32_t cfreq2; 2572 2573 if (!spectral) { 2574 spectral_err("Spectral object is NULL"); 2575 return QDF_STATUS_E_FAILURE; 2576 } 2577 2578 pdev = spectral->pdev_obj; 2579 if (!pdev) { 2580 spectral_err("pdev object is NULL"); 2581 return QDF_STATUS_E_FAILURE; 2582 } 2583 2584 if (!is_overlapping) { 2585 spectral_err("Argument(is_overlapping) is NULL"); 2586 return QDF_STATUS_E_FAILURE; 2587 } 2588 2589 vdev = target_if_spectral_get_vdev(spectral); 2590 if (!vdev) { 2591 spectral_err("vdev is NULL"); 2592 return QDF_STATUS_E_FAILURE; 2593 } 2594 ch_width = target_if_vdev_get_ch_width(vdev); 2595 chan_freq = target_if_vdev_get_chan_freq(vdev); 2596 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); 2597 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2598 if (cfreq2 < 0) 2599 return QDF_STATUS_E_FAILURE; 2600 2601 if (ch_width == CH_WIDTH_20MHZ) { 2602 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; 2603 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; 2604 } else { 2605 wlan_reg_get_5g_bonded_channel_and_state_for_freq 2606 (pdev, chan_freq, ch_width, &bonded_chan_ptr); 2607 if (!bonded_chan_ptr) { 2608 spectral_err("Bonded channel is not found"); 2609 return QDF_STATUS_E_FAILURE; 2610 } 2611 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; 2612 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; 2613 } 2614 2615 agile_ch_width = target_if_spectral_find_agile_width(ch_width); 2616 if (agile_ch_width == CH_WIDTH_INVALID) 2617 return QDF_STATUS_E_FAILURE; 2618 agile_start_freq = ss_frequency - 2619 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2620 agile_end_freq = ss_frequency + 2621 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2622 if (agile_end_freq <= op_start_freq || op_end_freq <= agile_start_freq) 2623 *is_overlapping = false; 2624 else 2625 *is_overlapping = true; 2626 2627 /* Use non zero cfreq2 to identify 80p80 */ 2628 if (cfreq2) { 2629 uint32_t sec80_start_feq; 2630 uint32_t sec80_end_freq; 2631 2632 sec80_start_feq = cfreq2 - 40; 2633 sec80_end_freq = cfreq2 + 40; 2634 2635 if ((agile_end_freq > sec80_start_feq) && 2636 (sec80_end_freq > agile_start_freq)) 2637 *is_overlapping = true; 2638 } 2639 2640 return QDF_STATUS_SUCCESS; 2641 } 2642 2643 /** 2644 * _target_if_set_spectral_config() - Set spectral config 2645 * @spectral: Pointer to spectral object 2646 * @threshtype: config type 2647 * @value: config value 2648 * @smode: Spectral scan mode 2649 * @err: Spectral error code 2650 * 2651 * API to set spectral configurations 2652 * 2653 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 2654 */ 2655 static QDF_STATUS 2656 _target_if_set_spectral_config(struct target_if_spectral *spectral, 2657 const uint32_t threshtype, const uint32_t value, 2658 const enum spectral_scan_mode smode, 2659 enum spectral_cp_error_code *err) 2660 { 2661 struct spectral_config params; 2662 struct target_if_spectral_ops *p_sops; 2663 struct spectral_config *sparams; 2664 QDF_STATUS status; 2665 bool is_overlapping; 2666 uint16_t agile_cfreq; 2667 bool is_valid_chan; 2668 2669 if (!err) { 2670 spectral_err("Error code argument is null"); 2671 QDF_ASSERT(0); 2672 } 2673 *err = SPECTRAL_SCAN_ERR_INVALID; 2674 2675 if (!spectral) { 2676 spectral_err("spectral object is NULL"); 2677 return QDF_STATUS_E_FAILURE; 2678 } 2679 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2680 2681 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2682 spectral_err("Invalid Spectral mode %u", smode); 2683 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 2684 return QDF_STATUS_E_FAILURE; 2685 } 2686 2687 sparams = &spectral->params[smode]; 2688 2689 if (!spectral->params_valid[smode]) { 2690 target_if_spectral_info_read(spectral, 2691 smode, 2692 TARGET_IF_SPECTRAL_INFO_PARAMS, 2693 &spectral->params[smode], 2694 sizeof(spectral->params[smode])); 2695 spectral->params_valid[smode] = true; 2696 } 2697 2698 switch (threshtype) { 2699 case SPECTRAL_PARAM_FFT_PERIOD: 2700 sparams->ss_fft_period = value; 2701 break; 2702 case SPECTRAL_PARAM_SCAN_PERIOD: 2703 sparams->ss_period = value; 2704 break; 2705 case SPECTRAL_PARAM_SCAN_COUNT: 2706 sparams->ss_count = value; 2707 break; 2708 case SPECTRAL_PARAM_SHORT_REPORT: 2709 sparams->ss_short_report = (!!value) ? true : false; 2710 break; 2711 case SPECTRAL_PARAM_SPECT_PRI: 2712 sparams->ss_spectral_pri = (!!value) ? true : false; 2713 break; 2714 case SPECTRAL_PARAM_FFT_SIZE: 2715 if ((value < spectral->fft_size_min) || 2716 (value > spectral->fft_size_max)) { 2717 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2718 return QDF_STATUS_E_FAILURE; 2719 } 2720 sparams->ss_fft_size = value; 2721 break; 2722 case SPECTRAL_PARAM_GC_ENA: 2723 sparams->ss_gc_ena = !!value; 2724 break; 2725 case SPECTRAL_PARAM_RESTART_ENA: 2726 sparams->ss_restart_ena = !!value; 2727 break; 2728 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 2729 sparams->ss_noise_floor_ref = value; 2730 break; 2731 case SPECTRAL_PARAM_INIT_DELAY: 2732 sparams->ss_init_delay = value; 2733 break; 2734 case SPECTRAL_PARAM_NB_TONE_THR: 2735 sparams->ss_nb_tone_thr = value; 2736 break; 2737 case SPECTRAL_PARAM_STR_BIN_THR: 2738 sparams->ss_str_bin_thr = value; 2739 break; 2740 case SPECTRAL_PARAM_WB_RPT_MODE: 2741 sparams->ss_wb_rpt_mode = !!value; 2742 break; 2743 case SPECTRAL_PARAM_RSSI_RPT_MODE: 2744 sparams->ss_rssi_rpt_mode = !!value; 2745 break; 2746 case SPECTRAL_PARAM_RSSI_THR: 2747 sparams->ss_rssi_thr = value; 2748 break; 2749 case SPECTRAL_PARAM_PWR_FORMAT: 2750 sparams->ss_pwr_format = !!value; 2751 break; 2752 case SPECTRAL_PARAM_RPT_MODE: 2753 if ((value < SPECTRAL_PARAM_RPT_MODE_MIN) || 2754 (value > SPECTRAL_PARAM_RPT_MODE_MAX)) { 2755 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2756 return QDF_STATUS_E_FAILURE; 2757 } 2758 sparams->ss_rpt_mode = value; 2759 break; 2760 case SPECTRAL_PARAM_BIN_SCALE: 2761 sparams->ss_bin_scale = value; 2762 break; 2763 case SPECTRAL_PARAM_DBM_ADJ: 2764 sparams->ss_dbm_adj = !!value; 2765 break; 2766 case SPECTRAL_PARAM_CHN_MASK: 2767 sparams->ss_chn_mask = value; 2768 break; 2769 case SPECTRAL_PARAM_FREQUENCY: 2770 status = target_if_is_center_freq_of_any_chan 2771 (spectral->pdev_obj, value, &is_valid_chan); 2772 if (QDF_IS_STATUS_ERROR(status)) 2773 return QDF_STATUS_E_FAILURE; 2774 2775 if (is_valid_chan) { 2776 status = target_if_calculate_center_freq(spectral, 2777 value, 2778 &agile_cfreq); 2779 if (QDF_IS_STATUS_ERROR(status)) { 2780 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2781 return QDF_STATUS_E_FAILURE; 2782 } 2783 } else { 2784 bool is_valid_agile_cfreq; 2785 2786 status = target_if_validate_center_freq 2787 (spectral, value, &is_valid_agile_cfreq); 2788 if (QDF_IS_STATUS_ERROR(status)) 2789 return QDF_STATUS_E_FAILURE; 2790 2791 if (!is_valid_agile_cfreq) { 2792 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2793 spectral_err("Invalid agile center frequency"); 2794 return QDF_STATUS_E_FAILURE; 2795 } 2796 2797 agile_cfreq = value; 2798 } 2799 2800 status = target_if_is_agile_span_overlap_with_operating_span 2801 (spectral, agile_cfreq, &is_overlapping); 2802 if (QDF_IS_STATUS_ERROR(status)) 2803 return QDF_STATUS_E_FAILURE; 2804 2805 if (is_overlapping) { 2806 spectral_err("Agile span overlapping with current BW"); 2807 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2808 return QDF_STATUS_E_FAILURE; 2809 } 2810 sparams->ss_frequency = agile_cfreq; 2811 break; 2812 } 2813 2814 p_sops->configure_spectral(spectral, sparams, smode); 2815 /* only to validate the writes */ 2816 p_sops->get_spectral_config(spectral, ¶ms, smode); 2817 return QDF_STATUS_SUCCESS; 2818 } 2819 2820 QDF_STATUS 2821 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 2822 const uint32_t threshtype, const uint32_t value, 2823 const enum spectral_scan_mode smode, 2824 enum spectral_cp_error_code *err) 2825 { 2826 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; 2827 struct target_if_spectral *spectral; 2828 QDF_STATUS status; 2829 2830 if (!err) { 2831 spectral_err("Error code argument is null"); 2832 QDF_ASSERT(0); 2833 } 2834 *err = SPECTRAL_SCAN_ERR_INVALID; 2835 2836 if (!pdev) { 2837 spectral_err("pdev object is NULL"); 2838 return QDF_STATUS_E_FAILURE; 2839 } 2840 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2841 if (!spectral) { 2842 spectral_err("spectral object is NULL"); 2843 return QDF_STATUS_E_FAILURE; 2844 } 2845 2846 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2847 spectral_err("Invalid Spectral mode %u", smode); 2848 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 2849 return QDF_STATUS_E_FAILURE; 2850 } 2851 2852 if (!spectral->properties[smode][threshtype].supported) { 2853 spectral_err("Spectral parameter(%u) unsupported for mode %u", 2854 threshtype, smode); 2855 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 2856 return QDF_STATUS_E_FAILURE; 2857 } 2858 2859 if (spectral->properties[smode][threshtype].common_all_modes) { 2860 spectral_warn("Setting Spectral parameter %u for all modes", 2861 threshtype); 2862 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { 2863 status = _target_if_set_spectral_config 2864 (spectral, threshtype, value, 2865 mode, err); 2866 if (QDF_IS_STATUS_ERROR(status)) 2867 return QDF_STATUS_E_FAILURE; 2868 } 2869 return QDF_STATUS_SUCCESS; 2870 } 2871 2872 return _target_if_set_spectral_config(spectral, threshtype, 2873 value, smode, err); 2874 } 2875 2876 /** 2877 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 2878 * @fft_len: FFT length 2879 * @pdev: Pointer to pdev object 2880 * 2881 * API to get fft bin count for a given fft length 2882 * 2883 * Return: FFt bin count 2884 */ 2885 static int 2886 target_if_get_fft_bin_count(int fft_len) 2887 { 2888 int bin_count = 0; 2889 2890 switch (fft_len) { 2891 case 5: 2892 bin_count = 16; 2893 break; 2894 case 6: 2895 bin_count = 32; 2896 break; 2897 case 7: 2898 bin_count = 64; 2899 break; 2900 case 8: 2901 bin_count = 128; 2902 break; 2903 case 9: 2904 bin_count = 256; 2905 break; 2906 default: 2907 break; 2908 } 2909 2910 return bin_count; 2911 } 2912 2913 /** 2914 * target_if_init_upper_lower_flags() - Initializes control and extension 2915 * segment flags 2916 * @fft_len: FFT length 2917 * @pdev: Pointer to pdev object 2918 * 2919 * API to initialize the control and extension flags with the lower/upper 2920 * segment based on the HT mode 2921 * 2922 * Return: FFt bin count 2923 */ 2924 static void 2925 target_if_init_upper_lower_flags(struct target_if_spectral *spectral) 2926 { 2927 int current_channel = 0; 2928 int ext_channel = 0; 2929 struct target_if_spectral_ops *p_sops = 2930 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2931 2932 current_channel = p_sops->get_current_channel(spectral); 2933 ext_channel = p_sops->get_extension_channel(spectral); 2934 2935 if ((current_channel == 0) || (ext_channel == 0)) 2936 return; 2937 2938 if (spectral->sc_spectral_20_40_mode) { 2939 /* HT40 mode */ 2940 if (ext_channel < current_channel) { 2941 spectral->lower_is_extension = 1; 2942 spectral->upper_is_control = 1; 2943 spectral->lower_is_control = 0; 2944 spectral->upper_is_extension = 0; 2945 } else { 2946 spectral->lower_is_extension = 0; 2947 spectral->upper_is_control = 0; 2948 spectral->lower_is_control = 1; 2949 spectral->upper_is_extension = 1; 2950 } 2951 } else { 2952 /* HT20 mode, lower is always control */ 2953 spectral->lower_is_extension = 0; 2954 spectral->upper_is_control = 0; 2955 spectral->lower_is_control = 1; 2956 spectral->upper_is_extension = 0; 2957 } 2958 } 2959 2960 /** 2961 * target_if_get_spectral_config() - Get spectral configuration 2962 * @pdev: Pointer to pdev object 2963 * @param: Pointer to spectral_config structure in which the configuration 2964 * should be returned 2965 * @smode: Spectral scan mode 2966 * 2967 * API to get the current spectral configuration 2968 * 2969 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 2970 */ 2971 QDF_STATUS 2972 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 2973 struct spectral_config *param, 2974 enum spectral_scan_mode smode) 2975 { 2976 struct target_if_spectral_ops *p_sops = NULL; 2977 struct target_if_spectral *spectral = NULL; 2978 2979 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2980 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2981 2982 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2983 spectral_err("Invalid Spectral mode %u", smode); 2984 return QDF_STATUS_E_FAILURE; 2985 } 2986 2987 qdf_mem_zero(param, sizeof(struct spectral_config)); 2988 p_sops->get_spectral_config(spectral, param, smode); 2989 2990 return QDF_STATUS_SUCCESS; 2991 } 2992 2993 /** 2994 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 2995 * parameters 2996 * @spectral: Pointer to Spectral target_if internal private data 2997 * @spectral_params: Pointer to Spectral parameters 2998 * @smode: Spectral scan mode 2999 * @err: Spectral error code 3000 * 3001 * Enable use of desired Spectral parameters by configuring them into HW, and 3002 * starting Spectral scan 3003 * 3004 * Return: 0 on success, 1 on failure 3005 */ 3006 int 3007 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 3008 struct spectral_config *spectral_params, 3009 enum spectral_scan_mode smode, 3010 enum spectral_cp_error_code *err) 3011 { 3012 int extension_channel = 0; 3013 int current_channel = 0; 3014 struct target_if_spectral_ops *p_sops = NULL; 3015 struct wlan_objmgr_vdev *vdev = NULL; 3016 3017 if (!spectral) { 3018 spectral_err("Spectral LMAC object is NULL"); 3019 return 1; 3020 } 3021 3022 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3023 spectral_err("Invalid Spectral mode %u", smode); 3024 return 1; 3025 } 3026 3027 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3028 3029 if (!p_sops) { 3030 spectral_err("p_sops is NULL"); 3031 return 1; 3032 } 3033 3034 spectral->sc_spectral_noise_pwr_cal = 3035 spectral_params->ss_spectral_pri ? 1 : 0; 3036 3037 /* check if extension channel is present */ 3038 extension_channel = p_sops->get_extension_channel(spectral); 3039 current_channel = p_sops->get_current_channel(spectral); 3040 3041 vdev = target_if_spectral_get_vdev(spectral); 3042 if (!vdev) 3043 return 1; 3044 3045 spectral->ch_width = target_if_vdev_get_ch_width(vdev); 3046 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3047 3048 if (spectral->ch_width == CH_WIDTH_INVALID) 3049 return 1; 3050 3051 spectral->agile_ch_width = 3052 target_if_spectral_find_agile_width(spectral->ch_width); 3053 3054 if (spectral->capability.advncd_spectral_cap) { 3055 spectral->lb_edge_extrabins = 0; 3056 spectral->rb_edge_extrabins = 0; 3057 3058 if (spectral->is_lb_edge_extrabins_format && 3059 spectral->params[smode].ss_rpt_mode == 2) { 3060 spectral->lb_edge_extrabins = 4; 3061 } 3062 3063 if (spectral->is_rb_edge_extrabins_format && 3064 spectral->params[smode].ss_rpt_mode == 2) { 3065 spectral->rb_edge_extrabins = 4; 3066 } 3067 3068 if (spectral->ch_width == CH_WIDTH_20MHZ) { 3069 spectral->sc_spectral_20_40_mode = 0; 3070 3071 spectral->spectral_numbins = 3072 target_if_get_fft_bin_count( 3073 spectral->params[smode].ss_fft_size); 3074 spectral->spectral_fft_len = 3075 target_if_get_fft_bin_count( 3076 spectral->params[smode].ss_fft_size); 3077 spectral->spectral_data_len = 3078 target_if_get_fft_bin_count( 3079 spectral->params[smode].ss_fft_size); 3080 /* 3081 * Initialize classifier params to be sent to user 3082 * space classifier 3083 */ 3084 spectral->classifier_params.lower_chan_in_mhz = 3085 current_channel; 3086 spectral->classifier_params.upper_chan_in_mhz = 0; 3087 3088 } else if (spectral->ch_width == CH_WIDTH_40MHZ) { 3089 /* TODO : Remove this variable */ 3090 spectral->sc_spectral_20_40_mode = 1; 3091 spectral->spectral_numbins = 3092 target_if_get_fft_bin_count( 3093 spectral->params[smode].ss_fft_size); 3094 spectral->spectral_fft_len = 3095 target_if_get_fft_bin_count( 3096 spectral->params[smode].ss_fft_size); 3097 spectral->spectral_data_len = 3098 target_if_get_fft_bin_count( 3099 spectral->params[smode].ss_fft_size); 3100 3101 /* 3102 * Initialize classifier params to be sent to user 3103 * space classifier 3104 */ 3105 if (extension_channel < current_channel) { 3106 spectral->classifier_params.lower_chan_in_mhz = 3107 extension_channel; 3108 spectral->classifier_params.upper_chan_in_mhz = 3109 current_channel; 3110 } else { 3111 spectral->classifier_params.lower_chan_in_mhz = 3112 current_channel; 3113 spectral->classifier_params.upper_chan_in_mhz = 3114 extension_channel; 3115 } 3116 3117 } else if (spectral->ch_width == CH_WIDTH_80MHZ) { 3118 /* Set the FFT Size */ 3119 /* TODO : Remove this variable */ 3120 spectral->sc_spectral_20_40_mode = 0; 3121 spectral->spectral_numbins = 3122 target_if_get_fft_bin_count( 3123 spectral->params[smode].ss_fft_size); 3124 spectral->spectral_fft_len = 3125 target_if_get_fft_bin_count( 3126 spectral->params[smode].ss_fft_size); 3127 spectral->spectral_data_len = 3128 target_if_get_fft_bin_count( 3129 spectral->params[smode].ss_fft_size); 3130 3131 /* 3132 * Initialize classifier params to be sent to user 3133 * space classifier 3134 */ 3135 spectral->classifier_params.lower_chan_in_mhz = 3136 current_channel; 3137 spectral->classifier_params.upper_chan_in_mhz = 0; 3138 3139 /* 3140 * Initialize classifier params to be sent to user 3141 * space classifier 3142 */ 3143 if (extension_channel < current_channel) { 3144 spectral->classifier_params.lower_chan_in_mhz = 3145 extension_channel; 3146 spectral->classifier_params.upper_chan_in_mhz = 3147 current_channel; 3148 } else { 3149 spectral->classifier_params.lower_chan_in_mhz = 3150 current_channel; 3151 spectral->classifier_params.upper_chan_in_mhz = 3152 extension_channel; 3153 } 3154 3155 } else if (spectral->ch_width == CH_WIDTH_160MHZ) { 3156 /* Set the FFT Size */ 3157 3158 /* The below applies to both 160 and 80+80 cases */ 3159 3160 /* TODO : Remove this variable */ 3161 spectral->sc_spectral_20_40_mode = 0; 3162 spectral->spectral_numbins = 3163 target_if_get_fft_bin_count( 3164 spectral->params[smode].ss_fft_size); 3165 spectral->spectral_fft_len = 3166 target_if_get_fft_bin_count( 3167 spectral->params[smode].ss_fft_size); 3168 spectral->spectral_data_len = 3169 target_if_get_fft_bin_count( 3170 spectral->params[smode].ss_fft_size); 3171 3172 /* 3173 * Initialize classifier params to be sent to user 3174 * space classifier 3175 */ 3176 spectral->classifier_params.lower_chan_in_mhz = 3177 current_channel; 3178 spectral->classifier_params.upper_chan_in_mhz = 0; 3179 3180 /* 3181 * Initialize classifier params to be sent to user 3182 * space classifier 3183 */ 3184 if (extension_channel < current_channel) { 3185 spectral->classifier_params.lower_chan_in_mhz = 3186 extension_channel; 3187 spectral->classifier_params.upper_chan_in_mhz = 3188 current_channel; 3189 } else { 3190 spectral->classifier_params.lower_chan_in_mhz = 3191 current_channel; 3192 spectral->classifier_params.upper_chan_in_mhz = 3193 extension_channel; 3194 } 3195 } 3196 3197 if (spectral->spectral_numbins) { 3198 spectral->spectral_numbins += 3199 spectral->lb_edge_extrabins; 3200 spectral->spectral_numbins += 3201 spectral->rb_edge_extrabins; 3202 } 3203 3204 if (spectral->spectral_fft_len) { 3205 spectral->spectral_fft_len += 3206 spectral->lb_edge_extrabins; 3207 spectral->spectral_fft_len += 3208 spectral->rb_edge_extrabins; 3209 } 3210 3211 if (spectral->spectral_data_len) { 3212 spectral->spectral_data_len += 3213 spectral->lb_edge_extrabins; 3214 spectral->spectral_data_len += 3215 spectral->rb_edge_extrabins; 3216 } 3217 } else { 3218 /* 3219 * The decision to find 20/40 mode is found based on the 3220 * presence of extension channel 3221 * instead of channel width, as the channel width can 3222 * dynamically change 3223 */ 3224 3225 if (extension_channel == 0) { 3226 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 3227 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 3228 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 3229 spectral->spectral_data_len = 3230 SPECTRAL_HT20_TOTAL_DATA_LEN; 3231 /* only valid in 20-40 mode */ 3232 spectral->spectral_lower_max_index_offset = -1; 3233 /* only valid in 20-40 mode */ 3234 spectral->spectral_upper_max_index_offset = -1; 3235 spectral->spectral_max_index_offset = 3236 spectral->spectral_fft_len + 2; 3237 spectral->sc_spectral_20_40_mode = 0; 3238 3239 /* 3240 * Initialize classifier params to be sent to user 3241 * space classifier 3242 */ 3243 spectral->classifier_params.lower_chan_in_mhz = 3244 current_channel; 3245 spectral->classifier_params.upper_chan_in_mhz = 0; 3246 3247 } else { 3248 spectral->spectral_numbins = 3249 SPECTRAL_HT40_TOTAL_NUM_BINS; 3250 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 3251 spectral->spectral_data_len = 3252 SPECTRAL_HT40_TOTAL_DATA_LEN; 3253 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 3254 /* only valid in 20 mode */ 3255 spectral->spectral_max_index_offset = -1; 3256 spectral->spectral_lower_max_index_offset = 3257 spectral->spectral_fft_len + 2; 3258 spectral->spectral_upper_max_index_offset = 3259 spectral->spectral_fft_len + 5; 3260 spectral->sc_spectral_20_40_mode = 1; 3261 3262 /* 3263 * Initialize classifier params to be sent to user 3264 * space classifier 3265 */ 3266 if (extension_channel < current_channel) { 3267 spectral->classifier_params.lower_chan_in_mhz = 3268 extension_channel; 3269 spectral->classifier_params.upper_chan_in_mhz = 3270 current_channel; 3271 } else { 3272 spectral->classifier_params.lower_chan_in_mhz = 3273 current_channel; 3274 spectral->classifier_params.upper_chan_in_mhz = 3275 extension_channel; 3276 } 3277 } 3278 } 3279 3280 spectral->send_single_packet = 0; 3281 spectral->classifier_params.spectral_20_40_mode = 3282 spectral->sc_spectral_20_40_mode; 3283 spectral->classifier_params.spectral_dc_index = 3284 spectral->spectral_dc_index; 3285 spectral->spectral_sent_msg = 0; 3286 spectral->classify_scan = 0; 3287 spectral->num_spectral_data = 0; 3288 3289 if (!p_sops->is_spectral_active(spectral, smode)) { 3290 p_sops->configure_spectral(spectral, spectral_params, smode); 3291 p_sops->start_spectral_scan(spectral, smode, err); 3292 spectral->timestamp_war.timestamp_war_offset[smode] = 0; 3293 spectral->timestamp_war.last_fft_timestamp[smode] = 0; 3294 } 3295 3296 /* get current spectral configuration */ 3297 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode); 3298 3299 target_if_init_upper_lower_flags(spectral); 3300 3301 return 0; 3302 } 3303 3304 /** 3305 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by 3306 * Agile DFS 3307 * @psoc: Pointer to psoc 3308 * @object: Pointer to pdev 3309 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited 3310 * 3311 * This API checks whether Agile DFS is running on any of the pdevs. If so, it 3312 * indicates that Agile Spectral scan is prohibited by Agile DFS. 3313 * 3314 * Return: void 3315 */ 3316 static void 3317 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, 3318 void *object, void *arg) 3319 { 3320 bool *is_aspectral_prohibited = arg; 3321 struct wlan_objmgr_pdev *cur_pdev = object; 3322 bool is_agile_dfs_enabled_cur_pdev = false; 3323 QDF_STATUS status; 3324 3325 qdf_assert_always(is_aspectral_prohibited); 3326 if (*is_aspectral_prohibited) 3327 return; 3328 3329 qdf_assert_always(psoc); 3330 qdf_assert_always(cur_pdev); 3331 3332 status = ucfg_dfs_get_agile_precac_enable 3333 (cur_pdev, 3334 &is_agile_dfs_enabled_cur_pdev); 3335 if (QDF_IS_STATUS_ERROR(status)) { 3336 spectral_err("Get agile precac failed, prohibiting aSpectral"); 3337 *is_aspectral_prohibited = true; 3338 return; 3339 } 3340 3341 if (is_agile_dfs_enabled_cur_pdev) { 3342 spectral_err("aDFS is in progress on one of the pdevs"); 3343 *is_aspectral_prohibited = true; 3344 } 3345 } 3346 3347 /** 3348 * target_if_get_curr_band() - Get current operating band of pdev 3349 * 3350 * @spectral: pointer to spectral object 3351 * 3352 * API to get current operating band of a given pdev. 3353 * 3354 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure 3355 */ 3356 static enum reg_wifi_band 3357 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev) 3358 { 3359 struct wlan_objmgr_vdev *vdev; 3360 int16_t chan_freq; 3361 enum reg_wifi_band cur_band; 3362 3363 if (!pdev) { 3364 spectral_err("pdev is NULL"); 3365 return REG_BAND_UNKNOWN; 3366 } 3367 3368 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); 3369 if (!vdev) { 3370 spectral_debug("vdev is NULL"); 3371 return REG_BAND_UNKNOWN; 3372 } 3373 chan_freq = target_if_vdev_get_chan_freq(vdev); 3374 cur_band = wlan_reg_freq_to_band(chan_freq); 3375 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3376 3377 return cur_band; 3378 } 3379 3380 /** 3381 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on 3382 * any of the 5G pdevs 3383 * @psoc: Pointer to psoc 3384 * @object: Pointer to pdev 3385 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in 3386 * progress in any 5G pdevs 3387 * 3388 * Return: void 3389 */ 3390 static void 3391 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, 3392 void *object, void *arg) 3393 { 3394 enum reg_wifi_band band; 3395 bool *is_agile_scan_inprog_5g_pdev = arg; 3396 struct target_if_spectral *spectral; 3397 struct wlan_objmgr_pdev *cur_pdev = object; 3398 struct target_if_spectral_ops *p_sops; 3399 3400 if (*is_agile_scan_inprog_5g_pdev) 3401 return; 3402 3403 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); 3404 if (!spectral) { 3405 spectral_err("target if spectral handle is NULL"); 3406 return; 3407 } 3408 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3409 3410 band = target_if_get_curr_band(cur_pdev); 3411 if (band == REG_BAND_UNKNOWN) { 3412 spectral_debug("Failed to get current band"); 3413 return; 3414 } 3415 3416 if (band == REG_BAND_5G && 3417 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) 3418 *is_agile_scan_inprog_5g_pdev = true; 3419 } 3420 3421 /** 3422 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported 3423 * for current vdev rx chainmask. 3424 * 3425 * @spectral: Pointer to Spectral object 3426 * @is_supported: Pointer to is_supported 3427 * 3428 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3429 */ 3430 static QDF_STATUS 3431 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, 3432 bool *is_supported) 3433 { 3434 struct wlan_objmgr_vdev *vdev; 3435 uint8_t vdev_rxchainmask; 3436 struct wlan_objmgr_psoc *psoc; 3437 struct wlan_objmgr_pdev *pdev; 3438 struct target_psoc_info *tgt_psoc_info; 3439 struct wlan_psoc_host_service_ext_param *ext_svc_param; 3440 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 3441 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 3442 struct wlan_psoc_host_chainmask_table *table; 3443 int j; 3444 uint32_t table_id; 3445 enum phy_ch_width ch_width; 3446 uint8_t pdev_id; 3447 3448 if (!spectral) { 3449 spectral_err("spectral target if object is null"); 3450 return QDF_STATUS_E_FAILURE; 3451 } 3452 3453 if (!is_supported) { 3454 spectral_err("is supported argument is null"); 3455 return QDF_STATUS_E_FAILURE; 3456 } 3457 3458 if (spectral->spectral_gen <= SPECTRAL_GEN2) { 3459 spectral_err("HW Agile mode is not supported up to gen 2"); 3460 return QDF_STATUS_E_FAILURE; 3461 } 3462 3463 pdev = spectral->pdev_obj; 3464 if (!pdev) { 3465 spectral_err("pdev is null"); 3466 return QDF_STATUS_E_FAILURE; 3467 } 3468 3469 psoc = wlan_pdev_get_psoc(pdev); 3470 if (!psoc) { 3471 spectral_err("psoc is null"); 3472 return QDF_STATUS_E_FAILURE; 3473 } 3474 3475 vdev = target_if_spectral_get_vdev(spectral); 3476 if (!vdev) { 3477 spectral_err("First vdev is NULL"); 3478 return QDF_STATUS_E_FAILURE; 3479 } 3480 3481 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 3482 if (!vdev_rxchainmask) { 3483 spectral_err("vdev rx chainmask is zero"); 3484 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3485 return QDF_STATUS_E_FAILURE; 3486 } 3487 3488 ch_width = target_if_vdev_get_ch_width(vdev); 3489 if (ch_width == CH_WIDTH_INVALID) { 3490 spectral_err("Invalid channel width"); 3491 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3492 return QDF_STATUS_E_FAILURE; 3493 } 3494 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3495 3496 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 3497 if (!tgt_psoc_info) { 3498 spectral_err("target_psoc_info is null"); 3499 return QDF_STATUS_E_FAILURE; 3500 } 3501 3502 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 3503 if (!ext_svc_param) { 3504 spectral_err("Extended service ready param null"); 3505 return QDF_STATUS_E_FAILURE; 3506 } 3507 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 3508 3509 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 3510 if (!mac_phy_cap_arr) { 3511 spectral_err("mac phy cap array is null"); 3512 return QDF_STATUS_E_FAILURE; 3513 } 3514 3515 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 3516 if (!mac_phy_cap) { 3517 spectral_err("mac phy cap is null"); 3518 return QDF_STATUS_E_FAILURE; 3519 } 3520 3521 table_id = mac_phy_cap->chainmask_table_id; 3522 table = &ext_svc_param->chainmask_table[table_id]; 3523 if (!table) { 3524 spectral_err("chainmask table not found"); 3525 return QDF_STATUS_E_FAILURE; 3526 } 3527 3528 for (j = 0; j < table->num_valid_chainmasks; j++) { 3529 if (table->cap_list[j].chainmask == vdev_rxchainmask) { 3530 if (ch_width <= CH_WIDTH_80MHZ) 3531 *is_supported = 3532 table->cap_list[j].supports_aSpectral; 3533 else 3534 *is_supported = 3535 table->cap_list[j].supports_aSpectral_160; 3536 break; 3537 } 3538 } 3539 3540 if (j == table->num_valid_chainmasks) { 3541 spectral_err("vdev rx chainmask %u not found in table id = %u", 3542 vdev_rxchainmask, table_id); 3543 return QDF_STATUS_E_FAILURE; 3544 } 3545 3546 return QDF_STATUS_SUCCESS; 3547 } 3548 3549 QDF_STATUS 3550 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, 3551 const enum spectral_scan_mode smode, 3552 enum spectral_cp_error_code *err) 3553 { 3554 struct target_if_spectral_ops *p_sops; 3555 struct target_if_spectral *spectral; 3556 struct wlan_objmgr_psoc *psoc; 3557 enum reg_wifi_band band; 3558 3559 if (!err) { 3560 spectral_err("Error code argument is null"); 3561 QDF_ASSERT(0); 3562 } 3563 *err = SPECTRAL_SCAN_ERR_INVALID; 3564 3565 psoc = wlan_pdev_get_psoc(pdev); 3566 if (!psoc) { 3567 spectral_err("psoc is null"); 3568 return QDF_STATUS_E_FAILURE; 3569 } 3570 3571 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3572 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3573 spectral_err("Invalid Spectral mode %u", smode); 3574 return QDF_STATUS_E_FAILURE; 3575 } 3576 3577 if (!pdev) { 3578 spectral_err("pdev object is NUll"); 3579 return QDF_STATUS_E_FAILURE; 3580 } 3581 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3582 if (!spectral) { 3583 spectral_err("Spectral LMAC object is NUll"); 3584 return QDF_STATUS_E_FAILURE; 3585 } 3586 3587 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3588 3589 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 3590 QDF_STATUS status; 3591 bool is_supported = false; 3592 3593 status = target_if_is_agile_supported_cur_chmask(spectral, 3594 &is_supported); 3595 if (QDF_IS_STATUS_ERROR(status)) { 3596 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3597 return QDF_STATUS_E_FAILURE; 3598 } 3599 3600 if (!is_supported) { 3601 spectral_err("aSpectral unsupported for cur chainmask"); 3602 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3603 return QDF_STATUS_E_FAILURE; 3604 } 3605 } 3606 3607 band = target_if_get_curr_band(spectral->pdev_obj); 3608 if (band == REG_BAND_UNKNOWN) { 3609 spectral_err("Failed to get current band"); 3610 return QDF_STATUS_E_FAILURE; 3611 } 3612 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { 3613 struct target_psoc_info *tgt_hdl; 3614 enum wmi_host_hw_mode_config_type mode; 3615 bool is_agile_scan_inprog_5g_pdev; 3616 3617 if (p_sops->is_spectral_active(spectral, 3618 SPECTRAL_SCAN_MODE_AGILE)) { 3619 spectral_err("Agile Scan in progress in current pdev"); 3620 return QDF_STATUS_E_FAILURE; 3621 } 3622 3623 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 3624 if (!tgt_hdl) { 3625 target_if_err("target_psoc_info is null"); 3626 return QDF_STATUS_E_FAILURE; 3627 } 3628 3629 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 3630 switch (mode) { 3631 case WMI_HOST_HW_MODE_SBS_PASSIVE: 3632 case WMI_HOST_HW_MODE_SBS: 3633 case WMI_HOST_HW_MODE_DBS_SBS: 3634 case WMI_HOST_HW_MODE_DBS_OR_SBS: 3635 is_agile_scan_inprog_5g_pdev = false; 3636 wlan_objmgr_iterate_obj_list 3637 (psoc, WLAN_PDEV_OP, 3638 target_if_is_agile_scan_active_in_5g, 3639 &is_agile_scan_inprog_5g_pdev, 0, 3640 WLAN_SPECTRAL_ID); 3641 break; 3642 default: 3643 is_agile_scan_inprog_5g_pdev = false; 3644 break; 3645 } 3646 3647 if (is_agile_scan_inprog_5g_pdev) { 3648 spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); 3649 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3650 return QDF_STATUS_E_FAILURE; 3651 } 3652 } 3653 3654 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 3655 bool is_aspectral_prohibited = false; 3656 QDF_STATUS status; 3657 3658 status = wlan_objmgr_iterate_obj_list 3659 (psoc, WLAN_PDEV_OP, 3660 target_if_is_aspectral_prohibited_by_adfs, 3661 &is_aspectral_prohibited, 0, 3662 WLAN_SPECTRAL_ID); 3663 if (QDF_IS_STATUS_ERROR(status)) { 3664 spectral_err("Failed to iterate over pdevs"); 3665 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3666 return QDF_STATUS_E_FAILURE; 3667 } 3668 3669 if (is_aspectral_prohibited) { 3670 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3671 return QDF_STATUS_E_FAILURE; 3672 } 3673 } 3674 3675 if (!spectral->params_valid[smode]) { 3676 target_if_spectral_info_read(spectral, 3677 smode, 3678 TARGET_IF_SPECTRAL_INFO_PARAMS, 3679 &spectral->params[smode], 3680 sizeof(spectral->params[smode])); 3681 spectral->params_valid[smode] = true; 3682 } 3683 3684 qdf_spin_lock(&spectral->spectral_lock); 3685 if (smode == SPECTRAL_SCAN_MODE_AGILE && 3686 !spectral->params[smode].ss_frequency) { 3687 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 3688 qdf_spin_unlock(&spectral->spectral_lock); 3689 return QDF_STATUS_E_FAILURE; 3690 } 3691 3692 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 3693 QDF_STATUS status; 3694 bool is_overlapping; 3695 3696 status = target_if_is_agile_span_overlap_with_operating_span 3697 (spectral, 3698 spectral->params[smode].ss_frequency, 3699 &is_overlapping); 3700 if (QDF_IS_STATUS_ERROR(status)) { 3701 qdf_spin_unlock(&spectral->spectral_lock); 3702 return QDF_STATUS_E_FAILURE; 3703 } 3704 3705 if (is_overlapping) { 3706 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3707 qdf_spin_unlock(&spectral->spectral_lock); 3708 return QDF_STATUS_E_FAILURE; 3709 } 3710 } 3711 3712 target_if_spectral_scan_enable_params(spectral, 3713 &spectral->params[smode], smode, 3714 err); 3715 qdf_spin_unlock(&spectral->spectral_lock); 3716 3717 return QDF_STATUS_SUCCESS; 3718 } 3719 3720 QDF_STATUS 3721 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, 3722 const enum spectral_scan_mode smode, 3723 enum spectral_cp_error_code *err) 3724 { 3725 struct target_if_spectral_ops *p_sops; 3726 struct target_if_spectral *spectral; 3727 3728 if (!err) { 3729 spectral_err("Error code argument is null"); 3730 QDF_ASSERT(0); 3731 } 3732 *err = SPECTRAL_SCAN_ERR_INVALID; 3733 3734 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3735 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3736 spectral_err("Invalid Spectral mode %u", smode); 3737 return QDF_STATUS_E_FAILURE; 3738 } 3739 3740 if (!pdev) { 3741 spectral_err("pdev object is NUll "); 3742 return QDF_STATUS_E_FAILURE; 3743 } 3744 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3745 if (!spectral) { 3746 spectral_err("Spectral LMAC object is NUll "); 3747 return QDF_STATUS_E_FAILURE; 3748 } 3749 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3750 3751 qdf_spin_lock(&spectral->spectral_lock); 3752 p_sops->stop_spectral_scan(spectral, smode); 3753 if (spectral->classify_scan) { 3754 /* TODO : Check if this logic is necessary */ 3755 spectral->detects_control_channel = 0; 3756 spectral->detects_extension_channel = 0; 3757 spectral->detects_above_dc = 0; 3758 spectral->detects_below_dc = 0; 3759 spectral->classify_scan = 0; 3760 } 3761 3762 spectral->send_single_packet = 0; 3763 spectral->sc_spectral_scan = 0; 3764 3765 qdf_spin_unlock(&spectral->spectral_lock); 3766 3767 return QDF_STATUS_SUCCESS; 3768 } 3769 3770 /** 3771 * target_if_is_spectral_active() - Get whether Spectral is active 3772 * @pdev: Pointer to pdev object 3773 * @smode: Spectral scan mode 3774 * 3775 * API to get whether Spectral is active 3776 * 3777 * Return: True if Spectral is active, false if Spectral is not active 3778 */ 3779 bool 3780 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, 3781 const enum spectral_scan_mode smode) 3782 { 3783 struct target_if_spectral *spectral = NULL; 3784 struct target_if_spectral_ops *p_sops = NULL; 3785 3786 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3787 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3788 3789 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3790 spectral_err("Invalid Spectral mode %u", smode); 3791 return QDF_STATUS_E_FAILURE; 3792 } 3793 3794 return p_sops->is_spectral_active(spectral, smode); 3795 } 3796 3797 /** 3798 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 3799 * @pdev: Pointer to pdev object 3800 * @smode: Spectral scan mode 3801 * 3802 * API to get whether Spectral is enabled 3803 * 3804 * Return: True if Spectral is enabled, false if Spectral is not enabled 3805 */ 3806 bool 3807 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, 3808 enum spectral_scan_mode smode) 3809 { 3810 struct target_if_spectral *spectral = NULL; 3811 struct target_if_spectral_ops *p_sops = NULL; 3812 3813 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3814 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3815 3816 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3817 spectral_err("Invalid Spectral mode %u", smode); 3818 return QDF_STATUS_E_FAILURE; 3819 } 3820 3821 return p_sops->is_spectral_enabled(spectral, smode); 3822 } 3823 3824 #ifdef DIRECT_BUF_RX_DEBUG 3825 /** 3826 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug 3827 * @pdev: Pointer to pdev object 3828 * @enable: Enable/Disable Spectral DMA ring debug 3829 * 3830 * Start/stop Spectral DMA ring debug based on @enable. 3831 * Also save the state for future use. 3832 * 3833 * Return: QDF_STATUS of operation 3834 */ 3835 static QDF_STATUS 3836 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) 3837 { 3838 struct target_if_spectral *spectral; 3839 struct wlan_lmac_if_tx_ops *tx_ops; 3840 struct wlan_objmgr_psoc *psoc; 3841 3842 if (!pdev) 3843 return QDF_STATUS_E_FAILURE; 3844 3845 psoc = wlan_pdev_get_psoc(pdev); 3846 if (!psoc) { 3847 spectral_err("psoc is null"); 3848 return QDF_STATUS_E_INVAL; 3849 } 3850 tx_ops = &psoc->soc_cb.tx_ops; 3851 3852 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3853 if (!spectral) { 3854 spectral_err("Spectal LMAC object is NULL"); 3855 return QDF_STATUS_E_INVAL; 3856 } 3857 3858 /* Save the state */ 3859 spectral->dbr_ring_debug = enable; 3860 3861 if (enable) 3862 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( 3863 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); 3864 else 3865 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( 3866 pdev, 0); 3867 3868 return QDF_STATUS_SUCCESS; 3869 } 3870 3871 /** 3872 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug 3873 * @pdev: Pointer to pdev object 3874 * @enable: Enable/Disable Spectral DMA buffer debug 3875 * 3876 * Start/stop Spectral DMA buffer debug based on @enable. 3877 * Also save the state for future use. 3878 * 3879 * Return: QDF_STATUS of operation 3880 */ 3881 static QDF_STATUS 3882 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) 3883 { 3884 struct target_if_spectral *spectral; 3885 struct wlan_lmac_if_tx_ops *tx_ops; 3886 struct wlan_objmgr_psoc *psoc; 3887 3888 if (!pdev) 3889 return QDF_STATUS_E_FAILURE; 3890 3891 psoc = wlan_pdev_get_psoc(pdev); 3892 if (!psoc) { 3893 spectral_err("psoc is null"); 3894 return QDF_STATUS_E_INVAL; 3895 } 3896 tx_ops = &psoc->soc_cb.tx_ops; 3897 3898 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3899 if (!spectral) { 3900 spectral_err("Spectal LMAC object is NULL"); 3901 return QDF_STATUS_E_INVAL; 3902 } 3903 3904 /* Save the state */ 3905 spectral->dbr_buff_debug = enable; 3906 3907 if (enable) 3908 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( 3909 pdev, 0, MEM_POISON_SIGNATURE); 3910 else 3911 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( 3912 pdev, 0); 3913 } 3914 3915 /** 3916 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer 3917 * debug based on the previous state 3918 * @pdev: Pointer to pdev object 3919 * 3920 * Return: QDF_STATUS of operation 3921 */ 3922 static QDF_STATUS 3923 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) 3924 { 3925 struct target_if_spectral *spectral; 3926 3927 if (!pdev) { 3928 spectral_err("pdev is NULL!"); 3929 return QDF_STATUS_E_FAILURE; 3930 } 3931 3932 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3933 if (!spectral) { 3934 spectral_err("Spectal LMAC object is NULL"); 3935 return QDF_STATUS_E_INVAL; 3936 } 3937 3938 if (spectral->dbr_buff_debug) 3939 return target_if_spectral_do_dbr_buff_debug(pdev, true); 3940 else 3941 return target_if_spectral_do_dbr_buff_debug(pdev, false); 3942 } 3943 3944 /** 3945 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring 3946 * debug based on the previous state 3947 * @pdev: Pointer to pdev object 3948 * 3949 * Return: QDF_STATUS of operation 3950 */ 3951 static QDF_STATUS 3952 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) 3953 { 3954 struct target_if_spectral *spectral; 3955 3956 if (!pdev) { 3957 spectral_err("pdev is NULL!"); 3958 return QDF_STATUS_E_FAILURE; 3959 } 3960 3961 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3962 if (!spectral) { 3963 spectral_err("Spectal LMAC object is NULL"); 3964 return QDF_STATUS_E_INVAL; 3965 } 3966 3967 if (spectral->dbr_ring_debug) 3968 return target_if_spectral_do_dbr_ring_debug(pdev, true); 3969 else 3970 return target_if_spectral_do_dbr_ring_debug(pdev, false); 3971 } 3972 3973 /** 3974 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral 3975 * @pdev: Pointer to pdev object 3976 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug 3977 * @debug_value: Value to be set for @dma_debug_type 3978 * 3979 * Set DMA debug for Spectral and start/stop Spectral DMA debug function 3980 * based on @debug_value 3981 * 3982 * Return: QDF_STATUS of operation 3983 */ 3984 static QDF_STATUS 3985 target_if_spectral_set_dma_debug( 3986 struct wlan_objmgr_pdev *pdev, 3987 enum spectral_dma_debug dma_debug_type, 3988 bool debug_value) 3989 { 3990 struct target_if_spectral_ops *p_sops; 3991 struct wlan_objmgr_psoc *psoc; 3992 struct wlan_lmac_if_tx_ops *tx_ops; 3993 struct target_if_spectral *spectral; 3994 3995 if (!pdev) 3996 return QDF_STATUS_E_FAILURE; 3997 3998 psoc = wlan_pdev_get_psoc(pdev); 3999 if (!psoc) { 4000 spectral_err("psoc is null"); 4001 return QDF_STATUS_E_INVAL; 4002 } 4003 tx_ops = &psoc->soc_cb.tx_ops; 4004 4005 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { 4006 spectral_err("Unable to fetch target type"); 4007 return QDF_STATUS_E_FAILURE; 4008 } 4009 4010 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4011 if (!spectral) { 4012 spectral_err("Spectal LMAC object is NULL"); 4013 return QDF_STATUS_E_INVAL; 4014 } 4015 4016 if (spectral->direct_dma_support) { 4017 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4018 if (p_sops->is_spectral_active(spectral, 4019 SPECTRAL_SCAN_MODE_NORMAL) || 4020 p_sops->is_spectral_active(spectral, 4021 SPECTRAL_SCAN_MODE_AGILE)) { 4022 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); 4023 return QDF_STATUS_E_FAILURE; 4024 } 4025 4026 switch (dma_debug_type) { 4027 case SPECTRAL_DMA_RING_DEBUG: 4028 target_if_spectral_do_dbr_ring_debug(pdev, debug_value); 4029 break; 4030 4031 case SPECTRAL_DMA_BUFFER_DEBUG: 4032 target_if_spectral_do_dbr_buff_debug(pdev, debug_value); 4033 break; 4034 4035 default: 4036 spectral_err("Unsupported DMA debug type : %d", 4037 dma_debug_type); 4038 return QDF_STATUS_E_FAILURE; 4039 } 4040 } 4041 return QDF_STATUS_SUCCESS; 4042 } 4043 #endif /* DIRECT_BUF_RX_DEBUG */ 4044 4045 /** 4046 * target_if_spectral_direct_dma_support() - Get Direct-DMA support 4047 * @pdev: Pointer to pdev object 4048 * 4049 * Return: Whether Direct-DMA is supported on this radio 4050 */ 4051 static bool 4052 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) 4053 { 4054 struct target_if_spectral *spectral; 4055 4056 if (!pdev) { 4057 spectral_err("pdev is NULL!"); 4058 return false; 4059 } 4060 4061 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4062 if (!spectral) { 4063 spectral_err("Spectral LMAC object is NULL"); 4064 return false; 4065 } 4066 return spectral->direct_dma_support; 4067 } 4068 4069 /** 4070 * target_if_set_debug_level() - Set debug level for Spectral 4071 * @pdev: Pointer to pdev object 4072 * @debug_level: Debug level 4073 * 4074 * API to set the debug level for Spectral 4075 * 4076 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4077 */ 4078 QDF_STATUS 4079 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 4080 { 4081 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 4082 4083 return QDF_STATUS_SUCCESS; 4084 } 4085 4086 /** 4087 * target_if_get_debug_level() - Get debug level for Spectral 4088 * @pdev: Pointer to pdev object 4089 * 4090 * API to get the debug level for Spectral 4091 * 4092 * Return: Current debug level 4093 */ 4094 uint32_t 4095 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 4096 { 4097 return spectral_debug_level; 4098 } 4099 4100 /** 4101 * target_if_get_spectral_capinfo() - Get Spectral capability information 4102 * @pdev: Pointer to pdev object 4103 * @scaps: Buffer into which data should be copied 4104 * 4105 * API to get the spectral capability information 4106 * 4107 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4108 */ 4109 QDF_STATUS 4110 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, 4111 struct spectral_caps *scaps) 4112 { 4113 struct target_if_spectral *spectral = NULL; 4114 4115 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4116 qdf_mem_copy(scaps, &spectral->capability, 4117 sizeof(struct spectral_caps)); 4118 4119 return QDF_STATUS_SUCCESS; 4120 } 4121 4122 /** 4123 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 4124 * @pdev: Pointer to pdev object 4125 * @stats: Buffer into which data should be copied 4126 * 4127 * API to get the spectral diagnostic statistics 4128 * 4129 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4130 */ 4131 QDF_STATUS 4132 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, 4133 struct spectral_diag_stats *stats) 4134 { 4135 struct target_if_spectral *spectral = NULL; 4136 4137 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4138 qdf_mem_copy(stats, &spectral->diag_stats, 4139 sizeof(struct spectral_diag_stats)); 4140 4141 return QDF_STATUS_SUCCESS; 4142 } 4143 4144 /** 4145 * target_if_register_wmi_spectral_cmd_ops() - Register wmi_spectral_cmd_ops 4146 * @cmd_ops: Pointer to the structure having wmi_spectral_cmd function pointers 4147 * @pdev: Pointer to pdev object 4148 * 4149 * API for register wmi_spectral_cmd_ops in spectral internal data structure 4150 * 4151 * Return: void 4152 */ 4153 void 4154 target_if_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev, 4155 struct wmi_spectral_cmd_ops *cmd_ops) 4156 { 4157 struct target_if_spectral *spectral = 4158 get_target_if_spectral_handle_from_pdev(pdev); 4159 4160 if (!spectral) { 4161 spectral_err("Spectral LMAC object is null"); 4162 return; 4163 } 4164 spectral->param_wmi_cmd_ops = *cmd_ops; 4165 } 4166 4167 /** 4168 * target_if_register_netlink_cb() - Register Netlink callbacks 4169 * @pdev: Pointer to pdev object 4170 * @nl_cb: Netlink callbacks to register 4171 * 4172 * Return: void 4173 */ 4174 static void 4175 target_if_register_netlink_cb( 4176 struct wlan_objmgr_pdev *pdev, 4177 struct spectral_nl_cb *nl_cb) 4178 { 4179 struct target_if_spectral *spectral = NULL; 4180 4181 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4182 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 4183 4184 if (spectral->use_nl_bcast) 4185 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 4186 else 4187 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 4188 } 4189 4190 /** 4191 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 4192 * Netlink messages to the application layer 4193 * @pdev: Pointer to pdev object 4194 * 4195 * Return: true for broadcast, false for unicast 4196 */ 4197 static bool 4198 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 4199 { 4200 struct target_if_spectral *spectral = NULL; 4201 4202 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4203 return spectral->use_nl_bcast; 4204 } 4205 4206 /** 4207 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 4208 * @pdev: Pointer to pdev object 4209 * 4210 * Return: void 4211 */ 4212 static void 4213 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 4214 { 4215 struct target_if_spectral *spectral = NULL; 4216 4217 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4218 if (!spectral) { 4219 spectral_err("SPECTRAL : Module doesn't exist"); 4220 return; 4221 } 4222 4223 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 4224 } 4225 4226 static int 4227 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, 4228 void *payload) 4229 { 4230 struct target_if_spectral *spectral = NULL; 4231 struct target_if_spectral_ops *p_sops = NULL; 4232 4233 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4234 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4235 4236 return p_sops->process_spectral_report(pdev, payload); 4237 } 4238 4239 #ifdef DIRECT_BUF_RX_DEBUG 4240 static inline void 4241 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 4242 { 4243 if (!tx_ops) 4244 return; 4245 4246 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = 4247 target_if_spectral_set_dma_debug; 4248 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = 4249 target_if_spectral_check_and_do_dbr_ring_debug; 4250 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = 4251 target_if_spectral_check_and_do_dbr_buff_debug; 4252 } 4253 #else 4254 static inline void 4255 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 4256 { 4257 } 4258 #endif 4259 4260 void 4261 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 4262 { 4263 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 4264 target_if_pdev_spectral_init; 4265 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 4266 target_if_pdev_spectral_deinit; 4267 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 4268 target_if_set_spectral_config; 4269 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 4270 target_if_get_spectral_config; 4271 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 4272 target_if_start_spectral_scan; 4273 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 4274 target_if_stop_spectral_scan; 4275 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 4276 target_if_is_spectral_active; 4277 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 4278 target_if_is_spectral_enabled; 4279 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 4280 target_if_set_debug_level; 4281 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 4282 target_if_get_debug_level; 4283 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 4284 target_if_get_spectral_capinfo; 4285 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 4286 target_if_get_spectral_diagstats; 4287 tx_ops->sptrl_tx_ops.sptrlto_register_wmi_spectral_cmd_ops = 4288 target_if_register_wmi_spectral_cmd_ops; 4289 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 4290 target_if_register_netlink_cb; 4291 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 4292 target_if_use_nl_bcast; 4293 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 4294 target_if_deregister_netlink_cb; 4295 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = 4296 target_if_process_spectral_report; 4297 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = 4298 target_if_spectral_direct_dma_support; 4299 target_if_sptrl_debug_register_tx_ops(tx_ops); 4300 } 4301 qdf_export_symbol(target_if_sptrl_register_tx_ops); 4302 4303 void 4304 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 4305 uint16_t cw_int, uint32_t dcs_enabled) 4306 { 4307 struct spectral_samp_msg *msg = NULL; 4308 struct target_if_spectral_ops *p_sops = NULL; 4309 struct target_if_spectral *spectral = NULL; 4310 4311 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4312 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( 4313 spectral->pdev_obj, 4314 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, 4315 SPECTRAL_MSG_BUF_NEW); 4316 4317 if (msg) { 4318 msg->int_type = cw_int ? 4319 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 4320 msg->dcs_enabled = dcs_enabled; 4321 msg->signature = SPECTRAL_SIGNATURE; 4322 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4323 p_sops->get_mac_address(spectral, msg->macaddr); 4324 if (spectral->send_phy_data 4325 (pdev, 4326 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0) 4327 spectral->spectral_sent_msg++; 4328 } 4329 } 4330 qdf_export_symbol(target_if_spectral_send_intf_found_msg); 4331