1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 4 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 5 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 6 */ 7 8 #include <linux/relay.h> 9 #include "core.h" 10 #include "debug.h" 11 12 #define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT 2 13 #define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS 1 14 15 #define ATH11K_SPECTRAL_DWORD_SIZE 4 16 #define ATH11K_SPECTRAL_MIN_BINS 32 17 #define ATH11K_SPECTRAL_MIN_IB_BINS (ATH11K_SPECTRAL_MIN_BINS >> 1) 18 #define ATH11K_SPECTRAL_MAX_IB_BINS(x) ((x)->hw_params.spectral.max_fft_bins >> 1) 19 20 #define ATH11K_SPECTRAL_SCAN_COUNT_MAX 4095 21 22 /* Max channel computed by sum of 2g and 5g band channels */ 23 #define ATH11K_SPECTRAL_TOTAL_CHANNEL 41 24 #define ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL 70 25 #define ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x) (sizeof(struct fft_sample_ath11k) + \ 26 ATH11K_SPECTRAL_MAX_IB_BINS(x)) 27 #define ATH11K_SPECTRAL_TOTAL_SAMPLE (ATH11K_SPECTRAL_TOTAL_CHANNEL * \ 28 ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL) 29 #define ATH11K_SPECTRAL_SUB_BUFF_SIZE(x) ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x) 30 #define ATH11K_SPECTRAL_NUM_SUB_BUF ATH11K_SPECTRAL_TOTAL_SAMPLE 31 32 #define ATH11K_SPECTRAL_20MHZ 20 33 #define ATH11K_SPECTRAL_40MHZ 40 34 #define ATH11K_SPECTRAL_80MHZ 80 35 #define ATH11K_SPECTRAL_160MHZ 160 36 37 #define ATH11K_SPECTRAL_SIGNATURE 0xFA 38 39 #define ATH11K_SPECTRAL_TAG_RADAR_SUMMARY 0x0 40 #define ATH11K_SPECTRAL_TAG_RADAR_FFT 0x1 41 #define ATH11K_SPECTRAL_TAG_SCAN_SUMMARY 0x2 42 #define ATH11K_SPECTRAL_TAG_SCAN_SEARCH 0x3 43 44 #define SPECTRAL_TLV_HDR_LEN GENMASK(15, 0) 45 #define SPECTRAL_TLV_HDR_TAG GENMASK(23, 16) 46 #define SPECTRAL_TLV_HDR_SIGN GENMASK(31, 24) 47 48 #define SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN GENMASK(7, 0) 49 #define SPECTRAL_SUMMARY_INFO0_OB_FLAG BIT(8) 50 #define SPECTRAL_SUMMARY_INFO0_GRP_IDX GENMASK(16, 9) 51 #define SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT BIT(17) 52 #define SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB GENMASK(27, 18) 53 #define SPECTRAL_SUMMARY_INFO0_FALSE_SCAN BIT(28) 54 #define SPECTRAL_SUMMARY_INFO0_DETECTOR_ID GENMASK(30, 29) 55 #define SPECTRAL_SUMMARY_INFO0_PRI80 BIT(31) 56 57 #define SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX GENMASK(11, 0) 58 #define SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE GENMASK(21, 12) 59 #define SPECTRAL_SUMMARY_INFO2_NARROWBAND_MASK GENMASK(29, 22) 60 #define SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE BIT(30) 61 62 struct spectral_tlv { 63 __le32 timestamp; 64 __le32 header; 65 } __packed; 66 67 struct spectral_summary_fft_report { 68 __le32 timestamp; 69 __le32 tlv_header; 70 __le32 info0; 71 __le32 reserve0; 72 __le32 info2; 73 __le32 reserve1; 74 } __packed; 75 76 struct ath11k_spectral_summary_report { 77 struct wmi_dma_buf_release_meta_data meta; 78 u32 timestamp; 79 u8 agc_total_gain; 80 u8 grp_idx; 81 u16 inb_pwr_db; 82 s16 peak_idx; 83 u16 peak_mag; 84 u8 detector_id; 85 bool out_of_band_flag; 86 bool rf_saturation; 87 bool primary80; 88 bool gain_change; 89 bool false_scan; 90 }; 91 92 #define SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID GENMASK(1, 0) 93 #define SPECTRAL_FFT_REPORT_INFO0_FFT_NUM GENMASK(4, 2) 94 #define SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK GENMASK(16, 5) 95 #define SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX GENMASK(27, 17) 96 #define SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX GENMASK(30, 28) 97 98 #define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB GENMASK(8, 0) 99 #define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB GENMASK(16, 9) 100 101 #define SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS GENMASK(7, 0) 102 #define SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE GENMASK(17, 8) 103 #define SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB GENMASK(24, 18) 104 #define SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB GENMASK(31, 25) 105 106 struct spectral_search_fft_report { 107 __le32 timestamp; 108 __le32 tlv_header; 109 __le32 info0; 110 __le32 info1; 111 __le32 info2; 112 __le32 reserve0; 113 u8 bins[]; 114 } __packed; 115 116 struct ath11k_spectral_search_report { 117 u32 timestamp; 118 u8 detector_id; 119 u8 fft_count; 120 u16 radar_check; 121 s16 peak_idx; 122 u8 chain_idx; 123 u16 base_pwr_db; 124 u8 total_gain_db; 125 u8 strong_bin_count; 126 u16 peak_mag; 127 u8 avg_pwr_db; 128 u8 rel_pwr_db; 129 }; 130 131 static struct dentry *create_buf_file_handler(const char *filename, 132 struct dentry *parent, 133 umode_t mode, 134 struct rchan_buf *buf, 135 int *is_global) 136 { 137 struct dentry *buf_file; 138 139 buf_file = debugfs_create_file(filename, mode, parent, buf, 140 &relay_file_operations); 141 *is_global = 1; 142 return buf_file; 143 } 144 145 static int remove_buf_file_handler(struct dentry *dentry) 146 { 147 debugfs_remove(dentry); 148 149 return 0; 150 } 151 152 static const struct rchan_callbacks rfs_scan_cb = { 153 .create_buf_file = create_buf_file_handler, 154 .remove_buf_file = remove_buf_file_handler, 155 }; 156 157 static struct ath11k_vif *ath11k_spectral_get_vdev(struct ath11k *ar) 158 { 159 struct ath11k_vif *arvif; 160 161 lockdep_assert_held(&ar->conf_mutex); 162 163 if (list_empty(&ar->arvifs)) 164 return NULL; 165 166 /* if there already is a vif doing spectral, return that. */ 167 list_for_each_entry(arvif, &ar->arvifs, list) 168 if (arvif->spectral_enabled) 169 return arvif; 170 171 /* otherwise, return the first vif. */ 172 return list_first_entry(&ar->arvifs, typeof(*arvif), list); 173 } 174 175 static int ath11k_spectral_scan_trigger(struct ath11k *ar) 176 { 177 struct ath11k_vif *arvif; 178 int ret; 179 180 lockdep_assert_held(&ar->conf_mutex); 181 182 arvif = ath11k_spectral_get_vdev(ar); 183 if (!arvif) 184 return -ENODEV; 185 186 if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED) 187 return 0; 188 189 ar->spectral.is_primary = true; 190 191 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 192 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, 193 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); 194 if (ret) 195 return ret; 196 197 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 198 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER, 199 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); 200 if (ret) 201 return ret; 202 203 return 0; 204 } 205 206 static int ath11k_spectral_scan_config(struct ath11k *ar, 207 enum ath11k_spectral_mode mode) 208 { 209 struct ath11k_wmi_vdev_spectral_conf_param param = {}; 210 struct ath11k_vif *arvif; 211 int ret, count; 212 213 lockdep_assert_held(&ar->conf_mutex); 214 215 arvif = ath11k_spectral_get_vdev(ar); 216 if (!arvif) 217 return -ENODEV; 218 219 arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED); 220 221 spin_lock_bh(&ar->spectral.lock); 222 ar->spectral.mode = mode; 223 spin_unlock_bh(&ar->spectral.lock); 224 225 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 226 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, 227 ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE); 228 if (ret) { 229 ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret); 230 return ret; 231 } 232 233 if (mode == ATH11K_SPECTRAL_DISABLED) 234 return 0; 235 236 if (mode == ATH11K_SPECTRAL_BACKGROUND) 237 count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT; 238 else 239 count = max_t(u16, 1, ar->spectral.count); 240 241 param.vdev_id = arvif->vdev_id; 242 param.scan_count = count; 243 param.scan_fft_size = ar->spectral.fft_size; 244 param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT; 245 param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT; 246 param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT; 247 param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT; 248 param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT; 249 param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT; 250 param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT; 251 param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT; 252 param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT; 253 param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT; 254 param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT; 255 param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT; 256 param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT; 257 param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT; 258 param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT; 259 param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT; 260 261 ret = ath11k_wmi_vdev_spectral_conf(ar, ¶m); 262 if (ret) { 263 ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret); 264 return ret; 265 } 266 267 return 0; 268 } 269 270 static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file, 271 char __user *user_buf, 272 size_t count, loff_t *ppos) 273 { 274 struct ath11k *ar = file->private_data; 275 char *mode = ""; 276 size_t len; 277 enum ath11k_spectral_mode spectral_mode; 278 279 mutex_lock(&ar->conf_mutex); 280 spectral_mode = ar->spectral.mode; 281 mutex_unlock(&ar->conf_mutex); 282 283 switch (spectral_mode) { 284 case ATH11K_SPECTRAL_DISABLED: 285 mode = "disable"; 286 break; 287 case ATH11K_SPECTRAL_BACKGROUND: 288 mode = "background"; 289 break; 290 case ATH11K_SPECTRAL_MANUAL: 291 mode = "manual"; 292 break; 293 } 294 295 len = strlen(mode); 296 return simple_read_from_buffer(user_buf, count, ppos, mode, len); 297 } 298 299 static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file, 300 const char __user *user_buf, 301 size_t count, loff_t *ppos) 302 { 303 struct ath11k *ar = file->private_data; 304 char buf[32]; 305 ssize_t len; 306 int ret; 307 308 len = min(count, sizeof(buf) - 1); 309 if (copy_from_user(buf, user_buf, len)) 310 return -EFAULT; 311 312 buf[len] = '\0'; 313 314 mutex_lock(&ar->conf_mutex); 315 316 if (strncmp("trigger", buf, 7) == 0) { 317 if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL || 318 ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) { 319 /* reset the configuration to adopt possibly changed 320 * debugfs parameters 321 */ 322 ret = ath11k_spectral_scan_config(ar, ar->spectral.mode); 323 if (ret) { 324 ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n", 325 ret); 326 goto unlock; 327 } 328 329 ret = ath11k_spectral_scan_trigger(ar); 330 if (ret) { 331 ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n", 332 ret); 333 } 334 } else { 335 ret = -EINVAL; 336 } 337 } else if (strncmp("background", buf, 10) == 0) { 338 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND); 339 } else if (strncmp("manual", buf, 6) == 0) { 340 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL); 341 } else if (strncmp("disable", buf, 7) == 0) { 342 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED); 343 } else { 344 ret = -EINVAL; 345 } 346 347 unlock: 348 mutex_unlock(&ar->conf_mutex); 349 350 if (ret) 351 return ret; 352 353 return count; 354 } 355 356 static const struct file_operations fops_scan_ctl = { 357 .read = ath11k_read_file_spec_scan_ctl, 358 .write = ath11k_write_file_spec_scan_ctl, 359 .open = simple_open, 360 .owner = THIS_MODULE, 361 .llseek = default_llseek, 362 }; 363 364 static ssize_t ath11k_read_file_spectral_count(struct file *file, 365 char __user *user_buf, 366 size_t count, loff_t *ppos) 367 { 368 struct ath11k *ar = file->private_data; 369 char buf[32]; 370 size_t len; 371 u16 spectral_count; 372 373 mutex_lock(&ar->conf_mutex); 374 spectral_count = ar->spectral.count; 375 mutex_unlock(&ar->conf_mutex); 376 377 len = sprintf(buf, "%d\n", spectral_count); 378 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 379 } 380 381 static ssize_t ath11k_write_file_spectral_count(struct file *file, 382 const char __user *user_buf, 383 size_t count, loff_t *ppos) 384 { 385 struct ath11k *ar = file->private_data; 386 unsigned long val; 387 ssize_t ret; 388 389 ret = kstrtoul_from_user(user_buf, count, 0, &val); 390 if (ret) 391 return ret; 392 393 if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX) 394 return -EINVAL; 395 396 mutex_lock(&ar->conf_mutex); 397 ar->spectral.count = val; 398 mutex_unlock(&ar->conf_mutex); 399 400 return count; 401 } 402 403 static const struct file_operations fops_scan_count = { 404 .read = ath11k_read_file_spectral_count, 405 .write = ath11k_write_file_spectral_count, 406 .open = simple_open, 407 .owner = THIS_MODULE, 408 .llseek = default_llseek, 409 }; 410 411 static ssize_t ath11k_read_file_spectral_bins(struct file *file, 412 char __user *user_buf, 413 size_t count, loff_t *ppos) 414 { 415 struct ath11k *ar = file->private_data; 416 char buf[32]; 417 unsigned int bins, fft_size; 418 size_t len; 419 420 mutex_lock(&ar->conf_mutex); 421 422 fft_size = ar->spectral.fft_size; 423 bins = 1 << fft_size; 424 425 mutex_unlock(&ar->conf_mutex); 426 427 len = sprintf(buf, "%d\n", bins); 428 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 429 } 430 431 static ssize_t ath11k_write_file_spectral_bins(struct file *file, 432 const char __user *user_buf, 433 size_t count, loff_t *ppos) 434 { 435 struct ath11k *ar = file->private_data; 436 unsigned long val; 437 ssize_t ret; 438 439 ret = kstrtoul_from_user(user_buf, count, 0, &val); 440 if (ret) 441 return ret; 442 443 if (val < ATH11K_SPECTRAL_MIN_BINS || 444 val > ar->ab->hw_params.spectral.max_fft_bins) 445 return -EINVAL; 446 447 if (!is_power_of_2(val)) 448 return -EINVAL; 449 450 mutex_lock(&ar->conf_mutex); 451 ar->spectral.fft_size = ilog2(val); 452 mutex_unlock(&ar->conf_mutex); 453 454 return count; 455 } 456 457 static const struct file_operations fops_scan_bins = { 458 .read = ath11k_read_file_spectral_bins, 459 .write = ath11k_write_file_spectral_bins, 460 .open = simple_open, 461 .owner = THIS_MODULE, 462 .llseek = default_llseek, 463 }; 464 465 static int ath11k_spectral_pull_summary(struct ath11k *ar, 466 struct wmi_dma_buf_release_meta_data *meta, 467 struct spectral_summary_fft_report *summary, 468 struct ath11k_spectral_summary_report *report) 469 { 470 report->timestamp = __le32_to_cpu(summary->timestamp); 471 report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN, 472 __le32_to_cpu(summary->info0)); 473 report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG, 474 __le32_to_cpu(summary->info0)); 475 report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX, 476 __le32_to_cpu(summary->info0)); 477 report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT, 478 __le32_to_cpu(summary->info0)); 479 report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB, 480 __le32_to_cpu(summary->info0)); 481 report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN, 482 __le32_to_cpu(summary->info0)); 483 report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID, 484 __le32_to_cpu(summary->info0)); 485 report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80, 486 __le32_to_cpu(summary->info0)); 487 report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX, 488 __le32_to_cpu(summary->info2)); 489 report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE, 490 __le32_to_cpu(summary->info2)); 491 report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE, 492 __le32_to_cpu(summary->info2)); 493 494 memcpy(&report->meta, meta, sizeof(*meta)); 495 496 return 0; 497 } 498 499 static int ath11k_spectral_pull_search(struct ath11k *ar, 500 struct spectral_search_fft_report *search, 501 struct ath11k_spectral_search_report *report) 502 { 503 report->timestamp = __le32_to_cpu(search->timestamp); 504 report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID, 505 __le32_to_cpu(search->info0)); 506 report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM, 507 __le32_to_cpu(search->info0)); 508 report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK, 509 __le32_to_cpu(search->info0)); 510 report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 511 __le32_to_cpu(search->info0)); 512 report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX, 513 __le32_to_cpu(search->info0)); 514 report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB, 515 __le32_to_cpu(search->info1)); 516 report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB, 517 __le32_to_cpu(search->info1)); 518 report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS, 519 __le32_to_cpu(search->info2)); 520 report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE, 521 __le32_to_cpu(search->info2)); 522 report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB, 523 __le32_to_cpu(search->info2)); 524 report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB, 525 __le32_to_cpu(search->info2)); 526 527 return 0; 528 } 529 530 static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude, 531 int bin_len, u8 *bins) 532 { 533 int dc_pos; 534 u8 max_exp; 535 536 dc_pos = bin_len / 2; 537 538 /* peak index outside of bins */ 539 if (dc_pos <= max_index || -dc_pos >= max_index) 540 return 0; 541 542 for (max_exp = 0; max_exp < 8; max_exp++) { 543 if (bins[dc_pos + max_index] == (max_magnitude >> max_exp)) 544 break; 545 } 546 547 /* max_exp not found */ 548 if (bins[dc_pos + max_index] != (max_magnitude >> max_exp)) 549 return 0; 550 551 return max_exp; 552 } 553 554 static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz) 555 { 556 int i, j; 557 558 i = 0; 559 j = 0; 560 while (i < num_bins) { 561 outbins[i] = inbins[j]; 562 i++; 563 j += fft_sz; 564 } 565 } 566 567 static 568 int ath11k_spectral_process_fft(struct ath11k *ar, 569 struct ath11k_spectral_summary_report *summary, 570 void *data, 571 struct fft_sample_ath11k *fft_sample, 572 u32 data_len) 573 { 574 struct ath11k_base *ab = ar->ab; 575 struct spectral_search_fft_report *fft_report = data; 576 struct ath11k_spectral_search_report search; 577 struct spectral_tlv *tlv; 578 int tlv_len, bin_len, num_bins; 579 u16 length, freq; 580 u8 chan_width_mhz, bin_sz; 581 int ret; 582 u32 check_length; 583 bool fragment_sample = false; 584 585 lockdep_assert_held(&ar->spectral.lock); 586 587 if (!ab->hw_params.spectral.fft_sz) { 588 ath11k_warn(ab, "invalid bin size type for hw rev %d\n", 589 ab->hw_rev); 590 return -EINVAL; 591 } 592 593 tlv = data; 594 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header)); 595 /* convert Dword into bytes */ 596 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 597 bin_len = tlv_len - ab->hw_params.spectral.fft_hdr_len; 598 599 if (data_len < (bin_len + sizeof(*fft_report))) { 600 ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n", 601 bin_len, data_len); 602 return -EINVAL; 603 } 604 605 bin_sz = ab->hw_params.spectral.fft_sz + ab->hw_params.spectral.fft_pad_sz; 606 num_bins = bin_len / bin_sz; 607 /* Only In-band bins are useful to user for visualize */ 608 num_bins >>= 1; 609 610 if (num_bins < ATH11K_SPECTRAL_MIN_IB_BINS || 611 num_bins > ATH11K_SPECTRAL_MAX_IB_BINS(ab) || 612 !is_power_of_2(num_bins)) { 613 ath11k_warn(ab, "Invalid num of bins %d\n", num_bins); 614 return -EINVAL; 615 } 616 617 check_length = sizeof(*fft_report) + (num_bins * ab->hw_params.spectral.fft_sz); 618 ret = ath11k_dbring_validate_buffer(ar, data, check_length); 619 if (ret) { 620 ath11k_warn(ar->ab, "found magic value in fft data, dropping\n"); 621 return ret; 622 } 623 624 ret = ath11k_spectral_pull_search(ar, data, &search); 625 if (ret) { 626 ath11k_warn(ab, "failed to pull search report %d\n", ret); 627 return ret; 628 } 629 630 chan_width_mhz = summary->meta.ch_width; 631 632 switch (chan_width_mhz) { 633 case ATH11K_SPECTRAL_20MHZ: 634 case ATH11K_SPECTRAL_40MHZ: 635 case ATH11K_SPECTRAL_80MHZ: 636 fft_sample->chan_width_mhz = chan_width_mhz; 637 break; 638 case ATH11K_SPECTRAL_160MHZ: 639 if (ab->hw_params.spectral.fragment_160mhz) { 640 chan_width_mhz /= 2; 641 fragment_sample = true; 642 } 643 fft_sample->chan_width_mhz = chan_width_mhz; 644 break; 645 default: 646 ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz); 647 return -EINVAL; 648 } 649 650 length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins; 651 fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K; 652 fft_sample->tlv.length = __cpu_to_be16(length); 653 654 fft_sample->tsf = __cpu_to_be32(search.timestamp); 655 fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag); 656 fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 657 __le32_to_cpu(fft_report->info0)); 658 659 summary->inb_pwr_db >>= 1; 660 fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db); 661 fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]); 662 663 freq = summary->meta.freq1; 664 fft_sample->freq1 = __cpu_to_be16(freq); 665 666 freq = summary->meta.freq2; 667 fft_sample->freq2 = __cpu_to_be16(freq); 668 669 /* If freq2 is available then the spectral scan results are fragmented 670 * as primary and secondary 671 */ 672 if (fragment_sample && freq) { 673 if (!ar->spectral.is_primary) 674 fft_sample->freq1 = cpu_to_be16(freq); 675 676 /* We have to toggle the is_primary to handle the next report */ 677 ar->spectral.is_primary = !ar->spectral.is_primary; 678 } 679 680 ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins, 681 ab->hw_params.spectral.fft_sz); 682 683 fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index, 684 search.peak_mag, 685 num_bins, 686 fft_sample->data); 687 688 if (ar->spectral.rfs_scan) 689 relay_write(ar->spectral.rfs_scan, fft_sample, 690 length + sizeof(struct fft_sample_tlv)); 691 692 return 0; 693 } 694 695 static int ath11k_spectral_process_data(struct ath11k *ar, 696 struct ath11k_dbring_data *param) 697 { 698 struct ath11k_base *ab = ar->ab; 699 struct spectral_tlv *tlv; 700 struct spectral_summary_fft_report *summary = NULL; 701 struct ath11k_spectral_summary_report summ_rpt; 702 struct fft_sample_ath11k *fft_sample = NULL; 703 u8 *data; 704 u32 data_len, i; 705 u8 sign, tag; 706 int tlv_len, sample_sz; 707 int ret; 708 bool quit = false; 709 710 spin_lock_bh(&ar->spectral.lock); 711 712 if (!ar->spectral.enabled) { 713 ret = -EINVAL; 714 goto unlock; 715 } 716 717 sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab); 718 fft_sample = kmalloc(sample_sz, GFP_ATOMIC); 719 if (!fft_sample) { 720 ret = -ENOBUFS; 721 goto unlock; 722 } 723 724 data = param->data; 725 data_len = param->data_sz; 726 i = 0; 727 while (!quit && (i < data_len)) { 728 if ((i + sizeof(*tlv)) > data_len) { 729 ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n", 730 i); 731 ret = -EINVAL; 732 goto err; 733 } 734 735 tlv = (struct spectral_tlv *)&data[i]; 736 sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN, 737 __le32_to_cpu(tlv->header)); 738 if (sign != ATH11K_SPECTRAL_SIGNATURE) { 739 ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n", 740 sign, i); 741 ret = -EINVAL; 742 goto err; 743 } 744 745 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, 746 __le32_to_cpu(tlv->header)); 747 /* convert Dword into bytes */ 748 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 749 if ((i + sizeof(*tlv) + tlv_len) > data_len) { 750 ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n", 751 i, tlv_len, data_len); 752 ret = -EINVAL; 753 goto err; 754 } 755 756 tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG, 757 __le32_to_cpu(tlv->header)); 758 switch (tag) { 759 case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY: 760 /* HW bug in tlv length of summary report, 761 * HW report 3 DWORD size but the data payload 762 * is 4 DWORD size (16 bytes). 763 * Need to remove this workaround once HW bug fixed 764 */ 765 tlv_len = sizeof(*summary) - sizeof(*tlv) + 766 ab->hw_params.spectral.summary_pad_sz; 767 768 if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) { 769 ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n", 770 i, tlv_len); 771 ret = -EINVAL; 772 goto err; 773 } 774 775 ret = ath11k_dbring_validate_buffer(ar, data, tlv_len); 776 if (ret) { 777 ath11k_warn(ar->ab, "found magic value in spectral summary, dropping\n"); 778 goto err; 779 } 780 781 summary = (struct spectral_summary_fft_report *)tlv; 782 ath11k_spectral_pull_summary(ar, ¶m->meta, 783 summary, &summ_rpt); 784 break; 785 case ATH11K_SPECTRAL_TAG_SCAN_SEARCH: 786 if (tlv_len < (sizeof(struct spectral_search_fft_report) - 787 sizeof(*tlv))) { 788 ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n", 789 i); 790 ret = -EINVAL; 791 goto err; 792 } 793 794 memset(fft_sample, 0, sample_sz); 795 ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv, 796 fft_sample, 797 data_len - i); 798 if (ret) { 799 ath11k_warn(ab, "failed to process spectral fft at bytes %d\n", 800 i); 801 goto err; 802 } 803 quit = true; 804 break; 805 } 806 807 i += sizeof(*tlv) + tlv_len; 808 } 809 810 ret = 0; 811 812 err: 813 kfree(fft_sample); 814 unlock: 815 spin_unlock_bh(&ar->spectral.lock); 816 return ret; 817 } 818 819 static int ath11k_spectral_ring_alloc(struct ath11k *ar, 820 struct ath11k_dbring_cap *db_cap) 821 { 822 struct ath11k_spectral *sp = &ar->spectral; 823 int ret; 824 825 ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring, 826 0, db_cap->min_elem); 827 if (ret) { 828 ath11k_warn(ar->ab, "failed to setup db ring\n"); 829 return ret; 830 } 831 832 ath11k_dbring_set_cfg(ar, &sp->rx_ring, 833 ATH11K_SPECTRAL_NUM_RESP_PER_EVENT, 834 ATH11K_SPECTRAL_EVENT_TIMEOUT_MS, 835 ath11k_spectral_process_data); 836 837 ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap); 838 if (ret) { 839 ath11k_warn(ar->ab, "failed to setup db ring buffer\n"); 840 goto srng_cleanup; 841 } 842 843 ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring, 844 WMI_DIRECT_BUF_SPECTRAL); 845 if (ret) { 846 ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); 847 goto buffer_cleanup; 848 } 849 850 return 0; 851 852 buffer_cleanup: 853 ath11k_dbring_buf_cleanup(ar, &sp->rx_ring); 854 srng_cleanup: 855 ath11k_dbring_srng_cleanup(ar, &sp->rx_ring); 856 return ret; 857 } 858 859 static inline void ath11k_spectral_ring_free(struct ath11k *ar) 860 { 861 struct ath11k_spectral *sp = &ar->spectral; 862 863 ath11k_dbring_srng_cleanup(ar, &sp->rx_ring); 864 ath11k_dbring_buf_cleanup(ar, &sp->rx_ring); 865 } 866 867 static inline void ath11k_spectral_debug_unregister(struct ath11k *ar) 868 { 869 debugfs_remove(ar->spectral.scan_bins); 870 ar->spectral.scan_bins = NULL; 871 872 debugfs_remove(ar->spectral.scan_count); 873 ar->spectral.scan_count = NULL; 874 875 debugfs_remove(ar->spectral.scan_ctl); 876 ar->spectral.scan_ctl = NULL; 877 878 if (ar->spectral.rfs_scan) { 879 relay_close(ar->spectral.rfs_scan); 880 ar->spectral.rfs_scan = NULL; 881 } 882 } 883 884 int ath11k_spectral_vif_stop(struct ath11k_vif *arvif) 885 { 886 if (!arvif->spectral_enabled) 887 return 0; 888 889 return ath11k_spectral_scan_config(arvif->ar, ATH11K_SPECTRAL_DISABLED); 890 } 891 892 void ath11k_spectral_reset_buffer(struct ath11k *ar) 893 { 894 if (!ar->spectral.enabled) 895 return; 896 897 if (ar->spectral.rfs_scan) 898 relay_reset(ar->spectral.rfs_scan); 899 } 900 901 void ath11k_spectral_deinit(struct ath11k_base *ab) 902 { 903 struct ath11k *ar; 904 struct ath11k_spectral *sp; 905 int i; 906 907 for (i = 0; i < ab->num_radios; i++) { 908 ar = ab->pdevs[i].ar; 909 sp = &ar->spectral; 910 911 if (!sp->enabled) 912 continue; 913 914 mutex_lock(&ar->conf_mutex); 915 ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED); 916 mutex_unlock(&ar->conf_mutex); 917 918 spin_lock_bh(&sp->lock); 919 sp->enabled = false; 920 spin_unlock_bh(&sp->lock); 921 922 ath11k_spectral_debug_unregister(ar); 923 ath11k_spectral_ring_free(ar); 924 } 925 } 926 927 static inline int ath11k_spectral_debug_register(struct ath11k *ar) 928 { 929 int ret; 930 931 ar->spectral.rfs_scan = relay_open("spectral_scan", 932 ar->debug.debugfs_pdev, 933 ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar->ab), 934 ATH11K_SPECTRAL_NUM_SUB_BUF, 935 &rfs_scan_cb, NULL); 936 if (!ar->spectral.rfs_scan) { 937 ath11k_warn(ar->ab, "failed to open relay in pdev %d\n", 938 ar->pdev_idx); 939 return -EINVAL; 940 } 941 942 ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl", 943 0600, 944 ar->debug.debugfs_pdev, ar, 945 &fops_scan_ctl); 946 if (!ar->spectral.scan_ctl) { 947 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 948 ar->pdev_idx); 949 ret = -EINVAL; 950 goto debug_unregister; 951 } 952 953 ar->spectral.scan_count = debugfs_create_file("spectral_count", 954 0600, 955 ar->debug.debugfs_pdev, ar, 956 &fops_scan_count); 957 if (!ar->spectral.scan_count) { 958 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 959 ar->pdev_idx); 960 ret = -EINVAL; 961 goto debug_unregister; 962 } 963 964 ar->spectral.scan_bins = debugfs_create_file("spectral_bins", 965 0600, 966 ar->debug.debugfs_pdev, ar, 967 &fops_scan_bins); 968 if (!ar->spectral.scan_bins) { 969 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 970 ar->pdev_idx); 971 ret = -EINVAL; 972 goto debug_unregister; 973 } 974 975 return 0; 976 977 debug_unregister: 978 ath11k_spectral_debug_unregister(ar); 979 return ret; 980 } 981 982 int ath11k_spectral_init(struct ath11k_base *ab) 983 { 984 struct ath11k *ar; 985 struct ath11k_spectral *sp; 986 struct ath11k_dbring_cap db_cap; 987 int ret; 988 int i; 989 990 if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA, 991 ab->wmi_ab.svc_map)) 992 return 0; 993 994 if (!ab->hw_params.spectral.fft_sz) 995 return 0; 996 997 for (i = 0; i < ab->num_radios; i++) { 998 ar = ab->pdevs[i].ar; 999 sp = &ar->spectral; 1000 1001 ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx, 1002 WMI_DIRECT_BUF_SPECTRAL, 1003 &db_cap); 1004 if (ret) 1005 continue; 1006 1007 idr_init(&sp->rx_ring.bufs_idr); 1008 spin_lock_init(&sp->rx_ring.idr_lock); 1009 spin_lock_init(&sp->lock); 1010 1011 ret = ath11k_spectral_ring_alloc(ar, &db_cap); 1012 if (ret) { 1013 ath11k_warn(ab, "failed to init spectral ring for pdev %d\n", 1014 i); 1015 goto deinit; 1016 } 1017 1018 spin_lock_bh(&sp->lock); 1019 1020 sp->mode = ATH11K_SPECTRAL_DISABLED; 1021 sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT; 1022 sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT; 1023 sp->enabled = true; 1024 1025 spin_unlock_bh(&sp->lock); 1026 1027 ret = ath11k_spectral_debug_register(ar); 1028 if (ret) { 1029 ath11k_warn(ab, "failed to register spectral for pdev %d\n", 1030 i); 1031 goto deinit; 1032 } 1033 } 1034 1035 return 0; 1036 1037 deinit: 1038 ath11k_spectral_deinit(ab); 1039 return ret; 1040 } 1041 1042 enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar) 1043 { 1044 if (ar->spectral.enabled) 1045 return ar->spectral.mode; 1046 else 1047 return ATH11K_SPECTRAL_DISABLED; 1048 } 1049 1050 struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar) 1051 { 1052 if (ar->spectral.enabled) 1053 return &ar->spectral.rx_ring; 1054 else 1055 return NULL; 1056 } 1057