1// SPDX-License-Identifier: BSD-3-Clause-Clear
2/*
3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5 */
6
7#include <linux/relay.h>
8#include "core.h"
9#include "debug.h"
10
11#define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT	2
12#define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS	1
13
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)
18
19#define ATH11K_SPECTRAL_SCAN_COUNT_MAX		4095
20
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
30
31#define ATH11K_SPECTRAL_20MHZ			20
32#define ATH11K_SPECTRAL_40MHZ			40
33#define ATH11K_SPECTRAL_80MHZ			80
34#define ATH11K_SPECTRAL_160MHZ			160
35
36#define ATH11K_SPECTRAL_SIGNATURE		0xFA
37
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
42
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)
46
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)
55
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)
60
61struct spectral_tlv {
62	__le32 timestamp;
63	__le32 header;
64} __packed;
65
66struct spectral_summary_fft_report {
67	__le32 timestamp;
68	__le32 tlv_header;
69	__le32 info0;
70	__le32 reserve0;
71	__le32 info2;
72	__le32 reserve1;
73} __packed;
74
75struct ath11k_spectral_summary_report {
76	struct wmi_dma_buf_release_meta_data meta;
77	u32 timestamp;
78	u8 agc_total_gain;
79	u8 grp_idx;
80	u16 inb_pwr_db;
81	s16 peak_idx;
82	u16 peak_mag;
83	u8 detector_id;
84	bool out_of_band_flag;
85	bool rf_saturation;
86	bool primary80;
87	bool gain_change;
88	bool false_scan;
89};
90
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)
96
97#define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB		GENMASK(8, 0)
98#define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB		GENMASK(16, 9)
99
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)
104
105struct spectral_search_fft_report {
106	__le32 timestamp;
107	__le32 tlv_header;
108	__le32 info0;
109	__le32 info1;
110	__le32 info2;
111	__le32 reserve0;
112	u8 bins[];
113} __packed;
114
115struct ath11k_spectral_search_report {
116	u32 timestamp;
117	u8 detector_id;
118	u8 fft_count;
119	u16 radar_check;
120	s16 peak_idx;
121	u8 chain_idx;
122	u16 base_pwr_db;
123	u8 total_gain_db;
124	u8 strong_bin_count;
125	u16 peak_mag;
126	u8 avg_pwr_db;
127	u8 rel_pwr_db;
128};
129
130static struct dentry *create_buf_file_handler(const char *filename,
131					      struct dentry *parent,
132					      umode_t mode,
133					      struct rchan_buf *buf,
134					      int *is_global)
135{
136	struct dentry *buf_file;
137
138	buf_file = debugfs_create_file(filename, mode, parent, buf,
139				       &relay_file_operations);
140	*is_global = 1;
141	return buf_file;
142}
143
144static int remove_buf_file_handler(struct dentry *dentry)
145{
146	debugfs_remove(dentry);
147
148	return 0;
149}
150
151static const struct rchan_callbacks rfs_scan_cb = {
152	.create_buf_file = create_buf_file_handler,
153	.remove_buf_file = remove_buf_file_handler,
154};
155
156static struct ath11k_vif *ath11k_spectral_get_vdev(struct ath11k *ar)
157{
158	struct ath11k_vif *arvif;
159
160	lockdep_assert_held(&ar->conf_mutex);
161
162	if (list_empty(&ar->arvifs))
163		return NULL;
164
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)
168			return arvif;
169
170	/* otherwise, return the first vif. */
171	return list_first_entry(&ar->arvifs, typeof(*arvif), list);
172}
173
174static int ath11k_spectral_scan_trigger(struct ath11k *ar)
175{
176	struct ath11k_vif *arvif;
177	int ret;
178
179	lockdep_assert_held(&ar->conf_mutex);
180
181	arvif = ath11k_spectral_get_vdev(ar);
182	if (!arvif)
183		return -ENODEV;
184
185	if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED)
186		return 0;
187
188	ar->spectral.is_primary = true;
189
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);
193	if (ret)
194		return ret;
195
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);
199	if (ret)
200		return ret;
201
202	return 0;
203}
204
205static int ath11k_spectral_scan_config(struct ath11k *ar,
206				       enum ath11k_spectral_mode mode)
207{
208	struct ath11k_wmi_vdev_spectral_conf_param param = { 0 };
209	struct ath11k_vif *arvif;
210	int ret, count;
211
212	lockdep_assert_held(&ar->conf_mutex);
213
214	arvif = ath11k_spectral_get_vdev(ar);
215	if (!arvif)
216		return -ENODEV;
217
218	arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED);
219
220	spin_lock_bh(&ar->spectral.lock);
221	ar->spectral.mode = mode;
222	spin_unlock_bh(&ar->spectral.lock);
223
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);
227	if (ret) {
228		ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret);
229		return ret;
230	}
231
232	if (mode == ATH11K_SPECTRAL_DISABLED)
233		return 0;
234
235	if (mode == ATH11K_SPECTRAL_BACKGROUND)
236		count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
237	else
238		count = max_t(u16, 1, ar->spectral.count);
239
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;
259
260	ret = ath11k_wmi_vdev_spectral_conf(ar, &param);
261	if (ret) {
262		ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret);
263		return ret;
264	}
265
266	return 0;
267}
268
269static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file,
270					      char __user *user_buf,
271					      size_t count, loff_t *ppos)
272{
273	struct ath11k *ar = file->private_data;
274	char *mode = "";
275	size_t len;
276	enum ath11k_spectral_mode spectral_mode;
277
278	mutex_lock(&ar->conf_mutex);
279	spectral_mode = ar->spectral.mode;
280	mutex_unlock(&ar->conf_mutex);
281
282	switch (spectral_mode) {
283	case ATH11K_SPECTRAL_DISABLED:
284		mode = "disable";
285		break;
286	case ATH11K_SPECTRAL_BACKGROUND:
287		mode = "background";
288		break;
289	case ATH11K_SPECTRAL_MANUAL:
290		mode = "manual";
291		break;
292	}
293
294	len = strlen(mode);
295	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
296}
297
298static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file,
299					       const char __user *user_buf,
300					       size_t count, loff_t *ppos)
301{
302	struct ath11k *ar = file->private_data;
303	char buf[32];
304	ssize_t len;
305	int ret;
306
307	len = min(count, sizeof(buf) - 1);
308	if (copy_from_user(buf, user_buf, len))
309		return -EFAULT;
310
311	buf[len] = '\0';
312
313	mutex_lock(&ar->conf_mutex);
314
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
319			 * debugfs parameters
320			 */
321			ret = ath11k_spectral_scan_config(ar, ar->spectral.mode);
322			if (ret) {
323				ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n",
324					    ret);
325				goto unlock;
326			}
327
328			ret = ath11k_spectral_scan_trigger(ar);
329			if (ret) {
330				ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n",
331					    ret);
332			}
333		} else {
334			ret = -EINVAL;
335		}
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);
342	} else {
343		ret = -EINVAL;
344	}
345
346unlock:
347	mutex_unlock(&ar->conf_mutex);
348
349	if (ret)
350		return ret;
351
352	return count;
353}
354
355static const struct file_operations fops_scan_ctl = {
356	.read = ath11k_read_file_spec_scan_ctl,
357	.write = ath11k_write_file_spec_scan_ctl,
358	.open = simple_open,
359	.owner = THIS_MODULE,
360	.llseek = default_llseek,
361};
362
363static ssize_t ath11k_read_file_spectral_count(struct file *file,
364					       char __user *user_buf,
365					       size_t count, loff_t *ppos)
366{
367	struct ath11k *ar = file->private_data;
368	char buf[32];
369	size_t len;
370	u16 spectral_count;
371
372	mutex_lock(&ar->conf_mutex);
373	spectral_count = ar->spectral.count;
374	mutex_unlock(&ar->conf_mutex);
375
376	len = sprintf(buf, "%d\n", spectral_count);
377	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
378}
379
380static ssize_t ath11k_write_file_spectral_count(struct file *file,
381						const char __user *user_buf,
382						size_t count, loff_t *ppos)
383{
384	struct ath11k *ar = file->private_data;
385	unsigned long val;
386	ssize_t ret;
387
388	ret = kstrtoul_from_user(user_buf, count, 0, &val);
389	if (ret)
390		return ret;
391
392	if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX)
393		return -EINVAL;
394
395	mutex_lock(&ar->conf_mutex);
396	ar->spectral.count = val;
397	mutex_unlock(&ar->conf_mutex);
398
399	return count;
400}
401
402static const struct file_operations fops_scan_count = {
403	.read = ath11k_read_file_spectral_count,
404	.write = ath11k_write_file_spectral_count,
405	.open = simple_open,
406	.owner = THIS_MODULE,
407	.llseek = default_llseek,
408};
409
410static ssize_t ath11k_read_file_spectral_bins(struct file *file,
411					      char __user *user_buf,
412					      size_t count, loff_t *ppos)
413{
414	struct ath11k *ar = file->private_data;
415	char buf[32];
416	unsigned int bins, fft_size;
417	size_t len;
418
419	mutex_lock(&ar->conf_mutex);
420
421	fft_size = ar->spectral.fft_size;
422	bins = 1 << fft_size;
423
424	mutex_unlock(&ar->conf_mutex);
425
426	len = sprintf(buf, "%d\n", bins);
427	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
428}
429
430static ssize_t ath11k_write_file_spectral_bins(struct file *file,
431					       const char __user *user_buf,
432					       size_t count, loff_t *ppos)
433{
434	struct ath11k *ar = file->private_data;
435	unsigned long val;
436	ssize_t ret;
437
438	ret = kstrtoul_from_user(user_buf, count, 0, &val);
439	if (ret)
440		return ret;
441
442	if (val < ATH11K_SPECTRAL_MIN_BINS ||
443	    val > ar->ab->hw_params.spectral.max_fft_bins)
444		return -EINVAL;
445
446	if (!is_power_of_2(val))
447		return -EINVAL;
448
449	mutex_lock(&ar->conf_mutex);
450	ar->spectral.fft_size = ilog2(val);
451	mutex_unlock(&ar->conf_mutex);
452
453	return count;
454}
455
456static const struct file_operations fops_scan_bins = {
457	.read = ath11k_read_file_spectral_bins,
458	.write = ath11k_write_file_spectral_bins,
459	.open = simple_open,
460	.owner = THIS_MODULE,
461	.llseek = default_llseek,
462};
463
464static 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)
468{
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));
492
493	memcpy(&report->meta, meta, sizeof(*meta));
494
495	return 0;
496}
497
498static int ath11k_spectral_pull_search(struct ath11k *ar,
499				       struct spectral_search_fft_report *search,
500				       struct ath11k_spectral_search_report *report)
501{
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));
525
526	return 0;
527}
528
529static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude,
530				      int bin_len, u8 *bins)
531{
532	int dc_pos;
533	u8 max_exp;
534
535	dc_pos = bin_len / 2;
536
537	/* peak index outside of bins */
538	if (dc_pos <= max_index || -dc_pos >= max_index)
539		return 0;
540
541	for (max_exp = 0; max_exp < 8; max_exp++) {
542		if (bins[dc_pos + max_index] == (max_magnitude >> max_exp))
543			break;
544	}
545
546	/* max_exp not found */
547	if (bins[dc_pos + max_index] != (max_magnitude >> max_exp))
548		return 0;
549
550	return max_exp;
551}
552
553static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz)
554{
555	int i, j;
556
557	i = 0;
558	j = 0;
559	while (i < num_bins) {
560		outbins[i] = inbins[j];
561		i++;
562		j += fft_sz;
563	}
564}
565
566static
567int ath11k_spectral_process_fft(struct ath11k *ar,
568				struct ath11k_spectral_summary_report *summary,
569				void *data,
570				struct fft_sample_ath11k *fft_sample,
571				u32 data_len)
572{
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;
578	u16 length, freq;
579	u8 chan_width_mhz, bin_sz;
580	int ret;
581	u32 check_length;
582	bool fragment_sample = false;
583
584	lockdep_assert_held(&ar->spectral.lock);
585
586	if (!ab->hw_params.spectral.fft_sz) {
587		ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
588			    ab->hw_rev);
589		return -EINVAL;
590	}
591
592	tlv = data;
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;
597
598	if (data_len < (bin_len + sizeof(*fft_report))) {
599		ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n",
600			    bin_len, data_len);
601		return -EINVAL;
602	}
603
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 */
607	num_bins >>= 1;
608
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);
613		return -EINVAL;
614	}
615
616	check_length = sizeof(*fft_report) + (num_bins * ab->hw_params.spectral.fft_sz);
617	ret = ath11k_dbring_validate_buffer(ar, data, check_length);
618	if (ret) {
619		ath11k_warn(ar->ab, "found magic value in fft data, dropping\n");
620		return ret;
621	}
622
623	ret = ath11k_spectral_pull_search(ar, data, &search);
624	if (ret) {
625		ath11k_warn(ab, "failed to pull search report %d\n", ret);
626		return ret;
627	}
628
629	chan_width_mhz = summary->meta.ch_width;
630
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;
636		break;
637	case ATH11K_SPECTRAL_160MHZ:
638		if (ab->hw_params.spectral.fragment_160mhz) {
639			chan_width_mhz /= 2;
640			fragment_sample = true;
641		}
642		fft_sample->chan_width_mhz = chan_width_mhz;
643		break;
644	default:
645		ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
646		return -EINVAL;
647	}
648
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);
652
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));
657
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]);
661
662	freq = summary->meta.freq1;
663	fft_sample->freq1 = __cpu_to_be16(freq);
664
665	freq = summary->meta.freq2;
666	fft_sample->freq2 = __cpu_to_be16(freq);
667
668	/* If freq2 is available then the spectral scan results are fragmented
669	 * as primary and secondary
670	 */
671	if (fragment_sample && freq) {
672		if (!ar->spectral.is_primary)
673			fft_sample->freq1 = cpu_to_be16(freq);
674
675		/* We have to toggle the is_primary to handle the next report */
676		ar->spectral.is_primary = !ar->spectral.is_primary;
677	}
678
679	ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
680				  ab->hw_params.spectral.fft_sz);
681
682	fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
683							  search.peak_mag,
684							  num_bins,
685							  fft_sample->data);
686
687	if (ar->spectral.rfs_scan)
688		relay_write(ar->spectral.rfs_scan, fft_sample,
689			    length + sizeof(struct fft_sample_tlv));
690
691	return 0;
692}
693
694static int ath11k_spectral_process_data(struct ath11k *ar,
695					struct ath11k_dbring_data *param)
696{
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;
702	u8 *data;
703	u32 data_len, i;
704	u8 sign, tag;
705	int tlv_len, sample_sz;
706	int ret;
707	bool quit = false;
708
709	spin_lock_bh(&ar->spectral.lock);
710
711	if (!ar->spectral.enabled) {
712		ret = -EINVAL;
713		goto unlock;
714	}
715
716	sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab);
717	fft_sample = kmalloc(sample_sz, GFP_ATOMIC);
718	if (!fft_sample) {
719		ret = -ENOBUFS;
720		goto unlock;
721	}
722
723	data = param->data;
724	data_len = param->data_sz;
725	i = 0;
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",
729				    i);
730			ret = -EINVAL;
731			goto err;
732		}
733
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",
739				    sign, i);
740			ret = -EINVAL;
741			goto err;
742		}
743
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);
751			ret = -EINVAL;
752			goto err;
753		}
754
755		tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG,
756				__le32_to_cpu(tlv->header));
757		switch (tag) {
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
763			 */
764			tlv_len = sizeof(*summary) - sizeof(*tlv) +
765				  ab->hw_params.spectral.summary_pad_sz;
766
767			if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) {
768				ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
769					    i, tlv_len);
770				ret = -EINVAL;
771				goto err;
772			}
773
774			ret = ath11k_dbring_validate_buffer(ar, data, tlv_len);
775			if (ret) {
776				ath11k_warn(ar->ab, "found magic value in spectral summary, dropping\n");
777				goto err;
778			}
779
780			summary = (struct spectral_summary_fft_report *)tlv;
781			ath11k_spectral_pull_summary(ar, &param->meta,
782						     summary, &summ_rpt);
783			break;
784		case ATH11K_SPECTRAL_TAG_SCAN_SEARCH:
785			if (tlv_len < (sizeof(struct spectral_search_fft_report) -
786				       sizeof(*tlv))) {
787				ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n",
788					    i);
789				ret = -EINVAL;
790				goto err;
791			}
792
793			memset(fft_sample, 0, sample_sz);
794			ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv,
795							  fft_sample,
796							  data_len - i);
797			if (ret) {
798				ath11k_warn(ab, "failed to process spectral fft at bytes %d\n",
799					    i);
800				goto err;
801			}
802			quit = true;
803			break;
804		}
805
806		i += sizeof(*tlv) + tlv_len;
807	}
808
809	ret = 0;
810
811err:
812	kfree(fft_sample);
813unlock:
814	spin_unlock_bh(&ar->spectral.lock);
815	return ret;
816}
817
818static int ath11k_spectral_ring_alloc(struct ath11k *ar,
819				      struct ath11k_dbring_cap *db_cap)
820{
821	struct ath11k_spectral *sp = &ar->spectral;
822	int ret;
823
824	ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring,
825				       0, db_cap->min_elem);
826	if (ret) {
827		ath11k_warn(ar->ab, "failed to setup db ring\n");
828		return ret;
829	}
830
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);
835
836	ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap);
837	if (ret) {
838		ath11k_warn(ar->ab, "failed to setup db ring buffer\n");
839		goto srng_cleanup;
840	}
841
842	ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring,
843					  WMI_DIRECT_BUF_SPECTRAL);
844	if (ret) {
845		ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
846		goto buffer_cleanup;
847	}
848
849	return 0;
850
851buffer_cleanup:
852	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
853srng_cleanup:
854	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
855	return ret;
856}
857
858static inline void ath11k_spectral_ring_free(struct ath11k *ar)
859{
860	struct ath11k_spectral *sp = &ar->spectral;
861
862	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
863	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
864}
865
866static inline void ath11k_spectral_debug_unregister(struct ath11k *ar)
867{
868	debugfs_remove(ar->spectral.scan_bins);
869	ar->spectral.scan_bins = NULL;
870
871	debugfs_remove(ar->spectral.scan_count);
872	ar->spectral.scan_count = NULL;
873
874	debugfs_remove(ar->spectral.scan_ctl);
875	ar->spectral.scan_ctl = NULL;
876
877	if (ar->spectral.rfs_scan) {
878		relay_close(ar->spectral.rfs_scan);
879		ar->spectral.rfs_scan = NULL;
880	}
881}
882
883int ath11k_spectral_vif_stop(struct ath11k_vif *arvif)
884{
885	if (!arvif->spectral_enabled)
886		return 0;
887
888	return ath11k_spectral_scan_config(arvif->ar, ATH11K_SPECTRAL_DISABLED);
889}
890
891void ath11k_spectral_reset_buffer(struct ath11k *ar)
892{
893	if (!ar->spectral.enabled)
894		return;
895
896	if (ar->spectral.rfs_scan)
897		relay_reset(ar->spectral.rfs_scan);
898}
899
900void ath11k_spectral_deinit(struct ath11k_base *ab)
901{
902	struct ath11k *ar;
903	struct ath11k_spectral *sp;
904	int i;
905
906	for (i = 0; i <  ab->num_radios; i++) {
907		ar = ab->pdevs[i].ar;
908		sp = &ar->spectral;
909
910		if (!sp->enabled)
911			continue;
912
913		mutex_lock(&ar->conf_mutex);
914		ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
915		mutex_unlock(&ar->conf_mutex);
916
917		spin_lock_bh(&sp->lock);
918		sp->enabled = false;
919		spin_unlock_bh(&sp->lock);
920
921		ath11k_spectral_debug_unregister(ar);
922		ath11k_spectral_ring_free(ar);
923	}
924}
925
926static inline int ath11k_spectral_debug_register(struct ath11k *ar)
927{
928	int ret;
929
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,
934					   &rfs_scan_cb, NULL);
935	if (!ar->spectral.rfs_scan) {
936		ath11k_warn(ar->ab, "failed to open relay in pdev %d\n",
937			    ar->pdev_idx);
938		return -EINVAL;
939	}
940
941	ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl",
942						    0600,
943						    ar->debug.debugfs_pdev, ar,
944						    &fops_scan_ctl);
945	if (!ar->spectral.scan_ctl) {
946		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
947			    ar->pdev_idx);
948		ret = -EINVAL;
949		goto debug_unregister;
950	}
951
952	ar->spectral.scan_count = debugfs_create_file("spectral_count",
953						      0600,
954						      ar->debug.debugfs_pdev, ar,
955						      &fops_scan_count);
956	if (!ar->spectral.scan_count) {
957		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
958			    ar->pdev_idx);
959		ret = -EINVAL;
960		goto debug_unregister;
961	}
962
963	ar->spectral.scan_bins = debugfs_create_file("spectral_bins",
964						     0600,
965						     ar->debug.debugfs_pdev, ar,
966						     &fops_scan_bins);
967	if (!ar->spectral.scan_bins) {
968		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
969			    ar->pdev_idx);
970		ret = -EINVAL;
971		goto debug_unregister;
972	}
973
974	return 0;
975
976debug_unregister:
977	ath11k_spectral_debug_unregister(ar);
978	return ret;
979}
980
981int ath11k_spectral_init(struct ath11k_base *ab)
982{
983	struct ath11k *ar;
984	struct ath11k_spectral *sp;
985	struct ath11k_dbring_cap db_cap;
986	int ret;
987	int i;
988
989	if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA,
990		      ab->wmi_ab.svc_map))
991		return 0;
992
993	if (!ab->hw_params.spectral.fft_sz)
994		return 0;
995
996	for (i = 0; i < ab->num_radios; i++) {
997		ar = ab->pdevs[i].ar;
998		sp = &ar->spectral;
999
1000		ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
1001					    WMI_DIRECT_BUF_SPECTRAL,
1002					    &db_cap);
1003		if (ret)
1004			continue;
1005
1006		idr_init(&sp->rx_ring.bufs_idr);
1007		spin_lock_init(&sp->rx_ring.idr_lock);
1008		spin_lock_init(&sp->lock);
1009
1010		ret = ath11k_spectral_ring_alloc(ar, &db_cap);
1011		if (ret) {
1012			ath11k_warn(ab, "failed to init spectral ring for pdev %d\n",
1013				    i);
1014			goto deinit;
1015		}
1016
1017		spin_lock_bh(&sp->lock);
1018
1019		sp->mode = ATH11K_SPECTRAL_DISABLED;
1020		sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
1021		sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT;
1022		sp->enabled = true;
1023
1024		spin_unlock_bh(&sp->lock);
1025
1026		ret = ath11k_spectral_debug_register(ar);
1027		if (ret) {
1028			ath11k_warn(ab, "failed to register spectral for pdev %d\n",
1029				    i);
1030			goto deinit;
1031		}
1032	}
1033
1034	return 0;
1035
1036deinit:
1037	ath11k_spectral_deinit(ab);
1038	return ret;
1039}
1040
1041enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar)
1042{
1043	if (ar->spectral.enabled)
1044		return ar->spectral.mode;
1045	else
1046		return ATH11K_SPECTRAL_DISABLED;
1047}
1048
1049struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar)
1050{
1051	if (ar->spectral.enabled)
1052		return &ar->spectral.rx_ring;
1053	else
1054		return NULL;
1055}
1056