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