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