1 /* 2 * Copyright (c) 2011,2017-2018 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_ucfg.h> 29 #include <reg_services_public_struct.h> 30 #ifdef CONFIG_WIN 31 #include <wlan_mlme_dispatcher.h> 32 #endif /*CONFIG_WIN*/ 33 #include <reg_services_public_struct.h> 34 #include <target_if_spectral_sim.h> 35 #include <target_if.h> 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 struct wlan_objmgr_vdev * 46 target_if_spectral_get_vdev(struct target_if_spectral *spectral) 47 { 48 struct wlan_objmgr_pdev *pdev = NULL; 49 struct wlan_objmgr_vdev *vdev = NULL; 50 51 qdf_assert_always(spectral); 52 pdev = spectral->pdev_obj; 53 qdf_assert_always(pdev); 54 55 if (wlan_objmgr_pdev_try_get_ref(pdev, WLAN_SPECTRAL_ID) != 56 QDF_STATUS_SUCCESS) { 57 spectral_err("Unable to get pdev reference."); 58 return NULL; 59 } 60 61 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_SPECTRAL_ID); 62 63 wlan_objmgr_pdev_release_ref(pdev, WLAN_SPECTRAL_ID); 64 65 if (!vdev) { 66 spectral_warn("Unable to get first vdev of pdev."); 67 return NULL; 68 } 69 70 return vdev; 71 } 72 73 /** 74 * target_if_send_vdev_spectral_configure_cmd() - Send WMI command to configure 75 * spectral parameters 76 * @spectral: Pointer to Spectral target_if internal private data 77 * @param: Pointer to spectral_config giving the Spectral configuration 78 * 79 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 80 */ 81 static int 82 target_if_send_vdev_spectral_configure_cmd(struct target_if_spectral *spectral, 83 struct spectral_config *param) 84 { 85 struct vdev_spectral_configure_params sparam; 86 struct wlan_objmgr_pdev *pdev = NULL; 87 struct wlan_objmgr_vdev *vdev = NULL; 88 89 qdf_assert_always(spectral && param); 90 91 pdev = spectral->pdev_obj; 92 93 qdf_assert_always(pdev); 94 95 vdev = target_if_spectral_get_vdev(spectral); 96 if (!vdev) 97 return QDF_STATUS_E_NOENT; 98 99 qdf_mem_set(&sparam, sizeof(sparam), 0); 100 101 sparam.vdev_id = wlan_vdev_get_id(vdev); 102 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 103 104 sparam.count = param->ss_count; 105 sparam.period = param->ss_period; 106 sparam.spectral_pri = param->ss_spectral_pri; 107 sparam.fft_size = param->ss_fft_size; 108 sparam.gc_enable = param->ss_gc_ena; 109 sparam.restart_enable = param->ss_restart_ena; 110 sparam.noise_floor_ref = param->ss_noise_floor_ref; 111 sparam.init_delay = param->ss_init_delay; 112 sparam.nb_tone_thr = param->ss_nb_tone_thr; 113 sparam.str_bin_thr = param->ss_str_bin_thr; 114 sparam.wb_rpt_mode = param->ss_wb_rpt_mode; 115 sparam.rssi_rpt_mode = param->ss_rssi_rpt_mode; 116 sparam.rssi_thr = param->ss_rssi_thr; 117 sparam.pwr_format = param->ss_pwr_format; 118 sparam.rpt_mode = param->ss_rpt_mode; 119 sparam.bin_scale = param->ss_bin_scale; 120 sparam.dbm_adj = param->ss_dbm_adj; 121 sparam.chn_mask = param->ss_chn_mask; 122 123 return spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send( 124 GET_WMI_HDL_FROM_PDEV(pdev), &sparam); 125 } 126 127 /** 128 * target_if_send_vdev_spectral_enable_cmd() - Send WMI command to 129 * enable/disable Spectral 130 * @spectral: Pointer to Spectral target_if internal private data 131 * @is_spectral_active_valid: Flag to indicate if spectral activate (trigger) is 132 * valid 133 * @is_spectral_active: Value of spectral activate 134 * @is_spectral_enabled_valid: Flag to indicate if spectral enable is valid 135 * @is_spectral_enabled: Value of spectral enable 136 * 137 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 138 */ 139 static int 140 target_if_send_vdev_spectral_enable_cmd(struct target_if_spectral *spectral, 141 uint8_t is_spectral_active_valid, 142 uint8_t is_spectral_active, 143 uint8_t is_spectral_enabled_valid, 144 uint8_t is_spectral_enabled) 145 { 146 struct vdev_spectral_enable_params param; 147 struct wlan_objmgr_pdev *pdev = NULL; 148 struct wlan_objmgr_vdev *vdev = NULL; 149 150 qdf_assert_always(spectral); 151 152 pdev = spectral->pdev_obj; 153 154 qdf_assert_always(pdev); 155 156 vdev = target_if_spectral_get_vdev(spectral); 157 if (!vdev) 158 return QDF_STATUS_E_NOENT; 159 160 qdf_mem_set(¶m, sizeof(param), 0); 161 162 param.vdev_id = wlan_vdev_get_id(vdev); 163 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 164 165 param.active_valid = is_spectral_active_valid; 166 param.enabled_valid = is_spectral_enabled_valid; 167 param.active = is_spectral_active; 168 param.enabled = is_spectral_enabled; 169 170 return spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send( 171 GET_WMI_HDL_FROM_PDEV(pdev), ¶m); 172 } 173 174 /** 175 * target_if_spectral_info_init_defaults() - Helper function to load defaults 176 * for Spectral information (parameters and state) into cache. 177 * @spectral: Pointer to Spectral target_if internal private data 178 * 179 * It is assumed that the caller has obtained the requisite lock if applicable. 180 * Note that this is currently treated as a temporary function. Ideally, we 181 * would like to get defaults from the firmware. 182 * 183 * Return: QDF_STATUS_SUCCESS on success, negative error code on failure 184 */ 185 static int 186 target_if_spectral_info_init_defaults(struct target_if_spectral *spectral) 187 { 188 struct target_if_spectral_param_state_info *info = 189 &spectral->param_info; 190 struct wlan_objmgr_vdev *vdev = NULL; 191 192 /* State */ 193 info->osps_cache.osc_spectral_active = SPECTRAL_SCAN_ACTIVE_DEFAULT; 194 195 info->osps_cache.osc_spectral_enabled = SPECTRAL_SCAN_ENABLE_DEFAULT; 196 197 /* Parameters */ 198 info->osps_cache.osc_params.ss_count = SPECTRAL_SCAN_COUNT_DEFAULT; 199 200 info->osps_cache.osc_params.ss_period = SPECTRAL_SCAN_PERIOD_DEFAULT; 201 202 info->osps_cache.osc_params.ss_spectral_pri = 203 SPECTRAL_SCAN_PRIORITY_DEFAULT; 204 205 info->osps_cache.osc_params.ss_fft_size = 206 SPECTRAL_SCAN_FFT_SIZE_DEFAULT; 207 208 info->osps_cache.osc_params.ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT; 209 210 info->osps_cache.osc_params.ss_restart_ena = 211 SPECTRAL_SCAN_RESTART_ENA_DEFAULT; 212 213 info->osps_cache.osc_params.ss_noise_floor_ref = 214 SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT; 215 216 info->osps_cache.osc_params.ss_init_delay = 217 SPECTRAL_SCAN_INIT_DELAY_DEFAULT; 218 219 info->osps_cache.osc_params.ss_nb_tone_thr = 220 SPECTRAL_SCAN_NB_TONE_THR_DEFAULT; 221 222 info->osps_cache.osc_params.ss_str_bin_thr = 223 SPECTRAL_SCAN_STR_BIN_THR_DEFAULT; 224 225 info->osps_cache.osc_params.ss_wb_rpt_mode = 226 SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT; 227 228 info->osps_cache.osc_params.ss_rssi_rpt_mode = 229 SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT; 230 231 info->osps_cache.osc_params.ss_rssi_thr = 232 SPECTRAL_SCAN_RSSI_THR_DEFAULT; 233 234 info->osps_cache.osc_params.ss_pwr_format = 235 SPECTRAL_SCAN_PWR_FORMAT_DEFAULT; 236 237 info->osps_cache.osc_params.ss_rpt_mode = 238 SPECTRAL_SCAN_RPT_MODE_DEFAULT; 239 240 info->osps_cache.osc_params.ss_bin_scale = 241 SPECTRAL_SCAN_BIN_SCALE_DEFAULT; 242 243 info->osps_cache.osc_params.ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT; 244 245 vdev = target_if_spectral_get_vdev(spectral); 246 if (!vdev) 247 return QDF_STATUS_E_NOENT; 248 249 info->osps_cache.osc_params.ss_chn_mask = 250 wlan_vdev_mlme_get_rxchainmask(vdev); 251 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 252 253 /* The cache is now valid */ 254 info->osps_cache.osc_is_valid = 1; 255 256 return QDF_STATUS_SUCCESS; 257 } 258 259 #ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS 260 /** 261 * target_if_log_read_spectral_active() - Helper function to log whether 262 * spectral is active after reading cache 263 * @function_name: Function name 264 * @output: whether spectral is active or not 265 * 266 * Helper function to log whether spectral is active after reading cache 267 * 268 * Return: none 269 */ 270 static void 271 target_if_log_read_spectral_active( 272 const char *function_name, 273 unsigned char output) 274 { 275 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE. Returning val=%u", 276 function_name, output); 277 } 278 279 /** 280 * target_if_log_read_spectral_enabled() - Helper function to log whether 281 * spectral is enabled after reading cache 282 * @function_name: Function name 283 * @output: whether spectral is enabled or not 284 * 285 * Helper function to log whether spectral is enabled after reading cache 286 * 287 * Return: none 288 */ 289 static void 290 target_if_log_read_spectral_enabled( 291 const char *function_name, 292 unsigned char output) 293 { 294 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED. Returning val=%u", 295 function_name, output); 296 } 297 298 /** 299 * target_if_log_read_spectral_enabled() - Helper function to log spectral 300 * parameters after reading cache 301 * @function_name: Function name 302 * @pparam: Spectral parameters 303 * 304 * Helper function to log spectral parameters after reading cache 305 * 306 * Return: none 307 */ 308 static void 309 target_if_log_read_spectral_params( 310 const char *function_name, 311 struct spectral_config *pparam) 312 { 313 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\n", 314 function_name, 315 pparam->ss_count, 316 pparam->ss_period, 317 pparam->ss_spectral_pri, 318 pparam->ss_fft_size, 319 pparam->ss_gc_ena, 320 pparam->ss_restart_ena, 321 (int8_t)pparam->ss_noise_floor_ref, 322 pparam->ss_init_delay, 323 pparam->ss_nb_tone_thr, 324 pparam->ss_str_bin_thr, 325 pparam->ss_wb_rpt_mode, 326 pparam->ss_rssi_rpt_mode, 327 (int8_t)pparam->ss_rssi_thr, 328 pparam->ss_pwr_format, 329 pparam->ss_rpt_mode, 330 pparam->ss_bin_scale, 331 pparam->ss_dbm_adj, 332 pparam->ss_chn_mask); 333 } 334 335 /** 336 * target_if_log_read_spectral_active_catch_validate() - Helper function to 337 * log whether spectral is active after intializing the cache 338 * @function_name: Function name 339 * @output: whether spectral is active or not 340 * 341 * Helper function to log whether spectral is active after intializing cache 342 * 343 * Return: none 344 */ 345 static void 346 target_if_log_read_spectral_active_catch_validate( 347 const char *function_name, 348 unsigned char output) 349 { 350 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE on initial cache validation\nReturning val=%u", 351 function_name, output); 352 } 353 354 /** 355 * target_if_log_read_spectral_enabled_catch_validate() - Helper function to 356 * log whether spectral is enabled after intializing the cache 357 * @function_name: Function name 358 * @output: whether spectral is enabled or not 359 * 360 * Helper function to log whether spectral is enabled after intializing cache 361 * 362 * Return: none 363 */ 364 static void 365 target_if_log_read_spectral_enabled_catch_validate( 366 const char *function_name, 367 unsigned char output) 368 { 369 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED on initial cache validation\nReturning val=%u\n", 370 function_name, output); 371 } 372 373 /** 374 * target_if_log_read_spectral_params_catch_validate() - Helper function to 375 * log spectral parameters after intializing the cache 376 * @function_name: Function name 377 * @pparam: Spectral parameters 378 * 379 * Helper function to log spectral parameters after intializing the cache 380 * 381 * Return: none 382 */ 383 static void 384 target_if_log_read_spectral_params_catch_validate( 385 const char *function_name, 386 struct spectral_config *pparam) 387 { 388 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", 389 function_name, 390 pparam->ss_count, 391 pparam->ss_period, 392 pparam->ss_spectral_pri, 393 pparam->ss_fft_size, 394 pparam->ss_gc_ena, 395 pparam->ss_restart_ena, 396 (int8_t)pparam->ss_noise_floor_ref, 397 pparam->ss_init_delay, 398 pparam->ss_nb_tone_thr, 399 pparam->ss_str_bin_thr, 400 pparam->ss_wb_rpt_mode, 401 pparam->ss_rssi_rpt_mode, 402 (int8_t)pparam->ss_rssi_thr, 403 pparam->ss_pwr_format, 404 pparam->ss_rpt_mode, 405 pparam->ss_bin_scale, 406 pparam->ss_dbm_adj, pparam->ss_chn_mask); 407 } 408 409 #else 410 static void 411 target_if_log_read_spectral_active( 412 const char *function_name, 413 unsigned char output) 414 { 415 } 416 417 static void 418 target_if_log_read_spectral_enabled( 419 const char *function_name, 420 unsigned char output) 421 { 422 } 423 424 static void 425 target_if_log_read_spectral_params( 426 const char *function_name, 427 struct spectral_config *pparam) 428 { 429 } 430 431 static void 432 target_if_log_read_spectral_active_catch_validate( 433 const char *function_name, 434 unsigned char output) 435 { 436 } 437 438 static void 439 target_if_log_read_spectral_enabled_catch_validate( 440 const char *function_name, 441 unsigned char output) 442 { 443 } 444 445 static void 446 target_if_log_read_spectral_params_catch_validate( 447 const char *function_name, 448 struct spectral_config *pparam) 449 { 450 } 451 #endif 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 * @specifier: target_if_spectral_info enumeration specifying which 457 * information is required 458 * @output: Void output pointer into which the information will be read 459 * @output_len: size of object pointed to by output pointer 460 * 461 * Read spectral parameters or the desired state information from the cache. 462 * 463 * Return: 0 on success, negative error code on failure 464 */ 465 static int 466 target_if_spectral_info_read( 467 struct target_if_spectral *spectral, 468 enum target_if_spectral_info specifier, 469 void *output, int output_len) 470 { 471 /* 472 * Note: This function is designed to be able to accommodate 473 * WMI reads for defaults, non-cacheable information, etc 474 * if required. 475 */ 476 struct target_if_spectral_param_state_info *info = 477 &spectral->param_info; 478 int is_cacheable = 0; 479 int init_def_retval = 0; 480 481 if (!output) 482 return -EINVAL; 483 484 switch (specifier) { 485 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 486 if (output_len != sizeof(info->osps_cache.osc_spectral_active)) 487 return -EINVAL; 488 is_cacheable = 1; 489 break; 490 491 case TARGET_IF_SPECTRAL_INFO_ENABLED: 492 if (output_len != sizeof(info->osps_cache.osc_spectral_enabled)) 493 return -EINVAL; 494 is_cacheable = 1; 495 break; 496 497 case TARGET_IF_SPECTRAL_INFO_PARAMS: 498 if (output_len != sizeof(info->osps_cache.osc_params)) 499 return -EINVAL; 500 is_cacheable = 1; 501 break; 502 503 default: 504 spectral_err("Unknown target_if_spectral_info specifier"); 505 return -EINVAL; 506 } 507 508 qdf_spin_lock(&info->osps_lock); 509 510 if (is_cacheable) { 511 if (info->osps_cache.osc_is_valid) { 512 switch (specifier) { 513 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 514 qdf_mem_copy( 515 output, 516 &info->osps_cache.osc_spectral_active, 517 sizeof(info->osps_cache.osc_spectral_active)); 518 519 target_if_log_read_spectral_active( 520 __func__, 521 *((unsigned char *)output)); 522 break; 523 524 case TARGET_IF_SPECTRAL_INFO_ENABLED: 525 qdf_mem_copy( 526 output, 527 &info->osps_cache.osc_spectral_enabled, 528 sizeof( 529 info->osps_cache.osc_spectral_enabled)); 530 531 target_if_log_read_spectral_enabled( 532 __func__, 533 *((unsigned char *)output)); 534 break; 535 536 case TARGET_IF_SPECTRAL_INFO_PARAMS: 537 qdf_mem_copy( 538 output, 539 &info->osps_cache.osc_params, 540 sizeof(info->osps_cache.osc_params)); 541 542 target_if_log_read_spectral_params( 543 __func__, 544 (struct spectral_config *)output); 545 break; 546 547 default: 548 /* We can't reach this point */ 549 break; 550 } 551 qdf_spin_unlock(&info->osps_lock); 552 return 0; 553 } 554 } 555 556 /* Cache is invalid */ 557 558 /* 559 * If WMI Reads are implemented to fetch defaults/non-cacheable info, 560 * then the below implementation will change 561 */ 562 init_def_retval = target_if_spectral_info_init_defaults(spectral); 563 if (init_def_retval != QDF_STATUS_SUCCESS) { 564 qdf_spin_unlock(&info->osps_lock); 565 if (init_def_retval == QDF_STATUS_E_NOENT) 566 return -ENOENT; 567 else 568 return -EINVAL; 569 } 570 /* target_if_spectral_info_init_defaults() has set cache to valid */ 571 572 switch (specifier) { 573 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 574 qdf_mem_copy(output, 575 &info->osps_cache.osc_spectral_active, 576 sizeof(info->osps_cache.osc_spectral_active)); 577 578 target_if_log_read_spectral_active_catch_validate( 579 __func__, 580 *((unsigned char *)output)); 581 break; 582 583 case TARGET_IF_SPECTRAL_INFO_ENABLED: 584 qdf_mem_copy(output, 585 &info->osps_cache.osc_spectral_enabled, 586 sizeof(info->osps_cache.osc_spectral_enabled)); 587 588 target_if_log_read_spectral_enabled_catch_validate( 589 __func__, 590 *((unsigned char *)output)); 591 break; 592 593 case TARGET_IF_SPECTRAL_INFO_PARAMS: 594 qdf_mem_copy(output, 595 &info->osps_cache.osc_params, 596 sizeof(info->osps_cache.osc_params)); 597 598 target_if_log_read_spectral_params_catch_validate( 599 __func__, 600 (struct spectral_config *)output); 601 602 break; 603 604 default: 605 /* We can't reach this point */ 606 break; 607 } 608 609 qdf_spin_unlock(&info->osps_lock); 610 611 return 0; 612 } 613 614 #ifdef OL_SPECTRAL_DEBUG_CONFIG_INTERACTIONS 615 /** 616 * target_if_log_write_spectral_active() - Helper function to log inputs and 617 * return value of call to configure the Spectral 'active' configuration, 618 * TARGET_IF_SPECTRAL_INFO_ACTIVE into firmware 619 * @function_name: Function name in which this is called 620 * @pval: whether spectral is active or not 621 * @ret: return value of the firmware write function 622 * 623 * Return: none 624 */ 625 static void 626 target_if_log_write_spectral_active( 627 const char *function_name, 628 uint8_t pval, 629 int ret) 630 { 631 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ACTIVE with val=%u status=%d", 632 function_name, pval, ret); 633 } 634 635 /** 636 * target_if_log_write_spectral_enabled() - Helper function to log inputs and 637 * return value of call to configure the Spectral 'enabled' configuration, 638 * TARGET_IF_SPECTRAL_INFO_ENABLED into firmware 639 * @function_name: Function name in which this is called 640 * @pval: whether spectral is enabled or not 641 * @ret: return value of the firmware write function 642 * 643 * Return: none 644 */ 645 static void 646 target_if_log_write_spectral_enabled( 647 const char *function_name, 648 uint8_t pval, 649 int ret) 650 { 651 spectral_debug("%s: TARGET_IF_SPECTRAL_INFO_ENABLED with val=%u status=%d", 652 function_name, pval, ret); 653 } 654 655 /** 656 * target_if_log_write_spectral_params() - Helper function to log inputs and 657 * return value of call to configure Spectral parameters, 658 * TARGET_IF_SPECTRAL_INFO_PARAMS into firmware 659 * @param: Spectral parameters 660 * @function_name: Function name in which this is called 661 * @ret: return value of the firmware write function 662 * 663 * Return: none 664 */ 665 static void 666 target_if_log_write_spectral_params( 667 struct spectral_config *param, 668 const char *function_name, 669 int ret) 670 { 671 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\nstatus = %d", 672 function_name, 673 param->ss_count, 674 param->ss_period, 675 param->ss_spectral_pri, 676 param->ss_fft_size, 677 param->ss_gc_ena, 678 param->ss_restart_ena, 679 (int8_t)param->ss_noise_floor_ref, 680 param->ss_init_delay, 681 param->ss_nb_tone_thr, 682 param->ss_str_bin_thr, 683 param->ss_wb_rpt_mode, 684 param->ss_rssi_rpt_mode, 685 (int8_t)param->ss_rssi_thr, 686 param->ss_pwr_format, 687 param->ss_rpt_mode, 688 param->ss_bin_scale, 689 param->ss_dbm_adj, param->ss_chn_mask, ret); 690 } 691 #else 692 static void 693 target_if_log_write_spectral_active( 694 const char *function_name, 695 uint8_t pval, 696 int ret) 697 { 698 } 699 700 static void 701 target_if_log_write_spectral_enabled( 702 const char *function_name, 703 uint8_t pval, 704 int ret) 705 { 706 } 707 708 static void 709 target_if_log_write_spectral_params( 710 struct spectral_config *param, 711 const char *function_name, 712 int ret) 713 { 714 } 715 716 #endif 717 718 /** 719 * target_if_spectral_info_write() - Write Spectral information to the 720 * firmware, and update cache 721 * @spectral: Pointer to Spectral target_if internal private data 722 * @specifier: target_if_spectral_info enumeration specifying which 723 * information is involved 724 * @input: void input pointer containing the information to be written 725 * @input_len: size of object pointed to by input pointer 726 * 727 * Write Spectral parameters or the desired state information to 728 * the firmware, and update cache 729 * 730 * Return: 0 on success, negative error code on failure 731 */ 732 static int 733 target_if_spectral_info_write( 734 struct target_if_spectral *spectral, 735 enum target_if_spectral_info specifier, 736 void *input, int input_len) 737 { 738 struct target_if_spectral_param_state_info *info = 739 &spectral->param_info; 740 int ret; 741 uint8_t *pval = NULL; 742 struct spectral_config *param = NULL; 743 744 if (!input) 745 return -EINVAL; 746 747 switch (specifier) { 748 case TARGET_IF_SPECTRAL_INFO_ACTIVE: 749 if (input_len != sizeof(info->osps_cache.osc_spectral_active)) 750 return -EINVAL; 751 752 pval = (uint8_t *)input; 753 754 qdf_spin_lock(&info->osps_lock); 755 ret = target_if_send_vdev_spectral_enable_cmd(spectral, 756 1, *pval, 0, 0); 757 758 target_if_log_write_spectral_active( 759 __func__, 760 *pval, 761 ret); 762 763 if (ret < 0) { 764 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d", 765 ret); 766 qdf_spin_unlock(&info->osps_lock); 767 return ret; 768 } 769 770 info->osps_cache.osc_spectral_active = *pval; 771 qdf_spin_unlock(&info->osps_lock); 772 break; 773 774 case TARGET_IF_SPECTRAL_INFO_ENABLED: 775 if (input_len != sizeof(info->osps_cache.osc_spectral_enabled)) 776 return -EINVAL; 777 778 pval = (uint8_t *)input; 779 780 qdf_spin_lock(&info->osps_lock); 781 ret = target_if_send_vdev_spectral_enable_cmd(spectral, 782 0, 0, 1, *pval); 783 784 target_if_log_write_spectral_enabled( 785 __func__, 786 *pval, 787 ret); 788 789 if (ret < 0) { 790 spectral_err("target_if_send_vdev_spectral_enable_cmd failed with error=%d", 791 ret); 792 qdf_spin_unlock(&info->osps_lock); 793 return ret; 794 } 795 796 info->osps_cache.osc_spectral_enabled = *pval; 797 qdf_spin_unlock(&info->osps_lock); 798 break; 799 800 case TARGET_IF_SPECTRAL_INFO_PARAMS: 801 if (input_len != sizeof(info->osps_cache.osc_params)) 802 return -EINVAL; 803 804 param = (struct spectral_config *)input; 805 806 qdf_spin_lock(&info->osps_lock); 807 ret = target_if_send_vdev_spectral_configure_cmd(spectral, 808 param); 809 810 target_if_log_write_spectral_params( 811 param, 812 __func__, 813 ret); 814 815 if (ret < 0) { 816 spectral_err("target_if_send_vdev_spectral_configure_cmd failed with error=%d", 817 ret); 818 qdf_spin_unlock(&info->osps_lock); 819 return ret; 820 } 821 822 qdf_mem_copy(&info->osps_cache.osc_params, 823 param, sizeof(info->osps_cache.osc_params)); 824 qdf_spin_unlock(&info->osps_lock); 825 break; 826 827 default: 828 spectral_err("Unknown target_if_spectral_info specifier"); 829 return -EINVAL; 830 } 831 832 return 0; 833 } 834 835 /** 836 * target_if_spectral_get_tsf64() - Function to get the TSF value 837 * @arg: Pointer to handle for Spectral target_if internal private data 838 * 839 * Get the last TSF received in WMI buffer 840 * 841 * Return: TSF value 842 */ 843 static uint64_t 844 target_if_spectral_get_tsf64(void *arg) 845 { 846 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 847 848 return spectral->tsf64; 849 } 850 851 /** 852 * target_if_spectral_get_capability() - Function to get whether a 853 * given Spectral hardware capability is available 854 * @arg: Pointer to handle for Spectral target_if internal private data 855 * @type: Spectral hardware capability type 856 * 857 * Get whether a given Spectral hardware capability is available 858 * 859 * Return: True if the capability is available, false if the capability is not 860 * available 861 */ 862 uint32_t 863 target_if_spectral_get_capability(void *arg, enum spectral_capability_type type) 864 { 865 int status = STATUS_FAIL; 866 867 switch (type) { 868 case SPECTRAL_CAP_PHYDIAG: 869 case SPECTRAL_CAP_RADAR: 870 case SPECTRAL_CAP_SPECTRAL_SCAN: 871 case SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN: 872 status = STATUS_PASS; 873 break; 874 default: 875 status = STATUS_FAIL; 876 } 877 return status; 878 } 879 880 /** 881 * target_if_spectral_set_rxfilter() - Set the RX Filter before Spectral start 882 * @arg: Pointer to handle for Spectral target_if internal private data 883 * @rxfilter: Rx filter to be used 884 * 885 * Note: This is only a placeholder function. It is not currently required since 886 * FW should be taking care of setting the required filters. 887 * 888 * Return: 0 889 */ 890 uint32_t 891 target_if_spectral_set_rxfilter(void *arg, int rxfilter) 892 { 893 /* 894 * Will not be required since enabling of spectral in firmware 895 * will take care of this 896 */ 897 return 0; 898 } 899 900 /** 901 * target_if_spectral_get_rxfilter() - Get the current RX Filter settings 902 * @arg: Pointer to handle for Spectral target_if internal private data 903 * 904 * Note: This is only a placeholder function. It is not currently required since 905 * FW should be taking care of setting the required filters. 906 * 907 * Return: 0 908 */ 909 uint32_t 910 target_if_spectral_get_rxfilter(void *arg) 911 { 912 /* 913 * Will not be required since enabling of spectral in firmware 914 * will take care of this 915 */ 916 return 0; 917 } 918 919 /** 920 * target_if_sops_is_spectral_active() - Get whether Spectral is active 921 * @arg: Pointer to handle for Spectral target_if internal private data 922 * 923 * Function to check whether Spectral is active 924 * 925 * Return: True if Spectral is active, false if Spectral is not active 926 */ 927 uint32_t 928 target_if_sops_is_spectral_active(void *arg) 929 { 930 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 931 uint8_t val = 0; 932 int ret; 933 934 ret = target_if_spectral_info_read( 935 spectral, 936 TARGET_IF_SPECTRAL_INFO_ACTIVE, 937 &val, sizeof(val)); 938 939 if (ret != 0) { 940 /* 941 * Could not determine if Spectral is active. 942 * Return false as a safe value. 943 * XXX: Consider changing the function prototype 944 * to be able to indicate failure to fetch value. 945 */ 946 return 0; 947 } 948 949 return val; 950 } 951 952 /** 953 * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled 954 * @arg: Pointer to handle for Spectral target_if internal private data 955 * 956 * Function to check whether Spectral is enabled 957 * 958 * Return: True if Spectral is enabled, false if Spectral is not enabled 959 */ 960 uint32_t 961 target_if_sops_is_spectral_enabled(void *arg) 962 { 963 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 964 uint8_t val = 0; 965 int ret; 966 967 ret = target_if_spectral_info_read( 968 spectral, 969 TARGET_IF_SPECTRAL_INFO_ENABLED, 970 &val, sizeof(val)); 971 972 if (ret != 0) { 973 /* 974 * Could not determine if Spectral is enabled. 975 * Return false as a safe value. 976 * XXX: Consider changing the function prototype 977 * to be able to indicate failure to fetch value. 978 */ 979 return 0; 980 } 981 982 return val; 983 } 984 985 /** 986 * target_if_sops_start_spectral_scan() - Start Spectral scan 987 * @arg: Pointer to handle for Spectral target_if internal private data 988 * 989 * Function to start spectral scan 990 * 991 * Return: 0 on success else failure 992 */ 993 uint32_t 994 target_if_sops_start_spectral_scan(void *arg) 995 { 996 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 997 uint8_t val = 1; 998 uint8_t enabled = 0; 999 int ret; 1000 1001 ret = target_if_spectral_info_read( 1002 spectral, 1003 TARGET_IF_SPECTRAL_INFO_ENABLED, 1004 &enabled, sizeof(enabled)); 1005 1006 if (ret != 0) { 1007 /* 1008 * Could not determine if Spectral is enabled. Assume we need 1009 * to enable it 1010 */ 1011 enabled = 0; 1012 } 1013 1014 if (!enabled) { 1015 ret = target_if_spectral_info_write( 1016 spectral, 1017 TARGET_IF_SPECTRAL_INFO_ENABLED, 1018 &val, sizeof(val)); 1019 1020 if (ret != 0) 1021 return ret; 1022 } 1023 1024 ret = target_if_spectral_info_write( 1025 spectral, 1026 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1027 &val, sizeof(val)); 1028 1029 if (ret != 0) 1030 return ret; 1031 1032 return 0; 1033 } 1034 1035 /** 1036 * target_if_sops_stop_spectral_scan() - Stop Spectral scan 1037 * @arg: Pointer to handle for Spectral target_if internal private data 1038 * 1039 * Function to stop spectral scan 1040 * 1041 * Return: 0 on success else failure 1042 */ 1043 uint32_t 1044 target_if_sops_stop_spectral_scan(void *arg) 1045 { 1046 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1047 uint8_t val = 0; 1048 int tempret, ret = 0; 1049 1050 tempret = target_if_spectral_info_write( 1051 spectral, 1052 TARGET_IF_SPECTRAL_INFO_ACTIVE, 1053 &val, sizeof(val)); 1054 1055 if (tempret != 0) 1056 ret = tempret; 1057 1058 tempret = target_if_spectral_info_write( 1059 spectral, 1060 TARGET_IF_SPECTRAL_INFO_ENABLED, 1061 &val, sizeof(val)); 1062 1063 if (tempret != 0) 1064 ret = tempret; 1065 1066 return ret; 1067 } 1068 1069 /** 1070 * target_if_spectral_get_extension_channel() - Get the Extension channel 1071 * @arg: Pointer to handle for Spectral target_if internal private data 1072 * 1073 * Function to get the current Extension channel (in MHz) 1074 * 1075 * Return: Current Extension channel (in MHz) on success, 0 on failure or if 1076 * extension channel is not present. 1077 */ 1078 uint32_t 1079 target_if_spectral_get_extension_channel(void *arg) 1080 { 1081 /* 1082 * XXX: Once we expand to use cases where Spectral could be activated 1083 * without a channel being set to VDEV, we need to consider returning a 1084 * negative value in case of failure and having all callers handle this. 1085 */ 1086 1087 struct target_if_spectral *spectral = NULL; 1088 struct wlan_objmgr_vdev *vdev = NULL; 1089 uint16_t sec20chan_freq = 0; 1090 1091 qdf_assert_always(arg); 1092 spectral = (struct target_if_spectral *)arg; 1093 1094 vdev = target_if_spectral_get_vdev(spectral); 1095 if (!vdev) 1096 return 0; 1097 1098 if (target_if_vdev_get_sec20chan_freq_mhz(vdev, &sec20chan_freq) < 0) { 1099 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1100 return 0; 1101 } 1102 1103 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1104 1105 return sec20chan_freq; 1106 } 1107 1108 /** 1109 * target_if_spectral_get_current_channel() - Get the current channel 1110 * @arg: Pointer to handle for Spectral target_if internal private data 1111 * 1112 * Function to get the current channel (in MHz) 1113 * 1114 * Return: Current channel (in MHz) on success, 0 on failure 1115 */ 1116 uint32_t 1117 target_if_spectral_get_current_channel(void *arg) 1118 { 1119 /* 1120 * XXX: Once we expand to use cases where Spectral could be activated 1121 * without a channel being set to VDEV, we need to consider returning a 1122 * negative value in case of failure and having all callers handle this. 1123 */ 1124 1125 struct target_if_spectral *spectral = NULL; 1126 int16_t chan_freq = 0; 1127 struct wlan_objmgr_vdev *vdev = NULL; 1128 1129 qdf_assert_always(arg); 1130 spectral = (struct target_if_spectral *)arg; 1131 1132 vdev = target_if_spectral_get_vdev(spectral); 1133 if (!vdev) 1134 return 0; 1135 1136 chan_freq = target_if_vdev_get_chan_freq(vdev); 1137 if (chan_freq < 0) { 1138 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1139 return 0; 1140 } 1141 1142 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 1143 1144 return chan_freq; 1145 } 1146 1147 /** 1148 * target_if_spectral_reset_hw() - Reset the hardware 1149 * @arg: Pointer to handle for Spectral target_if internal private data 1150 * 1151 * This is only a placeholder since it is not currently required in the offload 1152 * case. 1153 * 1154 * Return: 0 1155 */ 1156 uint32_t 1157 target_if_spectral_reset_hw(void *arg) 1158 { 1159 not_yet_implemented(); 1160 return 0; 1161 } 1162 1163 /** 1164 * target_if_spectral_get_chain_noise_floor() - Get the Chain noise floor from 1165 * Noisefloor history buffer 1166 * @arg: Pointer to handle for Spectral target_if internal private data 1167 * @nf_buf: Pointer to buffer into which chain Noise Floor data should be copied 1168 * 1169 * This is only a placeholder since it is not currently required in the offload 1170 * case. 1171 * 1172 * Return: 0 1173 */ 1174 uint32_t 1175 target_if_spectral_get_chain_noise_floor(void *arg, int16_t *nf_buf) 1176 { 1177 not_yet_implemented(); 1178 return 0; 1179 } 1180 1181 /** 1182 * target_if_spectral_get_ext_noisefloor() - Get the extension channel 1183 * noisefloor 1184 * @arg: Pointer to handle for Spectral target_if internal private data 1185 * 1186 * This is only a placeholder since it is not currently required in the offload 1187 * case. 1188 * 1189 * Return: 0 1190 */ 1191 int8_t 1192 target_if_spectral_get_ext_noisefloor(void *arg) 1193 { 1194 not_yet_implemented(); 1195 return 0; 1196 } 1197 1198 /** 1199 * target_if_spectral_get_ctl_noisefloor() - Get the control channel noisefloor 1200 * @arg: Pointer to handle for Spectral target_if internal private data 1201 * 1202 * This is only a placeholder since it is not currently required in the offload 1203 * case. 1204 * 1205 * Return: 0 1206 */ 1207 int8_t 1208 target_if_spectral_get_ctl_noisefloor(void *arg) 1209 { 1210 not_yet_implemented(); 1211 return 0; 1212 } 1213 1214 /** 1215 * target_if_spectral_sops_configure_params() - Configure user supplied Spectral 1216 * parameters 1217 * @arg: Pointer to handle for Spectral target_if internal private data 1218 * @params: Spectral parameters 1219 * 1220 * Function to configure spectral parameters 1221 * 1222 * Return: 0 on success else failure 1223 */ 1224 uint32_t 1225 target_if_spectral_sops_configure_params( 1226 void *arg, struct spectral_config *params) 1227 { 1228 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1229 1230 return target_if_spectral_info_write( 1231 spectral, 1232 TARGET_IF_SPECTRAL_INFO_PARAMS, 1233 params, sizeof(*params)); 1234 } 1235 1236 /** 1237 * target_if_spectral_sops_get_params() - Get user configured Spectral 1238 * parameters 1239 * @arg: Pointer to handle for Spectral target_if internal private data 1240 * @params: Pointer to buffer into which Spectral parameters should be copied 1241 * 1242 * Function to get the configured spectral parameters 1243 * 1244 * Return: 0 on success else failure 1245 */ 1246 uint32_t 1247 target_if_spectral_sops_get_params(void *arg, struct spectral_config *params) 1248 { 1249 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1250 1251 return target_if_spectral_info_read( 1252 spectral, 1253 TARGET_IF_SPECTRAL_INFO_PARAMS, 1254 params, sizeof(*params)); 1255 } 1256 1257 /** 1258 * target_if_spectral_get_ent_mask() - Get enterprise mask 1259 * @arg: Pointer to handle for Spectral target_if internal private data 1260 * 1261 * This is only a placeholder since it is not currently required in the offload 1262 * case. 1263 * 1264 * Return: 0 1265 */ 1266 static uint32_t 1267 target_if_spectral_get_ent_mask(void *arg) 1268 { 1269 not_yet_implemented(); 1270 return 0; 1271 } 1272 1273 /** 1274 * target_if_spectral_get_macaddr() - Get radio MAC address 1275 * @arg: Pointer to handle for Spectral target_if internal private data 1276 * @addr: Pointer to buffer into which MAC address should be copied 1277 * 1278 * Function to get the MAC address of the pdev 1279 * 1280 * Return: 0 on success, -1 on failure 1281 */ 1282 static uint32_t 1283 target_if_spectral_get_macaddr(void *arg, char *addr) 1284 { 1285 uint8_t *myaddr = NULL; 1286 struct target_if_spectral *spectral = (struct target_if_spectral *)arg; 1287 struct wlan_objmgr_pdev *pdev = NULL; 1288 1289 pdev = spectral->pdev_obj; 1290 1291 wlan_pdev_obj_lock(pdev); 1292 myaddr = wlan_pdev_get_hw_macaddr(pdev); 1293 wlan_pdev_obj_unlock(pdev); 1294 qdf_mem_copy(addr, myaddr, IEEE80211_ADDR_LEN); 1295 1296 return 0; 1297 } 1298 1299 /** 1300 * target_if_init_spectral_capability() - Initialize Spectral capability 1301 * @spectral: Pointer to Spectral target_if internal private data 1302 * 1303 * This is a workaround. 1304 * 1305 * Return: None 1306 */ 1307 void 1308 target_if_init_spectral_capability(struct target_if_spectral *spectral) 1309 { 1310 struct spectral_caps *pcap = &spectral->capability; 1311 1312 /* XXX : Workaround: Set Spectral capability */ 1313 pcap = &spectral->capability; 1314 pcap->phydiag_cap = 1; 1315 pcap->radar_cap = 1; 1316 pcap->spectral_cap = 1; 1317 pcap->advncd_spectral_cap = 1; 1318 } 1319 1320 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1321 /** 1322 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 1323 * internal operations with functions related to spectral simulation 1324 * @p_sops: spectral low level ops table 1325 * 1326 * Initialize spectral target_if internal operations with functions 1327 * related to spectral simulation 1328 * 1329 * Return: None 1330 */ 1331 static void 1332 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 1333 { 1334 /* 1335 * Spectral simulation is currently intended for platform transitions 1336 * where underlying HW support may not be available for some time. 1337 * Hence, we do not currently provide a runtime switch to turn the 1338 * simulation on or off. 1339 * In case of future requirements where runtime switches are required, 1340 * this can be added. But it is suggested to use application layer 1341 * simulation as far as possible in such cases, since the main 1342 * use of record and replay of samples would concern higher 1343 * level sample processing rather than lower level delivery. 1344 */ 1345 p_sops->is_spectral_enabled = target_if_spectral_sops_sim_is_enabled; 1346 p_sops->is_spectral_active = target_if_spectral_sops_sim_is_active; 1347 p_sops->start_spectral_scan = target_if_spectral_sops_sim_start_scan; 1348 p_sops->stop_spectral_scan = target_if_spectral_sops_sim_stop_scan; 1349 p_sops->configure_spectral = 1350 target_if_spectral_sops_sim_configure_params; 1351 p_sops->get_spectral_config = target_if_spectral_sops_sim_get_params; 1352 } 1353 1354 #else 1355 /** 1356 * target_if_init_spectral_simulation_ops() - Initialize spectral target_if 1357 * internal operations 1358 * @p_sops: spectral low level ops table 1359 * 1360 * Return: None 1361 */ 1362 static void 1363 target_if_init_spectral_simulation_ops(struct target_if_spectral_ops *p_sops) 1364 { 1365 p_sops->is_spectral_enabled = target_if_sops_is_spectral_enabled; 1366 p_sops->is_spectral_active = target_if_sops_is_spectral_active; 1367 p_sops->start_spectral_scan = target_if_sops_start_spectral_scan; 1368 p_sops->stop_spectral_scan = target_if_sops_stop_spectral_scan; 1369 p_sops->configure_spectral = target_if_spectral_sops_configure_params; 1370 p_sops->get_spectral_config = target_if_spectral_sops_get_params; 1371 } 1372 #endif 1373 1374 /** 1375 * target_if_init_spectral_ops_common() - Initialize Spectral target_if internal 1376 * operations common to all Spectral chipset generations 1377 * 1378 * Initializes target_if_spectral_ops common to all chipset generations 1379 * 1380 * Return: None 1381 */ 1382 static void 1383 target_if_init_spectral_ops_common(void) 1384 { 1385 struct target_if_spectral_ops *p_sops = &spectral_ops; 1386 1387 p_sops->get_tsf64 = target_if_spectral_get_tsf64; 1388 p_sops->get_capability = target_if_spectral_get_capability; 1389 p_sops->set_rxfilter = target_if_spectral_set_rxfilter; 1390 p_sops->get_rxfilter = target_if_spectral_get_rxfilter; 1391 1392 target_if_init_spectral_simulation_ops(p_sops); 1393 1394 p_sops->get_extension_channel = 1395 target_if_spectral_get_extension_channel; 1396 p_sops->get_ctl_noisefloor = target_if_spectral_get_ctl_noisefloor; 1397 p_sops->get_ext_noisefloor = target_if_spectral_get_ext_noisefloor; 1398 p_sops->get_ent_spectral_mask = target_if_spectral_get_ent_mask; 1399 p_sops->get_mac_address = target_if_spectral_get_macaddr; 1400 p_sops->get_current_channel = target_if_spectral_get_current_channel; 1401 p_sops->reset_hw = target_if_spectral_reset_hw; 1402 p_sops->get_chain_noise_floor = 1403 target_if_spectral_get_chain_noise_floor; 1404 } 1405 1406 /** 1407 * target_if_init_spectral_ops_gen2() - Initialize Spectral target_if internal 1408 * operations specific to Spectral chipset generation 2. 1409 * 1410 * Initializes target_if_spectral_ops specific to Spectral chipset generation 2. 1411 * 1412 * Return: None 1413 */ 1414 static void 1415 target_if_init_spectral_ops_gen2(void) 1416 { 1417 struct target_if_spectral_ops *p_sops = &spectral_ops; 1418 1419 p_sops->spectral_process_phyerr = target_if_process_phyerr_gen2; 1420 } 1421 1422 /** 1423 * target_if_init_spectral_ops_gen3() - Initialize Spectral target_if internal 1424 * operations specific to Spectral chipset generation 3. 1425 * 1426 * Initializes target_if_spectral_ops specific to Spectral chipset generation 3. 1427 * 1428 * Return: None 1429 */ 1430 static void 1431 target_if_init_spectral_ops_gen3(void) 1432 { 1433 /* Placeholder */ 1434 spectral_debug("Placeholder for gen3 spectral ops registration"); 1435 return; 1436 } 1437 1438 /** 1439 * target_if_init_spectral_ops() - Initialize target_if internal Spectral 1440 * operations. 1441 * @spectral: Pointer to Spectral target_if internal private data 1442 * 1443 * Initializes all function pointers in target_if_spectral_ops for 1444 * all generations 1445 * 1446 * Return: None 1447 */ 1448 static void 1449 target_if_init_spectral_ops(struct target_if_spectral *spectral) 1450 { 1451 target_if_init_spectral_ops_common(); 1452 if (spectral->spectral_gen == SPECTRAL_GEN2) 1453 target_if_init_spectral_ops_gen2(); 1454 else if (spectral->spectral_gen == SPECTRAL_GEN3) 1455 target_if_init_spectral_ops_gen3(); 1456 else 1457 spectral_err("Invalid Spectral generation"); 1458 } 1459 1460 /* 1461 * Dummy Functions: 1462 * These functions are initially registered to avoid any crashes due to 1463 * invocation of spectral functions before they are registered. 1464 */ 1465 1466 static uint64_t 1467 null_get_tsf64(void *arg) 1468 { 1469 spectral_ops_not_registered("get_tsf64"); 1470 return 0; 1471 } 1472 1473 static uint32_t 1474 null_get_capability(void *arg, enum spectral_capability_type type) 1475 { 1476 /* 1477 * TODO : We should have conditional compilation to get the capability 1478 * : We have not yet attahced ATH layer here, so there is no 1479 * : way to check the HAL capbalities 1480 */ 1481 spectral_ops_not_registered("get_capability"); 1482 1483 /* TODO : For the time being, we are returning TRUE */ 1484 return true; 1485 } 1486 1487 static uint32_t 1488 null_set_rxfilter(void *arg, int rxfilter) 1489 { 1490 spectral_ops_not_registered("set_rxfilter"); 1491 return 1; 1492 } 1493 1494 static uint32_t 1495 null_get_rxfilter(void *arg) 1496 { 1497 spectral_ops_not_registered("get_rxfilter"); 1498 return 0; 1499 } 1500 1501 static uint32_t 1502 null_is_spectral_active(void *arg) 1503 { 1504 spectral_ops_not_registered("is_spectral_active"); 1505 return 1; 1506 } 1507 1508 static uint32_t 1509 null_is_spectral_enabled(void *arg) 1510 { 1511 spectral_ops_not_registered("is_spectral_enabled"); 1512 return 1; 1513 } 1514 1515 static uint32_t 1516 null_start_spectral_scan(void *arg) 1517 { 1518 spectral_ops_not_registered("start_spectral_scan"); 1519 return 1; 1520 } 1521 1522 static uint32_t 1523 null_stop_spectral_scan(void *arg) 1524 { 1525 spectral_ops_not_registered("stop_spectral_scan"); 1526 return 1; 1527 } 1528 1529 static uint32_t 1530 null_get_extension_channel(void *arg) 1531 { 1532 spectral_ops_not_registered("get_extension_channel"); 1533 return 1; 1534 } 1535 1536 static int8_t 1537 null_get_ctl_noisefloor(void *arg) 1538 { 1539 spectral_ops_not_registered("get_ctl_noisefloor"); 1540 return 1; 1541 } 1542 1543 static int8_t 1544 null_get_ext_noisefloor(void *arg) 1545 { 1546 spectral_ops_not_registered("get_ext_noisefloor"); 1547 return 0; 1548 } 1549 1550 static uint32_t 1551 null_configure_spectral(void *arg, struct spectral_config *params) 1552 { 1553 spectral_ops_not_registered("configure_spectral"); 1554 return 0; 1555 } 1556 1557 static uint32_t 1558 null_get_spectral_config(void *arg, struct spectral_config *params) 1559 { 1560 spectral_ops_not_registered("get_spectral_config"); 1561 return 0; 1562 } 1563 1564 static uint32_t 1565 null_get_ent_spectral_mask(void *arg) 1566 { 1567 spectral_ops_not_registered("get_ent_spectral_mask"); 1568 return 0; 1569 } 1570 1571 static uint32_t 1572 null_get_mac_address(void *arg, char *addr) 1573 { 1574 spectral_ops_not_registered("get_mac_address"); 1575 return 0; 1576 } 1577 1578 static uint32_t 1579 null_get_current_channel(void *arg) 1580 { 1581 spectral_ops_not_registered("get_current_channel"); 1582 return 0; 1583 } 1584 1585 static uint32_t 1586 null_reset_hw(void *arg) 1587 { 1588 spectral_ops_not_registered("get_current_channel"); 1589 return 0; 1590 } 1591 1592 static uint32_t 1593 null_get_chain_noise_floor(void *arg, int16_t *nf_buf) 1594 { 1595 spectral_ops_not_registered("get_chain_noise_floor"); 1596 return 0; 1597 } 1598 1599 static int 1600 null_spectral_process_phyerr(struct target_if_spectral *spectral, 1601 uint8_t *data, 1602 uint32_t datalen, 1603 struct target_if_spectral_rfqual_info *p_rfqual, 1604 struct target_if_spectral_chan_info *p_chaninfo, 1605 uint64_t tsf64, 1606 struct target_if_spectral_acs_stats *acs_stats) 1607 { 1608 spectral_ops_not_registered("spectral_process_phyerr"); 1609 return 0; 1610 } 1611 1612 /** 1613 * target_if_spectral_init_dummy_function_table() - 1614 * Initialize target_if internal 1615 * Spectral operations to dummy functions 1616 * @ps: Pointer to Spectral target_if internal private data 1617 * 1618 * Initialize all the function pointers in target_if_spectral_ops with 1619 * dummy functions. 1620 * 1621 * Return: None 1622 */ 1623 static void 1624 target_if_spectral_init_dummy_function_table(struct target_if_spectral *ps) 1625 { 1626 struct target_if_spectral_ops *p_sops = GET_TARGET_IF_SPECTRAL_OPS(ps); 1627 1628 p_sops->get_tsf64 = null_get_tsf64; 1629 p_sops->get_capability = null_get_capability; 1630 p_sops->set_rxfilter = null_set_rxfilter; 1631 p_sops->get_rxfilter = null_get_rxfilter; 1632 p_sops->is_spectral_enabled = null_is_spectral_enabled; 1633 p_sops->is_spectral_active = null_is_spectral_active; 1634 p_sops->start_spectral_scan = null_start_spectral_scan; 1635 p_sops->stop_spectral_scan = null_stop_spectral_scan; 1636 p_sops->get_extension_channel = null_get_extension_channel; 1637 p_sops->get_ctl_noisefloor = null_get_ctl_noisefloor; 1638 p_sops->get_ext_noisefloor = null_get_ext_noisefloor; 1639 p_sops->configure_spectral = null_configure_spectral; 1640 p_sops->get_spectral_config = null_get_spectral_config; 1641 p_sops->get_ent_spectral_mask = null_get_ent_spectral_mask; 1642 p_sops->get_mac_address = null_get_mac_address; 1643 p_sops->get_current_channel = null_get_current_channel; 1644 p_sops->reset_hw = null_reset_hw; 1645 p_sops->get_chain_noise_floor = null_get_chain_noise_floor; 1646 p_sops->spectral_process_phyerr = null_spectral_process_phyerr; 1647 } 1648 1649 /** 1650 * target_if_spectral_register_funcs() - Initialize target_if internal Spectral 1651 * operations 1652 * @spectral: Pointer to Spectral target_if internal private data 1653 * @p: Pointer to Spectral function table 1654 * 1655 * Return: None 1656 */ 1657 static void 1658 target_if_spectral_register_funcs(struct target_if_spectral *spectral, 1659 struct target_if_spectral_ops *p) 1660 { 1661 struct target_if_spectral_ops *p_sops = 1662 GET_TARGET_IF_SPECTRAL_OPS(spectral); 1663 1664 p_sops->get_tsf64 = p->get_tsf64; 1665 p_sops->get_capability = p->get_capability; 1666 p_sops->set_rxfilter = p->set_rxfilter; 1667 p_sops->get_rxfilter = p->get_rxfilter; 1668 p_sops->is_spectral_enabled = p->is_spectral_enabled; 1669 p_sops->is_spectral_active = p->is_spectral_active; 1670 p_sops->start_spectral_scan = p->start_spectral_scan; 1671 p_sops->stop_spectral_scan = p->stop_spectral_scan; 1672 p_sops->get_extension_channel = p->get_extension_channel; 1673 p_sops->get_ctl_noisefloor = p->get_ctl_noisefloor; 1674 p_sops->get_ext_noisefloor = p->get_ext_noisefloor; 1675 p_sops->configure_spectral = p->configure_spectral; 1676 p_sops->get_spectral_config = p->get_spectral_config; 1677 p_sops->get_ent_spectral_mask = p->get_ent_spectral_mask; 1678 p_sops->get_mac_address = p->get_mac_address; 1679 p_sops->get_current_channel = p->get_current_channel; 1680 p_sops->reset_hw = p->reset_hw; 1681 p_sops->get_chain_noise_floor = p->get_chain_noise_floor; 1682 p_sops->spectral_process_phyerr = p->spectral_process_phyerr; 1683 } 1684 1685 /** 1686 * target_if_spectral_clear_stats() - Clear Spectral stats 1687 * @spectral: Pointer to Spectral target_if internal private data 1688 * 1689 * Function to clear spectral stats 1690 * 1691 * Return: None 1692 */ 1693 static void 1694 target_if_spectral_clear_stats(struct target_if_spectral *spectral) 1695 { 1696 struct target_if_spectral_ops *p_sops = 1697 GET_TARGET_IF_SPECTRAL_OPS(spectral); 1698 1699 qdf_mem_zero(&spectral->spectral_stats, 1700 sizeof(struct target_if_spectral_stats)); 1701 spectral->spectral_stats.last_reset_tstamp = 1702 p_sops->get_tsf64(spectral); 1703 } 1704 1705 /** 1706 * target_if_spectral_check_hw_capability() - Check whether HW supports spectral 1707 * @spectral: Pointer to Spectral target_if internal private data 1708 * 1709 * Function to check whether hardware supports spectral 1710 * 1711 * Return: True if HW supports Spectral, false if HW does not support Spectral 1712 */ 1713 static int 1714 target_if_spectral_check_hw_capability(struct target_if_spectral *spectral) 1715 { 1716 struct target_if_spectral_ops *p_sops = NULL; 1717 struct spectral_caps *pcap = NULL; 1718 int is_spectral_supported = true; 1719 1720 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 1721 pcap = &spectral->capability; 1722 1723 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG) == false) { 1724 is_spectral_supported = false; 1725 spectral_info("SPECTRAL : No PHYDIAG support"); 1726 return is_spectral_supported; 1727 } 1728 pcap->phydiag_cap = 1; 1729 1730 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR) == false) { 1731 is_spectral_supported = false; 1732 spectral_info("SPECTRAL : No RADAR support"); 1733 return is_spectral_supported; 1734 } 1735 pcap->radar_cap = 1; 1736 1737 if (p_sops->get_capability(spectral, 1738 SPECTRAL_CAP_SPECTRAL_SCAN) == false) { 1739 is_spectral_supported = false; 1740 spectral_info("SPECTRAL : No SPECTRAL SUPPORT"); 1741 return is_spectral_supported; 1742 } 1743 pcap->spectral_cap = 1; 1744 1745 if (p_sops->get_capability(spectral, SPECTRAL_CAP_ADVNCD_SPECTRAL_SCAN) 1746 == false) { 1747 spectral_info("SPECTRAL : No ADVANCED SPECTRAL SUPPORT"); 1748 } else { 1749 pcap->advncd_spectral_cap = 1; 1750 } 1751 1752 return is_spectral_supported; 1753 } 1754 1755 /** 1756 * target_if_spectral_init_param_defaults() - Initialize Spectral 1757 * parameter defaults 1758 * @spectral: Pointer to Spectral target_if internal private data 1759 * 1760 * It is the caller's responsibility to ensure that the Spectral parameters 1761 * structure passed as part of Spectral target_if internal private data is 1762 * valid. 1763 * 1764 * Return: None 1765 */ 1766 static void 1767 target_if_spectral_init_param_defaults(struct target_if_spectral *spectral) 1768 { 1769 struct spectral_config *params = &spectral->params; 1770 1771 params->ss_count = SPECTRAL_SCAN_COUNT_DEFAULT; 1772 params->ss_period = SPECTRAL_SCAN_PERIOD_DEFAULT; 1773 params->ss_spectral_pri = SPECTRAL_SCAN_PRIORITY_DEFAULT; 1774 params->ss_fft_size = SPECTRAL_SCAN_FFT_SIZE_DEFAULT; 1775 params->ss_gc_ena = SPECTRAL_SCAN_GC_ENA_DEFAULT; 1776 params->ss_restart_ena = SPECTRAL_SCAN_RESTART_ENA_DEFAULT; 1777 params->ss_noise_floor_ref = SPECTRAL_SCAN_NOISE_FLOOR_REF_DEFAULT; 1778 params->ss_init_delay = SPECTRAL_SCAN_INIT_DELAY_DEFAULT; 1779 params->ss_nb_tone_thr = SPECTRAL_SCAN_NB_TONE_THR_DEFAULT; 1780 params->ss_str_bin_thr = SPECTRAL_SCAN_STR_BIN_THR_DEFAULT; 1781 params->ss_wb_rpt_mode = SPECTRAL_SCAN_WB_RPT_MODE_DEFAULT; 1782 params->ss_rssi_rpt_mode = SPECTRAL_SCAN_RSSI_RPT_MODE_DEFAULT; 1783 params->ss_rssi_thr = SPECTRAL_SCAN_RSSI_THR_DEFAULT; 1784 params->ss_pwr_format = SPECTRAL_SCAN_PWR_FORMAT_DEFAULT; 1785 params->ss_rpt_mode = SPECTRAL_SCAN_RPT_MODE_DEFAULT; 1786 params->ss_bin_scale = SPECTRAL_SCAN_BIN_SCALE_DEFAULT; 1787 params->ss_dbm_adj = SPECTRAL_SCAN_DBM_ADJ_DEFAULT; 1788 /* 1789 * XXX 1790 * SPECTRAL_SCAN_CHN_MASK_DEFAULT (0x1) specifies that chain 0 is to be 1791 * used 1792 * for Spectral. This is expected to be an optimal configuration for 1793 * most chipsets considering aspects like power save. But this can later 1794 * optionally be changed to be set to the default system Rx chainmask 1795 * advertised by FW (if required for some purpose), once the Convergence 1796 * framework supports such retrieval at pdev attach time. 1797 */ 1798 params->ss_chn_mask = SPECTRAL_SCAN_CHN_MASK_DEFAULT; 1799 params->ss_short_report = SPECTRAL_SCAN_SHORT_REPORT_DEFAULT; 1800 params->ss_fft_period = SPECTRAL_SCAN_FFT_PERIOD_DEFAULT; 1801 } 1802 1803 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1804 /** 1805 * target_if_spectral_detach_simulation() - De-initialize Spectral 1806 * Simulation functionality 1807 * @spectral: Pointer to Spectral target_if internal private data 1808 * 1809 * Function to de-initialize Spectral Simulation functionality 1810 * 1811 * Return: None 1812 */ 1813 static void 1814 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 1815 { 1816 target_if_spectral_sim_detach(spectral); 1817 } 1818 1819 #else 1820 static void 1821 target_if_spectral_detach_simulation(struct target_if_spectral *spectral) 1822 { 1823 } 1824 #endif 1825 1826 /** 1827 * target_if_spectral_detach() - De-initialize target_if Spectral 1828 * @pdev: Pointer to pdev object 1829 * 1830 * Function to detach target_if spectral 1831 * 1832 * Return: None 1833 */ 1834 static void 1835 target_if_spectral_detach(struct target_if_spectral *spectral) 1836 { 1837 spectral_info("spectral detach"); 1838 1839 if (spectral) { 1840 qdf_spinlock_destroy(&spectral->param_info.osps_lock); 1841 1842 target_if_spectral_detach_simulation(spectral); 1843 1844 qdf_spinlock_destroy(&spectral->spectral_lock); 1845 qdf_spinlock_destroy(&spectral->noise_pwr_reports_lock); 1846 1847 qdf_mem_free(spectral); 1848 spectral = NULL; 1849 } 1850 } 1851 1852 #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION 1853 /** 1854 * target_if_spectral_attach_simulation() - Initialize Spectral Simulation 1855 * functionality 1856 * @spectral: Pointer to Spectral target_if internal private data 1857 * 1858 * Function to initialize spectral simulation functionality 1859 * 1860 * Return: 0 on success, negative error code on failure 1861 */ 1862 static int 1863 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 1864 { 1865 if (target_if_spectral_sim_attach(spectral)) { 1866 qdf_mem_free(spectral); 1867 return -EPERM; 1868 } 1869 return 0; 1870 } 1871 1872 #else 1873 static int 1874 target_if_spectral_attach_simulation(struct target_if_spectral *spectral) 1875 { 1876 return 0; 1877 } 1878 #endif 1879 1880 /** 1881 * target_if_pdev_spectral_init() - Initialize target_if Spectral 1882 * functionality for the given pdev 1883 * @pdev: Pointer to pdev object 1884 * 1885 * Function to initialize pointer to spectral target_if internal private data 1886 * 1887 * Return: On success, pointer to Spectral target_if internal private data, on 1888 * failure, NULL 1889 */ 1890 void * 1891 target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) 1892 { 1893 struct target_if_spectral_ops *p_sops = NULL; 1894 struct target_if_spectral *spectral = NULL; 1895 #ifdef CONFIG_WIN 1896 uint32_t target_type; 1897 uint32_t target_revision; 1898 struct wlan_objmgr_psoc *psoc; 1899 struct wlan_lmac_if_target_tx_ops *tx_ops; 1900 #endif 1901 1902 if (!pdev) { 1903 spectral_err("SPECTRAL: pdev is NULL!"); 1904 return NULL; 1905 } 1906 spectral = (struct target_if_spectral *)qdf_mem_malloc( 1907 sizeof(struct target_if_spectral)); 1908 if (!spectral) { 1909 spectral_err("SPECTRAL : Memory allocation failed"); 1910 return spectral; 1911 } 1912 qdf_mem_zero(spectral, sizeof(struct target_if_spectral)); 1913 /* Store pdev in Spectral */ 1914 spectral->pdev_obj = pdev; 1915 1916 #ifdef CONFIG_WIN 1917 psoc = wlan_pdev_get_psoc(pdev); 1918 1919 tx_ops = &psoc->soc_cb.tx_ops.target_tx_ops; 1920 1921 if (tx_ops->tgt_get_tgt_type) { 1922 target_type = tx_ops->tgt_get_tgt_type(psoc); 1923 } else { 1924 qdf_mem_free(spectral); 1925 return NULL; 1926 } 1927 1928 if (tx_ops->tgt_get_tgt_revision) { 1929 target_revision = tx_ops->tgt_get_tgt_revision(psoc); 1930 } else { 1931 qdf_mem_free(spectral); 1932 return NULL; 1933 } 1934 #endif 1935 1936 /* init the function ptr table */ 1937 target_if_spectral_init_dummy_function_table(spectral); 1938 1939 /* get spectral function table */ 1940 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 1941 /* TODO : Should this be called here of after ath_attach ? */ 1942 if (p_sops->get_capability(spectral, SPECTRAL_CAP_PHYDIAG)) 1943 spectral_info("HAL_CAP_PHYDIAG : Capable"); 1944 1945 /* TODO: Need to fix the capablity check for RADAR */ 1946 if (p_sops->get_capability(spectral, SPECTRAL_CAP_RADAR)) 1947 spectral_info("HAL_CAP_RADAR : Capable"); 1948 1949 /* TODO : Need to fix the capablity check for SPECTRAL */ 1950 /* TODO : Should this be called here of after ath_attach ? */ 1951 if (p_sops->get_capability(spectral, SPECTRAL_CAP_SPECTRAL_SCAN)) 1952 spectral_info("HAL_CAP_SPECTRAL_SCAN : Capable"); 1953 1954 qdf_spinlock_create(&spectral->spectral_lock); 1955 qdf_spinlock_create(&spectral->noise_pwr_reports_lock); 1956 target_if_spectral_clear_stats(spectral); 1957 1958 /* Set the default values for spectral parameters */ 1959 target_if_spectral_init_param_defaults(spectral); 1960 #ifdef CONFIG_WIN 1961 if (target_type == TARGET_TYPE_QCA8074) 1962 spectral->fftbin_size_war = 1; 1963 else 1964 spectral->fftbin_size_war = 0; 1965 if ((target_type == TARGET_TYPE_QCA8074) || ( 1966 target_type == TARGET_TYPE_QCA6290)) { 1967 spectral->spectral_gen = SPECTRAL_GEN3; 1968 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN3; 1969 spectral->tag_sscan_summary_exp = 1970 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3; 1971 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN3; 1972 spectral->tlvhdr_size = SPECTRAL_PHYERR_TLVSIZE_GEN3; 1973 } else 1974 #endif 1975 { 1976 spectral->spectral_gen = SPECTRAL_GEN2; 1977 spectral->hdr_sig_exp = SPECTRAL_PHYERR_SIGNATURE_GEN2; 1978 spectral->tag_sscan_summary_exp = 1979 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2; 1980 spectral->tag_sscan_fft_exp = TLV_TAG_SEARCH_FFT_REPORT_GEN2; 1981 spectral->tlvhdr_size = sizeof(struct spectral_phyerr_tlv_gen2); 1982 } 1983 1984 if (target_if_spectral_attach_simulation(spectral) < 0) 1985 return NULL; 1986 1987 target_if_init_spectral_ops(spectral); 1988 1989 qdf_spinlock_create(&spectral->param_info.osps_lock); 1990 spectral->param_info.osps_cache.osc_is_valid = 0; 1991 1992 target_if_spectral_register_funcs(spectral, &spectral_ops); 1993 1994 if (target_if_spectral_check_hw_capability(spectral) == false) { 1995 target_if_spectral_detach(spectral); 1996 spectral = NULL; 1997 } else { 1998 /* 1999 * TODO: Once the driver architecture transitions to chipset 2000 * versioning based checks, reflect this here. 2001 */ 2002 spectral->is_160_format = false; 2003 spectral->is_lb_edge_extrabins_format = false; 2004 spectral->is_rb_edge_extrabins_format = false; 2005 #ifdef CONFIG_WIN 2006 2007 if (target_type == TARGET_TYPE_QCA9984 || 2008 target_type == TARGET_TYPE_QCA9888) { 2009 spectral->is_160_format = true; 2010 spectral->is_lb_edge_extrabins_format = true; 2011 spectral->is_rb_edge_extrabins_format = true; 2012 } else if ((target_type == TARGET_TYPE_AR900B) && 2013 (target_revision == AR900B_REV_2)) { 2014 spectral->is_rb_edge_extrabins_format = true; 2015 } 2016 2017 if (target_type == TARGET_TYPE_QCA9984 || 2018 target_type == TARGET_TYPE_QCA9888) 2019 spectral->is_sec80_rssi_war_required = true; 2020 spectral->use_nl_bcast = true; 2021 #else 2022 spectral->use_nl_bcast = false; 2023 #endif 2024 } 2025 2026 return spectral; 2027 } 2028 2029 /** 2030 * target_if_pdev_spectral_deinit() - De-initialize target_if Spectral 2031 * functionality for the given pdev 2032 * @pdev: Pointer to pdev object 2033 * 2034 * Function to de-initialize pointer to spectral target_if internal private data 2035 * 2036 * Return: None 2037 */ 2038 void 2039 target_if_pdev_spectral_deinit(struct wlan_objmgr_pdev *pdev) 2040 { 2041 struct target_if_spectral *spectral = NULL; 2042 2043 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2044 if (!spectral) { 2045 spectral_err("SPECTRAL : Module doesn't exist"); 2046 return; 2047 } 2048 target_if_spectral_detach(spectral); 2049 2050 return; 2051 } 2052 2053 /** 2054 * target_if_set_spectral_config() - Set spectral config 2055 * @pdev: Pointer to pdev object 2056 * @threshtype: config type 2057 * @value: config value 2058 * 2059 * API to set spectral configurations 2060 * 2061 * Return: 0 on success else failure 2062 */ 2063 int 2064 target_if_set_spectral_config(struct wlan_objmgr_pdev *pdev, 2065 const uint32_t threshtype, const uint32_t value) 2066 { 2067 struct spectral_config params; 2068 struct target_if_spectral_ops *p_sops = NULL; 2069 struct target_if_spectral *spectral = NULL; 2070 2071 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2072 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2073 if (!spectral) { 2074 spectral_err("spectral object is NULL"); 2075 return -EPERM; 2076 } 2077 2078 switch (threshtype) { 2079 case SPECTRAL_PARAM_FFT_PERIOD: 2080 spectral->params.ss_fft_period = value; 2081 break; 2082 case SPECTRAL_PARAM_SCAN_PERIOD: 2083 spectral->params.ss_period = value; 2084 break; 2085 case SPECTRAL_PARAM_SCAN_COUNT: 2086 spectral->params.ss_count = value; 2087 break; 2088 case SPECTRAL_PARAM_SHORT_REPORT: 2089 spectral->params.ss_short_report = (!!value) ? true : false; 2090 break; 2091 case SPECTRAL_PARAM_SPECT_PRI: 2092 spectral->params.ss_spectral_pri = (!!value) ? true : false; 2093 break; 2094 case SPECTRAL_PARAM_FFT_SIZE: 2095 spectral->params.ss_fft_size = value; 2096 break; 2097 case SPECTRAL_PARAM_GC_ENA: 2098 spectral->params.ss_gc_ena = !!value; 2099 break; 2100 case SPECTRAL_PARAM_RESTART_ENA: 2101 spectral->params.ss_restart_ena = !!value; 2102 break; 2103 case SPECTRAL_PARAM_NOISE_FLOOR_REF: 2104 spectral->params.ss_noise_floor_ref = value; 2105 break; 2106 case SPECTRAL_PARAM_INIT_DELAY: 2107 spectral->params.ss_init_delay = value; 2108 break; 2109 case SPECTRAL_PARAM_NB_TONE_THR: 2110 spectral->params.ss_nb_tone_thr = value; 2111 break; 2112 case SPECTRAL_PARAM_STR_BIN_THR: 2113 spectral->params.ss_str_bin_thr = value; 2114 break; 2115 case SPECTRAL_PARAM_WB_RPT_MODE: 2116 spectral->params.ss_wb_rpt_mode = !!value; 2117 break; 2118 case SPECTRAL_PARAM_RSSI_RPT_MODE: 2119 spectral->params.ss_rssi_rpt_mode = !!value; 2120 break; 2121 case SPECTRAL_PARAM_RSSI_THR: 2122 spectral->params.ss_rssi_thr = value; 2123 break; 2124 case SPECTRAL_PARAM_PWR_FORMAT: 2125 spectral->params.ss_pwr_format = !!value; 2126 break; 2127 case SPECTRAL_PARAM_RPT_MODE: 2128 spectral->params.ss_rpt_mode = value; 2129 break; 2130 case SPECTRAL_PARAM_BIN_SCALE: 2131 spectral->params.ss_bin_scale = value; 2132 break; 2133 case SPECTRAL_PARAM_DBM_ADJ: 2134 spectral->params.ss_dbm_adj = !!value; 2135 break; 2136 case SPECTRAL_PARAM_CHN_MASK: 2137 spectral->params.ss_chn_mask = value; 2138 break; 2139 } 2140 2141 p_sops->configure_spectral(spectral, &spectral->params); 2142 /* only to validate the writes */ 2143 p_sops->get_spectral_config(spectral, ¶ms); 2144 return 0; 2145 } 2146 2147 /** 2148 * target_if_get_fft_bin_count() - Get fft bin count for a given fft length 2149 * @fft_len: FFT length 2150 * @pdev: Pointer to pdev object 2151 * 2152 * API to get fft bin count for a given fft length 2153 * 2154 * Return: FFt bin count 2155 */ 2156 static int 2157 target_if_get_fft_bin_count(int fft_len) 2158 { 2159 int bin_count = 0; 2160 2161 switch (fft_len) { 2162 case 5: 2163 bin_count = 16; 2164 break; 2165 case 6: 2166 bin_count = 32; 2167 break; 2168 case 7: 2169 bin_count = 64; 2170 break; 2171 case 8: 2172 bin_count = 128; 2173 break; 2174 case 9: 2175 bin_count = 256; 2176 break; 2177 default: 2178 break; 2179 } 2180 2181 return bin_count; 2182 } 2183 2184 /** 2185 * target_if_init_upper_lower_flags() - Initializes control and extension 2186 * segment flags 2187 * @fft_len: FFT length 2188 * @pdev: Pointer to pdev object 2189 * 2190 * API to initialize the control and extension flags with the lower/upper 2191 * segment based on the HT mode 2192 * 2193 * Return: FFt bin count 2194 */ 2195 static void 2196 target_if_init_upper_lower_flags(struct target_if_spectral *spectral) 2197 { 2198 int current_channel = 0; 2199 int ext_channel = 0; 2200 struct target_if_spectral_ops *p_sops = 2201 GET_TARGET_IF_SPECTRAL_OPS(spectral); 2202 2203 current_channel = p_sops->get_current_channel(spectral); 2204 ext_channel = p_sops->get_extension_channel(spectral); 2205 2206 if ((current_channel == 0) || (ext_channel == 0)) 2207 return; 2208 2209 if (spectral->sc_spectral_20_40_mode) { 2210 /* HT40 mode */ 2211 if (ext_channel < current_channel) { 2212 spectral->lower_is_extension = 1; 2213 spectral->upper_is_control = 1; 2214 spectral->lower_is_control = 0; 2215 spectral->upper_is_extension = 0; 2216 } else { 2217 spectral->lower_is_extension = 0; 2218 spectral->upper_is_control = 0; 2219 spectral->lower_is_control = 1; 2220 spectral->upper_is_extension = 1; 2221 } 2222 } else { 2223 /* HT20 mode, lower is always control */ 2224 spectral->lower_is_extension = 0; 2225 spectral->upper_is_control = 0; 2226 spectral->lower_is_control = 1; 2227 spectral->upper_is_extension = 0; 2228 } 2229 } 2230 2231 /** 2232 * target_if_get_spectral_config() - Get spectral configuration 2233 * @pdev: Pointer to pdev object 2234 * @param: Pointer to spectral_config structure in which the configuration 2235 * should be returned 2236 * 2237 * API to get the current spectral configuration 2238 * 2239 * Return: None 2240 */ 2241 void 2242 target_if_get_spectral_config(struct wlan_objmgr_pdev *pdev, 2243 struct spectral_config *param) 2244 { 2245 struct target_if_spectral_ops *p_sops = NULL; 2246 struct target_if_spectral *spectral = NULL; 2247 2248 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2249 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2250 2251 qdf_mem_zero(param, sizeof(struct spectral_config)); 2252 p_sops->get_spectral_config(spectral, param); 2253 } 2254 2255 /** 2256 * target_if_spectral_scan_enable_params() - Enable use of desired Spectral 2257 * parameters 2258 * @spectral: Pointer to Spectral target_if internal private data 2259 * @spectral_params: Pointer to Spectral parameters 2260 * 2261 * Enable use of desired Spectral parameters by configuring them into HW, and 2262 * starting Spectral scan 2263 * 2264 * Return: 0 on success, 1 on failure 2265 */ 2266 int 2267 target_if_spectral_scan_enable_params(struct target_if_spectral *spectral, 2268 struct spectral_config *spectral_params) 2269 { 2270 int extension_channel = 0; 2271 int current_channel = 0; 2272 struct target_if_spectral_ops *p_sops = NULL; 2273 struct wlan_objmgr_vdev *vdev = NULL; 2274 2275 if (!spectral) { 2276 spectral_err("SPECTRAL : Spectral is NULL"); 2277 return 1; 2278 } 2279 2280 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2281 2282 if (!p_sops) { 2283 spectral_err("SPECTRAL : p_sops is NULL"); 2284 return 1; 2285 } 2286 2287 spectral->sc_spectral_noise_pwr_cal = 2288 spectral_params->ss_spectral_pri ? 1 : 0; 2289 2290 /* check if extension channel is present */ 2291 extension_channel = p_sops->get_extension_channel(spectral); 2292 current_channel = p_sops->get_current_channel(spectral); 2293 2294 vdev = target_if_spectral_get_vdev(spectral); 2295 if (!vdev) 2296 return 1; 2297 2298 spectral->ch_width = target_if_vdev_get_ch_width(vdev); 2299 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2300 2301 if (spectral->ch_width == CH_WIDTH_INVALID) 2302 return 1; 2303 2304 if (spectral->capability.advncd_spectral_cap) { 2305 spectral->lb_edge_extrabins = 0; 2306 spectral->rb_edge_extrabins = 0; 2307 2308 if (spectral->is_lb_edge_extrabins_format && 2309 spectral->params.ss_rpt_mode == 2) { 2310 spectral->lb_edge_extrabins = 4; 2311 } 2312 2313 if (spectral->is_rb_edge_extrabins_format && 2314 spectral->params.ss_rpt_mode == 2) { 2315 spectral->rb_edge_extrabins = 4; 2316 } 2317 2318 if (spectral->ch_width == CH_WIDTH_20MHZ) { 2319 spectral->sc_spectral_20_40_mode = 0; 2320 2321 spectral->spectral_numbins = 2322 target_if_get_fft_bin_count( 2323 spectral->params.ss_fft_size); 2324 spectral->spectral_fft_len = 2325 target_if_get_fft_bin_count( 2326 spectral->params.ss_fft_size); 2327 spectral->spectral_data_len = 2328 target_if_get_fft_bin_count( 2329 spectral->params.ss_fft_size); 2330 /* 2331 * Initialize classifier params to be sent to user 2332 * space classifier 2333 */ 2334 spectral->classifier_params.lower_chan_in_mhz = 2335 current_channel; 2336 spectral->classifier_params.upper_chan_in_mhz = 0; 2337 2338 } else if (spectral->ch_width == CH_WIDTH_40MHZ) { 2339 /* TODO : Remove this variable */ 2340 spectral->sc_spectral_20_40_mode = 1; 2341 spectral->spectral_numbins = 2342 target_if_get_fft_bin_count( 2343 spectral->params.ss_fft_size); 2344 spectral->spectral_fft_len = 2345 target_if_get_fft_bin_count( 2346 spectral->params.ss_fft_size); 2347 spectral->spectral_data_len = 2348 target_if_get_fft_bin_count( 2349 spectral->params.ss_fft_size); 2350 2351 /* 2352 * Initialize classifier params to be sent to user 2353 * space classifier 2354 */ 2355 if (extension_channel < current_channel) { 2356 spectral->classifier_params.lower_chan_in_mhz = 2357 extension_channel; 2358 spectral->classifier_params.upper_chan_in_mhz = 2359 current_channel; 2360 } else { 2361 spectral->classifier_params.lower_chan_in_mhz = 2362 current_channel; 2363 spectral->classifier_params.upper_chan_in_mhz = 2364 extension_channel; 2365 } 2366 2367 } else if (spectral->ch_width == CH_WIDTH_80MHZ) { 2368 /* Set the FFT Size */ 2369 /* TODO : Remove this variable */ 2370 spectral->sc_spectral_20_40_mode = 0; 2371 spectral->spectral_numbins = 2372 target_if_get_fft_bin_count( 2373 spectral->params.ss_fft_size); 2374 spectral->spectral_fft_len = 2375 target_if_get_fft_bin_count( 2376 spectral->params.ss_fft_size); 2377 spectral->spectral_data_len = 2378 target_if_get_fft_bin_count( 2379 spectral->params.ss_fft_size); 2380 2381 /* 2382 * Initialize classifier params to be sent to user 2383 * space classifier 2384 */ 2385 spectral->classifier_params.lower_chan_in_mhz = 2386 current_channel; 2387 spectral->classifier_params.upper_chan_in_mhz = 0; 2388 2389 /* 2390 * Initialize classifier params to be sent to user 2391 * space classifier 2392 */ 2393 if (extension_channel < current_channel) { 2394 spectral->classifier_params.lower_chan_in_mhz = 2395 extension_channel; 2396 spectral->classifier_params.upper_chan_in_mhz = 2397 current_channel; 2398 } else { 2399 spectral->classifier_params.lower_chan_in_mhz = 2400 current_channel; 2401 spectral->classifier_params.upper_chan_in_mhz = 2402 extension_channel; 2403 } 2404 2405 } else if (spectral->ch_width == CH_WIDTH_160MHZ) { 2406 /* Set the FFT Size */ 2407 2408 /* The below applies to both 160 and 80+80 cases */ 2409 2410 /* TODO : Remove this variable */ 2411 spectral->sc_spectral_20_40_mode = 0; 2412 spectral->spectral_numbins = 2413 target_if_get_fft_bin_count( 2414 spectral->params.ss_fft_size); 2415 spectral->spectral_fft_len = 2416 target_if_get_fft_bin_count( 2417 spectral->params.ss_fft_size); 2418 spectral->spectral_data_len = 2419 target_if_get_fft_bin_count( 2420 spectral->params.ss_fft_size); 2421 2422 /* 2423 * Initialize classifier params to be sent to user 2424 * space classifier 2425 */ 2426 spectral->classifier_params.lower_chan_in_mhz = 2427 current_channel; 2428 spectral->classifier_params.upper_chan_in_mhz = 0; 2429 2430 /* 2431 * Initialize classifier params to be sent to user 2432 * space classifier 2433 */ 2434 if (extension_channel < current_channel) { 2435 spectral->classifier_params.lower_chan_in_mhz = 2436 extension_channel; 2437 spectral->classifier_params.upper_chan_in_mhz = 2438 current_channel; 2439 } else { 2440 spectral->classifier_params.lower_chan_in_mhz = 2441 current_channel; 2442 spectral->classifier_params.upper_chan_in_mhz = 2443 extension_channel; 2444 } 2445 } 2446 2447 if (spectral->spectral_numbins) { 2448 spectral->spectral_numbins += 2449 spectral->lb_edge_extrabins; 2450 spectral->spectral_numbins += 2451 spectral->rb_edge_extrabins; 2452 } 2453 2454 if (spectral->spectral_fft_len) { 2455 spectral->spectral_fft_len += 2456 spectral->lb_edge_extrabins; 2457 spectral->spectral_fft_len += 2458 spectral->rb_edge_extrabins; 2459 } 2460 2461 if (spectral->spectral_data_len) { 2462 spectral->spectral_data_len += 2463 spectral->lb_edge_extrabins; 2464 spectral->spectral_data_len += 2465 spectral->rb_edge_extrabins; 2466 } 2467 } else { 2468 /* 2469 * The decision to find 20/40 mode is found based on the 2470 * presence of extension channel 2471 * instead of channel width, as the channel width can 2472 * dynamically change 2473 */ 2474 2475 if (extension_channel == 0) { 2476 spectral->spectral_numbins = SPECTRAL_HT20_NUM_BINS; 2477 spectral->spectral_dc_index = SPECTRAL_HT20_DC_INDEX; 2478 spectral->spectral_fft_len = SPECTRAL_HT20_FFT_LEN; 2479 spectral->spectral_data_len = 2480 SPECTRAL_HT20_TOTAL_DATA_LEN; 2481 /* only valid in 20-40 mode */ 2482 spectral->spectral_lower_max_index_offset = -1; 2483 /* only valid in 20-40 mode */ 2484 spectral->spectral_upper_max_index_offset = -1; 2485 spectral->spectral_max_index_offset = 2486 spectral->spectral_fft_len + 2; 2487 spectral->sc_spectral_20_40_mode = 0; 2488 2489 /* 2490 * Initialize classifier params to be sent to user 2491 * space classifier 2492 */ 2493 spectral->classifier_params.lower_chan_in_mhz = 2494 current_channel; 2495 spectral->classifier_params.upper_chan_in_mhz = 0; 2496 2497 } else { 2498 spectral->spectral_numbins = 2499 SPECTRAL_HT40_TOTAL_NUM_BINS; 2500 spectral->spectral_fft_len = SPECTRAL_HT40_FFT_LEN; 2501 spectral->spectral_data_len = 2502 SPECTRAL_HT40_TOTAL_DATA_LEN; 2503 spectral->spectral_dc_index = SPECTRAL_HT40_DC_INDEX; 2504 /* only valid in 20 mode */ 2505 spectral->spectral_max_index_offset = -1; 2506 spectral->spectral_lower_max_index_offset = 2507 spectral->spectral_fft_len + 2; 2508 spectral->spectral_upper_max_index_offset = 2509 spectral->spectral_fft_len + 5; 2510 spectral->sc_spectral_20_40_mode = 1; 2511 2512 /* 2513 * Initialize classifier params to be sent to user 2514 * space classifier 2515 */ 2516 if (extension_channel < current_channel) { 2517 spectral->classifier_params.lower_chan_in_mhz = 2518 extension_channel; 2519 spectral->classifier_params.upper_chan_in_mhz = 2520 current_channel; 2521 } else { 2522 spectral->classifier_params.lower_chan_in_mhz = 2523 current_channel; 2524 spectral->classifier_params.upper_chan_in_mhz = 2525 extension_channel; 2526 } 2527 } 2528 } 2529 2530 spectral->send_single_packet = 0; 2531 spectral->classifier_params.spectral_20_40_mode = 2532 spectral->sc_spectral_20_40_mode; 2533 spectral->classifier_params.spectral_dc_index = 2534 spectral->spectral_dc_index; 2535 spectral->spectral_sent_msg = 0; 2536 spectral->classify_scan = 0; 2537 spectral->num_spectral_data = 0; 2538 2539 if (!p_sops->is_spectral_active(spectral)) { 2540 p_sops->configure_spectral(spectral, spectral_params); 2541 p_sops->start_spectral_scan(spectral); 2542 } else { 2543 } 2544 2545 /* get current spectral configuration */ 2546 p_sops->get_spectral_config(spectral, &spectral->params); 2547 2548 target_if_init_upper_lower_flags(spectral); 2549 2550 return 0; 2551 } 2552 2553 /** 2554 * target_if_start_spectral_scan() - Start spectral scan 2555 * @pdev: Pointer to pdev object 2556 * 2557 * API to start spectral scan 2558 * 2559 * Return: 0 in case of success, -1 on failure 2560 */ 2561 int 2562 target_if_start_spectral_scan(struct wlan_objmgr_pdev *pdev) 2563 { 2564 struct target_if_spectral_ops *p_sops = NULL; 2565 struct target_if_spectral *spectral = NULL; 2566 2567 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2568 if (!spectral) { 2569 spectral_err("SPECTRAL : Spectral LMAC object is NUll"); 2570 return -EPERM; 2571 } 2572 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2573 2574 qdf_spin_lock(&spectral->spectral_lock); 2575 target_if_spectral_scan_enable_params(spectral, &spectral->params); 2576 qdf_spin_unlock(&spectral->spectral_lock); 2577 2578 return 0; 2579 } 2580 2581 void 2582 target_if_stop_spectral_scan(struct wlan_objmgr_pdev *pdev) 2583 { 2584 struct target_if_spectral_ops *p_sops = NULL; 2585 struct target_if_spectral *spectral = NULL; 2586 2587 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2588 if (!spectral) { 2589 spectral_err("SPECTRAL : Spectral LMAC object is NUll "); 2590 return; 2591 } 2592 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2593 2594 qdf_spin_lock(&spectral->spectral_lock); 2595 p_sops->stop_spectral_scan(spectral); 2596 if (spectral->classify_scan) { 2597 /* TODO : Check if this logic is necessary */ 2598 spectral->detects_control_channel = 0; 2599 spectral->detects_extension_channel = 0; 2600 spectral->detects_above_dc = 0; 2601 spectral->detects_below_dc = 0; 2602 spectral->classify_scan = 0; 2603 } 2604 2605 spectral->send_single_packet = 0; 2606 spectral->sc_spectral_scan = 0; 2607 spectral->sc_spectral_noise_pwr_cal = 0; 2608 2609 /* 2610 * Reset the priority because it stops WLAN rx. 2611 * If it is needed to set, user has to set it explicitly 2612 * 2613 */ 2614 /* Reset Priority */ 2615 spectral->params.ss_spectral_pri = 0; 2616 qdf_spin_unlock(&spectral->spectral_lock); 2617 } 2618 2619 /** 2620 * target_if_is_spectral_active() - Get whether Spectral is active 2621 * @pdev: Pointer to pdev object 2622 * 2623 * API to get whether Spectral is active 2624 * 2625 * Return: True if Spectral is active, false if Spectral is not active 2626 */ 2627 bool 2628 target_if_is_spectral_active(struct wlan_objmgr_pdev *pdev) 2629 { 2630 struct target_if_spectral *spectral = NULL; 2631 struct target_if_spectral_ops *p_sops = NULL; 2632 2633 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2634 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2635 return p_sops->is_spectral_active(spectral); 2636 } 2637 2638 /** 2639 * target_if_is_spectral_enabled() - Get whether Spectral is enabled 2640 * @pdev: Pointer to pdev object 2641 * 2642 * API to get whether Spectral is enabled 2643 * 2644 * Return: True if Spectral is enabled, false if Spectral is not enabled 2645 */ 2646 bool 2647 target_if_is_spectral_enabled(struct wlan_objmgr_pdev *pdev) 2648 { 2649 struct target_if_spectral *spectral = NULL; 2650 struct target_if_spectral_ops *p_sops = NULL; 2651 2652 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2653 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2654 return p_sops->is_spectral_enabled(spectral); 2655 } 2656 2657 /** 2658 * target_if_set_debug_level() - Set debug level for Spectral 2659 * @pdev: Pointer to pdev object 2660 * @debug_level: Debug level 2661 * 2662 * API to set the debug level for Spectral 2663 * 2664 * Return: 0 in case of success 2665 */ 2666 int 2667 target_if_set_debug_level(struct wlan_objmgr_pdev *pdev, uint32_t debug_level) 2668 { 2669 spectral_debug_level = (DEBUG_SPECTRAL << debug_level); 2670 return 0; 2671 } 2672 2673 /** 2674 * target_if_get_debug_level() - Get debug level for Spectral 2675 * @pdev: Pointer to pdev object 2676 * 2677 * API to get the debug level for Spectral 2678 * 2679 * Return: Current debug level 2680 */ 2681 uint32_t 2682 target_if_get_debug_level(struct wlan_objmgr_pdev *pdev) 2683 { 2684 return spectral_debug_level; 2685 } 2686 2687 /** 2688 * target_if_get_spectral_capinfo() - Get Spectral capability information 2689 * @pdev: Pointer to pdev object 2690 * @outdata: Buffer into which data should be copied 2691 * 2692 * API to get the spectral capability information 2693 * 2694 * Return: void 2695 */ 2696 void 2697 target_if_get_spectral_capinfo(struct wlan_objmgr_pdev *pdev, void *outdata) 2698 { 2699 struct target_if_spectral *spectral = NULL; 2700 2701 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2702 qdf_mem_copy(outdata, &spectral->capability, 2703 sizeof(struct spectral_caps)); 2704 } 2705 2706 /** 2707 * target_if_get_spectral_diagstats() - Get Spectral diagnostic statistics 2708 * @pdev: Pointer to pdev object 2709 * @outdata: Buffer into which data should be copied 2710 * 2711 * API to get the spectral diagnostic statistics 2712 * 2713 * Return: void 2714 */ 2715 void 2716 target_if_get_spectral_diagstats(struct wlan_objmgr_pdev *pdev, void *outdata) 2717 { 2718 struct target_if_spectral *spectral = NULL; 2719 2720 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2721 qdf_mem_copy(outdata, &spectral->diag_stats, 2722 sizeof(struct spectral_diag_stats)); 2723 } 2724 2725 /** 2726 * target_if_register_wmi_spectral_cmd_ops() - Register wmi_spectral_cmd_ops 2727 * @cmd_ops: Pointer to the structure having wmi_spectral_cmd function pointers 2728 * @pdev: Pointer to pdev object 2729 * 2730 * API for register wmi_spectral_cmd_ops in spectral internal data structure 2731 * 2732 * Return: void 2733 */ 2734 void 2735 target_if_register_wmi_spectral_cmd_ops(struct wlan_objmgr_pdev *pdev, 2736 struct wmi_spectral_cmd_ops *cmd_ops) 2737 { 2738 struct target_if_spectral *spectral = NULL; 2739 2740 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2741 spectral->param_wmi_cmd_ops.wmi_spectral_configure_cmd_send = 2742 cmd_ops->wmi_spectral_configure_cmd_send; 2743 spectral->param_wmi_cmd_ops.wmi_spectral_enable_cmd_send = 2744 cmd_ops->wmi_spectral_enable_cmd_send; 2745 } 2746 2747 /** 2748 * target_if_register_netlink_cb() - Register Netlink callbacks 2749 * @pdev: Pointer to pdev object 2750 * @nl_cb: Netlink callbacks to register 2751 * 2752 * Return: void 2753 */ 2754 static void 2755 target_if_register_netlink_cb( 2756 struct wlan_objmgr_pdev *pdev, 2757 struct spectral_nl_cb *nl_cb) 2758 { 2759 struct target_if_spectral *spectral = NULL; 2760 2761 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2762 qdf_mem_copy(&spectral->nl_cb, nl_cb, sizeof(struct spectral_nl_cb)); 2763 2764 if (spectral->use_nl_bcast) 2765 spectral->send_phy_data = spectral->nl_cb.send_nl_bcast; 2766 else 2767 spectral->send_phy_data = spectral->nl_cb.send_nl_unicast; 2768 } 2769 2770 /** 2771 * target_if_use_nl_bcast() - Get whether to use broadcast/unicast while sending 2772 * Netlink messages to the application layer 2773 * @pdev: Pointer to pdev object 2774 * 2775 * Return: true for broadcast, false for unicast 2776 */ 2777 static bool 2778 target_if_use_nl_bcast(struct wlan_objmgr_pdev *pdev) 2779 { 2780 struct target_if_spectral *spectral = NULL; 2781 2782 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2783 return spectral->use_nl_bcast; 2784 } 2785 2786 /** 2787 * target_if_deregister_netlink_cb() - De-register Netlink callbacks 2788 * @pdev: Pointer to pdev object 2789 * 2790 * Return: void 2791 */ 2792 static void 2793 target_if_deregister_netlink_cb(struct wlan_objmgr_pdev *pdev) 2794 { 2795 struct target_if_spectral *spectral = NULL; 2796 2797 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2798 if (!spectral) { 2799 spectral_err("SPECTRAL : Module doesn't exist"); 2800 return; 2801 } 2802 2803 qdf_mem_zero(&spectral->nl_cb, sizeof(struct spectral_nl_cb)); 2804 } 2805 2806 void 2807 target_if_sptrl_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 2808 { 2809 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_init = 2810 target_if_pdev_spectral_init; 2811 tx_ops->sptrl_tx_ops.sptrlto_pdev_spectral_deinit = 2812 target_if_pdev_spectral_deinit; 2813 tx_ops->sptrl_tx_ops.sptrlto_set_spectral_config = 2814 target_if_set_spectral_config; 2815 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_config = 2816 target_if_get_spectral_config; 2817 tx_ops->sptrl_tx_ops.sptrlto_start_spectral_scan = 2818 target_if_start_spectral_scan; 2819 tx_ops->sptrl_tx_ops.sptrlto_stop_spectral_scan = 2820 target_if_stop_spectral_scan; 2821 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_active = 2822 target_if_is_spectral_active; 2823 tx_ops->sptrl_tx_ops.sptrlto_is_spectral_enabled = 2824 target_if_is_spectral_enabled; 2825 tx_ops->sptrl_tx_ops.sptrlto_set_debug_level = 2826 target_if_set_debug_level; 2827 tx_ops->sptrl_tx_ops.sptrlto_get_debug_level = 2828 target_if_get_debug_level; 2829 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_capinfo = 2830 target_if_get_spectral_capinfo; 2831 tx_ops->sptrl_tx_ops.sptrlto_get_spectral_diagstats = 2832 target_if_get_spectral_diagstats; 2833 tx_ops->sptrl_tx_ops.sptrlto_register_wmi_spectral_cmd_ops = 2834 target_if_register_wmi_spectral_cmd_ops; 2835 tx_ops->sptrl_tx_ops.sptrlto_register_netlink_cb = 2836 target_if_register_netlink_cb; 2837 tx_ops->sptrl_tx_ops.sptrlto_use_nl_bcast = 2838 target_if_use_nl_bcast; 2839 tx_ops->sptrl_tx_ops.sptrlto_deregister_netlink_cb = 2840 target_if_deregister_netlink_cb; 2841 } 2842 EXPORT_SYMBOL(target_if_sptrl_register_tx_ops); 2843 2844 void 2845 target_if_spectral_send_intf_found_msg(struct wlan_objmgr_pdev *pdev, 2846 uint16_t cw_int, uint32_t dcs_enabled) 2847 { 2848 struct spectral_samp_msg *msg = NULL; 2849 struct target_if_spectral_ops *p_sops = NULL; 2850 struct target_if_spectral *spectral = NULL; 2851 2852 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2853 msg = (struct spectral_samp_msg *)spectral->nl_cb.get_nbuff( 2854 spectral->pdev_obj); 2855 2856 if (msg) { 2857 msg->int_type = cw_int ? 2858 SPECTRAL_DCS_INT_CW : SPECTRAL_DCS_INT_WIFI; 2859 msg->dcs_enabled = dcs_enabled; 2860 msg->signature = SPECTRAL_SIGNATURE; 2861 p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); 2862 p_sops->get_mac_address(spectral, msg->macaddr); 2863 if (spectral->send_phy_data(pdev) == 0) 2864 spectral->spectral_sent_msg++; 2865 } 2866 } 2867 EXPORT_SYMBOL(target_if_spectral_send_intf_found_msg); 2868