These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / wireless / ath / ath10k / spectral.c
1 /*
2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/relay.h>
18 #include "core.h"
19 #include "debug.h"
20 #include "wmi-ops.h"
21
22 static void send_fft_sample(struct ath10k *ar,
23                             const struct fft_sample_tlv *fft_sample_tlv)
24 {
25         int length;
26
27         if (!ar->spectral.rfs_chan_spec_scan)
28                 return;
29
30         length = __be16_to_cpu(fft_sample_tlv->length) +
31                  sizeof(*fft_sample_tlv);
32         relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
33 }
34
35 static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
36                            u8 *data)
37 {
38         int dc_pos;
39         u8 max_exp;
40
41         dc_pos = bin_len / 2;
42
43         /* peak index outside of bins */
44         if (dc_pos < max_index || -dc_pos >= max_index)
45                 return 0;
46
47         for (max_exp = 0; max_exp < 8; max_exp++) {
48                 if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
49                         break;
50         }
51
52         /* max_exp not found */
53         if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
54                 return 0;
55
56         return max_exp;
57 }
58
59 int ath10k_spectral_process_fft(struct ath10k *ar,
60                                 struct wmi_phyerr_ev_arg *phyerr,
61                                 const struct phyerr_fft_report *fftr,
62                                 size_t bin_len, u64 tsf)
63 {
64         struct fft_sample_ath10k *fft_sample;
65         u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
66         u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
67         u32 reg0, reg1;
68         u8 chain_idx, *bins;
69         int dc_pos;
70
71         fft_sample = (struct fft_sample_ath10k *)&buf;
72
73         if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
74                 return -EINVAL;
75
76         /* qca99x0 reports bin size as 68 bytes (64 bytes + 4 bytes) in
77          * report mode 2. First 64 bytes carries inband tones (-32 to +31)
78          * and last 4 byte carries band edge detection data (+32) mainly
79          * used in radar detection purpose. Strip last 4 byte to make bin
80          * size is valid one.
81          */
82         if (bin_len == 68)
83                 bin_len -= 4;
84
85         reg0 = __le32_to_cpu(fftr->reg0);
86         reg1 = __le32_to_cpu(fftr->reg1);
87
88         length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
89         fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
90         fft_sample->tlv.length = __cpu_to_be16(length);
91
92         /* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
93          * but the results/plots suggest that its actually 22/44/88 MHz.
94          */
95         switch (phyerr->chan_width_mhz) {
96         case 20:
97                 fft_sample->chan_width_mhz = 22;
98                 break;
99         case 40:
100                 fft_sample->chan_width_mhz = 44;
101                 break;
102         case 80:
103                 /* TODO: As experiments with an analogue sender and various
104                  * configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
105                  * show, the particular configuration of 80 MHz/64 bins does
106                  * not match with the other smaples at all. Until the reason
107                  * for that is found, don't report these samples.
108                  */
109                 if (bin_len == 64)
110                         return -EINVAL;
111                 fft_sample->chan_width_mhz = 88;
112                 break;
113         default:
114                 fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
115         }
116
117         fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
118         fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
119
120         peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
121         fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
122         fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
123         fft_sample->rssi = phyerr->rssi_combined;
124
125         total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
126         base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
127         fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
128         fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
129
130         freq1 = phyerr->freq1;
131         freq2 = phyerr->freq2;
132         fft_sample->freq1 = __cpu_to_be16(freq1);
133         fft_sample->freq2 = __cpu_to_be16(freq2);
134
135         chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
136
137         fft_sample->noise = __cpu_to_be16(phyerr->nf_chains[chain_idx]);
138
139         bins = (u8 *)fftr;
140         bins += sizeof(*fftr);
141
142         fft_sample->tsf = __cpu_to_be64(tsf);
143
144         /* max_exp has been directly reported by previous hardware (ath9k),
145          * maybe its possible to get it by other means?
146          */
147         fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
148                                           bin_len, bins);
149
150         memcpy(fft_sample->data, bins, bin_len);
151
152         /* DC value (value in the middle) is the blind spot of the spectral
153          * sample and invalid, interpolate it.
154          */
155         dc_pos = bin_len / 2;
156         fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
157                                     fft_sample->data[dc_pos - 1]) / 2;
158
159         send_fft_sample(ar, &fft_sample->tlv);
160
161         return 0;
162 }
163
164 static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
165 {
166         struct ath10k_vif *arvif;
167
168         lockdep_assert_held(&ar->conf_mutex);
169
170         if (list_empty(&ar->arvifs))
171                 return NULL;
172
173         /* if there already is a vif doing spectral, return that. */
174         list_for_each_entry(arvif, &ar->arvifs, list)
175                 if (arvif->spectral_enabled)
176                         return arvif;
177
178         /* otherwise, return the first vif. */
179         return list_first_entry(&ar->arvifs, typeof(*arvif), list);
180 }
181
182 static int ath10k_spectral_scan_trigger(struct ath10k *ar)
183 {
184         struct ath10k_vif *arvif;
185         int res;
186         int vdev_id;
187
188         lockdep_assert_held(&ar->conf_mutex);
189
190         arvif = ath10k_get_spectral_vdev(ar);
191         if (!arvif)
192                 return -ENODEV;
193         vdev_id = arvif->vdev_id;
194
195         if (ar->spectral.mode == SPECTRAL_DISABLED)
196                 return 0;
197
198         res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
199                                               WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
200                                               WMI_SPECTRAL_ENABLE_CMD_ENABLE);
201         if (res < 0)
202                 return res;
203
204         res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
205                                               WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
206                                               WMI_SPECTRAL_ENABLE_CMD_ENABLE);
207         if (res < 0)
208                 return res;
209
210         return 0;
211 }
212
213 static int ath10k_spectral_scan_config(struct ath10k *ar,
214                                        enum ath10k_spectral_mode mode)
215 {
216         struct wmi_vdev_spectral_conf_arg arg;
217         struct ath10k_vif *arvif;
218         int vdev_id, count, res = 0;
219
220         lockdep_assert_held(&ar->conf_mutex);
221
222         arvif = ath10k_get_spectral_vdev(ar);
223         if (!arvif)
224                 return -ENODEV;
225
226         vdev_id = arvif->vdev_id;
227
228         arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
229         ar->spectral.mode = mode;
230
231         res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
232                                               WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
233                                               WMI_SPECTRAL_ENABLE_CMD_DISABLE);
234         if (res < 0) {
235                 ath10k_warn(ar, "failed to enable spectral scan: %d\n", res);
236                 return res;
237         }
238
239         if (mode == SPECTRAL_DISABLED)
240                 return 0;
241
242         if (mode == SPECTRAL_BACKGROUND)
243                 count = WMI_SPECTRAL_COUNT_DEFAULT;
244         else
245                 count = max_t(u8, 1, ar->spectral.config.count);
246
247         arg.vdev_id = vdev_id;
248         arg.scan_count = count;
249         arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
250         arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
251         arg.scan_fft_size = ar->spectral.config.fft_size;
252         arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
253         arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
254         arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
255         arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
256         arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
257         arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
258         arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
259         arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
260         arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
261         arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
262         arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
263         arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
264         arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
265         arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
266
267         res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
268         if (res < 0) {
269                 ath10k_warn(ar, "failed to configure spectral scan: %d\n", res);
270                 return res;
271         }
272
273         return 0;
274 }
275
276 static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
277                                        size_t count, loff_t *ppos)
278 {
279         struct ath10k *ar = file->private_data;
280         char *mode = "";
281         unsigned int len;
282         enum ath10k_spectral_mode spectral_mode;
283
284         mutex_lock(&ar->conf_mutex);
285         spectral_mode = ar->spectral.mode;
286         mutex_unlock(&ar->conf_mutex);
287
288         switch (spectral_mode) {
289         case SPECTRAL_DISABLED:
290                 mode = "disable";
291                 break;
292         case SPECTRAL_BACKGROUND:
293                 mode = "background";
294                 break;
295         case SPECTRAL_MANUAL:
296                 mode = "manual";
297                 break;
298         }
299
300         len = strlen(mode);
301         return simple_read_from_buffer(user_buf, count, ppos, mode, len);
302 }
303
304 static ssize_t write_file_spec_scan_ctl(struct file *file,
305                                         const char __user *user_buf,
306                                         size_t count, loff_t *ppos)
307 {
308         struct ath10k *ar = file->private_data;
309         char buf[32];
310         ssize_t len;
311         int res;
312
313         len = min(count, sizeof(buf) - 1);
314         if (copy_from_user(buf, user_buf, len))
315                 return -EFAULT;
316
317         buf[len] = '\0';
318
319         mutex_lock(&ar->conf_mutex);
320
321         if (strncmp("trigger", buf, 7) == 0) {
322                 if (ar->spectral.mode == SPECTRAL_MANUAL ||
323                     ar->spectral.mode == SPECTRAL_BACKGROUND) {
324                         /* reset the configuration to adopt possibly changed
325                          * debugfs parameters
326                          */
327                         res = ath10k_spectral_scan_config(ar,
328                                                           ar->spectral.mode);
329                         if (res < 0) {
330                                 ath10k_warn(ar, "failed to reconfigure spectral scan: %d\n",
331                                             res);
332                         }
333                         res = ath10k_spectral_scan_trigger(ar);
334                         if (res < 0) {
335                                 ath10k_warn(ar, "failed to trigger spectral scan: %d\n",
336                                             res);
337                         }
338                 } else {
339                         res = -EINVAL;
340                 }
341         } else if (strncmp("background", buf, 9) == 0) {
342                 res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
343         } else if (strncmp("manual", buf, 6) == 0) {
344                 res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
345         } else if (strncmp("disable", buf, 7) == 0) {
346                 res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
347         } else {
348                 res = -EINVAL;
349         }
350
351         mutex_unlock(&ar->conf_mutex);
352
353         if (res < 0)
354                 return res;
355
356         return count;
357 }
358
359 static const struct file_operations fops_spec_scan_ctl = {
360         .read = read_file_spec_scan_ctl,
361         .write = write_file_spec_scan_ctl,
362         .open = simple_open,
363         .owner = THIS_MODULE,
364         .llseek = default_llseek,
365 };
366
367 static ssize_t read_file_spectral_count(struct file *file,
368                                         char __user *user_buf,
369                                         size_t count, loff_t *ppos)
370 {
371         struct ath10k *ar = file->private_data;
372         char buf[32];
373         unsigned int len;
374         u8 spectral_count;
375
376         mutex_lock(&ar->conf_mutex);
377         spectral_count = ar->spectral.config.count;
378         mutex_unlock(&ar->conf_mutex);
379
380         len = sprintf(buf, "%d\n", spectral_count);
381         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
382 }
383
384 static ssize_t write_file_spectral_count(struct file *file,
385                                          const char __user *user_buf,
386                                          size_t count, loff_t *ppos)
387 {
388         struct ath10k *ar = file->private_data;
389         unsigned long val;
390         char buf[32];
391         ssize_t len;
392
393         len = min(count, sizeof(buf) - 1);
394         if (copy_from_user(buf, user_buf, len))
395                 return -EFAULT;
396
397         buf[len] = '\0';
398         if (kstrtoul(buf, 0, &val))
399                 return -EINVAL;
400
401         if (val < 0 || val > 255)
402                 return -EINVAL;
403
404         mutex_lock(&ar->conf_mutex);
405         ar->spectral.config.count = val;
406         mutex_unlock(&ar->conf_mutex);
407
408         return count;
409 }
410
411 static const struct file_operations fops_spectral_count = {
412         .read = read_file_spectral_count,
413         .write = write_file_spectral_count,
414         .open = simple_open,
415         .owner = THIS_MODULE,
416         .llseek = default_llseek,
417 };
418
419 static ssize_t read_file_spectral_bins(struct file *file,
420                                        char __user *user_buf,
421                                        size_t count, loff_t *ppos)
422 {
423         struct ath10k *ar = file->private_data;
424         char buf[32];
425         unsigned int len, bins, fft_size, bin_scale;
426
427         mutex_lock(&ar->conf_mutex);
428
429         fft_size = ar->spectral.config.fft_size;
430         bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
431         bins = 1 << (fft_size - bin_scale);
432
433         mutex_unlock(&ar->conf_mutex);
434
435         len = sprintf(buf, "%d\n", bins);
436         return simple_read_from_buffer(user_buf, count, ppos, buf, len);
437 }
438
439 static ssize_t write_file_spectral_bins(struct file *file,
440                                         const char __user *user_buf,
441                                         size_t count, loff_t *ppos)
442 {
443         struct ath10k *ar = file->private_data;
444         unsigned long val;
445         char buf[32];
446         ssize_t len;
447
448         len = min(count, sizeof(buf) - 1);
449         if (copy_from_user(buf, user_buf, len))
450                 return -EFAULT;
451
452         buf[len] = '\0';
453         if (kstrtoul(buf, 0, &val))
454                 return -EINVAL;
455
456         if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
457                 return -EINVAL;
458
459         if (!is_power_of_2(val))
460                 return -EINVAL;
461
462         mutex_lock(&ar->conf_mutex);
463         ar->spectral.config.fft_size = ilog2(val);
464         ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
465         mutex_unlock(&ar->conf_mutex);
466
467         return count;
468 }
469
470 static const struct file_operations fops_spectral_bins = {
471         .read = read_file_spectral_bins,
472         .write = write_file_spectral_bins,
473         .open = simple_open,
474         .owner = THIS_MODULE,
475         .llseek = default_llseek,
476 };
477
478 static struct dentry *create_buf_file_handler(const char *filename,
479                                               struct dentry *parent,
480                                               umode_t mode,
481                                               struct rchan_buf *buf,
482                                               int *is_global)
483 {
484         struct dentry *buf_file;
485
486         buf_file = debugfs_create_file(filename, mode, parent, buf,
487                                        &relay_file_operations);
488         *is_global = 1;
489         return buf_file;
490 }
491
492 static int remove_buf_file_handler(struct dentry *dentry)
493 {
494         debugfs_remove(dentry);
495
496         return 0;
497 }
498
499 static struct rchan_callbacks rfs_spec_scan_cb = {
500         .create_buf_file = create_buf_file_handler,
501         .remove_buf_file = remove_buf_file_handler,
502 };
503
504 int ath10k_spectral_start(struct ath10k *ar)
505 {
506         struct ath10k_vif *arvif;
507
508         lockdep_assert_held(&ar->conf_mutex);
509
510         list_for_each_entry(arvif, &ar->arvifs, list)
511                 arvif->spectral_enabled = 0;
512
513         ar->spectral.mode = SPECTRAL_DISABLED;
514         ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
515         ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
516
517         return 0;
518 }
519
520 int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
521 {
522         if (!arvif->spectral_enabled)
523                 return 0;
524
525         return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
526 }
527
528 int ath10k_spectral_create(struct ath10k *ar)
529 {
530         /* The buffer size covers whole channels in dual bands up to 128 bins.
531          * Scan with bigger than 128 bins needs to be run on single band each.
532          */
533         ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
534                                                      ar->debug.debugfs_phy,
535                                                      1140, 2500,
536                                                      &rfs_spec_scan_cb, NULL);
537         debugfs_create_file("spectral_scan_ctl",
538                             S_IRUSR | S_IWUSR,
539                             ar->debug.debugfs_phy, ar,
540                             &fops_spec_scan_ctl);
541         debugfs_create_file("spectral_count",
542                             S_IRUSR | S_IWUSR,
543                             ar->debug.debugfs_phy, ar,
544                             &fops_spectral_count);
545         debugfs_create_file("spectral_bins",
546                             S_IRUSR | S_IWUSR,
547                             ar->debug.debugfs_phy, ar,
548                             &fops_spectral_bins);
549
550         return 0;
551 }
552
553 void ath10k_spectral_destroy(struct ath10k *ar)
554 {
555         if (ar->spectral.rfs_chan_spec_scan) {
556                 relay_close(ar->spectral.rfs_chan_spec_scan);
557                 ar->spectral.rfs_chan_spec_scan = NULL;
558         }
559 }