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