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