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