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