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[0]; 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 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 = (struct spectral_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 ret = ath11k_spectral_pull_search(ar, data, &search); 618 if (ret) { 619 ath11k_warn(ab, "failed to pull search report %d\n", ret); 620 return ret; 621 } 622 623 chan_width_mhz = summary->meta.ch_width; 624 625 switch (chan_width_mhz) { 626 case ATH11K_SPECTRAL_20MHZ: 627 case ATH11K_SPECTRAL_40MHZ: 628 case ATH11K_SPECTRAL_80MHZ: 629 fft_sample->chan_width_mhz = chan_width_mhz; 630 break; 631 default: 632 ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz); 633 return -EINVAL; 634 } 635 636 length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins; 637 fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K; 638 fft_sample->tlv.length = __cpu_to_be16(length); 639 640 fft_sample->tsf = __cpu_to_be32(search.timestamp); 641 fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag); 642 fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 643 __le32_to_cpu(fft_report->info0)); 644 645 summary->inb_pwr_db >>= 1; 646 fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db); 647 fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]); 648 649 freq = summary->meta.freq1; 650 fft_sample->freq1 = __cpu_to_be16(freq); 651 652 freq = summary->meta.freq2; 653 fft_sample->freq2 = __cpu_to_be16(freq); 654 655 ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins, 656 ab->hw_params.spectral.fft_sz); 657 658 fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index, 659 search.peak_mag, 660 num_bins, 661 fft_sample->data); 662 663 if (ar->spectral.rfs_scan) 664 relay_write(ar->spectral.rfs_scan, fft_sample, 665 length + sizeof(struct fft_sample_tlv)); 666 667 return 0; 668 } 669 670 static int ath11k_spectral_process_data(struct ath11k *ar, 671 struct ath11k_dbring_data *param) 672 { 673 struct ath11k_base *ab = ar->ab; 674 struct spectral_tlv *tlv; 675 struct spectral_summary_fft_report *summary = NULL; 676 struct ath11k_spectral_summary_report summ_rpt; 677 struct fft_sample_ath11k *fft_sample = NULL; 678 u8 *data; 679 u32 data_len, i; 680 u8 sign, tag; 681 int tlv_len, sample_sz; 682 int ret; 683 bool quit = false; 684 685 spin_lock_bh(&ar->spectral.lock); 686 687 if (!ar->spectral.enabled) { 688 ret = -EINVAL; 689 goto unlock; 690 } 691 692 sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab); 693 fft_sample = kmalloc(sample_sz, GFP_ATOMIC); 694 if (!fft_sample) { 695 ret = -ENOBUFS; 696 goto unlock; 697 } 698 699 data = param->data; 700 data_len = param->data_sz; 701 i = 0; 702 while (!quit && (i < data_len)) { 703 if ((i + sizeof(*tlv)) > data_len) { 704 ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n", 705 i); 706 ret = -EINVAL; 707 goto err; 708 } 709 710 tlv = (struct spectral_tlv *)&data[i]; 711 sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN, 712 __le32_to_cpu(tlv->header)); 713 if (sign != ATH11K_SPECTRAL_SIGNATURE) { 714 ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n", 715 sign, i); 716 ret = -EINVAL; 717 goto err; 718 } 719 720 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, 721 __le32_to_cpu(tlv->header)); 722 /* convert Dword into bytes */ 723 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 724 if ((i + sizeof(*tlv) + tlv_len) > data_len) { 725 ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n", 726 i, tlv_len, data_len); 727 ret = -EINVAL; 728 goto err; 729 } 730 731 tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG, 732 __le32_to_cpu(tlv->header)); 733 switch (tag) { 734 case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY: 735 /* HW bug in tlv length of summary report, 736 * HW report 3 DWORD size but the data payload 737 * is 4 DWORD size (16 bytes). 738 * Need to remove this workaround once HW bug fixed 739 */ 740 tlv_len = sizeof(*summary) - sizeof(*tlv) + 741 ab->hw_params.spectral.summary_pad_sz; 742 743 if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) { 744 ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n", 745 i, tlv_len); 746 ret = -EINVAL; 747 goto err; 748 } 749 750 summary = (struct spectral_summary_fft_report *)tlv; 751 ath11k_spectral_pull_summary(ar, ¶m->meta, 752 summary, &summ_rpt); 753 break; 754 case ATH11K_SPECTRAL_TAG_SCAN_SEARCH: 755 if (tlv_len < (sizeof(struct spectral_search_fft_report) - 756 sizeof(*tlv))) { 757 ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n", 758 i); 759 ret = -EINVAL; 760 goto err; 761 } 762 763 memset(fft_sample, 0, sample_sz); 764 ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv, 765 fft_sample, 766 data_len - i); 767 if (ret) { 768 ath11k_warn(ab, "failed to process spectral fft at bytes %d\n", 769 i); 770 goto err; 771 } 772 quit = true; 773 break; 774 } 775 776 i += sizeof(*tlv) + tlv_len; 777 } 778 779 ret = 0; 780 781 err: 782 kfree(fft_sample); 783 unlock: 784 spin_unlock_bh(&ar->spectral.lock); 785 return ret; 786 } 787 788 static int ath11k_spectral_ring_alloc(struct ath11k *ar, 789 struct ath11k_dbring_cap *db_cap) 790 { 791 struct ath11k_spectral *sp = &ar->spectral; 792 int ret; 793 794 ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring, 795 0, db_cap->min_elem); 796 if (ret) { 797 ath11k_warn(ar->ab, "failed to setup db ring\n"); 798 return ret; 799 } 800 801 ath11k_dbring_set_cfg(ar, &sp->rx_ring, 802 ATH11K_SPECTRAL_NUM_RESP_PER_EVENT, 803 ATH11K_SPECTRAL_EVENT_TIMEOUT_MS, 804 ath11k_spectral_process_data); 805 806 ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap); 807 if (ret) { 808 ath11k_warn(ar->ab, "failed to setup db ring buffer\n"); 809 goto srng_cleanup; 810 } 811 812 ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring, 813 WMI_DIRECT_BUF_SPECTRAL); 814 if (ret) { 815 ath11k_warn(ar->ab, "failed to setup db ring cfg\n"); 816 goto buffer_cleanup; 817 } 818 819 return 0; 820 821 buffer_cleanup: 822 ath11k_dbring_buf_cleanup(ar, &sp->rx_ring); 823 srng_cleanup: 824 ath11k_dbring_srng_cleanup(ar, &sp->rx_ring); 825 return ret; 826 } 827 828 static inline void ath11k_spectral_ring_free(struct ath11k *ar) 829 { 830 struct ath11k_spectral *sp = &ar->spectral; 831 832 if (!sp->enabled) 833 return; 834 835 ath11k_dbring_srng_cleanup(ar, &sp->rx_ring); 836 ath11k_dbring_buf_cleanup(ar, &sp->rx_ring); 837 } 838 839 static inline void ath11k_spectral_debug_unregister(struct ath11k *ar) 840 { 841 debugfs_remove(ar->spectral.scan_bins); 842 ar->spectral.scan_bins = NULL; 843 844 debugfs_remove(ar->spectral.scan_count); 845 ar->spectral.scan_count = NULL; 846 847 debugfs_remove(ar->spectral.scan_ctl); 848 ar->spectral.scan_ctl = NULL; 849 850 if (ar->spectral.rfs_scan) { 851 relay_close(ar->spectral.rfs_scan); 852 ar->spectral.rfs_scan = NULL; 853 } 854 } 855 856 int ath11k_spectral_vif_stop(struct ath11k_vif *arvif) 857 { 858 if (!arvif->spectral_enabled) 859 return 0; 860 861 return ath11k_spectral_scan_config(arvif->ar, ATH11K_SPECTRAL_DISABLED); 862 } 863 864 void ath11k_spectral_reset_buffer(struct ath11k *ar) 865 { 866 if (!ar->spectral.enabled) 867 return; 868 869 if (ar->spectral.rfs_scan) 870 relay_reset(ar->spectral.rfs_scan); 871 } 872 873 void ath11k_spectral_deinit(struct ath11k_base *ab) 874 { 875 struct ath11k *ar; 876 struct ath11k_spectral *sp; 877 int i; 878 879 for (i = 0; i < ab->num_radios; i++) { 880 ar = ab->pdevs[i].ar; 881 sp = &ar->spectral; 882 883 if (!sp->enabled) 884 continue; 885 886 ath11k_spectral_debug_unregister(ar); 887 ath11k_spectral_ring_free(ar); 888 889 spin_lock_bh(&sp->lock); 890 891 sp->mode = ATH11K_SPECTRAL_DISABLED; 892 sp->enabled = false; 893 894 spin_unlock_bh(&sp->lock); 895 } 896 } 897 898 static inline int ath11k_spectral_debug_register(struct ath11k *ar) 899 { 900 int ret; 901 902 ar->spectral.rfs_scan = relay_open("spectral_scan", 903 ar->debug.debugfs_pdev, 904 ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar->ab), 905 ATH11K_SPECTRAL_NUM_SUB_BUF, 906 &rfs_scan_cb, NULL); 907 if (!ar->spectral.rfs_scan) { 908 ath11k_warn(ar->ab, "failed to open relay in pdev %d\n", 909 ar->pdev_idx); 910 return -EINVAL; 911 } 912 913 ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl", 914 0600, 915 ar->debug.debugfs_pdev, ar, 916 &fops_scan_ctl); 917 if (!ar->spectral.scan_ctl) { 918 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 919 ar->pdev_idx); 920 ret = -EINVAL; 921 goto debug_unregister; 922 } 923 924 ar->spectral.scan_count = debugfs_create_file("spectral_count", 925 0600, 926 ar->debug.debugfs_pdev, ar, 927 &fops_scan_count); 928 if (!ar->spectral.scan_count) { 929 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 930 ar->pdev_idx); 931 ret = -EINVAL; 932 goto debug_unregister; 933 } 934 935 ar->spectral.scan_bins = debugfs_create_file("spectral_bins", 936 0600, 937 ar->debug.debugfs_pdev, ar, 938 &fops_scan_bins); 939 if (!ar->spectral.scan_bins) { 940 ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n", 941 ar->pdev_idx); 942 ret = -EINVAL; 943 goto debug_unregister; 944 } 945 946 return 0; 947 948 debug_unregister: 949 ath11k_spectral_debug_unregister(ar); 950 return ret; 951 } 952 953 int ath11k_spectral_init(struct ath11k_base *ab) 954 { 955 struct ath11k *ar; 956 struct ath11k_spectral *sp; 957 struct ath11k_dbring_cap db_cap; 958 int ret; 959 int i; 960 961 if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA, 962 ab->wmi_ab.svc_map)) 963 return 0; 964 965 if (!ab->hw_params.spectral.fft_sz) 966 return 0; 967 968 for (i = 0; i < ab->num_radios; i++) { 969 ar = ab->pdevs[i].ar; 970 sp = &ar->spectral; 971 972 ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx, 973 WMI_DIRECT_BUF_SPECTRAL, 974 &db_cap); 975 if (ret) 976 continue; 977 978 idr_init(&sp->rx_ring.bufs_idr); 979 spin_lock_init(&sp->rx_ring.idr_lock); 980 spin_lock_init(&sp->lock); 981 982 ret = ath11k_spectral_ring_alloc(ar, &db_cap); 983 if (ret) { 984 ath11k_warn(ab, "failed to init spectral ring for pdev %d\n", 985 i); 986 goto deinit; 987 } 988 989 spin_lock_bh(&sp->lock); 990 991 sp->mode = ATH11K_SPECTRAL_DISABLED; 992 sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT; 993 sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT; 994 sp->enabled = true; 995 996 spin_unlock_bh(&sp->lock); 997 998 ret = ath11k_spectral_debug_register(ar); 999 if (ret) { 1000 ath11k_warn(ab, "failed to register spectral for pdev %d\n", 1001 i); 1002 goto deinit; 1003 } 1004 } 1005 1006 return 0; 1007 1008 deinit: 1009 ath11k_spectral_deinit(ab); 1010 return ret; 1011 } 1012 1013 enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar) 1014 { 1015 if (ar->spectral.enabled) 1016 return ar->spectral.mode; 1017 else 1018 return ATH11K_SPECTRAL_DISABLED; 1019 } 1020 1021 struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar) 1022 { 1023 if (ar->spectral.enabled) 1024 return &ar->spectral.rx_ring; 1025 else 1026 return NULL; 1027 } 1028