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