1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
6 #include <linux/relay.h>
10 #define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT 2
11 #define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS 1
13 #define ATH11K_SPECTRAL_DWORD_SIZE 4
14 /* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes */
15 #define ATH11K_SPECTRAL_BIN_SIZE 4
16 #define ATH11K_SPECTRAL_ATH11K_MIN_BINS 64
17 #define ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS 32
18 #define ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS 256
20 #define ATH11K_SPECTRAL_SCAN_COUNT_MAX 4095
22 /* Max channel computed by sum of 2g and 5g band channels */
23 #define ATH11K_SPECTRAL_TOTAL_CHANNEL 41
24 #define ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL 70
25 #define ATH11K_SPECTRAL_PER_SAMPLE_SIZE (sizeof(struct fft_sample_ath11k) + \
26 ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS)
27 #define ATH11K_SPECTRAL_TOTAL_SAMPLE (ATH11K_SPECTRAL_TOTAL_CHANNEL * \
28 ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL)
29 #define ATH11K_SPECTRAL_SUB_BUFF_SIZE ATH11K_SPECTRAL_PER_SAMPLE_SIZE
30 #define ATH11K_SPECTRAL_NUM_SUB_BUF ATH11K_SPECTRAL_TOTAL_SAMPLE
32 #define ATH11K_SPECTRAL_20MHZ 20
33 #define ATH11K_SPECTRAL_40MHZ 40
34 #define ATH11K_SPECTRAL_80MHZ 80
36 #define ATH11K_SPECTRAL_SIGNATURE 0xFA
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
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)
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)
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)
66 struct spectral_summary_fft_report
{
75 struct ath11k_spectral_summary_report
{
76 struct wmi_dma_buf_release_meta_data meta
;
84 bool out_of_band_flag
;
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)
97 #define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB GENMASK(8, 0)
98 #define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB GENMASK(16, 9)
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)
105 struct spectral_search_fft_report
{
115 struct ath11k_spectral_search_report
{
130 static struct dentry
*create_buf_file_handler(const char *filename
,
131 struct dentry
*parent
,
133 struct rchan_buf
*buf
,
136 struct dentry
*buf_file
;
138 buf_file
= debugfs_create_file(filename
, mode
, parent
, buf
,
139 &relay_file_operations
);
144 static int remove_buf_file_handler(struct dentry
*dentry
)
146 debugfs_remove(dentry
);
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
,
156 static struct ath11k_vif
*ath11k_spectral_get_vdev(struct ath11k
*ar
)
158 struct ath11k_vif
*arvif
;
160 lockdep_assert_held(&ar
->conf_mutex
);
162 if (list_empty(&ar
->arvifs
))
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
)
170 /* otherwise, return the first vif. */
171 return list_first_entry(&ar
->arvifs
, typeof(*arvif
), list
);
174 static int ath11k_spectral_scan_trigger(struct ath11k
*ar
)
176 struct ath11k_vif
*arvif
;
179 lockdep_assert_held(&ar
->conf_mutex
);
181 arvif
= ath11k_spectral_get_vdev(ar
);
185 if (ar
->spectral
.mode
== ATH11K_SPECTRAL_DISABLED
)
188 ret
= ath11k_wmi_vdev_spectral_enable(ar
, arvif
->vdev_id
,
189 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR
,
190 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE
);
194 ret
= ath11k_wmi_vdev_spectral_enable(ar
, arvif
->vdev_id
,
195 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER
,
196 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE
);
203 static int ath11k_spectral_scan_config(struct ath11k
*ar
,
204 enum ath11k_spectral_mode mode
)
206 struct ath11k_wmi_vdev_spectral_conf_param param
= { 0 };
207 struct ath11k_vif
*arvif
;
210 lockdep_assert_held(&ar
->conf_mutex
);
212 arvif
= ath11k_spectral_get_vdev(ar
);
216 arvif
->spectral_enabled
= (mode
!= ATH11K_SPECTRAL_DISABLED
);
217 ar
->spectral
.mode
= mode
;
219 ret
= ath11k_wmi_vdev_spectral_enable(ar
, arvif
->vdev_id
,
220 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR
,
221 ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE
);
223 ath11k_warn(ar
->ab
, "failed to enable spectral scan: %d\n", ret
);
227 if (mode
== ATH11K_SPECTRAL_DISABLED
)
230 if (mode
== ATH11K_SPECTRAL_BACKGROUND
)
231 count
= ATH11K_WMI_SPECTRAL_COUNT_DEFAULT
;
233 count
= max_t(u16
, 1, ar
->spectral
.count
);
235 param
.vdev_id
= arvif
->vdev_id
;
236 param
.scan_count
= count
;
237 param
.scan_fft_size
= ar
->spectral
.fft_size
;
238 param
.scan_period
= ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT
;
239 param
.scan_priority
= ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT
;
240 param
.scan_gc_ena
= ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT
;
241 param
.scan_restart_ena
= ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT
;
242 param
.scan_noise_floor_ref
= ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT
;
243 param
.scan_init_delay
= ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT
;
244 param
.scan_nb_tone_thr
= ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT
;
245 param
.scan_str_bin_thr
= ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT
;
246 param
.scan_wb_rpt_mode
= ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT
;
247 param
.scan_rssi_rpt_mode
= ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT
;
248 param
.scan_rssi_thr
= ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT
;
249 param
.scan_pwr_format
= ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT
;
250 param
.scan_rpt_mode
= ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT
;
251 param
.scan_bin_scale
= ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT
;
252 param
.scan_dbm_adj
= ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT
;
253 param
.scan_chn_mask
= ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT
;
255 ret
= ath11k_wmi_vdev_spectral_conf(ar
, ¶m
);
257 ath11k_warn(ar
->ab
, "failed to configure spectral scan: %d\n", ret
);
264 static ssize_t
ath11k_read_file_spec_scan_ctl(struct file
*file
,
265 char __user
*user_buf
,
266 size_t count
, loff_t
*ppos
)
268 struct ath11k
*ar
= file
->private_data
;
271 enum ath11k_spectral_mode spectral_mode
;
273 mutex_lock(&ar
->conf_mutex
);
274 spectral_mode
= ar
->spectral
.mode
;
275 mutex_unlock(&ar
->conf_mutex
);
277 switch (spectral_mode
) {
278 case ATH11K_SPECTRAL_DISABLED
:
281 case ATH11K_SPECTRAL_BACKGROUND
:
284 case ATH11K_SPECTRAL_MANUAL
:
290 return simple_read_from_buffer(user_buf
, count
, ppos
, mode
, len
);
293 static ssize_t
ath11k_write_file_spec_scan_ctl(struct file
*file
,
294 const char __user
*user_buf
,
295 size_t count
, loff_t
*ppos
)
297 struct ath11k
*ar
= file
->private_data
;
302 len
= min(count
, sizeof(buf
) - 1);
303 if (copy_from_user(buf
, user_buf
, len
))
308 mutex_lock(&ar
->conf_mutex
);
310 if (strncmp("trigger", buf
, 7) == 0) {
311 if (ar
->spectral
.mode
== ATH11K_SPECTRAL_MANUAL
||
312 ar
->spectral
.mode
== ATH11K_SPECTRAL_BACKGROUND
) {
313 /* reset the configuration to adopt possibly changed
316 ret
= ath11k_spectral_scan_config(ar
, ar
->spectral
.mode
);
318 ath11k_warn(ar
->ab
, "failed to reconfigure spectral scan: %d\n",
323 ret
= ath11k_spectral_scan_trigger(ar
);
325 ath11k_warn(ar
->ab
, "failed to trigger spectral scan: %d\n",
331 } else if (strncmp("background", buf
, 10) == 0) {
332 ret
= ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_BACKGROUND
);
333 } else if (strncmp("manual", buf
, 6) == 0) {
334 ret
= ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_MANUAL
);
335 } else if (strncmp("disable", buf
, 7) == 0) {
336 ret
= ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_DISABLED
);
342 mutex_unlock(&ar
->conf_mutex
);
350 static const struct file_operations fops_scan_ctl
= {
351 .read
= ath11k_read_file_spec_scan_ctl
,
352 .write
= ath11k_write_file_spec_scan_ctl
,
354 .owner
= THIS_MODULE
,
355 .llseek
= default_llseek
,
358 static ssize_t
ath11k_read_file_spectral_count(struct file
*file
,
359 char __user
*user_buf
,
360 size_t count
, loff_t
*ppos
)
362 struct ath11k
*ar
= file
->private_data
;
367 mutex_lock(&ar
->conf_mutex
);
368 spectral_count
= ar
->spectral
.count
;
369 mutex_unlock(&ar
->conf_mutex
);
371 len
= sprintf(buf
, "%d\n", spectral_count
);
372 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
375 static ssize_t
ath11k_write_file_spectral_count(struct file
*file
,
376 const char __user
*user_buf
,
377 size_t count
, loff_t
*ppos
)
379 struct ath11k
*ar
= file
->private_data
;
384 len
= min(count
, sizeof(buf
) - 1);
385 if (copy_from_user(buf
, user_buf
, len
))
389 if (kstrtoul(buf
, 0, &val
))
392 if (val
> ATH11K_SPECTRAL_SCAN_COUNT_MAX
)
395 mutex_lock(&ar
->conf_mutex
);
396 ar
->spectral
.count
= val
;
397 mutex_unlock(&ar
->conf_mutex
);
402 static const struct file_operations fops_scan_count
= {
403 .read
= ath11k_read_file_spectral_count
,
404 .write
= ath11k_write_file_spectral_count
,
406 .owner
= THIS_MODULE
,
407 .llseek
= default_llseek
,
410 static ssize_t
ath11k_read_file_spectral_bins(struct file
*file
,
411 char __user
*user_buf
,
412 size_t count
, loff_t
*ppos
)
414 struct ath11k
*ar
= file
->private_data
;
416 unsigned int bins
, fft_size
;
419 mutex_lock(&ar
->conf_mutex
);
421 fft_size
= ar
->spectral
.fft_size
;
422 bins
= 1 << fft_size
;
424 mutex_unlock(&ar
->conf_mutex
);
426 len
= sprintf(buf
, "%d\n", bins
);
427 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
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
)
434 struct ath11k
*ar
= file
->private_data
;
439 len
= min(count
, sizeof(buf
) - 1);
440 if (copy_from_user(buf
, user_buf
, len
))
444 if (kstrtoul(buf
, 0, &val
))
447 if (val
< ATH11K_SPECTRAL_ATH11K_MIN_BINS
||
448 val
> SPECTRAL_ATH11K_MAX_NUM_BINS
)
451 if (!is_power_of_2(val
))
454 mutex_lock(&ar
->conf_mutex
);
455 ar
->spectral
.fft_size
= ilog2(val
);
456 mutex_unlock(&ar
->conf_mutex
);
461 static const struct file_operations fops_scan_bins
= {
462 .read
= ath11k_read_file_spectral_bins
,
463 .write
= ath11k_write_file_spectral_bins
,
465 .owner
= THIS_MODULE
,
466 .llseek
= default_llseek
,
469 static int ath11k_spectral_pull_summary(struct ath11k
*ar
,
470 struct wmi_dma_buf_release_meta_data
*meta
,
471 struct spectral_summary_fft_report
*summary
,
472 struct ath11k_spectral_summary_report
*report
)
474 report
->timestamp
= __le32_to_cpu(summary
->timestamp
);
475 report
->agc_total_gain
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN
,
476 __le32_to_cpu(summary
->info0
));
477 report
->out_of_band_flag
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG
,
478 __le32_to_cpu(summary
->info0
));
479 report
->grp_idx
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX
,
480 __le32_to_cpu(summary
->info0
));
481 report
->rf_saturation
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT
,
482 __le32_to_cpu(summary
->info0
));
483 report
->inb_pwr_db
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB
,
484 __le32_to_cpu(summary
->info0
));
485 report
->false_scan
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN
,
486 __le32_to_cpu(summary
->info0
));
487 report
->detector_id
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID
,
488 __le32_to_cpu(summary
->info0
));
489 report
->primary80
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80
,
490 __le32_to_cpu(summary
->info0
));
491 report
->peak_idx
= FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX
,
492 __le32_to_cpu(summary
->info2
));
493 report
->peak_mag
= FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE
,
494 __le32_to_cpu(summary
->info2
));
495 report
->gain_change
= FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE
,
496 __le32_to_cpu(summary
->info2
));
498 memcpy(&report
->meta
, meta
, sizeof(*meta
));
503 static int ath11k_spectral_pull_search(struct ath11k
*ar
,
504 struct spectral_search_fft_report
*search
,
505 struct ath11k_spectral_search_report
*report
)
507 report
->timestamp
= __le32_to_cpu(search
->timestamp
);
508 report
->detector_id
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID
,
509 __le32_to_cpu(search
->info0
));
510 report
->fft_count
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM
,
511 __le32_to_cpu(search
->info0
));
512 report
->radar_check
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK
,
513 __le32_to_cpu(search
->info0
));
514 report
->peak_idx
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX
,
515 __le32_to_cpu(search
->info0
));
516 report
->chain_idx
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX
,
517 __le32_to_cpu(search
->info0
));
518 report
->base_pwr_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB
,
519 __le32_to_cpu(search
->info1
));
520 report
->total_gain_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB
,
521 __le32_to_cpu(search
->info1
));
522 report
->strong_bin_count
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS
,
523 __le32_to_cpu(search
->info2
));
524 report
->peak_mag
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE
,
525 __le32_to_cpu(search
->info2
));
526 report
->avg_pwr_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB
,
527 __le32_to_cpu(search
->info2
));
528 report
->rel_pwr_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB
,
529 __le32_to_cpu(search
->info2
));
534 static u8
ath11k_spectral_get_max_exp(s8 max_index
, u8 max_magnitude
,
535 int bin_len
, u8
*bins
)
540 dc_pos
= bin_len
/ 2;
542 /* peak index outside of bins */
543 if (dc_pos
<= max_index
|| -dc_pos
>= max_index
)
546 for (max_exp
= 0; max_exp
< 8; max_exp
++) {
547 if (bins
[dc_pos
+ max_index
] == (max_magnitude
>> max_exp
))
551 /* max_exp not found */
552 if (bins
[dc_pos
+ max_index
] != (max_magnitude
>> max_exp
))
558 static void ath11k_spectral_parse_fft(u8
*outbins
, u8
*inbins
, int num_bins
, u8 fft_sz
)
564 while (i
< num_bins
) {
565 outbins
[i
] = inbins
[j
];
572 int ath11k_spectral_process_fft(struct ath11k
*ar
,
573 struct ath11k_spectral_summary_report
*summary
,
575 struct fft_sample_ath11k
*fft_sample
,
578 struct ath11k_base
*ab
= ar
->ab
;
579 struct spectral_search_fft_report
*fft_report
= data
;
580 struct ath11k_spectral_search_report search
;
581 struct spectral_tlv
*tlv
;
582 int tlv_len
, bin_len
, num_bins
;
587 lockdep_assert_held(&ar
->spectral
.lock
);
589 if (!ab
->hw_params
.spectral_fft_sz
) {
590 ath11k_warn(ab
, "invalid bin size type for hw rev %d\n",
595 tlv
= (struct spectral_tlv
*)data
;
596 tlv_len
= FIELD_GET(SPECTRAL_TLV_HDR_LEN
, __le32_to_cpu(tlv
->header
));
597 /* convert Dword into bytes */
598 tlv_len
*= ATH11K_SPECTRAL_DWORD_SIZE
;
599 bin_len
= tlv_len
- (sizeof(*fft_report
) - sizeof(*tlv
));
601 if (data_len
< (bin_len
+ sizeof(*fft_report
))) {
602 ath11k_warn(ab
, "mismatch in expected bin len %d and data len %d\n",
607 num_bins
= bin_len
/ ATH11K_SPECTRAL_BIN_SIZE
;
608 /* Only In-band bins are useful to user for visualize */
611 if (num_bins
< ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS
||
612 num_bins
> ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS
||
613 !is_power_of_2(num_bins
)) {
614 ath11k_warn(ab
, "Invalid num of bins %d\n", num_bins
);
618 ret
= ath11k_spectral_pull_search(ar
, data
, &search
);
620 ath11k_warn(ab
, "failed to pull search report %d\n", ret
);
624 chan_width_mhz
= summary
->meta
.ch_width
;
626 switch (chan_width_mhz
) {
627 case ATH11K_SPECTRAL_20MHZ
:
628 case ATH11K_SPECTRAL_40MHZ
:
629 case ATH11K_SPECTRAL_80MHZ
:
630 fft_sample
->chan_width_mhz
= chan_width_mhz
;
633 ath11k_warn(ab
, "invalid channel width %d\n", chan_width_mhz
);
637 length
= sizeof(*fft_sample
) - sizeof(struct fft_sample_tlv
) + num_bins
;
638 fft_sample
->tlv
.type
= ATH_FFT_SAMPLE_ATH11K
;
639 fft_sample
->tlv
.length
= __cpu_to_be16(length
);
641 fft_sample
->tsf
= __cpu_to_be32(search
.timestamp
);
642 fft_sample
->max_magnitude
= __cpu_to_be16(search
.peak_mag
);
643 fft_sample
->max_index
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX
,
644 __le32_to_cpu(fft_report
->info0
));
646 summary
->inb_pwr_db
>>= 1;
647 fft_sample
->rssi
= __cpu_to_be16(summary
->inb_pwr_db
);
648 fft_sample
->noise
= __cpu_to_be32(summary
->meta
.noise_floor
[search
.chain_idx
]);
650 freq
= summary
->meta
.freq1
;
651 fft_sample
->freq1
= __cpu_to_be16(freq
);
653 freq
= summary
->meta
.freq2
;
654 fft_sample
->freq2
= __cpu_to_be16(freq
);
656 ath11k_spectral_parse_fft(fft_sample
->data
, fft_report
->bins
, num_bins
,
657 ab
->hw_params
.spectral_fft_sz
);
659 fft_sample
->max_exp
= ath11k_spectral_get_max_exp(fft_sample
->max_index
,
664 if (ar
->spectral
.rfs_scan
)
665 relay_write(ar
->spectral
.rfs_scan
, fft_sample
,
666 length
+ sizeof(struct fft_sample_tlv
));
671 static int ath11k_spectral_process_data(struct ath11k
*ar
,
672 struct ath11k_dbring_data
*param
)
674 struct ath11k_base
*ab
= ar
->ab
;
675 struct spectral_tlv
*tlv
;
676 struct spectral_summary_fft_report
*summary
= NULL
;
677 struct ath11k_spectral_summary_report summ_rpt
;
678 struct fft_sample_ath11k
*fft_sample
= NULL
;
682 int tlv_len
, sample_sz
;
686 spin_lock_bh(&ar
->spectral
.lock
);
688 if (!ar
->spectral
.enabled
) {
693 sample_sz
= sizeof(*fft_sample
) + ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS
;
694 fft_sample
= kmalloc(sample_sz
, GFP_ATOMIC
);
701 data_len
= param
->data_sz
;
703 while (!quit
&& (i
< data_len
)) {
704 if ((i
+ sizeof(*tlv
)) > data_len
) {
705 ath11k_warn(ab
, "failed to parse spectral tlv hdr at bytes %d\n",
711 tlv
= (struct spectral_tlv
*)&data
[i
];
712 sign
= FIELD_GET(SPECTRAL_TLV_HDR_SIGN
,
713 __le32_to_cpu(tlv
->header
));
714 if (sign
!= ATH11K_SPECTRAL_SIGNATURE
) {
715 ath11k_warn(ab
, "Invalid sign 0x%x at bytes %d\n",
721 tlv_len
= FIELD_GET(SPECTRAL_TLV_HDR_LEN
,
722 __le32_to_cpu(tlv
->header
));
723 /* convert Dword into bytes */
724 tlv_len
*= ATH11K_SPECTRAL_DWORD_SIZE
;
725 if ((i
+ sizeof(*tlv
) + tlv_len
) > data_len
) {
726 ath11k_warn(ab
, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n",
727 i
, tlv_len
, data_len
);
732 tag
= FIELD_GET(SPECTRAL_TLV_HDR_TAG
,
733 __le32_to_cpu(tlv
->header
));
735 case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY
:
736 /* HW bug in tlv length of summary report,
737 * HW report 3 DWORD size but the data payload
738 * is 4 DWORD size (16 bytes).
739 * Need to remove this workaround once HW bug fixed
741 tlv_len
= sizeof(*summary
) - sizeof(*tlv
);
743 if (tlv_len
< (sizeof(*summary
) - sizeof(*tlv
))) {
744 ath11k_warn(ab
, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
750 summary
= (struct spectral_summary_fft_report
*)tlv
;
751 ath11k_spectral_pull_summary(ar
, ¶m
->meta
,
754 case ATH11K_SPECTRAL_TAG_SCAN_SEARCH
:
755 if (tlv_len
< (sizeof(struct spectral_search_fft_report
) -
757 ath11k_warn(ab
, "failed to parse spectral search fft at bytes %d\n",
763 memset(fft_sample
, 0, sample_sz
);
764 ret
= ath11k_spectral_process_fft(ar
, &summ_rpt
, tlv
,
768 ath11k_warn(ab
, "failed to process spectral fft at bytes %d\n",
776 i
+= sizeof(*tlv
) + tlv_len
;
784 spin_unlock_bh(&ar
->spectral
.lock
);
788 static int ath11k_spectral_ring_alloc(struct ath11k
*ar
,
789 struct ath11k_dbring_cap
*db_cap
)
791 struct ath11k_spectral
*sp
= &ar
->spectral
;
794 ret
= ath11k_dbring_srng_setup(ar
, &sp
->rx_ring
,
795 0, db_cap
->min_elem
);
797 ath11k_warn(ar
->ab
, "failed to setup db ring\n");
801 ath11k_dbring_set_cfg(ar
, &sp
->rx_ring
,
802 ATH11K_SPECTRAL_NUM_RESP_PER_EVENT
,
803 ATH11K_SPECTRAL_EVENT_TIMEOUT_MS
,
804 ath11k_spectral_process_data
);
806 ret
= ath11k_dbring_buf_setup(ar
, &sp
->rx_ring
, db_cap
);
808 ath11k_warn(ar
->ab
, "failed to setup db ring buffer\n");
812 ret
= ath11k_dbring_wmi_cfg_setup(ar
, &sp
->rx_ring
,
813 WMI_DIRECT_BUF_SPECTRAL
);
815 ath11k_warn(ar
->ab
, "failed to setup db ring cfg\n");
822 ath11k_dbring_buf_cleanup(ar
, &sp
->rx_ring
);
824 ath11k_dbring_srng_cleanup(ar
, &sp
->rx_ring
);
828 static inline void ath11k_spectral_ring_free(struct ath11k
*ar
)
830 struct ath11k_spectral
*sp
= &ar
->spectral
;
835 ath11k_dbring_srng_cleanup(ar
, &sp
->rx_ring
);
836 ath11k_dbring_buf_cleanup(ar
, &sp
->rx_ring
);
839 static inline void ath11k_spectral_debug_unregister(struct ath11k
*ar
)
841 debugfs_remove(ar
->spectral
.scan_bins
);
842 ar
->spectral
.scan_bins
= NULL
;
844 debugfs_remove(ar
->spectral
.scan_count
);
845 ar
->spectral
.scan_count
= NULL
;
847 debugfs_remove(ar
->spectral
.scan_ctl
);
848 ar
->spectral
.scan_ctl
= NULL
;
850 if (ar
->spectral
.rfs_scan
) {
851 relay_close(ar
->spectral
.rfs_scan
);
852 ar
->spectral
.rfs_scan
= NULL
;
856 int ath11k_spectral_vif_stop(struct ath11k_vif
*arvif
)
858 if (!arvif
->spectral_enabled
)
861 return ath11k_spectral_scan_config(arvif
->ar
, ATH11K_SPECTRAL_DISABLED
);
864 void ath11k_spectral_reset_buffer(struct ath11k
*ar
)
866 if (!ar
->spectral
.enabled
)
869 if (ar
->spectral
.rfs_scan
)
870 relay_reset(ar
->spectral
.rfs_scan
);
873 void ath11k_spectral_deinit(struct ath11k_base
*ab
)
876 struct ath11k_spectral
*sp
;
879 for (i
= 0; i
< ab
->num_radios
; i
++) {
880 ar
= ab
->pdevs
[i
].ar
;
886 ath11k_spectral_debug_unregister(ar
);
887 ath11k_spectral_ring_free(ar
);
889 spin_lock_bh(&sp
->lock
);
891 sp
->mode
= ATH11K_SPECTRAL_DISABLED
;
894 spin_unlock_bh(&sp
->lock
);
898 static inline int ath11k_spectral_debug_register(struct ath11k
*ar
)
902 ar
->spectral
.rfs_scan
= relay_open("spectral_scan",
903 ar
->debug
.debugfs_pdev
,
904 ATH11K_SPECTRAL_SUB_BUFF_SIZE
,
905 ATH11K_SPECTRAL_NUM_SUB_BUF
,
907 if (!ar
->spectral
.rfs_scan
) {
908 ath11k_warn(ar
->ab
, "failed to open relay in pdev %d\n",
913 ar
->spectral
.scan_ctl
= debugfs_create_file("spectral_scan_ctl",
915 ar
->debug
.debugfs_pdev
, ar
,
917 if (!ar
->spectral
.scan_ctl
) {
918 ath11k_warn(ar
->ab
, "failed to open debugfs in pdev %d\n",
921 goto debug_unregister
;
924 ar
->spectral
.scan_count
= debugfs_create_file("spectral_count",
926 ar
->debug
.debugfs_pdev
, ar
,
928 if (!ar
->spectral
.scan_count
) {
929 ath11k_warn(ar
->ab
, "failed to open debugfs in pdev %d\n",
932 goto debug_unregister
;
935 ar
->spectral
.scan_bins
= debugfs_create_file("spectral_bins",
937 ar
->debug
.debugfs_pdev
, ar
,
939 if (!ar
->spectral
.scan_bins
) {
940 ath11k_warn(ar
->ab
, "failed to open debugfs in pdev %d\n",
943 goto debug_unregister
;
949 ath11k_spectral_debug_unregister(ar
);
953 int ath11k_spectral_init(struct ath11k_base
*ab
)
956 struct ath11k_spectral
*sp
;
957 struct ath11k_dbring_cap db_cap
;
961 if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA
,
965 if (!ab
->hw_params
.spectral_fft_sz
)
968 for (i
= 0; i
< ab
->num_radios
; i
++) {
969 ar
= ab
->pdevs
[i
].ar
;
972 ret
= ath11k_dbring_get_cap(ar
->ab
, ar
->pdev_idx
,
973 WMI_DIRECT_BUF_SPECTRAL
,
978 idr_init(&sp
->rx_ring
.bufs_idr
);
979 spin_lock_init(&sp
->rx_ring
.idr_lock
);
980 spin_lock_init(&sp
->lock
);
982 ret
= ath11k_spectral_ring_alloc(ar
, &db_cap
);
984 ath11k_warn(ab
, "failed to init spectral ring for pdev %d\n",
989 spin_lock_bh(&sp
->lock
);
991 sp
->mode
= ATH11K_SPECTRAL_DISABLED
;
992 sp
->count
= ATH11K_WMI_SPECTRAL_COUNT_DEFAULT
;
993 sp
->fft_size
= ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT
;
996 spin_unlock_bh(&sp
->lock
);
998 ret
= ath11k_spectral_debug_register(ar
);
1000 ath11k_warn(ab
, "failed to register spectral for pdev %d\n",
1009 ath11k_spectral_deinit(ab
);
1013 enum ath11k_spectral_mode
ath11k_spectral_get_mode(struct ath11k
*ar
)
1015 if (ar
->spectral
.enabled
)
1016 return ar
->spectral
.mode
;
1018 return ATH11K_SPECTRAL_DISABLED
;
1021 struct ath11k_dbring
*ath11k_spectral_get_dbring(struct ath11k
*ar
)
1023 if (ar
->spectral
.enabled
)
1024 return &ar
->spectral
.rx_ring
;