]> Git Repo - J-linux.git/blob - drivers/net/wireless/ath/ath11k/spectral.c
Merge tag 'amd-drm-next-6.5-2023-06-09' of https://gitlab.freedesktop.org/agd5f/linux...
[J-linux.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 #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
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
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
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
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
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, &param);
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
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
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
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
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
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
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
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
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
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
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
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
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, &param->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
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
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
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
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
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
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
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
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
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
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 }
This page took 0.096547 seconds and 4 git commands to generate.