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 ar->spectral.mode = mode; 216 217 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 218 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, 219 ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE); 220 if (ret) { 221 ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret); 222 return ret; 223 } 224 225 if (mode == ATH11K_SPECTRAL_DISABLED) 226 return 0; 227 228 if (mode == ATH11K_SPECTRAL_BACKGROUND) 229 count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT; 230 else 231 count = max_t(u16, 1, ar->spectral.count); 232 233 param.vdev_id = arvif->vdev_id; 234 param.scan_count = count; 235 param.scan_fft_size = ar->spectral.fft_size; 236 param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT; 237 param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT; 238 param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT; 239 param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT; 240 param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT; 241 param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT; 242 param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT; 243 param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT; 244 param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT; 245 param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT; 246 param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT; 247 param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT; 248 param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT; 249 param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT; 250 param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT; 251 param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT; 252 253 ret = ath11k_wmi_vdev_spectral_conf(ar, ¶m); 254 if (ret) { 255 ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret); 256 return ret; 257 } 258 259 return 0; 260 } 261 262 static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file, 263 char __user *user_buf, 264 size_t count, loff_t *ppos) 265 { 266 struct ath11k *ar = file->private_data; 267 char *mode = ""; 268 size_t len; 269 enum ath11k_spectral_mode spectral_mode; 270 271 mutex_lock(&ar->conf_mutex); 272 spectral_mode = ar->spectral.mode; 273 mutex_unlock(&ar->conf_mutex); 274 275 switch (spectral_mode) { 276 case ATH11K_SPECTRAL_DISABLED: 277 mode = "disable"; 278 break; 279 case ATH11K_SPECTRAL_BACKGROUND: 280 mode = "background"; 281 break; 282 case ATH11K_SPECTRAL_MANUAL: 283 mode = "manual"; 284 break; 285 } 286 287 len = strlen(mode); 288 return simple_read_from_buffer(user_buf, count, ppos, mode, len); 289 } 290 291 static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file, 292 const char __user *user_buf, 293 size_t count, loff_t *ppos) 294 { 295 struct ath11k *ar = file->private_data; 296 char buf[32]; 297 ssize_t len; 298 int ret; 299 300 len = min(count, sizeof(buf) - 1); 301 if (copy_from_user(buf, user_buf, len)) 302 return -EFAULT; 303 304 buf[len] = '\0'; 305 306 mutex_lock(&ar->conf_mutex); 307 308 if (strncmp("trigger", buf, 7) == 0) { 309 if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL || 310 ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) { 311 /* reset the configuration to adopt possibly changed 312 * debugfs parameters 313 */ 314 ret = ath11k_spectral_scan_config(ar, ar->spectral.mode); 315 if (ret) { 316 ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n", 317 ret); 318 goto unlock; 319 } 320 321 ret = ath11k_spectral_scan_trigger(ar); 322 if (ret) { 323 ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n", 324 ret); 325 } 326 } else { 327 ret = -EINVAL; 328 } 329 } else if (strncmp("background", buf, 10) == 0) { 330 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND); 331 } else if (strncmp("manual", buf, 6) == 0) { 332 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL); 333 } else if (strncmp("disable", buf, 7) == 0) { 334 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED); 335 } else { 336 ret = -EINVAL; 337 } 338 339 unlock: 340 mutex_unlock(&ar->conf_mutex); 341 342 if (ret) 343 return ret; 344 345 return count; 346 } 347 348 static const struct file_operations fops_scan_ctl = { 349 .read = ath11k_read_file_spec_scan_ctl, 350 .write = ath11k_write_file_spec_scan_ctl, 351 .open = simple_open, 352 .owner = THIS_MODULE, 353 .llseek = default_llseek, 354 }; 355 356 static ssize_t ath11k_read_file_spectral_count(struct file *file, 357 char __user *user_buf, 358 size_t count, loff_t *ppos) 359 { 360 struct ath11k *ar = file->private_data; 361 char buf[32]; 362 size_t len; 363 u16 spectral_count; 364 365 mutex_lock(&ar->conf_mutex); 366 spectral_count = ar->spectral.count; 367 mutex_unlock(&ar->conf_mutex); 368 369 len = sprintf(buf, "%d\n", spectral_count); 370 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 371 } 372 373 static ssize_t ath11k_write_file_spectral_count(struct file *file, 374 const char __user *user_buf, 375 size_t count, loff_t *ppos) 376 { 377 struct ath11k *ar = file->private_data; 378 unsigned long val; 379 char buf[32]; 380 ssize_t len; 381 382 len = min(count, sizeof(buf) - 1); 383 if (copy_from_user(buf, user_buf, len)) 384 return -EFAULT; 385 386 buf[len] = '\0'; 387 if (kstrtoul(buf, 0, &val)) 388 return -EINVAL; 389 390 if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX) 391 return -EINVAL; 392 393 mutex_lock(&ar->conf_mutex); 394 ar->spectral.count = val; 395 mutex_unlock(&ar->conf_mutex); 396 397 return count; 398 } 399 400 static const struct file_operations fops_scan_count = { 401 .read = ath11k_read_file_spectral_count, 402 .write = ath11k_write_file_spectral_count, 403 .open = simple_open, 404 .owner = THIS_MODULE, 405 .llseek = default_llseek, 406 }; 407 408 static ssize_t ath11k_read_file_spectral_bins(struct file *file, 409 char __user *user_buf, 410 size_t count, loff_t *ppos) 411 { 412 struct ath11k *ar = file->private_data; 413 char buf[32]; 414 unsigned int bins, fft_size; 415 size_t len; 416 417 mutex_lock(&ar->conf_mutex); 418 419 fft_size = ar->spectral.fft_size; 420 bins = 1 << fft_size; 421 422 mutex_unlock(&ar->conf_mutex); 423 424 len = sprintf(buf, "%d\n", bins); 425 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 426 } 427 428 static ssize_t ath11k_write_file_spectral_bins(struct file *file, 429 const char __user *user_buf, 430 size_t count, loff_t *ppos) 431 { 432 struct ath11k *ar = file->private_data; 433 unsigned long val; 434 char buf[32]; 435 ssize_t len; 436 437 len = min(count, sizeof(buf) - 1); 438 if (copy_from_user(buf, user_buf, len)) 439 return -EFAULT; 440 441 buf[len] = '\0'; 442 if (kstrtoul(buf, 0, &val)) 443 return -EINVAL; 444 445 if (val < ATH11K_SPECTRAL_MIN_BINS || 446 val > ar->ab->hw_params.spectral.max_fft_bins) 447 return -EINVAL; 448 449 if (!is_power_of_2(val)) 450 return -EINVAL; 451 452 mutex_lock(&ar->conf_mutex); 453 ar->spectral.fft_size = ilog2(val); 454 mutex_unlock(&ar->conf_mutex); 455 456 return count; 457 } 458 459 static const struct file_operations fops_scan_bins = { 460 .read = ath11k_read_file_spectral_bins, 461 .write = ath11k_write_file_spectral_bins, 462 .open = simple_open, 463 .owner = THIS_MODULE, 464 .llseek = default_llseek, 465 }; 466 467 static int ath11k_spectral_pull_summary(struct ath11k *ar, 468 struct wmi_dma_buf_release_meta_data *meta, 469 struct spectral_summary_fft_report *summary, 470 struct ath11k_spectral_summary_report *report) 471 { 472 report->timestamp = __le32_to_cpu(summary->timestamp); 473 report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN, 474 __le32_to_cpu(summary->info0)); 475 report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG, 476 __le32_to_cpu(summary->info0)); 477 report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX, 478 __le32_to_cpu(summary->info0)); 479 report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT, 480 __le32_to_cpu(summary->info0)); 481 report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB, 482 __le32_to_cpu(summary->info0)); 483 report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN, 484 __le32_to_cpu(summary->info0)); 485 report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID, 486 __le32_to_cpu(summary->info0)); 487 report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80, 488 __le32_to_cpu(summary->info0)); 489 report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX, 490 __le32_to_cpu(summary->info2)); 491 report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE, 492 __le32_to_cpu(summary->info2)); 493 report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE, 494 __le32_to_cpu(summary->info2)); 495 496 memcpy(&report->meta, meta, sizeof(*meta)); 497 498 return 0; 499 } 500 501 static int ath11k_spectral_pull_search(struct ath11k *ar, 502 struct spectral_search_fft_report *search, 503 struct ath11k_spectral_search_report *report) 504 { 505 report->timestamp = __le32_to_cpu(search->timestamp); 506 report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID, 507 __le32_to_cpu(search->info0)); 508 report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM, 509 __le32_to_cpu(search->info0)); 510 report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK, 511 __le32_to_cpu(search->info0)); 512 report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 513 __le32_to_cpu(search->info0)); 514 report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX, 515 __le32_to_cpu(search->info0)); 516 report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB, 517 __le32_to_cpu(search->info1)); 518 report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB, 519 __le32_to_cpu(search->info1)); 520 report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS, 521 __le32_to_cpu(search->info2)); 522 report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE, 523 __le32_to_cpu(search->info2)); 524 report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB, 525 __le32_to_cpu(search->info2)); 526 report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB, 527 __le32_to_cpu(search->info2)); 528 529 return 0; 530 } 531 532 static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude, 533 int bin_len, u8 *bins) 534 { 535 int dc_pos; 536 u8 max_exp; 537 538 dc_pos = bin_len / 2; 539 540 /* peak index outside of bins */ 541 if (dc_pos <= max_index || -dc_pos >= max_index) 542 return 0; 543 544 for (max_exp = 0; max_exp < 8; max_exp++) { 545 if (bins[dc_pos + max_index] == (max_magnitude >> max_exp)) 546 break; 547 } 548 549 /* max_exp not found */ 550 if (bins[dc_pos + max_index] != (max_magnitude >> max_exp)) 551 return 0; 552 553 return max_exp; 554 } 555 556 static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz) 557 { 558 int i, j; 559 560 i = 0; 561 j = 0; 562 while (i < num_bins) { 563 outbins[i] = inbins[j]; 564 i++; 565 j += fft_sz; 566 } 567 } 568 569 static 570 int ath11k_spectral_process_fft(struct ath11k *ar, 571 struct ath11k_spectral_summary_report *summary, 572 void *data, 573 struct fft_sample_ath11k *fft_sample, 574 u32 data_len) 575 { 576 struct ath11k_base *ab = ar->ab; 577 struct spectral_search_fft_report *fft_report = data; 578 struct ath11k_spectral_search_report search; 579 struct spectral_tlv *tlv; 580 int tlv_len, bin_len, num_bins; 581 u16 length, freq; 582 u8 chan_width_mhz, bin_sz; 583 int ret; 584 u32 check_length; 585 586 lockdep_assert_held(&ar->spectral.lock); 587 588 if (!ab->hw_params.spectral.fft_sz) { 589 ath11k_warn(ab, "invalid bin size type for hw rev %d\n", 590 ab->hw_rev); 591 return -EINVAL; 592 } 593 594 tlv = (struct spectral_tlv *)data; 595 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header)); 596 /* convert Dword into bytes */ 597 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 598 bin_len = tlv_len - ab->hw_params.spectral.fft_hdr_len; 599 600 if (data_len < (bin_len + sizeof(*fft_report))) { 601 ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n", 602 bin_len, data_len); 603 return -EINVAL; 604 } 605 606 bin_sz = ab->hw_params.spectral.fft_sz + ab->hw_params.spectral.fft_pad_sz; 607 num_bins = bin_len / bin_sz; 608 /* Only In-band bins are useful to user for visualize */ 609 num_bins >>= 1; 610 611 if (num_bins < ATH11K_SPECTRAL_MIN_IB_BINS || 612 num_bins > ATH11K_SPECTRAL_MAX_IB_BINS(ab) || 613 !is_power_of_2(num_bins)) { 614 ath11k_warn(ab, "Invalid num of bins %d\n", num_bins); 615 return -EINVAL; 616 } 617 618 check_length = sizeof(*fft_report) + (num_bins * ab->hw_params.spectral.fft_sz); 619 ret = ath11k_dbring_validate_buffer(ar, data, check_length); 620 if (ret) { 621 ath11k_warn(ar->ab, "found magic value in fft data, dropping\n"); 622 return ret; 623 } 624 625 ret = ath11k_spectral_pull_search(ar, data, &search); 626 if (ret) { 627 ath11k_warn(ab, "failed to pull search report %d\n", ret); 628 return ret; 629 } 630 631 chan_width_mhz = summary->meta.ch_width; 632 633 switch (chan_width_mhz) { 634 case ATH11K_SPECTRAL_20MHZ: 635 case ATH11K_SPECTRAL_40MHZ: 636 case ATH11K_SPECTRAL_80MHZ: 637 fft_sample->chan_width_mhz = chan_width_mhz; 638 break; 639 default: 640 ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz); 641 return -EINVAL; 642 } 643 644 length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins; 645 fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K; 646 fft_sample->tlv.length = __cpu_to_be16(length); 647 648 fft_sample->tsf = __cpu_to_be32(search.timestamp); 649 fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag); 650 fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 651 __le32_to_cpu(fft_report->info0)); 652 653 summary->inb_pwr_db >>= 1; 654 fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db); 655 fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]); 656 657 freq = summary->meta.freq1; 658 fft_sample->freq1 = __cpu_to_be16(freq); 659 660 freq = summary->meta.freq2; 661 fft_sample->freq2 = __cpu_to_be16(freq); 662 663 ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins, 664 ab->hw_params.spectral.fft_sz); 665 666 fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index, 667 search.peak_mag, 668 num_bins, 669 fft_sample->data); 670 671 if (ar->spectral.rfs_scan) 672 relay_write(ar->spectral.rfs_scan, fft_sample, 673 length + sizeof(struct fft_sample_tlv)); 674 675 return 0; 676 } 677 678 static int ath11k_spectral_process_data(struct ath11k *ar, 679 struct ath11k_dbring_data *param) 680 { 681 struct ath11k_base *ab = ar->ab; 682 struct spectral_tlv *tlv; 683 struct spectral_summary_fft_report *summary = NULL; 684 struct ath11k_spectral_summary_report summ_rpt; 685 struct fft_sample_ath11k *fft_sample = NULL; 686 u8 *data; 687 u32 data_len, i; 688 u8 sign, tag; 689 int tlv_len, sample_sz; 690 int ret; 691 bool quit = false; 692 693 spin_lock_bh(&ar->spectral.lock); 694 695 if (!ar->spectral.enabled) { 696 ret = -EINVAL; 697 goto unlock; 698 } 699 700 sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab); 701 fft_sample = kmalloc(sample_sz, GFP_ATOMIC); 702 if (!fft_sample) { 703 ret = -ENOBUFS; 704 goto unlock; 705 } 706 707 data = param->data; 708 data_len = param->data_sz; 709 i = 0; 710 while (!quit && (i < data_len)) { 711 if ((i + sizeof(*tlv)) > data_len) { 712 ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n", 713 i); 714 ret = -EINVAL; 715 goto err; 716 } 717 718 tlv = (struct spectral_tlv *)&data[i]; 719 sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN, 720 __le32_to_cpu(tlv->header)); 721 if (sign != ATH11K_SPECTRAL_SIGNATURE) { 722 ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n", 723 sign, i); 724 ret = -EINVAL; 725 goto err; 726 } 727 728 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, 729 __le32_to_cpu(tlv->header)); 730 /* convert Dword into bytes */ 731 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 732 if ((i + sizeof(*tlv) + tlv_len) > data_len) { 733 ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n", 734 i, tlv_len, data_len); 735 ret = -EINVAL; 736 goto err; 737 } 738 739 tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG, 740 __le32_to_cpu(tlv->header)); 741 switch (tag) { 742 case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY: 743 /* HW bug in tlv length of summary report, 744 * HW report 3 DWORD size but the data payload 745 * is 4 DWORD size (16 bytes). 746 * Need to remove this workaround once HW bug fixed 747 */ 748 tlv_len = sizeof(*summary) - sizeof(*tlv) + 749 ab->hw_params.spectral.summary_pad_sz; 750 751 if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) { 752 ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n", 753 i, tlv_len); 754 ret = -EINVAL; 755 goto err; 756 } 757 758 ret = ath11k_dbring_validate_buffer(ar, data, tlv_len); 759 if (ret) { 760 ath11k_warn(ar->ab, "found magic value in spectral summary, dropping\n"); 761 goto err; 762 } 763 764 summary = (struct spectral_summary_fft_report *)tlv; 765 ath11k_spectral_pull_summary(ar, ¶m->meta, 766 summary, &summ_rpt); 767 break; 768 case ATH11K_SPECTRAL_TAG_SCAN_SEARCH: 769 if (tlv_len < (sizeof(struct spectral_search_fft_report) - 770 sizeof(*tlv))) { 771 ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n", 772 i); 773 ret = -EINVAL; 774 goto err; 775 } 776 777 memset(fft_sample, 0, sample_sz); 778 ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv, 779 fft_sample, 780 data_len - i); 781 if (ret) { 782 ath11k_warn(ab, "failed to process spectral fft at bytes %d\n", 783 i); 784 goto err; 785 } 786 quit = true; 787 break; 788 } 789 790 i += sizeof(*tlv) + tlv_len; 791 } 792 793 ret = 0; 794 795 err: 796 kfree(fft_sample); 797 unlock: 798 spin_unlock_bh(&ar->spectral.lock); 799 return ret; 800 } 801 802 static int ath11k_spectral_ring_alloc(struct ath11k *ar, 803 struct ath11k_dbring_cap *db_cap) 804 { 805 struct ath11k_spectral *sp = &ar->spectral; 806 int ret; 807 808 ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring, 809 0, db_cap->min_elem); 810 if (ret) { 811 ath11k_warn(ar->ab, "failed to setup db ring\n"); 812 return ret; 813 } 814 815 ath11k_dbring_set_cfg(ar, &sp->rx_ring, 816 ATH11K_SPECTRAL_NUM_RESP_PER_EVENT, 817 ATH11K_SPECTRAL_EVENT_TIMEOUT_MS, 818 ath11k_spectral_process_data); 819 820 ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap); 821 if (ret) { 822 ath11k_warn(ar->ab, "failed to setup db ring buffer\n"); 823 goto srng_cleanup; 824 } 825 826 ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring, 827 WMI_DIRECT_BUF_SPECTRAL); 828 if (ret) { 829 ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); 830 goto buffer_cleanup; 831 } 832 833 return 0; 834 835 buffer_cleanup: 836 ath11k_dbring_buf_cleanup(ar, &sp->rx_ring); 837 srng_cleanup: 838 ath11k_dbring_srng_cleanup(ar, &sp->rx_ring); 839 return ret; 840 } 841 842 static inline void ath11k_spectral_ring_free(struct ath11k *ar) 843 { 844 struct ath11k_spectral *sp = &ar->spectral; 845 846 if (!sp->enabled) 847 return; 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 ath11k_spectral_debug_unregister(ar); 901 ath11k_spectral_ring_free(ar); 902 903 spin_lock_bh(&sp->lock); 904 905 sp->mode = ATH11K_SPECTRAL_DISABLED; 906 sp->enabled = false; 907 908 spin_unlock_bh(&sp->lock); 909 } 910 } 911 912 static inline int ath11k_spectral_debug_register(struct ath11k *ar) 913 { 914 int ret; 915 916 ar->spectral.rfs_scan = relay_open("spectral_scan", 917 ar->debug.debugfs_pdev, 918 ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar->ab), 919 ATH11K_SPECTRAL_NUM_SUB_BUF, 920 &rfs_scan_cb, NULL); 921 if (!ar->spectral.rfs_scan) { 922 ath11k_warn(ar->ab, "failed to open relay in pdev %d\n", 923 ar->pdev_idx); 924 return -EINVAL; 925 } 926 927 ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl", 928 0600, 929 ar->debug.debugfs_pdev, ar, 930 &fops_scan_ctl); 931 if (!ar->spectral.scan_ctl) { 932 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 933 ar->pdev_idx); 934 ret = -EINVAL; 935 goto debug_unregister; 936 } 937 938 ar->spectral.scan_count = debugfs_create_file("spectral_count", 939 0600, 940 ar->debug.debugfs_pdev, ar, 941 &fops_scan_count); 942 if (!ar->spectral.scan_count) { 943 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 944 ar->pdev_idx); 945 ret = -EINVAL; 946 goto debug_unregister; 947 } 948 949 ar->spectral.scan_bins = debugfs_create_file("spectral_bins", 950 0600, 951 ar->debug.debugfs_pdev, ar, 952 &fops_scan_bins); 953 if (!ar->spectral.scan_bins) { 954 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 955 ar->pdev_idx); 956 ret = -EINVAL; 957 goto debug_unregister; 958 } 959 960 return 0; 961 962 debug_unregister: 963 ath11k_spectral_debug_unregister(ar); 964 return ret; 965 } 966 967 int ath11k_spectral_init(struct ath11k_base *ab) 968 { 969 struct ath11k *ar; 970 struct ath11k_spectral *sp; 971 struct ath11k_dbring_cap db_cap; 972 int ret; 973 int i; 974 975 if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA, 976 ab->wmi_ab.svc_map)) 977 return 0; 978 979 if (!ab->hw_params.spectral.fft_sz) 980 return 0; 981 982 for (i = 0; i < ab->num_radios; i++) { 983 ar = ab->pdevs[i].ar; 984 sp = &ar->spectral; 985 986 ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx, 987 WMI_DIRECT_BUF_SPECTRAL, 988 &db_cap); 989 if (ret) 990 continue; 991 992 idr_init(&sp->rx_ring.bufs_idr); 993 spin_lock_init(&sp->rx_ring.idr_lock); 994 spin_lock_init(&sp->lock); 995 996 ret = ath11k_spectral_ring_alloc(ar, &db_cap); 997 if (ret) { 998 ath11k_warn(ab, "failed to init spectral ring for pdev %d\n", 999 i); 1000 goto deinit; 1001 } 1002 1003 spin_lock_bh(&sp->lock); 1004 1005 sp->mode = ATH11K_SPECTRAL_DISABLED; 1006 sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT; 1007 sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT; 1008 sp->enabled = true; 1009 1010 spin_unlock_bh(&sp->lock); 1011 1012 ret = ath11k_spectral_debug_register(ar); 1013 if (ret) { 1014 ath11k_warn(ab, "failed to register spectral for pdev %d\n", 1015 i); 1016 goto deinit; 1017 } 1018 } 1019 1020 return 0; 1021 1022 deinit: 1023 ath11k_spectral_deinit(ab); 1024 return ret; 1025 } 1026 1027 enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar) 1028 { 1029 if (ar->spectral.enabled) 1030 return ar->spectral.mode; 1031 else 1032 return ATH11K_SPECTRAL_DISABLED; 1033 } 1034 1035 struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar) 1036 { 1037 if (ar->spectral.enabled) 1038 return &ar->spectral.rx_ring; 1039 else 1040 return NULL; 1041 } 1042