1 /* 2 * Copyright (c) 2011,2017-2019 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_pdev_spectral_init() - Initialize target_if Spectral 2013 * functionality for the given pdev 2014 * @pdev: Pointer to pdev object 2015 * 2016 * Function to initialize pointer to spectral target_if internal private data 2017 * 2018 * Return: On success, pointer to Spectral target_if internal private data, on 2019 * failure, NULL 2020 */ 2021 void * 2022 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 2023 { 2024 struct target_if_spectral_ops *p_sops = NULL; 2025 struct target_if_spectral *spectral = NULL; 2026 uint32_t target_type; 2027 uint32_t target_revision; 2028 struct wlan_objmgr_psoc *psoc; 2029 struct wlan_lmac_if_target_tx_ops *tx_ops; 2030 enum spectral_scan_mode smode = SPECTRAL_SCAN_MODE_NORMAL; 2031 2032 if (!pdev) { 2033 spectral_err("SPECTRAL: pdev is NULL!"); 2034 return NULL; 2035 } 2036 spectral = (struct target_if_spectral *)qdf_mem_malloc( 2037 sizeof(struct target_if_spectral)); 2038 if (!spectral) 2039 return spectral; 2040 2041 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 2042 /* Store pdev in Spectral */ 2043 spectral->pdev_obj = pdev; 2044 2045 psoc = wlan_pdev_get_psoc(pdev); 2046 2047 tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; 2048 2049 if (tx_ops->tgt_get_tgt_type) { 2050 target_type = tx_ops->tgt_get_tgt_type(psoc); 2051 } else { 2052 qdf_mem_free(spectral); 2053 return NULL; 2054 } 2055 2056 if (tx_ops->tgt_get_tgt_revision) { 2057 target_revision = tx_ops->tgt_get_tgt_revision(psoc); 2058 } else { 2059 qdf_mem_free(spectral); 2060 return NULL; 2061 } 2062 2063 /* init the function ptr table */ 2064 target_if_spectral_init_dummy_function_table(spectral); 2065 2066 /* get spectral function table */ 2067 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2068 /* TODO : Should this be called here of after ath_attach ? */ 2069 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 2070 spectral_info("HAL_CAP_PHYDIAG : Capable"); 2071 2072 /* TODO: Need to fix the capablity check for RADAR */ 2073 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 2074 spectral_info("HAL_CAP_RADAR : Capable"); 2075 2076 /* TODO : Need to fix the capablity check for SPECTRAL */ 2077 /* TODO : Should this be called here of after ath_attach ? */ 2078 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 2079 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 2080 2081 qdf_spinlock_create(&spectral->spectral_lock); 2082 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 2083 target_if_spectral_clear_stats(spectral); 2084 2085 if (target_type == TARGET_TYPE_QCA8074 || 2086 target_type == TARGET_TYPE_QCA8074V2 || 2087 target_type == TARGET_TYPE_QCA6018 || 2088 target_type == TARGET_TYPE_QCA6390) 2089 spectral->direct_dma_support = true; 2090 2091 if (target_type == TARGET_TYPE_QCA8074V2) 2092 spectral->fftbin_size_war = 2093 SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE; 2094 else if (target_type == TARGET_TYPE_QCA8074 || 2095 target_type == TARGET_TYPE_QCA6018 || 2096 target_type == TARGET_TYPE_QCA6390) 2097 spectral->fftbin_size_war = 2098 SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE; 2099 else 2100 spectral->fftbin_size_war = SPECTRAL_FFTBIN_SIZE_NO_WAR; 2101 2102 if (target_type == TARGET_TYPE_QCA8074 || 2103 target_type == TARGET_TYPE_QCA8074V2 || 2104 target_type == TARGET_TYPE_QCA6018) { 2105 spectral->inband_fftbin_size_adj = 1; 2106 spectral->null_fftbin_adj = 1; 2107 } else { 2108 spectral->inband_fftbin_size_adj = 0; 2109 spectral->null_fftbin_adj = 0; 2110 } 2111 2112 if ((target_type == TARGET_TYPE_QCA8074) || 2113 (target_type == TARGET_TYPE_QCA8074V2) || 2114 (target_type == TARGET_TYPE_QCA6018) || 2115 (target_type == TARGET_TYPE_QCN9000) || 2116 (target_type == TARGET_TYPE_QCA6290) || 2117 (target_type == TARGET_TYPE_QCA6390)) { 2118 spectral->spectral_gen = SPECTRAL_GEN3; 2119 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 2120 spectral->tag_sscan_summary_exp = 2121 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 2122 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 2123 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 2124 spectral->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN3; 2125 spectral->fft_size_max = SPECTRAL_PARAM_FFT_SIZE_MAX_GEN3; 2126 } else { 2127 spectral->spectral_gen = SPECTRAL_GEN2; 2128 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 2129 spectral->tag_sscan_summary_exp = 2130 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 2131 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 2132 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 2133 spectral->fft_size_min = SPECTRAL_PARAM_FFT_SIZE_MIN_GEN2; 2134 spectral->fft_size_max = SPECTRAL_PARAM_FFT_SIZE_MAX_GEN2; 2135 } 2136 2137 target_if_init_spectral_param_properties(spectral); 2138 /* Init spectral capability */ 2139 if (target_if_init_spectral_capability(spectral) != 2140 QDF_STATUS_SUCCESS) { 2141 qdf_mem_free(spectral); 2142 return NULL; 2143 } 2144 if (target_if_spectral_attach_simulation(spectral) < 0) 2145 return NULL; 2146 2147 target_if_init_spectral_ops(spectral); 2148 2149 /* Spectral mode specific init */ 2150 spectral->target_reset_count = 0; 2151 for (; smode < SPECTRAL_SCAN_MODE_MAX; smode++) { 2152 spectral->last_fft_timestamp[smode] = 0; 2153 spectral->timestamp_war_offset[smode] = 0; 2154 spectral->params_valid[smode] = false; 2155 qdf_spinlock_create(&spectral->param_info[smode].osps_lock); 2156 spectral->param_info[smode].osps_cache.osc_is_valid = 0; 2157 } 2158 2159 target_if_spectral_register_funcs(spectral, &spectral_ops); 2160 2161 if (target_if_spectral_check_hw_capability(spectral) == false) { 2162 target_if_spectral_detach(spectral); 2163 spectral = NULL; 2164 } else { 2165 /* 2166 * TODO: Once the driver architecture transitions to chipset 2167 * versioning based checks, reflect this here. 2168 */ 2169 spectral->is_160_format = false; 2170 spectral->is_lb_edge_extrabins_format = false; 2171 spectral->is_rb_edge_extrabins_format = false; 2172 2173 if (target_type == TARGET_TYPE_QCA9984 || 2174 target_type == TARGET_TYPE_QCA9888) { 2175 spectral->is_160_format = true; 2176 spectral->is_lb_edge_extrabins_format = true; 2177 spectral->is_rb_edge_extrabins_format = true; 2178 } else if ((target_type == TARGET_TYPE_AR900B) && 2179 (target_revision == AR900B_REV_2)) { 2180 spectral->is_rb_edge_extrabins_format = true; 2181 } 2182 2183 if (target_type == TARGET_TYPE_QCA9984 || 2184 target_type == TARGET_TYPE_QCA9888) 2185 spectral->is_sec80_rssi_war_required = true; 2186 2187 spectral->use_nl_bcast = SPECTRAL_USE_NL_BCAST; 2188 2189 if (spectral->spectral_gen == SPECTRAL_GEN3) 2190 init_160mhz_delivery_state_machine(spectral); 2191 } 2192 2193 return spectral; 2194 } 2195 2196 /** 2197 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 2198 * functionality for the given pdev 2199 * @pdev: Pointer to pdev object 2200 * 2201 * Function to de-initialize pointer to spectral target_if internal private data 2202 * 2203 * Return: None 2204 */ 2205 void 2206 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 2207 { 2208 struct target_if_spectral *spectral = NULL; 2209 2210 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2211 if (!spectral) { 2212 spectral_err("SPECTRAL : Module doesn't exist"); 2213 return; 2214 } 2215 target_if_spectral_detach(spectral); 2216 2217 return; 2218 } 2219 2220 /* target_if_spectral_find_agile_width() - Given a channel width enum, find the 2221 * corresponding translation for Agile channel width. 2222 * Translation schema of different operating modes: 2223 * 20 -> 20, 40 -> 40, (80 & 160 & 80_80) -> 80. 2224 * @chwidth: Channel width enum. 2225 * 2226 * Return: The translated channel width enum. 2227 */ 2228 static enum phy_ch_width 2229 target_if_spectral_find_agile_width(enum phy_ch_width chwidth) 2230 { 2231 switch (chwidth) { 2232 case CH_WIDTH_20MHZ: 2233 return CH_WIDTH_20MHZ; 2234 case CH_WIDTH_40MHZ: 2235 return CH_WIDTH_40MHZ; 2236 case CH_WIDTH_80MHZ: 2237 case CH_WIDTH_80P80MHZ: 2238 case CH_WIDTH_160MHZ: 2239 return CH_WIDTH_80MHZ; 2240 default: 2241 spectral_err("Invalid chwidth enum %d", chwidth); 2242 return CH_WIDTH_INVALID; 2243 } 2244 } 2245 2246 /** 2247 * target_if_calculate_center_freq() - Helper routine to 2248 * check whether given frequency is center frequency of a 2249 * WLAN channel 2250 * 2251 * @spectral: Pointer to Spectral object 2252 * @chan_freq: Center frequency of a WLAN channel 2253 * @is_valid: Indicates whether given frequency is valid 2254 * 2255 * Return: QDF_STATUS 2256 */ 2257 static QDF_STATUS 2258 target_if_is_center_freq_of_any_chan(struct wlan_objmgr_pdev *pdev, 2259 uint32_t chan_freq, 2260 bool *is_valid) 2261 { 2262 struct regulatory_channel *cur_chan_list; 2263 int i; 2264 2265 if (!pdev) { 2266 spectral_err("pdev object is null"); 2267 return QDF_STATUS_E_FAILURE; 2268 } 2269 2270 if (!is_valid) { 2271 spectral_err("is valid argument is null"); 2272 return QDF_STATUS_E_FAILURE; 2273 } 2274 2275 cur_chan_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(*cur_chan_list)); 2276 if (!cur_chan_list) 2277 return QDF_STATUS_E_FAILURE; 2278 2279 if (wlan_reg_get_current_chan_list( 2280 pdev, cur_chan_list) != QDF_STATUS_SUCCESS) { 2281 spectral_err("Failed to get cur_chan list"); 2282 qdf_mem_free(cur_chan_list); 2283 return QDF_STATUS_E_FAILURE; 2284 } 2285 2286 *is_valid = false; 2287 for (i = 0; i < NUM_CHANNELS; i++) { 2288 uint32_t flags; 2289 uint32_t center_freq; 2290 2291 flags = cur_chan_list[i].chan_flags; 2292 center_freq = cur_chan_list[i].center_freq; 2293 2294 if (!(flags & REGULATORY_CHAN_DISABLED) && 2295 (center_freq == chan_freq)) { 2296 *is_valid = true; 2297 break; 2298 } 2299 } 2300 2301 qdf_mem_free(cur_chan_list); 2302 2303 return QDF_STATUS_SUCCESS; 2304 } 2305 2306 /** 2307 * target_if_calculate_center_freq() - Helper routine to 2308 * find the center frequency of the agile span from a 2309 * WLAN channel center frequency 2310 * 2311 * @spectral: Pointer to Spectral object 2312 * @chan_freq: Center frequency of a WLAN channel 2313 * @center_freq: Pointer to center frequency 2314 * 2315 * Return: QDF_STATUS 2316 */ 2317 static QDF_STATUS 2318 target_if_calculate_center_freq(struct target_if_spectral *spectral, 2319 uint16_t chan_freq, 2320 uint16_t *center_freq) 2321 { 2322 struct wlan_objmgr_vdev *vdev; 2323 enum phy_ch_width ch_width; 2324 enum phy_ch_width agile_ch_width; 2325 2326 if (!spectral) { 2327 spectral_err("spectral target if object is null"); 2328 return QDF_STATUS_E_FAILURE; 2329 } 2330 2331 if (!center_freq) { 2332 spectral_err("center_freq argument is null"); 2333 return QDF_STATUS_E_FAILURE; 2334 } 2335 2336 vdev = target_if_spectral_get_vdev(spectral); 2337 if (!vdev) { 2338 spectral_err("vdev is NULL"); 2339 return QDF_STATUS_E_FAILURE; 2340 } 2341 ch_width = target_if_vdev_get_ch_width(vdev); 2342 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2343 agile_ch_width = target_if_spectral_find_agile_width(ch_width); 2344 2345 if (agile_ch_width == CH_WIDTH_20MHZ) { 2346 *center_freq = chan_freq; 2347 } else { 2348 uint16_t start_freq; 2349 uint16_t end_freq; 2350 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2351 2352 wlan_reg_get_5g_bonded_channel_and_state_for_freq 2353 (spectral->pdev_obj, chan_freq, agile_ch_width, 2354 &bonded_chan_ptr); 2355 if (!bonded_chan_ptr) { 2356 spectral_err("Bonded channel is not found"); 2357 return QDF_STATUS_E_FAILURE; 2358 } 2359 start_freq = bonded_chan_ptr->start_freq; 2360 end_freq = bonded_chan_ptr->end_freq; 2361 *center_freq = (start_freq + end_freq) >> 1; 2362 } 2363 2364 return QDF_STATUS_SUCCESS; 2365 } 2366 2367 /** 2368 * target_if_validate_center_freq() - Helper routine to 2369 * validate user provided agile center frequency 2370 * 2371 * @spectral: Pointer to Spectral object 2372 * @center_freq: User provided agile span center frequency 2373 * @is_valid: Indicates whether agile span center frequency is valid 2374 * 2375 * Return: QDF_STATUS 2376 */ 2377 static QDF_STATUS 2378 target_if_validate_center_freq(struct target_if_spectral *spectral, 2379 uint16_t center_freq, 2380 bool *is_valid) 2381 { 2382 struct wlan_objmgr_vdev *vdev; 2383 enum phy_ch_width ch_width; 2384 enum phy_ch_width agile_ch_width; 2385 struct wlan_objmgr_pdev *pdev; 2386 QDF_STATUS status; 2387 2388 if (!spectral) { 2389 spectral_err("spectral target if object is null"); 2390 return QDF_STATUS_E_FAILURE; 2391 } 2392 2393 if (!is_valid) { 2394 spectral_err("is_valid argument is null"); 2395 return QDF_STATUS_E_FAILURE; 2396 } 2397 2398 pdev = spectral->pdev_obj; 2399 vdev = target_if_spectral_get_vdev(spectral); 2400 if (!vdev) { 2401 spectral_err("vdev is NULL"); 2402 return QDF_STATUS_E_FAILURE; 2403 } 2404 ch_width = target_if_vdev_get_ch_width(vdev); 2405 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2406 agile_ch_width = target_if_spectral_find_agile_width(ch_width); 2407 2408 if (agile_ch_width == CH_WIDTH_20MHZ) { 2409 status = target_if_is_center_freq_of_any_chan 2410 (pdev, center_freq, is_valid); 2411 if (QDF_IS_STATUS_ERROR(status)) 2412 return QDF_STATUS_E_FAILURE; 2413 } else { 2414 uint16_t start_freq; 2415 uint16_t end_freq; 2416 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2417 bool is_chan; 2418 2419 status = target_if_is_center_freq_of_any_chan 2420 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2421 &is_chan); 2422 if (QDF_IS_STATUS_ERROR(status)) 2423 return QDF_STATUS_E_FAILURE; 2424 2425 if (is_chan) { 2426 uint32_t calulated_center_freq; 2427 2428 wlan_reg_get_5g_bonded_channel_and_state_for_freq 2429 (pdev, center_freq + FREQ_OFFSET_10MHZ, 2430 agile_ch_width, 2431 &bonded_chan_ptr); 2432 if (!bonded_chan_ptr) { 2433 spectral_err("Bonded channel is not found"); 2434 return QDF_STATUS_E_FAILURE; 2435 } 2436 start_freq = bonded_chan_ptr->start_freq; 2437 end_freq = bonded_chan_ptr->end_freq; 2438 calulated_center_freq = (start_freq + end_freq) >> 1; 2439 *is_valid = (center_freq == calulated_center_freq); 2440 } else { 2441 *is_valid = false; 2442 } 2443 } 2444 2445 return QDF_STATUS_SUCCESS; 2446 } 2447 2448 /** 2449 * target_if_is_agile_span_overlap_with_operating_span() - Helper routine to 2450 * check whether agile span overlaps with current operating band. 2451 * 2452 * @spectral: Pointer to Spectral object 2453 * @ss_frequency: Agile span center frequency 2454 * @is_overlapping: Indicates whether Agile span overlaps with operating span 2455 * 2456 * Helper routine to check whether agile span overlaps with current 2457 * operating band. 2458 * 2459 * Return: QDF_STATUS 2460 */ 2461 static QDF_STATUS 2462 target_if_is_agile_span_overlap_with_operating_span 2463 (struct target_if_spectral *spectral, 2464 uint32_t ss_frequency, 2465 bool *is_overlapping) 2466 { 2467 enum phy_ch_width ch_width; 2468 enum phy_ch_width agile_ch_width; 2469 const struct bonded_channel_freq *bonded_chan_ptr = NULL; 2470 struct wlan_objmgr_vdev *vdev; 2471 struct wlan_objmgr_pdev *pdev; 2472 int16_t chan_freq; 2473 uint32_t op_start_freq; 2474 uint32_t op_end_freq; 2475 uint32_t agile_start_freq; 2476 uint32_t agile_end_freq; 2477 uint32_t cfreq2; 2478 2479 if (!spectral) { 2480 spectral_err("Spectral object is NULL"); 2481 return QDF_STATUS_E_FAILURE; 2482 } 2483 2484 pdev = spectral->pdev_obj; 2485 if (!pdev) { 2486 spectral_err("pdev object is NULL"); 2487 return QDF_STATUS_E_FAILURE; 2488 } 2489 2490 if (!is_overlapping) { 2491 spectral_err("Argument(is_overlapping) is NULL"); 2492 return QDF_STATUS_E_FAILURE; 2493 } 2494 2495 vdev = target_if_spectral_get_vdev(spectral); 2496 if (!vdev) { 2497 spectral_err("vdev is NULL"); 2498 return QDF_STATUS_E_FAILURE; 2499 } 2500 ch_width = target_if_vdev_get_ch_width(vdev); 2501 chan_freq = target_if_vdev_get_chan_freq(vdev); 2502 cfreq2 = target_if_vdev_get_chan_freq_seg2(vdev); 2503 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2504 if (cfreq2 < 0) 2505 return QDF_STATUS_E_FAILURE; 2506 2507 if (ch_width == CH_WIDTH_20MHZ) { 2508 op_start_freq = chan_freq - FREQ_OFFSET_10MHZ; 2509 op_end_freq = chan_freq + FREQ_OFFSET_10MHZ; 2510 } else { 2511 wlan_reg_get_5g_bonded_channel_and_state_for_freq 2512 (pdev, chan_freq, ch_width, &bonded_chan_ptr); 2513 if (!bonded_chan_ptr) { 2514 spectral_err("Bonded channel is not found"); 2515 return QDF_STATUS_E_FAILURE; 2516 } 2517 op_start_freq = bonded_chan_ptr->start_freq - FREQ_OFFSET_10MHZ; 2518 op_end_freq = bonded_chan_ptr->end_freq - FREQ_OFFSET_10MHZ; 2519 } 2520 2521 agile_ch_width = target_if_spectral_find_agile_width(ch_width); 2522 if (agile_ch_width == CH_WIDTH_INVALID) 2523 return QDF_STATUS_E_FAILURE; 2524 agile_start_freq = ss_frequency - 2525 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2526 agile_end_freq = ss_frequency + 2527 (wlan_reg_get_bw_value(agile_ch_width) >> 1); 2528 if (agile_end_freq <= op_start_freq || op_end_freq <= agile_start_freq) 2529 *is_overlapping = false; 2530 else 2531 *is_overlapping = true; 2532 2533 /* Use non zero cfreq2 to identify 80p80 */ 2534 if (cfreq2) { 2535 uint32_t sec80_start_feq; 2536 uint32_t sec80_end_freq; 2537 2538 sec80_start_feq = cfreq2 - 40; 2539 sec80_end_freq = cfreq2 + 40; 2540 2541 if ((agile_end_freq > sec80_start_feq) && 2542 (sec80_end_freq > agile_start_freq)) 2543 *is_overlapping = true; 2544 } 2545 2546 return QDF_STATUS_SUCCESS; 2547 } 2548 2549 /** 2550 * _target_if_set_spectral_config() - Set spectral config 2551 * @spectral: Pointer to spectral object 2552 * @threshtype: config type 2553 * @value: config value 2554 * @smode: Spectral scan mode 2555 * @err: Spectral error code 2556 * 2557 * API to set spectral configurations 2558 * 2559 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 2560 */ 2561 static QDF_STATUS 2562 _target_if_set_spectral_config(struct target_if_spectral *spectral, 2563 const uint32_t threshtype, const uint32_t value, 2564 const enum spectral_scan_mode smode, 2565 enum spectral_cp_error_code *err) 2566 { 2567 struct spectral_config params; 2568 struct target_if_spectral_ops *p_sops; 2569 struct spectral_config *sparams; 2570 QDF_STATUS status; 2571 bool is_overlapping; 2572 uint16_t agile_cfreq; 2573 bool is_valid_chan; 2574 2575 if (!err) { 2576 spectral_err("Error code argument is null"); 2577 QDF_ASSERT(0); 2578 } 2579 *err = SPECTRAL_SCAN_ERR_INVALID; 2580 2581 if (!spectral) { 2582 spectral_err("spectral object is NULL"); 2583 return QDF_STATUS_E_FAILURE; 2584 } 2585 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2586 2587 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2588 spectral_err("Invalid Spectral mode %u", smode); 2589 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 2590 return QDF_STATUS_E_FAILURE; 2591 } 2592 2593 sparams = &spectral->params[smode]; 2594 2595 if (!spectral->params_valid[smode]) { 2596 target_if_spectral_info_read(spectral, 2597 smode, 2598 TARGET_IF_SPECTRAL_INFO_PARAMS, 2599 &spectral->params[smode], 2600 sizeof(spectral->params[smode])); 2601 spectral->params_valid[smode] = true; 2602 } 2603 2604 switch (threshtype) { 2605 case SPECTRAL_PARAM_FFT_PERIOD: 2606 sparams->ss_fft_period = value; 2607 break; 2608 case SPECTRAL_PARAM_SCAN_PERIOD: 2609 sparams->ss_period = value; 2610 break; 2611 case SPECTRAL_PARAM_SCAN_COUNT: 2612 sparams->ss_count = value; 2613 break; 2614 case SPECTRAL_PARAM_SHORT_REPORT: 2615 sparams->ss_short_report = (!!value) ? true : false; 2616 break; 2617 case SPECTRAL_PARAM_SPECT_PRI: 2618 sparams->ss_spectral_pri = (!!value) ? true : false; 2619 break; 2620 case SPECTRAL_PARAM_FFT_SIZE: 2621 if ((value < spectral->fft_size_min) || 2622 (value > spectral->fft_size_max)) { 2623 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2624 return QDF_STATUS_E_FAILURE; 2625 } 2626 sparams->ss_fft_size = value; 2627 break; 2628 case SPECTRAL_PARAM_GC_ENA: 2629 sparams->ss_gc_ena = !!value; 2630 break; 2631 case SPECTRAL_PARAM_RESTART_ENA: 2632 sparams->ss_restart_ena = !!value; 2633 break; 2634 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 2635 sparams->ss_noise_floor_ref = value; 2636 break; 2637 case SPECTRAL_PARAM_INIT_DELAY: 2638 sparams->ss_init_delay = value; 2639 break; 2640 case SPECTRAL_PARAM_NB_TONE_THR: 2641 sparams->ss_nb_tone_thr = value; 2642 break; 2643 case SPECTRAL_PARAM_STR_BIN_THR: 2644 sparams->ss_str_bin_thr = value; 2645 break; 2646 case SPECTRAL_PARAM_WB_RPT_MODE: 2647 sparams->ss_wb_rpt_mode = !!value; 2648 break; 2649 case SPECTRAL_PARAM_RSSI_RPT_MODE: 2650 sparams->ss_rssi_rpt_mode = !!value; 2651 break; 2652 case SPECTRAL_PARAM_RSSI_THR: 2653 sparams->ss_rssi_thr = value; 2654 break; 2655 case SPECTRAL_PARAM_PWR_FORMAT: 2656 sparams->ss_pwr_format = !!value; 2657 break; 2658 case SPECTRAL_PARAM_RPT_MODE: 2659 if ((value < SPECTRAL_PARAM_RPT_MODE_MIN) || 2660 (value > SPECTRAL_PARAM_RPT_MODE_MAX)) { 2661 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2662 return QDF_STATUS_E_FAILURE; 2663 } 2664 sparams->ss_rpt_mode = value; 2665 break; 2666 case SPECTRAL_PARAM_BIN_SCALE: 2667 sparams->ss_bin_scale = value; 2668 break; 2669 case SPECTRAL_PARAM_DBM_ADJ: 2670 sparams->ss_dbm_adj = !!value; 2671 break; 2672 case SPECTRAL_PARAM_CHN_MASK: 2673 sparams->ss_chn_mask = value; 2674 break; 2675 case SPECTRAL_PARAM_FREQUENCY: 2676 status = target_if_is_center_freq_of_any_chan 2677 (spectral->pdev_obj, value, &is_valid_chan); 2678 if (QDF_IS_STATUS_ERROR(status)) 2679 return QDF_STATUS_E_FAILURE; 2680 2681 if (is_valid_chan) { 2682 status = target_if_calculate_center_freq(spectral, 2683 value, 2684 &agile_cfreq); 2685 if (QDF_IS_STATUS_ERROR(status)) { 2686 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2687 return QDF_STATUS_E_FAILURE; 2688 } 2689 } else { 2690 bool is_valid_agile_cfreq; 2691 2692 status = target_if_validate_center_freq 2693 (spectral, value, &is_valid_agile_cfreq); 2694 if (QDF_IS_STATUS_ERROR(status)) 2695 return QDF_STATUS_E_FAILURE; 2696 2697 if (!is_valid_agile_cfreq) { 2698 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2699 spectral_err("Invalid agile center frequency"); 2700 return QDF_STATUS_E_FAILURE; 2701 } 2702 2703 agile_cfreq = value; 2704 } 2705 2706 status = target_if_is_agile_span_overlap_with_operating_span 2707 (spectral, agile_cfreq, &is_overlapping); 2708 if (QDF_IS_STATUS_ERROR(status)) 2709 return QDF_STATUS_E_FAILURE; 2710 2711 if (is_overlapping) { 2712 spectral_err("Agile span overlapping with current BW"); 2713 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 2714 return QDF_STATUS_E_FAILURE; 2715 } 2716 sparams->ss_frequency = agile_cfreq; 2717 break; 2718 } 2719 2720 p_sops->configure_spectral(spectral, sparams, smode); 2721 /* only to validate the writes */ 2722 p_sops->get_spectral_config(spectral, ¶ms, smode); 2723 return QDF_STATUS_SUCCESS; 2724 } 2725 2726 QDF_STATUS 2727 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 2728 const uint32_t threshtype, const uint32_t value, 2729 const enum spectral_scan_mode smode, 2730 enum spectral_cp_error_code *err) 2731 { 2732 enum spectral_scan_mode mode = SPECTRAL_SCAN_MODE_NORMAL; 2733 struct target_if_spectral *spectral; 2734 QDF_STATUS status; 2735 2736 if (!err) { 2737 spectral_err("Error code argument is null"); 2738 QDF_ASSERT(0); 2739 } 2740 *err = SPECTRAL_SCAN_ERR_INVALID; 2741 2742 if (!pdev) { 2743 spectral_err("pdev object is NULL"); 2744 return QDF_STATUS_E_FAILURE; 2745 } 2746 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2747 if (!spectral) { 2748 spectral_err("spectral object is NULL"); 2749 return QDF_STATUS_E_FAILURE; 2750 } 2751 2752 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2753 spectral_err("Invalid Spectral mode %u", smode); 2754 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 2755 return QDF_STATUS_E_FAILURE; 2756 } 2757 2758 if (!spectral->properties[smode][threshtype].supported) { 2759 spectral_err("Spectral parameter(%u) unsupported for mode %u", 2760 threshtype, smode); 2761 *err = SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED; 2762 return QDF_STATUS_E_FAILURE; 2763 } 2764 2765 if (spectral->properties[smode][threshtype].common_all_modes) { 2766 spectral_warn("Setting Spectral parameter %u for all modes", 2767 threshtype); 2768 for (; mode < SPECTRAL_SCAN_MODE_MAX; mode++) { 2769 status = _target_if_set_spectral_config 2770 (spectral, threshtype, value, 2771 mode, err); 2772 if (QDF_IS_STATUS_ERROR(status)) 2773 return QDF_STATUS_E_FAILURE; 2774 } 2775 return QDF_STATUS_SUCCESS; 2776 } 2777 2778 return _target_if_set_spectral_config(spectral, threshtype, 2779 value, smode, err); 2780 } 2781 2782 /** 2783 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 2784 * @fft_len: FFT length 2785 * @pdev: Pointer to pdev object 2786 * 2787 * API to get fft bin count for a given fft length 2788 * 2789 * Return: FFt bin count 2790 */ 2791 static int 2792 target_if_get_fft_bin_count(int fft_len) 2793 { 2794 int bin_count = 0; 2795 2796 switch (fft_len) { 2797 case 5: 2798 bin_count = 16; 2799 break; 2800 case 6: 2801 bin_count = 32; 2802 break; 2803 case 7: 2804 bin_count = 64; 2805 break; 2806 case 8: 2807 bin_count = 128; 2808 break; 2809 case 9: 2810 bin_count = 256; 2811 break; 2812 default: 2813 break; 2814 } 2815 2816 return bin_count; 2817 } 2818 2819 /** 2820 * target_if_init_upper_lower_flags() - Initializes control and extension 2821 * segment flags 2822 * @fft_len: FFT length 2823 * @pdev: Pointer to pdev object 2824 * 2825 * API to initialize the control and extension flags with the lower/upper 2826 * segment based on the HT mode 2827 * 2828 * Return: FFt bin count 2829 */ 2830 static void 2831 target_if_init_upper_lower_flags(struct target_if_spectral *spectral) 2832 { 2833 int current_channel = 0; 2834 int ext_channel = 0; 2835 struct target_if_spectral_ops *p_sops = 2836 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2837 2838 current_channel = p_sops->get_current_channel(spectral); 2839 ext_channel = p_sops->get_extension_channel(spectral); 2840 2841 if ((current_channel == 0) || (ext_channel == 0)) 2842 return; 2843 2844 if (spectral->sc_spectral_20_40_mode) { 2845 /* HT40 mode */ 2846 if (ext_channel < current_channel) { 2847 spectral->lower_is_extension = 1; 2848 spectral->upper_is_control = 1; 2849 spectral->lower_is_control = 0; 2850 spectral->upper_is_extension = 0; 2851 } else { 2852 spectral->lower_is_extension = 0; 2853 spectral->upper_is_control = 0; 2854 spectral->lower_is_control = 1; 2855 spectral->upper_is_extension = 1; 2856 } 2857 } else { 2858 /* HT20 mode, lower is always control */ 2859 spectral->lower_is_extension = 0; 2860 spectral->upper_is_control = 0; 2861 spectral->lower_is_control = 1; 2862 spectral->upper_is_extension = 0; 2863 } 2864 } 2865 2866 /** 2867 * target_if_get_spectral_config() - Get spectral configuration 2868 * @pdev: Pointer to pdev object 2869 * @param: Pointer to spectral_config structure in which the configuration 2870 * should be returned 2871 * @smode: Spectral scan mode 2872 * 2873 * API to get the current spectral configuration 2874 * 2875 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 2876 */ 2877 QDF_STATUS 2878 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 2879 struct spectral_config *param, 2880 enum spectral_scan_mode smode) 2881 { 2882 struct target_if_spectral_ops *p_sops = NULL; 2883 struct target_if_spectral *spectral = NULL; 2884 2885 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2886 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2887 2888 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2889 spectral_err("Invalid Spectral mode %u", smode); 2890 return QDF_STATUS_E_FAILURE; 2891 } 2892 2893 qdf_mem_zero(param, sizeof(struct spectral_config)); 2894 p_sops->get_spectral_config(spectral, param, smode); 2895 2896 return QDF_STATUS_SUCCESS; 2897 } 2898 2899 /** 2900 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 2901 * parameters 2902 * @spectral: Pointer to Spectral target_if internal private data 2903 * @spectral_params: Pointer to Spectral parameters 2904 * @smode: Spectral scan mode 2905 * @err: Spectral error code 2906 * 2907 * Enable use of desired Spectral parameters by configuring them into HW, and 2908 * starting Spectral scan 2909 * 2910 * Return: 0 on success, 1 on failure 2911 */ 2912 int 2913 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 2914 struct spectral_config *spectral_params, 2915 enum spectral_scan_mode smode, 2916 enum spectral_cp_error_code *err) 2917 { 2918 int extension_channel = 0; 2919 int current_channel = 0; 2920 struct target_if_spectral_ops *p_sops = NULL; 2921 struct wlan_objmgr_vdev *vdev = NULL; 2922 2923 if (!spectral) { 2924 spectral_err("Spectral LMAC object is NULL"); 2925 return 1; 2926 } 2927 2928 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 2929 spectral_err("Invalid Spectral mode %u", smode); 2930 return 1; 2931 } 2932 2933 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2934 2935 if (!p_sops) { 2936 spectral_err("p_sops is NULL"); 2937 return 1; 2938 } 2939 2940 spectral->sc_spectral_noise_pwr_cal = 2941 spectral_params->ss_spectral_pri ? 1 : 0; 2942 2943 /* check if extension channel is present */ 2944 extension_channel = p_sops->get_extension_channel(spectral); 2945 current_channel = p_sops->get_current_channel(spectral); 2946 2947 vdev = target_if_spectral_get_vdev(spectral); 2948 if (!vdev) 2949 return 1; 2950 2951 spectral->ch_width = target_if_vdev_get_ch_width(vdev); 2952 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2953 2954 if (spectral->ch_width == CH_WIDTH_INVALID) 2955 return 1; 2956 2957 spectral->agile_ch_width = 2958 target_if_spectral_find_agile_width(spectral->ch_width); 2959 2960 if (spectral->capability.advncd_spectral_cap) { 2961 spectral->lb_edge_extrabins = 0; 2962 spectral->rb_edge_extrabins = 0; 2963 2964 if (spectral->is_lb_edge_extrabins_format && 2965 spectral->params[smode].ss_rpt_mode == 2) { 2966 spectral->lb_edge_extrabins = 4; 2967 } 2968 2969 if (spectral->is_rb_edge_extrabins_format && 2970 spectral->params[smode].ss_rpt_mode == 2) { 2971 spectral->rb_edge_extrabins = 4; 2972 } 2973 2974 if (spectral->ch_width == CH_WIDTH_20MHZ) { 2975 spectral->sc_spectral_20_40_mode = 0; 2976 2977 spectral->spectral_numbins = 2978 target_if_get_fft_bin_count( 2979 spectral->params[smode].ss_fft_size); 2980 spectral->spectral_fft_len = 2981 target_if_get_fft_bin_count( 2982 spectral->params[smode].ss_fft_size); 2983 spectral->spectral_data_len = 2984 target_if_get_fft_bin_count( 2985 spectral->params[smode].ss_fft_size); 2986 /* 2987 * Initialize classifier params to be sent to user 2988 * space classifier 2989 */ 2990 spectral->classifier_params.lower_chan_in_mhz = 2991 current_channel; 2992 spectral->classifier_params.upper_chan_in_mhz = 0; 2993 2994 } else if (spectral->ch_width == CH_WIDTH_40MHZ) { 2995 /* TODO : Remove this variable */ 2996 spectral->sc_spectral_20_40_mode = 1; 2997 spectral->spectral_numbins = 2998 target_if_get_fft_bin_count( 2999 spectral->params[smode].ss_fft_size); 3000 spectral->spectral_fft_len = 3001 target_if_get_fft_bin_count( 3002 spectral->params[smode].ss_fft_size); 3003 spectral->spectral_data_len = 3004 target_if_get_fft_bin_count( 3005 spectral->params[smode].ss_fft_size); 3006 3007 /* 3008 * Initialize classifier params to be sent to user 3009 * space classifier 3010 */ 3011 if (extension_channel < current_channel) { 3012 spectral->classifier_params.lower_chan_in_mhz = 3013 extension_channel; 3014 spectral->classifier_params.upper_chan_in_mhz = 3015 current_channel; 3016 } else { 3017 spectral->classifier_params.lower_chan_in_mhz = 3018 current_channel; 3019 spectral->classifier_params.upper_chan_in_mhz = 3020 extension_channel; 3021 } 3022 3023 } else if (spectral->ch_width == CH_WIDTH_80MHZ) { 3024 /* Set the FFT Size */ 3025 /* TODO : Remove this variable */ 3026 spectral->sc_spectral_20_40_mode = 0; 3027 spectral->spectral_numbins = 3028 target_if_get_fft_bin_count( 3029 spectral->params[smode].ss_fft_size); 3030 spectral->spectral_fft_len = 3031 target_if_get_fft_bin_count( 3032 spectral->params[smode].ss_fft_size); 3033 spectral->spectral_data_len = 3034 target_if_get_fft_bin_count( 3035 spectral->params[smode].ss_fft_size); 3036 3037 /* 3038 * Initialize classifier params to be sent to user 3039 * space classifier 3040 */ 3041 spectral->classifier_params.lower_chan_in_mhz = 3042 current_channel; 3043 spectral->classifier_params.upper_chan_in_mhz = 0; 3044 3045 /* 3046 * Initialize classifier params to be sent to user 3047 * space classifier 3048 */ 3049 if (extension_channel < current_channel) { 3050 spectral->classifier_params.lower_chan_in_mhz = 3051 extension_channel; 3052 spectral->classifier_params.upper_chan_in_mhz = 3053 current_channel; 3054 } else { 3055 spectral->classifier_params.lower_chan_in_mhz = 3056 current_channel; 3057 spectral->classifier_params.upper_chan_in_mhz = 3058 extension_channel; 3059 } 3060 3061 } else if (spectral->ch_width == CH_WIDTH_160MHZ) { 3062 /* Set the FFT Size */ 3063 3064 /* The below applies to both 160 and 80+80 cases */ 3065 3066 /* TODO : Remove this variable */ 3067 spectral->sc_spectral_20_40_mode = 0; 3068 spectral->spectral_numbins = 3069 target_if_get_fft_bin_count( 3070 spectral->params[smode].ss_fft_size); 3071 spectral->spectral_fft_len = 3072 target_if_get_fft_bin_count( 3073 spectral->params[smode].ss_fft_size); 3074 spectral->spectral_data_len = 3075 target_if_get_fft_bin_count( 3076 spectral->params[smode].ss_fft_size); 3077 3078 /* 3079 * Initialize classifier params to be sent to user 3080 * space classifier 3081 */ 3082 spectral->classifier_params.lower_chan_in_mhz = 3083 current_channel; 3084 spectral->classifier_params.upper_chan_in_mhz = 0; 3085 3086 /* 3087 * Initialize classifier params to be sent to user 3088 * space classifier 3089 */ 3090 if (extension_channel < current_channel) { 3091 spectral->classifier_params.lower_chan_in_mhz = 3092 extension_channel; 3093 spectral->classifier_params.upper_chan_in_mhz = 3094 current_channel; 3095 } else { 3096 spectral->classifier_params.lower_chan_in_mhz = 3097 current_channel; 3098 spectral->classifier_params.upper_chan_in_mhz = 3099 extension_channel; 3100 } 3101 } 3102 3103 if (spectral->spectral_numbins) { 3104 spectral->spectral_numbins += 3105 spectral->lb_edge_extrabins; 3106 spectral->spectral_numbins += 3107 spectral->rb_edge_extrabins; 3108 } 3109 3110 if (spectral->spectral_fft_len) { 3111 spectral->spectral_fft_len += 3112 spectral->lb_edge_extrabins; 3113 spectral->spectral_fft_len += 3114 spectral->rb_edge_extrabins; 3115 } 3116 3117 if (spectral->spectral_data_len) { 3118 spectral->spectral_data_len += 3119 spectral->lb_edge_extrabins; 3120 spectral->spectral_data_len += 3121 spectral->rb_edge_extrabins; 3122 } 3123 } else { 3124 /* 3125 * The decision to find 20/40 mode is found based on the 3126 * presence of extension channel 3127 * instead of channel width, as the channel width can 3128 * dynamically change 3129 */ 3130 3131 if (extension_channel == 0) { 3132 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 3133 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 3134 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 3135 spectral->spectral_data_len = 3136 SPECTRAL_HT20_TOTAL_DATA_LEN; 3137 /* only valid in 20-40 mode */ 3138 spectral->spectral_lower_max_index_offset = -1; 3139 /* only valid in 20-40 mode */ 3140 spectral->spectral_upper_max_index_offset = -1; 3141 spectral->spectral_max_index_offset = 3142 spectral->spectral_fft_len + 2; 3143 spectral->sc_spectral_20_40_mode = 0; 3144 3145 /* 3146 * Initialize classifier params to be sent to user 3147 * space classifier 3148 */ 3149 spectral->classifier_params.lower_chan_in_mhz = 3150 current_channel; 3151 spectral->classifier_params.upper_chan_in_mhz = 0; 3152 3153 } else { 3154 spectral->spectral_numbins = 3155 SPECTRAL_HT40_TOTAL_NUM_BINS; 3156 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 3157 spectral->spectral_data_len = 3158 SPECTRAL_HT40_TOTAL_DATA_LEN; 3159 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 3160 /* only valid in 20 mode */ 3161 spectral->spectral_max_index_offset = -1; 3162 spectral->spectral_lower_max_index_offset = 3163 spectral->spectral_fft_len + 2; 3164 spectral->spectral_upper_max_index_offset = 3165 spectral->spectral_fft_len + 5; 3166 spectral->sc_spectral_20_40_mode = 1; 3167 3168 /* 3169 * Initialize classifier params to be sent to user 3170 * space classifier 3171 */ 3172 if (extension_channel < current_channel) { 3173 spectral->classifier_params.lower_chan_in_mhz = 3174 extension_channel; 3175 spectral->classifier_params.upper_chan_in_mhz = 3176 current_channel; 3177 } else { 3178 spectral->classifier_params.lower_chan_in_mhz = 3179 current_channel; 3180 spectral->classifier_params.upper_chan_in_mhz = 3181 extension_channel; 3182 } 3183 } 3184 } 3185 3186 spectral->send_single_packet = 0; 3187 spectral->classifier_params.spectral_20_40_mode = 3188 spectral->sc_spectral_20_40_mode; 3189 spectral->classifier_params.spectral_dc_index = 3190 spectral->spectral_dc_index; 3191 spectral->spectral_sent_msg = 0; 3192 spectral->classify_scan = 0; 3193 spectral->num_spectral_data = 0; 3194 3195 if (!p_sops->is_spectral_active(spectral, smode)) { 3196 p_sops->configure_spectral(spectral, spectral_params, smode); 3197 p_sops->start_spectral_scan(spectral, smode, err); 3198 spectral->timestamp_war_offset[smode] = 0; 3199 spectral->last_fft_timestamp[smode] = 0; 3200 } 3201 3202 /* get current spectral configuration */ 3203 p_sops->get_spectral_config(spectral, &spectral->params[smode], smode); 3204 3205 target_if_init_upper_lower_flags(spectral); 3206 3207 return 0; 3208 } 3209 3210 /** 3211 * target_if_is_aspectral_prohibited_by_adfs() - Is Agile Spectral prohibited by 3212 * Agile DFS 3213 * @psoc: Pointer to psoc 3214 * @object: Pointer to pdev 3215 * @arg: Pointer to flag which indicates whether Agile Spectral is prohibited 3216 * 3217 * This API checks whether Agile DFS is running on any of the pdevs. If so, it 3218 * indicates that Agile Spectral scan is prohibited by Agile DFS. 3219 * 3220 * Return: void 3221 */ 3222 static void 3223 target_if_is_aspectral_prohibited_by_adfs(struct wlan_objmgr_psoc *psoc, 3224 void *object, void *arg) 3225 { 3226 bool *is_aspectral_prohibited = arg; 3227 struct wlan_objmgr_pdev *cur_pdev = object; 3228 bool is_agile_dfs_enabled_cur_pdev = false; 3229 QDF_STATUS status; 3230 3231 qdf_assert_always(is_aspectral_prohibited); 3232 if (*is_aspectral_prohibited) 3233 return; 3234 3235 qdf_assert_always(psoc); 3236 qdf_assert_always(cur_pdev); 3237 3238 status = ucfg_dfs_get_agile_precac_enable 3239 (cur_pdev, 3240 &is_agile_dfs_enabled_cur_pdev); 3241 if (QDF_IS_STATUS_ERROR(status)) { 3242 spectral_err("Get agile precac failed, prohibiting aSpectral"); 3243 *is_aspectral_prohibited = true; 3244 return; 3245 } 3246 3247 if (is_agile_dfs_enabled_cur_pdev) { 3248 spectral_err("aDFS is in progress on one of the pdevs"); 3249 *is_aspectral_prohibited = true; 3250 } 3251 } 3252 3253 /** 3254 * target_if_get_curr_band() - Get current operating band of pdev 3255 * 3256 * @spectral: pointer to spectral object 3257 * 3258 * API to get current operating band of a given pdev. 3259 * 3260 * Return: if success enum reg_wifi_band, REG_BAND_UNKNOWN in case of failure 3261 */ 3262 static enum reg_wifi_band 3263 target_if_get_curr_band(struct wlan_objmgr_pdev *pdev) 3264 { 3265 struct wlan_objmgr_vdev *vdev; 3266 int16_t chan_freq; 3267 enum reg_wifi_band cur_band; 3268 3269 if (!pdev) { 3270 spectral_err("pdev is NULL"); 3271 return REG_BAND_UNKNOWN; 3272 } 3273 3274 vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID); 3275 if (!vdev) { 3276 spectral_debug("vdev is NULL"); 3277 return REG_BAND_UNKNOWN; 3278 } 3279 chan_freq = target_if_vdev_get_chan_freq(vdev); 3280 cur_band = wlan_reg_freq_to_band(chan_freq); 3281 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3282 3283 return cur_band; 3284 } 3285 3286 /** 3287 * target_if_is_agile_scan_active_in_5g() - Is Agile Spectral scan active on 3288 * any of the 5G pdevs 3289 * @psoc: Pointer to psoc 3290 * @object: Pointer to pdev 3291 * @arg: Pointer to flag which indicates whether Agile Spectral scan is in 3292 * progress in any 5G pdevs 3293 * 3294 * Return: void 3295 */ 3296 static void 3297 target_if_is_agile_scan_active_in_5g(struct wlan_objmgr_psoc *psoc, 3298 void *object, void *arg) 3299 { 3300 enum reg_wifi_band band; 3301 bool *is_agile_scan_inprog_5g_pdev = arg; 3302 struct target_if_spectral *spectral; 3303 struct wlan_objmgr_pdev *cur_pdev = object; 3304 struct target_if_spectral_ops *p_sops; 3305 3306 if (*is_agile_scan_inprog_5g_pdev) 3307 return; 3308 3309 spectral = get_target_if_spectral_handle_from_pdev(cur_pdev); 3310 if (!spectral) { 3311 spectral_err("target if spectral handle is NULL"); 3312 return; 3313 } 3314 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3315 3316 band = target_if_get_curr_band(cur_pdev); 3317 if (band == REG_BAND_UNKNOWN) { 3318 spectral_debug("Failed to get current band"); 3319 return; 3320 } 3321 3322 if (band == REG_BAND_5G && 3323 p_sops->is_spectral_active(spectral, SPECTRAL_SCAN_MODE_AGILE)) 3324 *is_agile_scan_inprog_5g_pdev = true; 3325 } 3326 3327 /** 3328 * target_if_is_agile_supported_cur_chmask() - Is Agile Spectral scan supported 3329 * for current vdev rx chainmask. 3330 * 3331 * @spectral: Pointer to Spectral object 3332 * @is_supported: Pointer to is_supported 3333 * 3334 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3335 */ 3336 static QDF_STATUS 3337 target_if_is_agile_supported_cur_chmask(struct target_if_spectral *spectral, 3338 bool *is_supported) 3339 { 3340 struct wlan_objmgr_vdev *vdev; 3341 uint8_t vdev_rxchainmask; 3342 struct wlan_objmgr_psoc *psoc; 3343 struct wlan_objmgr_pdev *pdev; 3344 struct target_psoc_info *tgt_psoc_info; 3345 struct wlan_psoc_host_service_ext_param *ext_svc_param; 3346 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr = NULL; 3347 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap = NULL; 3348 struct wlan_psoc_host_chainmask_table *table; 3349 int j; 3350 uint32_t table_id; 3351 enum phy_ch_width ch_width; 3352 uint8_t pdev_id; 3353 3354 if (!spectral) { 3355 spectral_err("spectral target if object is null"); 3356 return QDF_STATUS_E_FAILURE; 3357 } 3358 3359 if (!is_supported) { 3360 spectral_err("is supported argument is null"); 3361 return QDF_STATUS_E_FAILURE; 3362 } 3363 3364 if (spectral->spectral_gen <= SPECTRAL_GEN2) { 3365 spectral_err("HW Agile mode is not supported up to gen 2"); 3366 return QDF_STATUS_E_FAILURE; 3367 } 3368 3369 pdev = spectral->pdev_obj; 3370 if (!pdev) { 3371 spectral_err("pdev is null"); 3372 return QDF_STATUS_E_FAILURE; 3373 } 3374 3375 psoc = wlan_pdev_get_psoc(pdev); 3376 if (!psoc) { 3377 spectral_err("psoc is null"); 3378 return QDF_STATUS_E_FAILURE; 3379 } 3380 3381 vdev = target_if_spectral_get_vdev(spectral); 3382 if (!vdev) { 3383 spectral_err("First vdev is NULL"); 3384 return QDF_STATUS_E_FAILURE; 3385 } 3386 3387 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 3388 if (!vdev_rxchainmask) { 3389 spectral_err("vdev rx chainmask is zero"); 3390 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3391 return QDF_STATUS_E_FAILURE; 3392 } 3393 3394 ch_width = target_if_vdev_get_ch_width(vdev); 3395 if (ch_width == CH_WIDTH_INVALID) { 3396 spectral_err("Invalid channel width"); 3397 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3398 return QDF_STATUS_E_FAILURE; 3399 } 3400 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 3401 3402 tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 3403 if (!tgt_psoc_info) { 3404 spectral_err("target_psoc_info is null"); 3405 return QDF_STATUS_E_FAILURE; 3406 } 3407 3408 ext_svc_param = target_psoc_get_service_ext_param(tgt_psoc_info); 3409 if (!ext_svc_param) { 3410 spectral_err("Extended service ready param null"); 3411 return QDF_STATUS_E_FAILURE; 3412 } 3413 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 3414 3415 mac_phy_cap_arr = target_psoc_get_mac_phy_cap(tgt_psoc_info); 3416 if (!mac_phy_cap_arr) { 3417 spectral_err("mac phy cap array is null"); 3418 return QDF_STATUS_E_FAILURE; 3419 } 3420 3421 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 3422 if (!mac_phy_cap) { 3423 spectral_err("mac phy cap is null"); 3424 return QDF_STATUS_E_FAILURE; 3425 } 3426 3427 table_id = mac_phy_cap->chainmask_table_id; 3428 table = &ext_svc_param->chainmask_table[table_id]; 3429 if (!table) { 3430 spectral_err("chainmask table not found"); 3431 return QDF_STATUS_E_FAILURE; 3432 } 3433 3434 for (j = 0; j < table->num_valid_chainmasks; j++) { 3435 if (table->cap_list[j].chainmask == vdev_rxchainmask) { 3436 if (ch_width <= CH_WIDTH_80MHZ) 3437 *is_supported = 3438 table->cap_list[j].supports_aSpectral; 3439 else 3440 *is_supported = 3441 table->cap_list[j].supports_aSpectral_160; 3442 break; 3443 } 3444 } 3445 3446 if (j == table->num_valid_chainmasks) { 3447 spectral_err("vdev rx chainmask %u not found in table id = %u", 3448 vdev_rxchainmask, table_id); 3449 return QDF_STATUS_E_FAILURE; 3450 } 3451 3452 return QDF_STATUS_SUCCESS; 3453 } 3454 3455 QDF_STATUS 3456 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev, 3457 const enum spectral_scan_mode smode, 3458 enum spectral_cp_error_code *err) 3459 { 3460 struct target_if_spectral_ops *p_sops; 3461 struct target_if_spectral *spectral; 3462 struct wlan_objmgr_psoc *psoc; 3463 enum reg_wifi_band band; 3464 3465 if (!err) { 3466 spectral_err("Error code argument is null"); 3467 QDF_ASSERT(0); 3468 } 3469 *err = SPECTRAL_SCAN_ERR_INVALID; 3470 3471 psoc = wlan_pdev_get_psoc(pdev); 3472 if (!psoc) { 3473 spectral_err("psoc is null"); 3474 return QDF_STATUS_E_FAILURE; 3475 } 3476 3477 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3478 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3479 spectral_err("Invalid Spectral mode %u", smode); 3480 return QDF_STATUS_E_FAILURE; 3481 } 3482 3483 if (!pdev) { 3484 spectral_err("pdev object is NUll"); 3485 return QDF_STATUS_E_FAILURE; 3486 } 3487 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3488 if (!spectral) { 3489 spectral_err("Spectral LMAC object is NUll"); 3490 return QDF_STATUS_E_FAILURE; 3491 } 3492 3493 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3494 3495 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 3496 QDF_STATUS status; 3497 bool is_supported = false; 3498 3499 status = target_if_is_agile_supported_cur_chmask(spectral, 3500 &is_supported); 3501 if (QDF_IS_STATUS_ERROR(status)) { 3502 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3503 return QDF_STATUS_E_FAILURE; 3504 } 3505 3506 if (!is_supported) { 3507 spectral_err("aSpectral unsupported for cur chainmask"); 3508 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3509 return QDF_STATUS_E_FAILURE; 3510 } 3511 } 3512 3513 band = target_if_get_curr_band(spectral->pdev_obj); 3514 if (band == REG_BAND_UNKNOWN) { 3515 spectral_err("Failed to get current band"); 3516 return QDF_STATUS_E_FAILURE; 3517 } 3518 if ((band == REG_BAND_5G) && (smode == SPECTRAL_SCAN_MODE_AGILE)) { 3519 struct target_psoc_info *tgt_hdl; 3520 enum wmi_host_hw_mode_config_type mode; 3521 bool is_agile_scan_inprog_5g_pdev; 3522 3523 if (p_sops->is_spectral_active(spectral, 3524 SPECTRAL_SCAN_MODE_AGILE)) { 3525 spectral_err("Agile Scan in progress in current pdev"); 3526 return QDF_STATUS_E_FAILURE; 3527 } 3528 3529 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 3530 if (!tgt_hdl) { 3531 target_if_err("target_psoc_info is null"); 3532 return QDF_STATUS_E_FAILURE; 3533 } 3534 3535 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 3536 switch (mode) { 3537 case WMI_HOST_HW_MODE_SBS_PASSIVE: 3538 case WMI_HOST_HW_MODE_SBS: 3539 case WMI_HOST_HW_MODE_DBS_SBS: 3540 case WMI_HOST_HW_MODE_DBS_OR_SBS: 3541 is_agile_scan_inprog_5g_pdev = false; 3542 wlan_objmgr_iterate_obj_list 3543 (psoc, WLAN_PDEV_OP, 3544 target_if_is_agile_scan_active_in_5g, 3545 &is_agile_scan_inprog_5g_pdev, 0, 3546 WLAN_SPECTRAL_ID); 3547 break; 3548 default: 3549 is_agile_scan_inprog_5g_pdev = false; 3550 break; 3551 } 3552 3553 if (is_agile_scan_inprog_5g_pdev) { 3554 spectral_err("Agile Scan in progress in one of the SBS 5G pdev"); 3555 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3556 return QDF_STATUS_E_FAILURE; 3557 } 3558 } 3559 3560 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 3561 bool is_aspectral_prohibited = false; 3562 QDF_STATUS status; 3563 3564 status = wlan_objmgr_iterate_obj_list 3565 (psoc, WLAN_PDEV_OP, 3566 target_if_is_aspectral_prohibited_by_adfs, 3567 &is_aspectral_prohibited, 0, 3568 WLAN_SPECTRAL_ID); 3569 if (QDF_IS_STATUS_ERROR(status)) { 3570 spectral_err("Failed to iterate over pdevs"); 3571 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3572 return QDF_STATUS_E_FAILURE; 3573 } 3574 3575 if (is_aspectral_prohibited) { 3576 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3577 return QDF_STATUS_E_FAILURE; 3578 } 3579 } 3580 3581 if (!spectral->params_valid[smode]) { 3582 target_if_spectral_info_read(spectral, 3583 smode, 3584 TARGET_IF_SPECTRAL_INFO_PARAMS, 3585 &spectral->params[smode], 3586 sizeof(spectral->params[smode])); 3587 spectral->params_valid[smode] = true; 3588 } 3589 3590 qdf_spin_lock(&spectral->spectral_lock); 3591 if (smode == SPECTRAL_SCAN_MODE_AGILE && 3592 !spectral->params[smode].ss_frequency) { 3593 *err = SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED; 3594 qdf_spin_unlock(&spectral->spectral_lock); 3595 return QDF_STATUS_E_FAILURE; 3596 } 3597 3598 if (smode == SPECTRAL_SCAN_MODE_AGILE) { 3599 QDF_STATUS status; 3600 bool is_overlapping; 3601 3602 status = target_if_is_agile_span_overlap_with_operating_span 3603 (spectral, 3604 spectral->params[smode].ss_frequency, 3605 &is_overlapping); 3606 if (QDF_IS_STATUS_ERROR(status)) { 3607 qdf_spin_unlock(&spectral->spectral_lock); 3608 return QDF_STATUS_E_FAILURE; 3609 } 3610 3611 if (is_overlapping) { 3612 *err = SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE; 3613 qdf_spin_unlock(&spectral->spectral_lock); 3614 return QDF_STATUS_E_FAILURE; 3615 } 3616 } 3617 3618 target_if_spectral_scan_enable_params(spectral, 3619 &spectral->params[smode], smode, 3620 err); 3621 qdf_spin_unlock(&spectral->spectral_lock); 3622 3623 return QDF_STATUS_SUCCESS; 3624 } 3625 3626 QDF_STATUS 3627 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev, 3628 const enum spectral_scan_mode smode, 3629 enum spectral_cp_error_code *err) 3630 { 3631 struct target_if_spectral_ops *p_sops; 3632 struct target_if_spectral *spectral; 3633 3634 if (!err) { 3635 spectral_err("Error code argument is null"); 3636 QDF_ASSERT(0); 3637 } 3638 *err = SPECTRAL_SCAN_ERR_INVALID; 3639 3640 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3641 *err = SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED; 3642 spectral_err("Invalid Spectral mode %u", smode); 3643 return QDF_STATUS_E_FAILURE; 3644 } 3645 3646 if (!pdev) { 3647 spectral_err("pdev object is NUll "); 3648 return QDF_STATUS_E_FAILURE; 3649 } 3650 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3651 if (!spectral) { 3652 spectral_err("Spectral LMAC object is NUll "); 3653 return QDF_STATUS_E_FAILURE; 3654 } 3655 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3656 3657 qdf_spin_lock(&spectral->spectral_lock); 3658 p_sops->stop_spectral_scan(spectral, smode); 3659 if (spectral->classify_scan) { 3660 /* TODO : Check if this logic is necessary */ 3661 spectral->detects_control_channel = 0; 3662 spectral->detects_extension_channel = 0; 3663 spectral->detects_above_dc = 0; 3664 spectral->detects_below_dc = 0; 3665 spectral->classify_scan = 0; 3666 } 3667 3668 spectral->send_single_packet = 0; 3669 spectral->sc_spectral_scan = 0; 3670 3671 qdf_spin_unlock(&spectral->spectral_lock); 3672 3673 return QDF_STATUS_SUCCESS; 3674 } 3675 3676 /** 3677 * target_if_is_spectral_active() - Get whether Spectral is active 3678 * @pdev: Pointer to pdev object 3679 * @smode: Spectral scan mode 3680 * 3681 * API to get whether Spectral is active 3682 * 3683 * Return: True if Spectral is active, false if Spectral is not active 3684 */ 3685 bool 3686 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev, 3687 const enum spectral_scan_mode smode) 3688 { 3689 struct target_if_spectral *spectral = NULL; 3690 struct target_if_spectral_ops *p_sops = NULL; 3691 3692 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3693 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3694 3695 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3696 spectral_err("Invalid Spectral mode %u", smode); 3697 return QDF_STATUS_E_FAILURE; 3698 } 3699 3700 return p_sops->is_spectral_active(spectral, smode); 3701 } 3702 3703 /** 3704 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 3705 * @pdev: Pointer to pdev object 3706 * @smode: Spectral scan mode 3707 * 3708 * API to get whether Spectral is enabled 3709 * 3710 * Return: True if Spectral is enabled, false if Spectral is not enabled 3711 */ 3712 bool 3713 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev, 3714 enum spectral_scan_mode smode) 3715 { 3716 struct target_if_spectral *spectral = NULL; 3717 struct target_if_spectral_ops *p_sops = NULL; 3718 3719 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3720 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3721 3722 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 3723 spectral_err("Invalid Spectral mode %u", smode); 3724 return QDF_STATUS_E_FAILURE; 3725 } 3726 3727 return p_sops->is_spectral_enabled(spectral, smode); 3728 } 3729 3730 #ifdef DIRECT_BUF_RX_DEBUG 3731 /** 3732 * target_if_spectral_do_dbr_ring_debug() - Start/Stop Spectral DMA ring debug 3733 * @pdev: Pointer to pdev object 3734 * @enable: Enable/Disable Spectral DMA ring debug 3735 * 3736 * Start/stop Spectral DMA ring debug based on @enable. 3737 * Also save the state for future use. 3738 * 3739 * Return: QDF_STATUS of operation 3740 */ 3741 static QDF_STATUS 3742 target_if_spectral_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev, bool enable) 3743 { 3744 struct target_if_spectral *spectral; 3745 struct wlan_lmac_if_tx_ops *tx_ops; 3746 struct wlan_objmgr_psoc *psoc; 3747 3748 if (!pdev) 3749 return QDF_STATUS_E_FAILURE; 3750 3751 psoc = wlan_pdev_get_psoc(pdev); 3752 if (!psoc) { 3753 spectral_err("psoc is null"); 3754 return QDF_STATUS_E_INVAL; 3755 } 3756 tx_ops = &psoc->soc_cb.tx_ops; 3757 3758 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3759 if (!spectral) { 3760 spectral_err("Spectal LMAC object is NULL"); 3761 return QDF_STATUS_E_INVAL; 3762 } 3763 3764 /* Save the state */ 3765 spectral->dbr_ring_debug = enable; 3766 3767 if (enable) 3768 return tx_ops->dbr_tx_ops.direct_buf_rx_start_ring_debug( 3769 pdev, 0, SPECTRAL_DBR_RING_DEBUG_SIZE); 3770 else 3771 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_ring_debug( 3772 pdev, 0); 3773 3774 return QDF_STATUS_SUCCESS; 3775 } 3776 3777 /** 3778 * target_if_spectral_do_dbr_buff_debug() - Start/Stop Spectral DMA buffer debug 3779 * @pdev: Pointer to pdev object 3780 * @enable: Enable/Disable Spectral DMA buffer debug 3781 * 3782 * Start/stop Spectral DMA buffer debug based on @enable. 3783 * Also save the state for future use. 3784 * 3785 * Return: QDF_STATUS of operation 3786 */ 3787 static QDF_STATUS 3788 target_if_spectral_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev, bool enable) 3789 { 3790 struct target_if_spectral *spectral; 3791 struct wlan_lmac_if_tx_ops *tx_ops; 3792 struct wlan_objmgr_psoc *psoc; 3793 3794 if (!pdev) 3795 return QDF_STATUS_E_FAILURE; 3796 3797 psoc = wlan_pdev_get_psoc(pdev); 3798 if (!psoc) { 3799 spectral_err("psoc is null"); 3800 return QDF_STATUS_E_INVAL; 3801 } 3802 tx_ops = &psoc->soc_cb.tx_ops; 3803 3804 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3805 if (!spectral) { 3806 spectral_err("Spectal LMAC object is NULL"); 3807 return QDF_STATUS_E_INVAL; 3808 } 3809 3810 /* Save the state */ 3811 spectral->dbr_buff_debug = enable; 3812 3813 if (enable) 3814 return tx_ops->dbr_tx_ops.direct_buf_rx_start_buffer_poisoning( 3815 pdev, 0, MEM_POISON_SIGNATURE); 3816 else 3817 return tx_ops->dbr_tx_ops.direct_buf_rx_stop_buffer_poisoning( 3818 pdev, 0); 3819 } 3820 3821 /** 3822 * target_if_spectral_check_and_do_dbr_buff_debug() - Start/Stop Spectral buffer 3823 * debug based on the previous state 3824 * @pdev: Pointer to pdev object 3825 * 3826 * Return: QDF_STATUS of operation 3827 */ 3828 static QDF_STATUS 3829 target_if_spectral_check_and_do_dbr_buff_debug(struct wlan_objmgr_pdev *pdev) 3830 { 3831 struct target_if_spectral *spectral; 3832 3833 if (!pdev) { 3834 spectral_err("pdev is NULL!"); 3835 return QDF_STATUS_E_FAILURE; 3836 } 3837 3838 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3839 if (!spectral) { 3840 spectral_err("Spectal LMAC object is NULL"); 3841 return QDF_STATUS_E_INVAL; 3842 } 3843 3844 if (spectral->dbr_buff_debug) 3845 return target_if_spectral_do_dbr_buff_debug(pdev, true); 3846 else 3847 return target_if_spectral_do_dbr_buff_debug(pdev, false); 3848 } 3849 3850 /** 3851 * target_if_spectral_check_and_do_dbr_ring_debug() - Start/Stop Spectral ring 3852 * debug based on the previous state 3853 * @pdev: Pointer to pdev object 3854 * 3855 * Return: QDF_STATUS of operation 3856 */ 3857 static QDF_STATUS 3858 target_if_spectral_check_and_do_dbr_ring_debug(struct wlan_objmgr_pdev *pdev) 3859 { 3860 struct target_if_spectral *spectral; 3861 3862 if (!pdev) { 3863 spectral_err("pdev is NULL!"); 3864 return QDF_STATUS_E_FAILURE; 3865 } 3866 3867 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3868 if (!spectral) { 3869 spectral_err("Spectal LMAC object is NULL"); 3870 return QDF_STATUS_E_INVAL; 3871 } 3872 3873 if (spectral->dbr_ring_debug) 3874 return target_if_spectral_do_dbr_ring_debug(pdev, true); 3875 else 3876 return target_if_spectral_do_dbr_ring_debug(pdev, false); 3877 } 3878 3879 /** 3880 * target_if_spectral_set_dma_debug() - Set DMA debug for Spectral 3881 * @pdev: Pointer to pdev object 3882 * @dma_debug_type: Type of Spectral DMA debug i.e., ring or buffer debug 3883 * @debug_value: Value to be set for @dma_debug_type 3884 * 3885 * Set DMA debug for Spectral and start/stop Spectral DMA debug function 3886 * based on @debug_value 3887 * 3888 * Return: QDF_STATUS of operation 3889 */ 3890 static QDF_STATUS 3891 target_if_spectral_set_dma_debug( 3892 struct wlan_objmgr_pdev *pdev, 3893 enum spectral_dma_debug dma_debug_type, 3894 bool debug_value) 3895 { 3896 struct target_if_spectral_ops *p_sops; 3897 struct wlan_objmgr_psoc *psoc; 3898 struct wlan_lmac_if_tx_ops *tx_ops; 3899 struct target_if_spectral *spectral; 3900 3901 if (!pdev) 3902 return QDF_STATUS_E_FAILURE; 3903 3904 psoc = wlan_pdev_get_psoc(pdev); 3905 if (!psoc) { 3906 spectral_err("psoc is null"); 3907 return QDF_STATUS_E_INVAL; 3908 } 3909 tx_ops = &psoc->soc_cb.tx_ops; 3910 3911 if (!tx_ops->target_tx_ops.tgt_get_tgt_type) { 3912 spectral_err("Unable to fetch target type"); 3913 return QDF_STATUS_E_FAILURE; 3914 } 3915 3916 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3917 if (!spectral) { 3918 spectral_err("Spectal LMAC object is NULL"); 3919 return QDF_STATUS_E_INVAL; 3920 } 3921 3922 if (spectral->direct_dma_support) { 3923 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 3924 if (p_sops->is_spectral_active(spectral, 3925 SPECTRAL_SCAN_MODE_NORMAL) || 3926 p_sops->is_spectral_active(spectral, 3927 SPECTRAL_SCAN_MODE_AGILE)) { 3928 spectral_err("Altering DBR debug config isn't allowed during an ongoing scan"); 3929 return QDF_STATUS_E_FAILURE; 3930 } 3931 3932 switch (dma_debug_type) { 3933 case SPECTRAL_DMA_RING_DEBUG: 3934 target_if_spectral_do_dbr_ring_debug(pdev, debug_value); 3935 break; 3936 3937 case SPECTRAL_DMA_BUFFER_DEBUG: 3938 target_if_spectral_do_dbr_buff_debug(pdev, debug_value); 3939 break; 3940 3941 default: 3942 spectral_err("Unsupported DMA debug type : %d", 3943 dma_debug_type); 3944 return QDF_STATUS_E_FAILURE; 3945 } 3946 } 3947 return QDF_STATUS_SUCCESS; 3948 } 3949 #endif /* DIRECT_BUF_RX_DEBUG */ 3950 3951 /** 3952 * target_if_spectral_direct_dma_support() - Get Direct-DMA support 3953 * @pdev: Pointer to pdev object 3954 * 3955 * Return: Whether Direct-DMA is supported on this radio 3956 */ 3957 static bool 3958 target_if_spectral_direct_dma_support(struct wlan_objmgr_pdev *pdev) 3959 { 3960 struct target_if_spectral *spectral; 3961 3962 if (!pdev) { 3963 spectral_err("pdev is NULL!"); 3964 return false; 3965 } 3966 3967 spectral = get_target_if_spectral_handle_from_pdev(pdev); 3968 if (!spectral) { 3969 spectral_err("Spectral LMAC object is NULL"); 3970 return false; 3971 } 3972 return spectral->direct_dma_support; 3973 } 3974 3975 /** 3976 * target_if_set_debug_level() - Set debug level for Spectral 3977 * @pdev: Pointer to pdev object 3978 * @debug_level: Debug level 3979 * 3980 * API to set the debug level for Spectral 3981 * 3982 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 3983 */ 3984 QDF_STATUS 3985 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 3986 { 3987 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 3988 3989 return QDF_STATUS_SUCCESS; 3990 } 3991 3992 /** 3993 * target_if_get_debug_level() - Get debug level for Spectral 3994 * @pdev: Pointer to pdev object 3995 * 3996 * API to get the debug level for Spectral 3997 * 3998 * Return: Current debug level 3999 */ 4000 uint32_t 4001 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 4002 { 4003 return spectral_debug_level; 4004 } 4005 4006 /** 4007 * target_if_get_spectral_capinfo() - Get Spectral capability information 4008 * @pdev: Pointer to pdev object 4009 * @scaps: Buffer into which data should be copied 4010 * 4011 * API to get the spectral capability information 4012 * 4013 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4014 */ 4015 QDF_STATUS 4016 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, 4017 struct spectral_caps *scaps) 4018 { 4019 struct target_if_spectral *spectral = NULL; 4020 4021 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4022 qdf_mem_copy(scaps, &spectral->capability, 4023 sizeof(struct spectral_caps)); 4024 4025 return QDF_STATUS_SUCCESS; 4026 } 4027 4028 /** 4029 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 4030 * @pdev: Pointer to pdev object 4031 * @stats: Buffer into which data should be copied 4032 * 4033 * API to get the spectral diagnostic statistics 4034 * 4035 * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure 4036 */ 4037 QDF_STATUS 4038 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, 4039 struct spectral_diag_stats *stats) 4040 { 4041 struct target_if_spectral *spectral = NULL; 4042 4043 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4044 qdf_mem_copy(stats, &spectral->diag_stats, 4045 sizeof(struct spectral_diag_stats)); 4046 4047 return QDF_STATUS_SUCCESS; 4048 } 4049 4050 /** 4051 * target_if_register_wmi_spectral_cmd_ops() - Register wmi_spectral_cmd_ops 4052 * @cmd_ops: Pointer to the structure having wmi_spectral_cmd function pointers 4053 * @pdev: Pointer to pdev object 4054 * 4055 * API for register wmi_spectral_cmd_ops in spectral internal data structure 4056 * 4057 * Return: void 4058 */ 4059 void 4060 target_if_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev, 4061 struct wmi_spectral_cmd_ops *cmd_ops) 4062 { 4063 struct target_if_spectral *spectral = 4064 get_target_if_spectral_handle_from_pdev(pdev); 4065 4066 if (!spectral) { 4067 spectral_err("Spectral LMAC object is null"); 4068 return; 4069 } 4070 spectral->param_wmi_cmd_ops = *cmd_ops; 4071 } 4072 4073 /** 4074 * target_if_register_netlink_cb() - Register Netlink callbacks 4075 * @pdev: Pointer to pdev object 4076 * @nl_cb: Netlink callbacks to register 4077 * 4078 * Return: void 4079 */ 4080 static void 4081 target_if_register_netlink_cb( 4082 struct wlan_objmgr_pdev *pdev, 4083 struct spectral_nl_cb *nl_cb) 4084 { 4085 struct target_if_spectral *spectral = NULL; 4086 4087 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4088 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 4089 4090 if (spectral->use_nl_bcast) 4091 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 4092 else 4093 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 4094 } 4095 4096 /** 4097 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 4098 * Netlink messages to the application layer 4099 * @pdev: Pointer to pdev object 4100 * 4101 * Return: true for broadcast, false for unicast 4102 */ 4103 static bool 4104 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 4105 { 4106 struct target_if_spectral *spectral = NULL; 4107 4108 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4109 return spectral->use_nl_bcast; 4110 } 4111 4112 /** 4113 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 4114 * @pdev: Pointer to pdev object 4115 * 4116 * Return: void 4117 */ 4118 static void 4119 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 4120 { 4121 struct target_if_spectral *spectral = NULL; 4122 4123 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4124 if (!spectral) { 4125 spectral_err("SPECTRAL : Module doesn't exist"); 4126 return; 4127 } 4128 4129 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 4130 } 4131 4132 static int 4133 target_if_process_spectral_report(struct wlan_objmgr_pdev *pdev, 4134 void *payload) 4135 { 4136 struct target_if_spectral *spectral = NULL; 4137 struct target_if_spectral_ops *p_sops = NULL; 4138 4139 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4140 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4141 4142 return p_sops->process_spectral_report(pdev, payload); 4143 } 4144 4145 #ifdef DIRECT_BUF_RX_DEBUG 4146 static inline void 4147 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 4148 { 4149 if (!tx_ops) 4150 return; 4151 4152 tx_ops->sptrl_tx_ops.sptrlto_set_dma_debug = 4153 target_if_spectral_set_dma_debug; 4154 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_ring_debug = 4155 target_if_spectral_check_and_do_dbr_ring_debug; 4156 tx_ops->sptrl_tx_ops.sptrlto_check_and_do_dbr_buff_debug = 4157 target_if_spectral_check_and_do_dbr_buff_debug; 4158 } 4159 #else 4160 static inline void 4161 target_if_sptrl_debug_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 4162 { 4163 } 4164 #endif 4165 4166 void 4167 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 4168 { 4169 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 4170 target_if_pdev_spectral_init; 4171 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 4172 target_if_pdev_spectral_deinit; 4173 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 4174 target_if_set_spectral_config; 4175 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 4176 target_if_get_spectral_config; 4177 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 4178 target_if_start_spectral_scan; 4179 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 4180 target_if_stop_spectral_scan; 4181 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 4182 target_if_is_spectral_active; 4183 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 4184 target_if_is_spectral_enabled; 4185 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 4186 target_if_set_debug_level; 4187 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 4188 target_if_get_debug_level; 4189 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 4190 target_if_get_spectral_capinfo; 4191 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 4192 target_if_get_spectral_diagstats; 4193 tx_ops->sptrl_tx_ops.sptrlto_register_wmi_spectral_cmd_ops = 4194 target_if_register_wmi_spectral_cmd_ops; 4195 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 4196 target_if_register_netlink_cb; 4197 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 4198 target_if_use_nl_bcast; 4199 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 4200 target_if_deregister_netlink_cb; 4201 tx_ops->sptrl_tx_ops.sptrlto_process_spectral_report = 4202 target_if_process_spectral_report; 4203 tx_ops->sptrl_tx_ops.sptrlto_direct_dma_support = 4204 target_if_spectral_direct_dma_support; 4205 target_if_sptrl_debug_register_tx_ops(tx_ops); 4206 } 4207 qdf_export_symbol(target_if_sptrl_register_tx_ops); 4208 4209 void 4210 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 4211 uint16_t cw_int, uint32_t dcs_enabled) 4212 { 4213 struct spectral_samp_msg *msg = NULL; 4214 struct target_if_spectral_ops *p_sops = NULL; 4215 struct target_if_spectral *spectral = NULL; 4216 4217 spectral = get_target_if_spectral_handle_from_pdev(pdev); 4218 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_sbuff( 4219 spectral->pdev_obj, 4220 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION, 4221 SPECTRAL_MSG_BUF_NEW); 4222 4223 if (msg) { 4224 msg->int_type = cw_int ? 4225 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 4226 msg->dcs_enabled = dcs_enabled; 4227 msg->signature = SPECTRAL_SIGNATURE; 4228 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 4229 p_sops->get_mac_address(spectral, msg->macaddr); 4230 if (spectral->send_phy_data 4231 (pdev, 4232 SPECTRAL_MSG_INTERFERENCE_NOTIFICATION) == 0) 4233 spectral->spectral_sent_msg++; 4234 } 4235 } 4236 qdf_export_symbol(target_if_spectral_send_intf_found_msg); 4237