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