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
create_buf_file_handler(const char * filename,struct dentry * parent,umode_t mode,struct rchan_buf * buf,int * is_global)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
remove_buf_file_handler(struct dentry * dentry)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
ath11k_spectral_get_vdev(struct ath11k * ar)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
ath11k_spectral_scan_trigger(struct ath11k * ar)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
ath11k_spectral_scan_config(struct ath11k * ar,enum ath11k_spectral_mode mode)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
ath11k_read_file_spec_scan_ctl(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)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
ath11k_write_file_spec_scan_ctl(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)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
ath11k_read_file_spectral_count(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)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
ath11k_write_file_spectral_count(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)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
ath11k_read_file_spectral_bins(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)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
ath11k_write_file_spectral_bins(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)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
ath11k_spectral_pull_summary(struct ath11k * ar,struct wmi_dma_buf_release_meta_data * meta,struct spectral_summary_fft_report * summary,struct ath11k_spectral_summary_report * report)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
ath11k_spectral_pull_search(struct ath11k * ar,struct spectral_search_fft_report * search,struct ath11k_spectral_search_report * report)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
ath11k_spectral_get_max_exp(s8 max_index,u8 max_magnitude,int bin_len,u8 * bins)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
ath11k_spectral_parse_fft(u8 * outbins,u8 * inbins,int num_bins,u8 fft_sz)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
ath11k_spectral_process_fft(struct ath11k * ar,struct ath11k_spectral_summary_report * summary,void * data,struct fft_sample_ath11k * fft_sample,u32 data_len)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
ath11k_spectral_process_data(struct ath11k * ar,struct ath11k_dbring_data * param)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
ath11k_spectral_ring_alloc(struct ath11k * ar,struct ath11k_dbring_cap * db_cap)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
ath11k_spectral_ring_free(struct ath11k * ar)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
ath11k_spectral_debug_unregister(struct ath11k * ar)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
ath11k_spectral_vif_stop(struct ath11k_vif * arvif)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
ath11k_spectral_reset_buffer(struct ath11k * ar)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
ath11k_spectral_deinit(struct ath11k_base * ab)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
ath11k_spectral_debug_register(struct ath11k * ar)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
ath11k_spectral_init(struct ath11k_base * ab)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
ath11k_spectral_get_mode(struct ath11k * ar)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
ath11k_spectral_get_dbring(struct ath11k * ar)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