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 /* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes */ 15 #define ATH11K_SPECTRAL_BIN_SIZE 4 16 #define ATH11K_SPECTRAL_ATH11K_MIN_BINS 64 17 #define ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS 32 18 #define ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS 256 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 (sizeof(struct fft_sample_ath11k) + \ 26 ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS) 27 #define ATH11K_SPECTRAL_TOTAL_SAMPLE (ATH11K_SPECTRAL_TOTAL_CHANNEL * \ 28 ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL) 29 #define ATH11K_SPECTRAL_SUB_BUFF_SIZE ATH11K_SPECTRAL_PER_SAMPLE_SIZE 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 36 #define ATH11K_SPECTRAL_SIGNATURE 0xFA 37 38 #define ATH11K_SPECTRAL_TAG_RADAR_SUMMARY 0x0 39 #define ATH11K_SPECTRAL_TAG_RADAR_FFT 0x1 40 #define ATH11K_SPECTRAL_TAG_SCAN_SUMMARY 0x2 41 #define ATH11K_SPECTRAL_TAG_SCAN_SEARCH 0x3 42 43 #define SPECTRAL_TLV_HDR_LEN GENMASK(15, 0) 44 #define SPECTRAL_TLV_HDR_TAG GENMASK(23, 16) 45 #define SPECTRAL_TLV_HDR_SIGN GENMASK(31, 24) 46 47 #define SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN GENMASK(7, 0) 48 #define SPECTRAL_SUMMARY_INFO0_OB_FLAG BIT(8) 49 #define SPECTRAL_SUMMARY_INFO0_GRP_IDX GENMASK(16, 9) 50 #define SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT BIT(17) 51 #define SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB GENMASK(27, 18) 52 #define SPECTRAL_SUMMARY_INFO0_FALSE_SCAN BIT(28) 53 #define SPECTRAL_SUMMARY_INFO0_DETECTOR_ID GENMASK(30, 29) 54 #define SPECTRAL_SUMMARY_INFO0_PRI80 BIT(31) 55 56 #define SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX GENMASK(11, 0) 57 #define SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE GENMASK(21, 12) 58 #define SPECTRAL_SUMMARY_INFO2_NARROWBAND_MASK GENMASK(29, 22) 59 #define SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE BIT(30) 60 61 struct spectral_tlv { 62 __le32 timestamp; 63 __le32 header; 64 } __packed; 65 66 struct spectral_summary_fft_report { 67 __le32 timestamp; 68 __le32 tlv_header; 69 __le32 info0; 70 __le32 reserve0; 71 __le32 info2; 72 __le32 reserve1; 73 } __packed; 74 75 struct ath11k_spectral_summary_report { 76 struct wmi_dma_buf_release_meta_data meta; 77 u32 timestamp; 78 u8 agc_total_gain; 79 u8 grp_idx; 80 u16 inb_pwr_db; 81 s16 peak_idx; 82 u16 peak_mag; 83 u8 detector_id; 84 bool out_of_band_flag; 85 bool rf_saturation; 86 bool primary80; 87 bool gain_change; 88 bool false_scan; 89 }; 90 91 #define SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID GENMASK(1, 0) 92 #define SPECTRAL_FFT_REPORT_INFO0_FFT_NUM GENMASK(4, 2) 93 #define SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK GENMASK(16, 5) 94 #define SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX GENMASK(27, 17) 95 #define SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX GENMASK(30, 28) 96 97 #define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB GENMASK(8, 0) 98 #define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB GENMASK(16, 9) 99 100 #define SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS GENMASK(7, 0) 101 #define SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE GENMASK(17, 8) 102 #define SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB GENMASK(24, 18) 103 #define SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB GENMASK(31, 25) 104 105 struct spectral_search_fft_report { 106 __le32 timestamp; 107 __le32 tlv_header; 108 __le32 info0; 109 __le32 info1; 110 __le32 info2; 111 __le32 reserve0; 112 u8 bins[0]; 113 } __packed; 114 115 struct ath11k_spectral_search_report { 116 u32 timestamp; 117 u8 detector_id; 118 u8 fft_count; 119 u16 radar_check; 120 s16 peak_idx; 121 u8 chain_idx; 122 u16 base_pwr_db; 123 u8 total_gain_db; 124 u8 strong_bin_count; 125 u16 peak_mag; 126 u8 avg_pwr_db; 127 u8 rel_pwr_db; 128 }; 129 130 static struct dentry *create_buf_file_handler(const char *filename, 131 struct dentry *parent, 132 umode_t mode, 133 struct rchan_buf *buf, 134 int *is_global) 135 { 136 struct dentry *buf_file; 137 138 buf_file = debugfs_create_file(filename, mode, parent, buf, 139 &relay_file_operations); 140 *is_global = 1; 141 return buf_file; 142 } 143 144 static int remove_buf_file_handler(struct dentry *dentry) 145 { 146 debugfs_remove(dentry); 147 148 return 0; 149 } 150 151 static struct rchan_callbacks rfs_scan_cb = { 152 .create_buf_file = create_buf_file_handler, 153 .remove_buf_file = remove_buf_file_handler, 154 }; 155 156 static struct ath11k_vif *ath11k_spectral_get_vdev(struct ath11k *ar) 157 { 158 struct ath11k_vif *arvif; 159 160 lockdep_assert_held(&ar->conf_mutex); 161 162 if (list_empty(&ar->arvifs)) 163 return NULL; 164 165 /* if there already is a vif doing spectral, return that. */ 166 list_for_each_entry(arvif, &ar->arvifs, list) 167 if (arvif->spectral_enabled) 168 return arvif; 169 170 /* otherwise, return the first vif. */ 171 return list_first_entry(&ar->arvifs, typeof(*arvif), list); 172 } 173 174 static int ath11k_spectral_scan_trigger(struct ath11k *ar) 175 { 176 struct ath11k_vif *arvif; 177 int ret; 178 179 lockdep_assert_held(&ar->conf_mutex); 180 181 arvif = ath11k_spectral_get_vdev(ar); 182 if (!arvif) 183 return -ENODEV; 184 185 if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED) 186 return 0; 187 188 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 189 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, 190 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); 191 if (ret) 192 return ret; 193 194 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 195 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER, 196 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE); 197 if (ret) 198 return ret; 199 200 return 0; 201 } 202 203 static int ath11k_spectral_scan_config(struct ath11k *ar, 204 enum ath11k_spectral_mode mode) 205 { 206 struct ath11k_wmi_vdev_spectral_conf_param param = { 0 }; 207 struct ath11k_vif *arvif; 208 int ret, count; 209 210 lockdep_assert_held(&ar->conf_mutex); 211 212 arvif = ath11k_spectral_get_vdev(ar); 213 if (!arvif) 214 return -ENODEV; 215 216 arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED); 217 ar->spectral.mode = mode; 218 219 ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id, 220 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR, 221 ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE); 222 if (ret) { 223 ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret); 224 return ret; 225 } 226 227 if (mode == ATH11K_SPECTRAL_DISABLED) 228 return 0; 229 230 if (mode == ATH11K_SPECTRAL_BACKGROUND) 231 count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT; 232 else 233 count = max_t(u16, 1, ar->spectral.count); 234 235 param.vdev_id = arvif->vdev_id; 236 param.scan_count = count; 237 param.scan_fft_size = ar->spectral.fft_size; 238 param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT; 239 param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT; 240 param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT; 241 param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT; 242 param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT; 243 param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT; 244 param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT; 245 param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT; 246 param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT; 247 param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT; 248 param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT; 249 param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT; 250 param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT; 251 param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT; 252 param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT; 253 param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT; 254 255 ret = ath11k_wmi_vdev_spectral_conf(ar, ¶m); 256 if (ret) { 257 ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret); 258 return ret; 259 } 260 261 return 0; 262 } 263 264 static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file, 265 char __user *user_buf, 266 size_t count, loff_t *ppos) 267 { 268 struct ath11k *ar = file->private_data; 269 char *mode = ""; 270 size_t len; 271 enum ath11k_spectral_mode spectral_mode; 272 273 mutex_lock(&ar->conf_mutex); 274 spectral_mode = ar->spectral.mode; 275 mutex_unlock(&ar->conf_mutex); 276 277 switch (spectral_mode) { 278 case ATH11K_SPECTRAL_DISABLED: 279 mode = "disable"; 280 break; 281 case ATH11K_SPECTRAL_BACKGROUND: 282 mode = "background"; 283 break; 284 case ATH11K_SPECTRAL_MANUAL: 285 mode = "manual"; 286 break; 287 } 288 289 len = strlen(mode); 290 return simple_read_from_buffer(user_buf, count, ppos, mode, len); 291 } 292 293 static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file, 294 const char __user *user_buf, 295 size_t count, loff_t *ppos) 296 { 297 struct ath11k *ar = file->private_data; 298 char buf[32]; 299 ssize_t len; 300 int ret; 301 302 len = min(count, sizeof(buf) - 1); 303 if (copy_from_user(buf, user_buf, len)) 304 return -EFAULT; 305 306 buf[len] = '\0'; 307 308 mutex_lock(&ar->conf_mutex); 309 310 if (strncmp("trigger", buf, 7) == 0) { 311 if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL || 312 ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) { 313 /* reset the configuration to adopt possibly changed 314 * debugfs parameters 315 */ 316 ret = ath11k_spectral_scan_config(ar, ar->spectral.mode); 317 if (ret) { 318 ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n", 319 ret); 320 goto unlock; 321 } 322 323 ret = ath11k_spectral_scan_trigger(ar); 324 if (ret) { 325 ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n", 326 ret); 327 } 328 } else { 329 ret = -EINVAL; 330 } 331 } else if (strncmp("background", buf, 10) == 0) { 332 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND); 333 } else if (strncmp("manual", buf, 6) == 0) { 334 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL); 335 } else if (strncmp("disable", buf, 7) == 0) { 336 ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED); 337 } else { 338 ret = -EINVAL; 339 } 340 341 unlock: 342 mutex_unlock(&ar->conf_mutex); 343 344 if (ret) 345 return ret; 346 347 return count; 348 } 349 350 static const struct file_operations fops_scan_ctl = { 351 .read = ath11k_read_file_spec_scan_ctl, 352 .write = ath11k_write_file_spec_scan_ctl, 353 .open = simple_open, 354 .owner = THIS_MODULE, 355 .llseek = default_llseek, 356 }; 357 358 static ssize_t ath11k_read_file_spectral_count(struct file *file, 359 char __user *user_buf, 360 size_t count, loff_t *ppos) 361 { 362 struct ath11k *ar = file->private_data; 363 char buf[32]; 364 size_t len; 365 u16 spectral_count; 366 367 mutex_lock(&ar->conf_mutex); 368 spectral_count = ar->spectral.count; 369 mutex_unlock(&ar->conf_mutex); 370 371 len = sprintf(buf, "%d\n", spectral_count); 372 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 373 } 374 375 static ssize_t ath11k_write_file_spectral_count(struct file *file, 376 const char __user *user_buf, 377 size_t count, loff_t *ppos) 378 { 379 struct ath11k *ar = file->private_data; 380 unsigned long val; 381 char buf[32]; 382 ssize_t len; 383 384 len = min(count, sizeof(buf) - 1); 385 if (copy_from_user(buf, user_buf, len)) 386 return -EFAULT; 387 388 buf[len] = '\0'; 389 if (kstrtoul(buf, 0, &val)) 390 return -EINVAL; 391 392 if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX) 393 return -EINVAL; 394 395 mutex_lock(&ar->conf_mutex); 396 ar->spectral.count = val; 397 mutex_unlock(&ar->conf_mutex); 398 399 return count; 400 } 401 402 static const struct file_operations fops_scan_count = { 403 .read = ath11k_read_file_spectral_count, 404 .write = ath11k_write_file_spectral_count, 405 .open = simple_open, 406 .owner = THIS_MODULE, 407 .llseek = default_llseek, 408 }; 409 410 static ssize_t ath11k_read_file_spectral_bins(struct file *file, 411 char __user *user_buf, 412 size_t count, loff_t *ppos) 413 { 414 struct ath11k *ar = file->private_data; 415 char buf[32]; 416 unsigned int bins, fft_size; 417 size_t len; 418 419 mutex_lock(&ar->conf_mutex); 420 421 fft_size = ar->spectral.fft_size; 422 bins = 1 << fft_size; 423 424 mutex_unlock(&ar->conf_mutex); 425 426 len = sprintf(buf, "%d\n", bins); 427 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 428 } 429 430 static ssize_t ath11k_write_file_spectral_bins(struct file *file, 431 const char __user *user_buf, 432 size_t count, loff_t *ppos) 433 { 434 struct ath11k *ar = file->private_data; 435 unsigned long val; 436 char buf[32]; 437 ssize_t len; 438 439 len = min(count, sizeof(buf) - 1); 440 if (copy_from_user(buf, user_buf, len)) 441 return -EFAULT; 442 443 buf[len] = '\0'; 444 if (kstrtoul(buf, 0, &val)) 445 return -EINVAL; 446 447 if (val < ATH11K_SPECTRAL_ATH11K_MIN_BINS || 448 val > SPECTRAL_ATH11K_MAX_NUM_BINS) 449 return -EINVAL; 450 451 if (!is_power_of_2(val)) 452 return -EINVAL; 453 454 mutex_lock(&ar->conf_mutex); 455 ar->spectral.fft_size = ilog2(val); 456 mutex_unlock(&ar->conf_mutex); 457 458 return count; 459 } 460 461 static const struct file_operations fops_scan_bins = { 462 .read = ath11k_read_file_spectral_bins, 463 .write = ath11k_write_file_spectral_bins, 464 .open = simple_open, 465 .owner = THIS_MODULE, 466 .llseek = default_llseek, 467 }; 468 469 static int ath11k_spectral_pull_summary(struct ath11k *ar, 470 struct wmi_dma_buf_release_meta_data *meta, 471 struct spectral_summary_fft_report *summary, 472 struct ath11k_spectral_summary_report *report) 473 { 474 report->timestamp = __le32_to_cpu(summary->timestamp); 475 report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN, 476 __le32_to_cpu(summary->info0)); 477 report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG, 478 __le32_to_cpu(summary->info0)); 479 report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX, 480 __le32_to_cpu(summary->info0)); 481 report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT, 482 __le32_to_cpu(summary->info0)); 483 report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB, 484 __le32_to_cpu(summary->info0)); 485 report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN, 486 __le32_to_cpu(summary->info0)); 487 report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID, 488 __le32_to_cpu(summary->info0)); 489 report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80, 490 __le32_to_cpu(summary->info0)); 491 report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX, 492 __le32_to_cpu(summary->info2)); 493 report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE, 494 __le32_to_cpu(summary->info2)); 495 report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE, 496 __le32_to_cpu(summary->info2)); 497 498 memcpy(&report->meta, meta, sizeof(*meta)); 499 500 return 0; 501 } 502 503 static int ath11k_spectral_pull_search(struct ath11k *ar, 504 struct spectral_search_fft_report *search, 505 struct ath11k_spectral_search_report *report) 506 { 507 report->timestamp = __le32_to_cpu(search->timestamp); 508 report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID, 509 __le32_to_cpu(search->info0)); 510 report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM, 511 __le32_to_cpu(search->info0)); 512 report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK, 513 __le32_to_cpu(search->info0)); 514 report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 515 __le32_to_cpu(search->info0)); 516 report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX, 517 __le32_to_cpu(search->info0)); 518 report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB, 519 __le32_to_cpu(search->info1)); 520 report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB, 521 __le32_to_cpu(search->info1)); 522 report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS, 523 __le32_to_cpu(search->info2)); 524 report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE, 525 __le32_to_cpu(search->info2)); 526 report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB, 527 __le32_to_cpu(search->info2)); 528 report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB, 529 __le32_to_cpu(search->info2)); 530 531 return 0; 532 } 533 534 static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude, 535 int bin_len, u8 *bins) 536 { 537 int dc_pos; 538 u8 max_exp; 539 540 dc_pos = bin_len / 2; 541 542 /* peak index outside of bins */ 543 if (dc_pos <= max_index || -dc_pos >= max_index) 544 return 0; 545 546 for (max_exp = 0; max_exp < 8; max_exp++) { 547 if (bins[dc_pos + max_index] == (max_magnitude >> max_exp)) 548 break; 549 } 550 551 /* max_exp not found */ 552 if (bins[dc_pos + max_index] != (max_magnitude >> max_exp)) 553 return 0; 554 555 return max_exp; 556 } 557 558 static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz) 559 { 560 int i, j; 561 562 i = 0; 563 j = 0; 564 while (i < num_bins) { 565 outbins[i] = inbins[j]; 566 i++; 567 j += fft_sz; 568 } 569 } 570 571 static 572 int ath11k_spectral_process_fft(struct ath11k *ar, 573 struct ath11k_spectral_summary_report *summary, 574 void *data, 575 struct fft_sample_ath11k *fft_sample, 576 u32 data_len) 577 { 578 struct ath11k_base *ab = ar->ab; 579 struct spectral_search_fft_report *fft_report = data; 580 struct ath11k_spectral_search_report search; 581 struct spectral_tlv *tlv; 582 int tlv_len, bin_len, num_bins; 583 u16 length, freq; 584 u8 chan_width_mhz; 585 int ret; 586 587 lockdep_assert_held(&ar->spectral.lock); 588 589 if (!ab->hw_params.spectral_fft_sz) { 590 ath11k_warn(ab, "invalid bin size type for hw rev %d\n", 591 ab->hw_rev); 592 return -EINVAL; 593 } 594 595 tlv = (struct spectral_tlv *)data; 596 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header)); 597 /* convert Dword into bytes */ 598 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 599 bin_len = tlv_len - (sizeof(*fft_report) - sizeof(*tlv)); 600 601 if (data_len < (bin_len + sizeof(*fft_report))) { 602 ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n", 603 bin_len, data_len); 604 return -EINVAL; 605 } 606 607 num_bins = bin_len / ATH11K_SPECTRAL_BIN_SIZE; 608 /* Only In-band bins are useful to user for visualize */ 609 num_bins >>= 1; 610 611 if (num_bins < ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS || 612 num_bins > ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS || 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 ret = ath11k_spectral_pull_search(ar, data, &search); 619 if (ret) { 620 ath11k_warn(ab, "failed to pull search report %d\n", ret); 621 return ret; 622 } 623 624 chan_width_mhz = summary->meta.ch_width; 625 626 switch (chan_width_mhz) { 627 case ATH11K_SPECTRAL_20MHZ: 628 case ATH11K_SPECTRAL_40MHZ: 629 case ATH11K_SPECTRAL_80MHZ: 630 fft_sample->chan_width_mhz = chan_width_mhz; 631 break; 632 default: 633 ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz); 634 return -EINVAL; 635 } 636 637 length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins; 638 fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K; 639 fft_sample->tlv.length = __cpu_to_be16(length); 640 641 fft_sample->tsf = __cpu_to_be32(search.timestamp); 642 fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag); 643 fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX, 644 __le32_to_cpu(fft_report->info0)); 645 646 summary->inb_pwr_db >>= 1; 647 fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db); 648 fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]); 649 650 freq = summary->meta.freq1; 651 fft_sample->freq1 = __cpu_to_be16(freq); 652 653 freq = summary->meta.freq2; 654 fft_sample->freq2 = __cpu_to_be16(freq); 655 656 ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins, 657 ab->hw_params.spectral_fft_sz); 658 659 fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index, 660 search.peak_mag, 661 num_bins, 662 fft_sample->data); 663 664 if (ar->spectral.rfs_scan) 665 relay_write(ar->spectral.rfs_scan, fft_sample, 666 length + sizeof(struct fft_sample_tlv)); 667 668 return 0; 669 } 670 671 static int ath11k_spectral_process_data(struct ath11k *ar, 672 struct ath11k_dbring_data *param) 673 { 674 struct ath11k_base *ab = ar->ab; 675 struct spectral_tlv *tlv; 676 struct spectral_summary_fft_report *summary = NULL; 677 struct ath11k_spectral_summary_report summ_rpt; 678 struct fft_sample_ath11k *fft_sample = NULL; 679 u8 *data; 680 u32 data_len, i; 681 u8 sign, tag; 682 int tlv_len, sample_sz; 683 int ret; 684 bool quit = false; 685 686 spin_lock_bh(&ar->spectral.lock); 687 688 if (!ar->spectral.enabled) { 689 ret = -EINVAL; 690 goto unlock; 691 } 692 693 sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS; 694 fft_sample = kmalloc(sample_sz, GFP_ATOMIC); 695 if (!fft_sample) { 696 ret = -ENOBUFS; 697 goto unlock; 698 } 699 700 data = param->data; 701 data_len = param->data_sz; 702 i = 0; 703 while (!quit && (i < data_len)) { 704 if ((i + sizeof(*tlv)) > data_len) { 705 ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n", 706 i); 707 ret = -EINVAL; 708 goto err; 709 } 710 711 tlv = (struct spectral_tlv *)&data[i]; 712 sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN, 713 __le32_to_cpu(tlv->header)); 714 if (sign != ATH11K_SPECTRAL_SIGNATURE) { 715 ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n", 716 sign, i); 717 ret = -EINVAL; 718 goto err; 719 } 720 721 tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, 722 __le32_to_cpu(tlv->header)); 723 /* convert Dword into bytes */ 724 tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE; 725 if ((i + sizeof(*tlv) + tlv_len) > data_len) { 726 ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n", 727 i, tlv_len, data_len); 728 ret = -EINVAL; 729 goto err; 730 } 731 732 tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG, 733 __le32_to_cpu(tlv->header)); 734 switch (tag) { 735 case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY: 736 /* HW bug in tlv length of summary report, 737 * HW report 3 DWORD size but the data payload 738 * is 4 DWORD size (16 bytes). 739 * Need to remove this workaround once HW bug fixed 740 */ 741 tlv_len = sizeof(*summary) - sizeof(*tlv); 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, 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