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