2 * Copyright (c) 2013-2017 Qualcomm Atheros, Inc.
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.
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.
17 #include <linux/relay.h>
22 static void send_fft_sample(struct ath10k
*ar
,
23 const struct fft_sample_tlv
*fft_sample_tlv
)
27 if (!ar
->spectral
.rfs_chan_spec_scan
)
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
);
35 static uint8_t get_max_exp(s8 max_index
, u16 max_magnitude
, size_t bin_len
,
43 /* peak index outside of bins */
44 if (dc_pos
< max_index
|| -dc_pos
>= max_index
)
47 for (max_exp
= 0; max_exp
< 8; max_exp
++) {
48 if (data
[dc_pos
+ max_index
] == (max_magnitude
>> max_exp
))
52 /* max_exp not found */
53 if (data
[dc_pos
+ max_index
] != (max_magnitude
>> max_exp
))
59 static inline size_t ath10k_spectral_fix_bin_size(struct ath10k
*ar
,
62 /* some chipsets reports bin size as 2^n bytes + 'm' bytes in
63 * report mode 2. First 2^n bytes carries inband tones and last
64 * 'm' bytes carries band edge detection data mainly used in
65 * radar detection purpose. Strip last 'm' bytes to make bin size
66 * as a valid one. 'm' can take possible values of 4, 12.
68 if (!is_power_of_2(bin_len
))
69 bin_len
-= ar
->hw_params
.spectral_bin_discard
;
74 int ath10k_spectral_process_fft(struct ath10k
*ar
,
75 struct wmi_phyerr_ev_arg
*phyerr
,
76 const struct phyerr_fft_report
*fftr
,
77 size_t bin_len
, u64 tsf
)
79 struct fft_sample_ath10k
*fft_sample
;
80 u8 buf
[sizeof(*fft_sample
) + SPECTRAL_ATH10K_MAX_NUM_BINS
];
81 u16 freq1
, freq2
, total_gain_db
, base_pwr_db
, length
, peak_mag
;
86 fft_sample
= (struct fft_sample_ath10k
*)&buf
;
88 bin_len
= ath10k_spectral_fix_bin_size(ar
, bin_len
);
90 if (bin_len
< 64 || bin_len
> SPECTRAL_ATH10K_MAX_NUM_BINS
)
93 reg0
= __le32_to_cpu(fftr
->reg0
);
94 reg1
= __le32_to_cpu(fftr
->reg1
);
96 length
= sizeof(*fft_sample
) - sizeof(struct fft_sample_tlv
) + bin_len
;
97 fft_sample
->tlv
.type
= ATH_FFT_SAMPLE_ATH10K
;
98 fft_sample
->tlv
.length
= __cpu_to_be16(length
);
100 /* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
101 * but the results/plots suggest that its actually 22/44/88 MHz.
103 switch (phyerr
->chan_width_mhz
) {
105 fft_sample
->chan_width_mhz
= 22;
108 fft_sample
->chan_width_mhz
= 44;
111 /* TODO: As experiments with an analogue sender and various
112 * configurations (fft-sizes of 64/128/256 and 20/40/80 Mhz)
113 * show, the particular configuration of 80 MHz/64 bins does
114 * not match with the other samples at all. Until the reason
115 * for that is found, don't report these samples.
119 fft_sample
->chan_width_mhz
= 88;
122 fft_sample
->chan_width_mhz
= phyerr
->chan_width_mhz
;
125 fft_sample
->relpwr_db
= MS(reg1
, SEARCH_FFT_REPORT_REG1_RELPWR_DB
);
126 fft_sample
->avgpwr_db
= MS(reg1
, SEARCH_FFT_REPORT_REG1_AVGPWR_DB
);
128 peak_mag
= MS(reg1
, SEARCH_FFT_REPORT_REG1_PEAK_MAG
);
129 fft_sample
->max_magnitude
= __cpu_to_be16(peak_mag
);
130 fft_sample
->max_index
= MS(reg0
, SEARCH_FFT_REPORT_REG0_PEAK_SIDX
);
131 fft_sample
->rssi
= phyerr
->rssi_combined
;
133 total_gain_db
= MS(reg0
, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB
);
134 base_pwr_db
= MS(reg0
, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB
);
135 fft_sample
->total_gain_db
= __cpu_to_be16(total_gain_db
);
136 fft_sample
->base_pwr_db
= __cpu_to_be16(base_pwr_db
);
138 freq1
= phyerr
->freq1
;
139 freq2
= phyerr
->freq2
;
140 fft_sample
->freq1
= __cpu_to_be16(freq1
);
141 fft_sample
->freq2
= __cpu_to_be16(freq2
);
143 chain_idx
= MS(reg0
, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX
);
145 fft_sample
->noise
= __cpu_to_be16(phyerr
->nf_chains
[chain_idx
]);
148 bins
+= sizeof(*fftr
);
150 fft_sample
->tsf
= __cpu_to_be64(tsf
);
152 /* max_exp has been directly reported by previous hardware (ath9k),
153 * maybe its possible to get it by other means?
155 fft_sample
->max_exp
= get_max_exp(fft_sample
->max_index
, peak_mag
,
158 memcpy(fft_sample
->data
, bins
, bin_len
);
160 /* DC value (value in the middle) is the blind spot of the spectral
161 * sample and invalid, interpolate it.
163 dc_pos
= bin_len
/ 2;
164 fft_sample
->data
[dc_pos
] = (fft_sample
->data
[dc_pos
+ 1] +
165 fft_sample
->data
[dc_pos
- 1]) / 2;
167 send_fft_sample(ar
, &fft_sample
->tlv
);
172 static struct ath10k_vif
*ath10k_get_spectral_vdev(struct ath10k
*ar
)
174 struct ath10k_vif
*arvif
;
176 lockdep_assert_held(&ar
->conf_mutex
);
178 if (list_empty(&ar
->arvifs
))
181 /* if there already is a vif doing spectral, return that. */
182 list_for_each_entry(arvif
, &ar
->arvifs
, list
)
183 if (arvif
->spectral_enabled
)
186 /* otherwise, return the first vif. */
187 return list_first_entry(&ar
->arvifs
, typeof(*arvif
), list
);
190 static int ath10k_spectral_scan_trigger(struct ath10k
*ar
)
192 struct ath10k_vif
*arvif
;
196 lockdep_assert_held(&ar
->conf_mutex
);
198 arvif
= ath10k_get_spectral_vdev(ar
);
201 vdev_id
= arvif
->vdev_id
;
203 if (ar
->spectral
.mode
== SPECTRAL_DISABLED
)
206 res
= ath10k_wmi_vdev_spectral_enable(ar
, vdev_id
,
207 WMI_SPECTRAL_TRIGGER_CMD_CLEAR
,
208 WMI_SPECTRAL_ENABLE_CMD_ENABLE
);
212 res
= ath10k_wmi_vdev_spectral_enable(ar
, vdev_id
,
213 WMI_SPECTRAL_TRIGGER_CMD_TRIGGER
,
214 WMI_SPECTRAL_ENABLE_CMD_ENABLE
);
221 static int ath10k_spectral_scan_config(struct ath10k
*ar
,
222 enum ath10k_spectral_mode mode
)
224 struct wmi_vdev_spectral_conf_arg arg
;
225 struct ath10k_vif
*arvif
;
226 int vdev_id
, count
, res
= 0;
228 lockdep_assert_held(&ar
->conf_mutex
);
230 arvif
= ath10k_get_spectral_vdev(ar
);
234 vdev_id
= arvif
->vdev_id
;
236 arvif
->spectral_enabled
= (mode
!= SPECTRAL_DISABLED
);
237 ar
->spectral
.mode
= mode
;
239 res
= ath10k_wmi_vdev_spectral_enable(ar
, vdev_id
,
240 WMI_SPECTRAL_TRIGGER_CMD_CLEAR
,
241 WMI_SPECTRAL_ENABLE_CMD_DISABLE
);
243 ath10k_warn(ar
, "failed to enable spectral scan: %d\n", res
);
247 if (mode
== SPECTRAL_DISABLED
)
250 if (mode
== SPECTRAL_BACKGROUND
)
251 count
= WMI_SPECTRAL_COUNT_DEFAULT
;
253 count
= max_t(u8
, 1, ar
->spectral
.config
.count
);
255 arg
.vdev_id
= vdev_id
;
256 arg
.scan_count
= count
;
257 arg
.scan_period
= WMI_SPECTRAL_PERIOD_DEFAULT
;
258 arg
.scan_priority
= WMI_SPECTRAL_PRIORITY_DEFAULT
;
259 arg
.scan_fft_size
= ar
->spectral
.config
.fft_size
;
260 arg
.scan_gc_ena
= WMI_SPECTRAL_GC_ENA_DEFAULT
;
261 arg
.scan_restart_ena
= WMI_SPECTRAL_RESTART_ENA_DEFAULT
;
262 arg
.scan_noise_floor_ref
= WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT
;
263 arg
.scan_init_delay
= WMI_SPECTRAL_INIT_DELAY_DEFAULT
;
264 arg
.scan_nb_tone_thr
= WMI_SPECTRAL_NB_TONE_THR_DEFAULT
;
265 arg
.scan_str_bin_thr
= WMI_SPECTRAL_STR_BIN_THR_DEFAULT
;
266 arg
.scan_wb_rpt_mode
= WMI_SPECTRAL_WB_RPT_MODE_DEFAULT
;
267 arg
.scan_rssi_rpt_mode
= WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT
;
268 arg
.scan_rssi_thr
= WMI_SPECTRAL_RSSI_THR_DEFAULT
;
269 arg
.scan_pwr_format
= WMI_SPECTRAL_PWR_FORMAT_DEFAULT
;
270 arg
.scan_rpt_mode
= WMI_SPECTRAL_RPT_MODE_DEFAULT
;
271 arg
.scan_bin_scale
= WMI_SPECTRAL_BIN_SCALE_DEFAULT
;
272 arg
.scan_dbm_adj
= WMI_SPECTRAL_DBM_ADJ_DEFAULT
;
273 arg
.scan_chn_mask
= WMI_SPECTRAL_CHN_MASK_DEFAULT
;
275 res
= ath10k_wmi_vdev_spectral_conf(ar
, &arg
);
277 ath10k_warn(ar
, "failed to configure spectral scan: %d\n", res
);
284 static ssize_t
read_file_spec_scan_ctl(struct file
*file
, char __user
*user_buf
,
285 size_t count
, loff_t
*ppos
)
287 struct ath10k
*ar
= file
->private_data
;
290 enum ath10k_spectral_mode spectral_mode
;
292 mutex_lock(&ar
->conf_mutex
);
293 spectral_mode
= ar
->spectral
.mode
;
294 mutex_unlock(&ar
->conf_mutex
);
296 switch (spectral_mode
) {
297 case SPECTRAL_DISABLED
:
300 case SPECTRAL_BACKGROUND
:
303 case SPECTRAL_MANUAL
:
309 return simple_read_from_buffer(user_buf
, count
, ppos
, mode
, len
);
312 static ssize_t
write_file_spec_scan_ctl(struct file
*file
,
313 const char __user
*user_buf
,
314 size_t count
, loff_t
*ppos
)
316 struct ath10k
*ar
= file
->private_data
;
321 len
= min(count
, sizeof(buf
) - 1);
322 if (copy_from_user(buf
, user_buf
, len
))
327 mutex_lock(&ar
->conf_mutex
);
329 if (strncmp("trigger", buf
, 7) == 0) {
330 if (ar
->spectral
.mode
== SPECTRAL_MANUAL
||
331 ar
->spectral
.mode
== SPECTRAL_BACKGROUND
) {
332 /* reset the configuration to adopt possibly changed
335 res
= ath10k_spectral_scan_config(ar
,
338 ath10k_warn(ar
, "failed to reconfigure spectral scan: %d\n",
341 res
= ath10k_spectral_scan_trigger(ar
);
343 ath10k_warn(ar
, "failed to trigger spectral scan: %d\n",
349 } else if (strncmp("background", buf
, 10) == 0) {
350 res
= ath10k_spectral_scan_config(ar
, SPECTRAL_BACKGROUND
);
351 } else if (strncmp("manual", buf
, 6) == 0) {
352 res
= ath10k_spectral_scan_config(ar
, SPECTRAL_MANUAL
);
353 } else if (strncmp("disable", buf
, 7) == 0) {
354 res
= ath10k_spectral_scan_config(ar
, SPECTRAL_DISABLED
);
359 mutex_unlock(&ar
->conf_mutex
);
367 static const struct file_operations fops_spec_scan_ctl
= {
368 .read
= read_file_spec_scan_ctl
,
369 .write
= write_file_spec_scan_ctl
,
371 .owner
= THIS_MODULE
,
372 .llseek
= default_llseek
,
375 static ssize_t
read_file_spectral_count(struct file
*file
,
376 char __user
*user_buf
,
377 size_t count
, loff_t
*ppos
)
379 struct ath10k
*ar
= file
->private_data
;
384 mutex_lock(&ar
->conf_mutex
);
385 spectral_count
= ar
->spectral
.config
.count
;
386 mutex_unlock(&ar
->conf_mutex
);
388 len
= sprintf(buf
, "%d\n", spectral_count
);
389 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
392 static ssize_t
write_file_spectral_count(struct file
*file
,
393 const char __user
*user_buf
,
394 size_t count
, loff_t
*ppos
)
396 struct ath10k
*ar
= file
->private_data
;
401 len
= min(count
, sizeof(buf
) - 1);
402 if (copy_from_user(buf
, user_buf
, len
))
406 if (kstrtoul(buf
, 0, &val
))
412 mutex_lock(&ar
->conf_mutex
);
413 ar
->spectral
.config
.count
= val
;
414 mutex_unlock(&ar
->conf_mutex
);
419 static const struct file_operations fops_spectral_count
= {
420 .read
= read_file_spectral_count
,
421 .write
= write_file_spectral_count
,
423 .owner
= THIS_MODULE
,
424 .llseek
= default_llseek
,
427 static ssize_t
read_file_spectral_bins(struct file
*file
,
428 char __user
*user_buf
,
429 size_t count
, loff_t
*ppos
)
431 struct ath10k
*ar
= file
->private_data
;
433 unsigned int bins
, fft_size
, bin_scale
;
436 mutex_lock(&ar
->conf_mutex
);
438 fft_size
= ar
->spectral
.config
.fft_size
;
439 bin_scale
= WMI_SPECTRAL_BIN_SCALE_DEFAULT
;
440 bins
= 1 << (fft_size
- bin_scale
);
442 mutex_unlock(&ar
->conf_mutex
);
444 len
= sprintf(buf
, "%d\n", bins
);
445 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
448 static ssize_t
write_file_spectral_bins(struct file
*file
,
449 const char __user
*user_buf
,
450 size_t count
, loff_t
*ppos
)
452 struct ath10k
*ar
= file
->private_data
;
457 len
= min(count
, sizeof(buf
) - 1);
458 if (copy_from_user(buf
, user_buf
, len
))
462 if (kstrtoul(buf
, 0, &val
))
465 if (val
< 64 || val
> SPECTRAL_ATH10K_MAX_NUM_BINS
)
468 if (!is_power_of_2(val
))
471 mutex_lock(&ar
->conf_mutex
);
472 ar
->spectral
.config
.fft_size
= ilog2(val
);
473 ar
->spectral
.config
.fft_size
+= WMI_SPECTRAL_BIN_SCALE_DEFAULT
;
474 mutex_unlock(&ar
->conf_mutex
);
479 static const struct file_operations fops_spectral_bins
= {
480 .read
= read_file_spectral_bins
,
481 .write
= write_file_spectral_bins
,
483 .owner
= THIS_MODULE
,
484 .llseek
= default_llseek
,
487 static struct dentry
*create_buf_file_handler(const char *filename
,
488 struct dentry
*parent
,
490 struct rchan_buf
*buf
,
493 struct dentry
*buf_file
;
495 buf_file
= debugfs_create_file(filename
, mode
, parent
, buf
,
496 &relay_file_operations
);
501 static int remove_buf_file_handler(struct dentry
*dentry
)
503 debugfs_remove(dentry
);
508 static struct rchan_callbacks rfs_spec_scan_cb
= {
509 .create_buf_file
= create_buf_file_handler
,
510 .remove_buf_file
= remove_buf_file_handler
,
513 int ath10k_spectral_start(struct ath10k
*ar
)
515 struct ath10k_vif
*arvif
;
517 lockdep_assert_held(&ar
->conf_mutex
);
519 list_for_each_entry(arvif
, &ar
->arvifs
, list
)
520 arvif
->spectral_enabled
= 0;
522 ar
->spectral
.mode
= SPECTRAL_DISABLED
;
523 ar
->spectral
.config
.count
= WMI_SPECTRAL_COUNT_DEFAULT
;
524 ar
->spectral
.config
.fft_size
= WMI_SPECTRAL_FFT_SIZE_DEFAULT
;
529 int ath10k_spectral_vif_stop(struct ath10k_vif
*arvif
)
531 if (!arvif
->spectral_enabled
)
534 return ath10k_spectral_scan_config(arvif
->ar
, SPECTRAL_DISABLED
);
537 int ath10k_spectral_create(struct ath10k
*ar
)
539 /* The buffer size covers whole channels in dual bands up to 128 bins.
540 * Scan with bigger than 128 bins needs to be run on single band each.
542 ar
->spectral
.rfs_chan_spec_scan
= relay_open("spectral_scan",
543 ar
->debug
.debugfs_phy
,
545 &rfs_spec_scan_cb
, NULL
);
546 debugfs_create_file("spectral_scan_ctl",
548 ar
->debug
.debugfs_phy
, ar
,
549 &fops_spec_scan_ctl
);
550 debugfs_create_file("spectral_count",
552 ar
->debug
.debugfs_phy
, ar
,
553 &fops_spectral_count
);
554 debugfs_create_file("spectral_bins",
556 ar
->debug
.debugfs_phy
, ar
,
557 &fops_spectral_bins
);
562 void ath10k_spectral_destroy(struct ath10k
*ar
)
564 if (ar
->spectral
.rfs_chan_spec_scan
) {
565 relay_close(ar
->spectral
.rfs_chan_spec_scan
);
566 ar
->spectral
.rfs_chan_spec_scan
= NULL
;