1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
7 #include <linux/relay.h>
11 #define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT 2
12 #define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS 1
14 #define ATH11K_SPECTRAL_DWORD_SIZE 4
15 #define ATH11K_SPECTRAL_MIN_BINS 32
16 #define ATH11K_SPECTRAL_MIN_IB_BINS (ATH11K_SPECTRAL_MIN_BINS >> 1)
17 #define ATH11K_SPECTRAL_MAX_IB_BINS(x) ((x)->hw_params.spectral.max_fft_bins >> 1)
19 #define ATH11K_SPECTRAL_SCAN_COUNT_MAX 4095
21 /* Max channel computed by sum of 2g and 5g band channels */
22 #define ATH11K_SPECTRAL_TOTAL_CHANNEL 41
23 #define ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL 70
24 #define ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x) (sizeof(struct fft_sample_ath11k) + \
25 ATH11K_SPECTRAL_MAX_IB_BINS(x))
26 #define ATH11K_SPECTRAL_TOTAL_SAMPLE (ATH11K_SPECTRAL_TOTAL_CHANNEL * \
27 ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL)
28 #define ATH11K_SPECTRAL_SUB_BUFF_SIZE(x) ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x)
29 #define ATH11K_SPECTRAL_NUM_SUB_BUF ATH11K_SPECTRAL_TOTAL_SAMPLE
31 #define ATH11K_SPECTRAL_20MHZ 20
32 #define ATH11K_SPECTRAL_40MHZ 40
33 #define ATH11K_SPECTRAL_80MHZ 80
34 #define ATH11K_SPECTRAL_160MHZ 160
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 ar
->spectral
.is_primary
= true;
190 ret
= ath11k_wmi_vdev_spectral_enable(ar
, arvif
->vdev_id
,
191 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR
,
192 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE
);
196 ret
= ath11k_wmi_vdev_spectral_enable(ar
, arvif
->vdev_id
,
197 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER
,
198 ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE
);
205 static int ath11k_spectral_scan_config(struct ath11k
*ar
,
206 enum ath11k_spectral_mode mode
)
208 struct ath11k_wmi_vdev_spectral_conf_param param
= { 0 };
209 struct ath11k_vif
*arvif
;
212 lockdep_assert_held(&ar
->conf_mutex
);
214 arvif
= ath11k_spectral_get_vdev(ar
);
218 arvif
->spectral_enabled
= (mode
!= ATH11K_SPECTRAL_DISABLED
);
220 spin_lock_bh(&ar
->spectral
.lock
);
221 ar
->spectral
.mode
= mode
;
222 spin_unlock_bh(&ar
->spectral
.lock
);
224 ret
= ath11k_wmi_vdev_spectral_enable(ar
, arvif
->vdev_id
,
225 ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR
,
226 ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE
);
228 ath11k_warn(ar
->ab
, "failed to enable spectral scan: %d\n", ret
);
232 if (mode
== ATH11K_SPECTRAL_DISABLED
)
235 if (mode
== ATH11K_SPECTRAL_BACKGROUND
)
236 count
= ATH11K_WMI_SPECTRAL_COUNT_DEFAULT
;
238 count
= max_t(u16
, 1, ar
->spectral
.count
);
240 param
.vdev_id
= arvif
->vdev_id
;
241 param
.scan_count
= count
;
242 param
.scan_fft_size
= ar
->spectral
.fft_size
;
243 param
.scan_period
= ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT
;
244 param
.scan_priority
= ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT
;
245 param
.scan_gc_ena
= ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT
;
246 param
.scan_restart_ena
= ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT
;
247 param
.scan_noise_floor_ref
= ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT
;
248 param
.scan_init_delay
= ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT
;
249 param
.scan_nb_tone_thr
= ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT
;
250 param
.scan_str_bin_thr
= ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT
;
251 param
.scan_wb_rpt_mode
= ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT
;
252 param
.scan_rssi_rpt_mode
= ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT
;
253 param
.scan_rssi_thr
= ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT
;
254 param
.scan_pwr_format
= ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT
;
255 param
.scan_rpt_mode
= ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT
;
256 param
.scan_bin_scale
= ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT
;
257 param
.scan_dbm_adj
= ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT
;
258 param
.scan_chn_mask
= ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT
;
260 ret
= ath11k_wmi_vdev_spectral_conf(ar
, ¶m
);
262 ath11k_warn(ar
->ab
, "failed to configure spectral scan: %d\n", ret
);
269 static ssize_t
ath11k_read_file_spec_scan_ctl(struct file
*file
,
270 char __user
*user_buf
,
271 size_t count
, loff_t
*ppos
)
273 struct ath11k
*ar
= file
->private_data
;
276 enum ath11k_spectral_mode spectral_mode
;
278 mutex_lock(&ar
->conf_mutex
);
279 spectral_mode
= ar
->spectral
.mode
;
280 mutex_unlock(&ar
->conf_mutex
);
282 switch (spectral_mode
) {
283 case ATH11K_SPECTRAL_DISABLED
:
286 case ATH11K_SPECTRAL_BACKGROUND
:
289 case ATH11K_SPECTRAL_MANUAL
:
295 return simple_read_from_buffer(user_buf
, count
, ppos
, mode
, len
);
298 static ssize_t
ath11k_write_file_spec_scan_ctl(struct file
*file
,
299 const char __user
*user_buf
,
300 size_t count
, loff_t
*ppos
)
302 struct ath11k
*ar
= file
->private_data
;
307 len
= min(count
, sizeof(buf
) - 1);
308 if (copy_from_user(buf
, user_buf
, len
))
313 mutex_lock(&ar
->conf_mutex
);
315 if (strncmp("trigger", buf
, 7) == 0) {
316 if (ar
->spectral
.mode
== ATH11K_SPECTRAL_MANUAL
||
317 ar
->spectral
.mode
== ATH11K_SPECTRAL_BACKGROUND
) {
318 /* reset the configuration to adopt possibly changed
321 ret
= ath11k_spectral_scan_config(ar
, ar
->spectral
.mode
);
323 ath11k_warn(ar
->ab
, "failed to reconfigure spectral scan: %d\n",
328 ret
= ath11k_spectral_scan_trigger(ar
);
330 ath11k_warn(ar
->ab
, "failed to trigger spectral scan: %d\n",
336 } else if (strncmp("background", buf
, 10) == 0) {
337 ret
= ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_BACKGROUND
);
338 } else if (strncmp("manual", buf
, 6) == 0) {
339 ret
= ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_MANUAL
);
340 } else if (strncmp("disable", buf
, 7) == 0) {
341 ret
= ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_DISABLED
);
347 mutex_unlock(&ar
->conf_mutex
);
355 static const struct file_operations fops_scan_ctl
= {
356 .read
= ath11k_read_file_spec_scan_ctl
,
357 .write
= ath11k_write_file_spec_scan_ctl
,
359 .owner
= THIS_MODULE
,
360 .llseek
= default_llseek
,
363 static ssize_t
ath11k_read_file_spectral_count(struct file
*file
,
364 char __user
*user_buf
,
365 size_t count
, loff_t
*ppos
)
367 struct ath11k
*ar
= file
->private_data
;
372 mutex_lock(&ar
->conf_mutex
);
373 spectral_count
= ar
->spectral
.count
;
374 mutex_unlock(&ar
->conf_mutex
);
376 len
= sprintf(buf
, "%d\n", spectral_count
);
377 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
380 static ssize_t
ath11k_write_file_spectral_count(struct file
*file
,
381 const char __user
*user_buf
,
382 size_t count
, loff_t
*ppos
)
384 struct ath11k
*ar
= file
->private_data
;
388 ret
= kstrtoul_from_user(user_buf
, count
, 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
;
438 ret
= kstrtoul_from_user(user_buf
, count
, 0, &val
);
442 if (val
< ATH11K_SPECTRAL_MIN_BINS
||
443 val
> ar
->ab
->hw_params
.spectral
.max_fft_bins
)
446 if (!is_power_of_2(val
))
449 mutex_lock(&ar
->conf_mutex
);
450 ar
->spectral
.fft_size
= ilog2(val
);
451 mutex_unlock(&ar
->conf_mutex
);
456 static const struct file_operations fops_scan_bins
= {
457 .read
= ath11k_read_file_spectral_bins
,
458 .write
= ath11k_write_file_spectral_bins
,
460 .owner
= THIS_MODULE
,
461 .llseek
= default_llseek
,
464 static int ath11k_spectral_pull_summary(struct ath11k
*ar
,
465 struct wmi_dma_buf_release_meta_data
*meta
,
466 struct spectral_summary_fft_report
*summary
,
467 struct ath11k_spectral_summary_report
*report
)
469 report
->timestamp
= __le32_to_cpu(summary
->timestamp
);
470 report
->agc_total_gain
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN
,
471 __le32_to_cpu(summary
->info0
));
472 report
->out_of_band_flag
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG
,
473 __le32_to_cpu(summary
->info0
));
474 report
->grp_idx
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX
,
475 __le32_to_cpu(summary
->info0
));
476 report
->rf_saturation
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT
,
477 __le32_to_cpu(summary
->info0
));
478 report
->inb_pwr_db
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB
,
479 __le32_to_cpu(summary
->info0
));
480 report
->false_scan
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN
,
481 __le32_to_cpu(summary
->info0
));
482 report
->detector_id
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID
,
483 __le32_to_cpu(summary
->info0
));
484 report
->primary80
= FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80
,
485 __le32_to_cpu(summary
->info0
));
486 report
->peak_idx
= FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX
,
487 __le32_to_cpu(summary
->info2
));
488 report
->peak_mag
= FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE
,
489 __le32_to_cpu(summary
->info2
));
490 report
->gain_change
= FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE
,
491 __le32_to_cpu(summary
->info2
));
493 memcpy(&report
->meta
, meta
, sizeof(*meta
));
498 static int ath11k_spectral_pull_search(struct ath11k
*ar
,
499 struct spectral_search_fft_report
*search
,
500 struct ath11k_spectral_search_report
*report
)
502 report
->timestamp
= __le32_to_cpu(search
->timestamp
);
503 report
->detector_id
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID
,
504 __le32_to_cpu(search
->info0
));
505 report
->fft_count
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM
,
506 __le32_to_cpu(search
->info0
));
507 report
->radar_check
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK
,
508 __le32_to_cpu(search
->info0
));
509 report
->peak_idx
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX
,
510 __le32_to_cpu(search
->info0
));
511 report
->chain_idx
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX
,
512 __le32_to_cpu(search
->info0
));
513 report
->base_pwr_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB
,
514 __le32_to_cpu(search
->info1
));
515 report
->total_gain_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB
,
516 __le32_to_cpu(search
->info1
));
517 report
->strong_bin_count
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS
,
518 __le32_to_cpu(search
->info2
));
519 report
->peak_mag
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE
,
520 __le32_to_cpu(search
->info2
));
521 report
->avg_pwr_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB
,
522 __le32_to_cpu(search
->info2
));
523 report
->rel_pwr_db
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB
,
524 __le32_to_cpu(search
->info2
));
529 static u8
ath11k_spectral_get_max_exp(s8 max_index
, u8 max_magnitude
,
530 int bin_len
, u8
*bins
)
535 dc_pos
= bin_len
/ 2;
537 /* peak index outside of bins */
538 if (dc_pos
<= max_index
|| -dc_pos
>= max_index
)
541 for (max_exp
= 0; max_exp
< 8; max_exp
++) {
542 if (bins
[dc_pos
+ max_index
] == (max_magnitude
>> max_exp
))
546 /* max_exp not found */
547 if (bins
[dc_pos
+ max_index
] != (max_magnitude
>> max_exp
))
553 static void ath11k_spectral_parse_fft(u8
*outbins
, u8
*inbins
, int num_bins
, u8 fft_sz
)
559 while (i
< num_bins
) {
560 outbins
[i
] = inbins
[j
];
567 int ath11k_spectral_process_fft(struct ath11k
*ar
,
568 struct ath11k_spectral_summary_report
*summary
,
570 struct fft_sample_ath11k
*fft_sample
,
573 struct ath11k_base
*ab
= ar
->ab
;
574 struct spectral_search_fft_report
*fft_report
= data
;
575 struct ath11k_spectral_search_report search
;
576 struct spectral_tlv
*tlv
;
577 int tlv_len
, bin_len
, num_bins
;
579 u8 chan_width_mhz
, bin_sz
;
582 bool fragment_sample
= false;
584 lockdep_assert_held(&ar
->spectral
.lock
);
586 if (!ab
->hw_params
.spectral
.fft_sz
) {
587 ath11k_warn(ab
, "invalid bin size type for hw rev %d\n",
593 tlv_len
= FIELD_GET(SPECTRAL_TLV_HDR_LEN
, __le32_to_cpu(tlv
->header
));
594 /* convert Dword into bytes */
595 tlv_len
*= ATH11K_SPECTRAL_DWORD_SIZE
;
596 bin_len
= tlv_len
- ab
->hw_params
.spectral
.fft_hdr_len
;
598 if (data_len
< (bin_len
+ sizeof(*fft_report
))) {
599 ath11k_warn(ab
, "mismatch in expected bin len %d and data len %d\n",
604 bin_sz
= ab
->hw_params
.spectral
.fft_sz
+ ab
->hw_params
.spectral
.fft_pad_sz
;
605 num_bins
= bin_len
/ bin_sz
;
606 /* Only In-band bins are useful to user for visualize */
609 if (num_bins
< ATH11K_SPECTRAL_MIN_IB_BINS
||
610 num_bins
> ATH11K_SPECTRAL_MAX_IB_BINS(ab
) ||
611 !is_power_of_2(num_bins
)) {
612 ath11k_warn(ab
, "Invalid num of bins %d\n", num_bins
);
616 check_length
= sizeof(*fft_report
) + (num_bins
* ab
->hw_params
.spectral
.fft_sz
);
617 ret
= ath11k_dbring_validate_buffer(ar
, data
, check_length
);
619 ath11k_warn(ar
->ab
, "found magic value in fft data, dropping\n");
623 ret
= ath11k_spectral_pull_search(ar
, data
, &search
);
625 ath11k_warn(ab
, "failed to pull search report %d\n", ret
);
629 chan_width_mhz
= summary
->meta
.ch_width
;
631 switch (chan_width_mhz
) {
632 case ATH11K_SPECTRAL_20MHZ
:
633 case ATH11K_SPECTRAL_40MHZ
:
634 case ATH11K_SPECTRAL_80MHZ
:
635 fft_sample
->chan_width_mhz
= chan_width_mhz
;
637 case ATH11K_SPECTRAL_160MHZ
:
638 if (ab
->hw_params
.spectral
.fragment_160mhz
) {
640 fragment_sample
= true;
642 fft_sample
->chan_width_mhz
= chan_width_mhz
;
645 ath11k_warn(ab
, "invalid channel width %d\n", chan_width_mhz
);
649 length
= sizeof(*fft_sample
) - sizeof(struct fft_sample_tlv
) + num_bins
;
650 fft_sample
->tlv
.type
= ATH_FFT_SAMPLE_ATH11K
;
651 fft_sample
->tlv
.length
= __cpu_to_be16(length
);
653 fft_sample
->tsf
= __cpu_to_be32(search
.timestamp
);
654 fft_sample
->max_magnitude
= __cpu_to_be16(search
.peak_mag
);
655 fft_sample
->max_index
= FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX
,
656 __le32_to_cpu(fft_report
->info0
));
658 summary
->inb_pwr_db
>>= 1;
659 fft_sample
->rssi
= __cpu_to_be16(summary
->inb_pwr_db
);
660 fft_sample
->noise
= __cpu_to_be32(summary
->meta
.noise_floor
[search
.chain_idx
]);
662 freq
= summary
->meta
.freq1
;
663 fft_sample
->freq1
= __cpu_to_be16(freq
);
665 freq
= summary
->meta
.freq2
;
666 fft_sample
->freq2
= __cpu_to_be16(freq
);
668 /* If freq2 is available then the spectral scan results are fragmented
669 * as primary and secondary
671 if (fragment_sample
&& freq
) {
672 if (!ar
->spectral
.is_primary
)
673 fft_sample
->freq1
= cpu_to_be16(freq
);
675 /* We have to toggle the is_primary to handle the next report */
676 ar
->spectral
.is_primary
= !ar
->spectral
.is_primary
;
679 ath11k_spectral_parse_fft(fft_sample
->data
, fft_report
->bins
, num_bins
,
680 ab
->hw_params
.spectral
.fft_sz
);
682 fft_sample
->max_exp
= ath11k_spectral_get_max_exp(fft_sample
->max_index
,
687 if (ar
->spectral
.rfs_scan
)
688 relay_write(ar
->spectral
.rfs_scan
, fft_sample
,
689 length
+ sizeof(struct fft_sample_tlv
));
694 static int ath11k_spectral_process_data(struct ath11k
*ar
,
695 struct ath11k_dbring_data
*param
)
697 struct ath11k_base
*ab
= ar
->ab
;
698 struct spectral_tlv
*tlv
;
699 struct spectral_summary_fft_report
*summary
= NULL
;
700 struct ath11k_spectral_summary_report summ_rpt
;
701 struct fft_sample_ath11k
*fft_sample
= NULL
;
705 int tlv_len
, sample_sz
;
709 spin_lock_bh(&ar
->spectral
.lock
);
711 if (!ar
->spectral
.enabled
) {
716 sample_sz
= sizeof(*fft_sample
) + ATH11K_SPECTRAL_MAX_IB_BINS(ab
);
717 fft_sample
= kmalloc(sample_sz
, GFP_ATOMIC
);
724 data_len
= param
->data_sz
;
726 while (!quit
&& (i
< data_len
)) {
727 if ((i
+ sizeof(*tlv
)) > data_len
) {
728 ath11k_warn(ab
, "failed to parse spectral tlv hdr at bytes %d\n",
734 tlv
= (struct spectral_tlv
*)&data
[i
];
735 sign
= FIELD_GET(SPECTRAL_TLV_HDR_SIGN
,
736 __le32_to_cpu(tlv
->header
));
737 if (sign
!= ATH11K_SPECTRAL_SIGNATURE
) {
738 ath11k_warn(ab
, "Invalid sign 0x%x at bytes %d\n",
744 tlv_len
= FIELD_GET(SPECTRAL_TLV_HDR_LEN
,
745 __le32_to_cpu(tlv
->header
));
746 /* convert Dword into bytes */
747 tlv_len
*= ATH11K_SPECTRAL_DWORD_SIZE
;
748 if ((i
+ sizeof(*tlv
) + tlv_len
) > data_len
) {
749 ath11k_warn(ab
, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n",
750 i
, tlv_len
, data_len
);
755 tag
= FIELD_GET(SPECTRAL_TLV_HDR_TAG
,
756 __le32_to_cpu(tlv
->header
));
758 case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY
:
759 /* HW bug in tlv length of summary report,
760 * HW report 3 DWORD size but the data payload
761 * is 4 DWORD size (16 bytes).
762 * Need to remove this workaround once HW bug fixed
764 tlv_len
= sizeof(*summary
) - sizeof(*tlv
) +
765 ab
->hw_params
.spectral
.summary_pad_sz
;
767 if (tlv_len
< (sizeof(*summary
) - sizeof(*tlv
))) {
768 ath11k_warn(ab
, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
774 ret
= ath11k_dbring_validate_buffer(ar
, data
, tlv_len
);
776 ath11k_warn(ar
->ab
, "found magic value in spectral summary, dropping\n");
780 summary
= (struct spectral_summary_fft_report
*)tlv
;
781 ath11k_spectral_pull_summary(ar
, ¶m
->meta
,
784 case ATH11K_SPECTRAL_TAG_SCAN_SEARCH
:
785 if (tlv_len
< (sizeof(struct spectral_search_fft_report
) -
787 ath11k_warn(ab
, "failed to parse spectral search fft at bytes %d\n",
793 memset(fft_sample
, 0, sample_sz
);
794 ret
= ath11k_spectral_process_fft(ar
, &summ_rpt
, tlv
,
798 ath11k_warn(ab
, "failed to process spectral fft at bytes %d\n",
806 i
+= sizeof(*tlv
) + tlv_len
;
814 spin_unlock_bh(&ar
->spectral
.lock
);
818 static int ath11k_spectral_ring_alloc(struct ath11k
*ar
,
819 struct ath11k_dbring_cap
*db_cap
)
821 struct ath11k_spectral
*sp
= &ar
->spectral
;
824 ret
= ath11k_dbring_srng_setup(ar
, &sp
->rx_ring
,
825 0, db_cap
->min_elem
);
827 ath11k_warn(ar
->ab
, "failed to setup db ring\n");
831 ath11k_dbring_set_cfg(ar
, &sp
->rx_ring
,
832 ATH11K_SPECTRAL_NUM_RESP_PER_EVENT
,
833 ATH11K_SPECTRAL_EVENT_TIMEOUT_MS
,
834 ath11k_spectral_process_data
);
836 ret
= ath11k_dbring_buf_setup(ar
, &sp
->rx_ring
, db_cap
);
838 ath11k_warn(ar
->ab
, "failed to setup db ring buffer\n");
842 ret
= ath11k_dbring_wmi_cfg_setup(ar
, &sp
->rx_ring
,
843 WMI_DIRECT_BUF_SPECTRAL
);
845 ath11k_warn(ar
->ab
, "failed to setup db ring cfg\n");
852 ath11k_dbring_buf_cleanup(ar
, &sp
->rx_ring
);
854 ath11k_dbring_srng_cleanup(ar
, &sp
->rx_ring
);
858 static inline void ath11k_spectral_ring_free(struct ath11k
*ar
)
860 struct ath11k_spectral
*sp
= &ar
->spectral
;
862 ath11k_dbring_srng_cleanup(ar
, &sp
->rx_ring
);
863 ath11k_dbring_buf_cleanup(ar
, &sp
->rx_ring
);
866 static inline void ath11k_spectral_debug_unregister(struct ath11k
*ar
)
868 debugfs_remove(ar
->spectral
.scan_bins
);
869 ar
->spectral
.scan_bins
= NULL
;
871 debugfs_remove(ar
->spectral
.scan_count
);
872 ar
->spectral
.scan_count
= NULL
;
874 debugfs_remove(ar
->spectral
.scan_ctl
);
875 ar
->spectral
.scan_ctl
= NULL
;
877 if (ar
->spectral
.rfs_scan
) {
878 relay_close(ar
->spectral
.rfs_scan
);
879 ar
->spectral
.rfs_scan
= NULL
;
883 int ath11k_spectral_vif_stop(struct ath11k_vif
*arvif
)
885 if (!arvif
->spectral_enabled
)
888 return ath11k_spectral_scan_config(arvif
->ar
, ATH11K_SPECTRAL_DISABLED
);
891 void ath11k_spectral_reset_buffer(struct ath11k
*ar
)
893 if (!ar
->spectral
.enabled
)
896 if (ar
->spectral
.rfs_scan
)
897 relay_reset(ar
->spectral
.rfs_scan
);
900 void ath11k_spectral_deinit(struct ath11k_base
*ab
)
903 struct ath11k_spectral
*sp
;
906 for (i
= 0; i
< ab
->num_radios
; i
++) {
907 ar
= ab
->pdevs
[i
].ar
;
913 mutex_lock(&ar
->conf_mutex
);
914 ath11k_spectral_scan_config(ar
, ATH11K_SPECTRAL_DISABLED
);
915 mutex_unlock(&ar
->conf_mutex
);
917 spin_lock_bh(&sp
->lock
);
919 spin_unlock_bh(&sp
->lock
);
921 ath11k_spectral_debug_unregister(ar
);
922 ath11k_spectral_ring_free(ar
);
926 static inline int ath11k_spectral_debug_register(struct ath11k
*ar
)
930 ar
->spectral
.rfs_scan
= relay_open("spectral_scan",
931 ar
->debug
.debugfs_pdev
,
932 ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar
->ab
),
933 ATH11K_SPECTRAL_NUM_SUB_BUF
,
935 if (!ar
->spectral
.rfs_scan
) {
936 ath11k_warn(ar
->ab
, "failed to open relay in pdev %d\n",
941 ar
->spectral
.scan_ctl
= debugfs_create_file("spectral_scan_ctl",
943 ar
->debug
.debugfs_pdev
, ar
,
945 if (!ar
->spectral
.scan_ctl
) {
946 ath11k_warn(ar
->ab
, "failed to open debugfs in pdev %d\n",
949 goto debug_unregister
;
952 ar
->spectral
.scan_count
= debugfs_create_file("spectral_count",
954 ar
->debug
.debugfs_pdev
, ar
,
956 if (!ar
->spectral
.scan_count
) {
957 ath11k_warn(ar
->ab
, "failed to open debugfs in pdev %d\n",
960 goto debug_unregister
;
963 ar
->spectral
.scan_bins
= debugfs_create_file("spectral_bins",
965 ar
->debug
.debugfs_pdev
, ar
,
967 if (!ar
->spectral
.scan_bins
) {
968 ath11k_warn(ar
->ab
, "failed to open debugfs in pdev %d\n",
971 goto debug_unregister
;
977 ath11k_spectral_debug_unregister(ar
);
981 int ath11k_spectral_init(struct ath11k_base
*ab
)
984 struct ath11k_spectral
*sp
;
985 struct ath11k_dbring_cap db_cap
;
989 if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA
,
993 if (!ab
->hw_params
.spectral
.fft_sz
)
996 for (i
= 0; i
< ab
->num_radios
; i
++) {
997 ar
= ab
->pdevs
[i
].ar
;
1000 ret
= ath11k_dbring_get_cap(ar
->ab
, ar
->pdev_idx
,
1001 WMI_DIRECT_BUF_SPECTRAL
,
1006 idr_init(&sp
->rx_ring
.bufs_idr
);
1007 spin_lock_init(&sp
->rx_ring
.idr_lock
);
1008 spin_lock_init(&sp
->lock
);
1010 ret
= ath11k_spectral_ring_alloc(ar
, &db_cap
);
1012 ath11k_warn(ab
, "failed to init spectral ring for pdev %d\n",
1017 spin_lock_bh(&sp
->lock
);
1019 sp
->mode
= ATH11K_SPECTRAL_DISABLED
;
1020 sp
->count
= ATH11K_WMI_SPECTRAL_COUNT_DEFAULT
;
1021 sp
->fft_size
= ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT
;
1024 spin_unlock_bh(&sp
->lock
);
1026 ret
= ath11k_spectral_debug_register(ar
);
1028 ath11k_warn(ab
, "failed to register spectral for pdev %d\n",
1037 ath11k_spectral_deinit(ab
);
1041 enum ath11k_spectral_mode
ath11k_spectral_get_mode(struct ath11k
*ar
)
1043 if (ar
->spectral
.enabled
)
1044 return ar
->spectral
.mode
;
1046 return ATH11K_SPECTRAL_DISABLED
;
1049 struct ath11k_dbring
*ath11k_spectral_get_dbring(struct ath11k
*ar
)
1051 if (ar
->spectral
.enabled
)
1052 return &ar
->spectral
.rx_ring
;