1// SPDX-License-Identifier: BSD-3-Clause-Clear
2/*
3 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/relay.h>
7#include "core.h"
8#include "debug.h"
9
10#define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT	2
11#define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS	1
12
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
19
20#define ATH11K_SPECTRAL_SCAN_COUNT_MAX		4095
21
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
31
32#define ATH11K_SPECTRAL_20MHZ			20
33#define ATH11K_SPECTRAL_40MHZ			40
34#define ATH11K_SPECTRAL_80MHZ			80
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[0];
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 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	ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
189					      ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
190					      ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
191	if (ret)
192		return ret;
193
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);
197	if (ret)
198		return ret;
199
200	return 0;
201}
202
203static int ath11k_spectral_scan_config(struct ath11k *ar,
204				       enum ath11k_spectral_mode mode)
205{
206	struct ath11k_wmi_vdev_spectral_conf_param param = { 0 };
207	struct ath11k_vif *arvif;
208	int ret, count;
209
210	lockdep_assert_held(&ar->conf_mutex);
211
212	arvif = ath11k_spectral_get_vdev(ar);
213	if (!arvif)
214		return -ENODEV;
215
216	arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED);
217
218	spin_lock_bh(&ar->spectral.lock);
219	ar->spectral.mode = mode;
220	spin_unlock_bh(&ar->spectral.lock);
221
222	ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
223					      ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
224					      ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE);
225	if (ret) {
226		ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret);
227		return ret;
228	}
229
230	if (mode == ATH11K_SPECTRAL_DISABLED)
231		return 0;
232
233	if (mode == ATH11K_SPECTRAL_BACKGROUND)
234		count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
235	else
236		count = max_t(u16, 1, ar->spectral.count);
237
238	param.vdev_id = arvif->vdev_id;
239	param.scan_count = count;
240	param.scan_fft_size = ar->spectral.fft_size;
241	param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT;
242	param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT;
243	param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT;
244	param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT;
245	param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
246	param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT;
247	param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
248	param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
249	param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
250	param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
251	param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT;
252	param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
253	param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT;
254	param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT;
255	param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT;
256	param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT;
257
258	ret = ath11k_wmi_vdev_spectral_conf(ar, &param);
259	if (ret) {
260		ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret);
261		return ret;
262	}
263
264	return 0;
265}
266
267static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file,
268					      char __user *user_buf,
269					      size_t count, loff_t *ppos)
270{
271	struct ath11k *ar = file->private_data;
272	char *mode = "";
273	size_t len;
274	enum ath11k_spectral_mode spectral_mode;
275
276	mutex_lock(&ar->conf_mutex);
277	spectral_mode = ar->spectral.mode;
278	mutex_unlock(&ar->conf_mutex);
279
280	switch (spectral_mode) {
281	case ATH11K_SPECTRAL_DISABLED:
282		mode = "disable";
283		break;
284	case ATH11K_SPECTRAL_BACKGROUND:
285		mode = "background";
286		break;
287	case ATH11K_SPECTRAL_MANUAL:
288		mode = "manual";
289		break;
290	}
291
292	len = strlen(mode);
293	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
294}
295
296static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file,
297					       const char __user *user_buf,
298					       size_t count, loff_t *ppos)
299{
300	struct ath11k *ar = file->private_data;
301	char buf[32];
302	ssize_t len;
303	int ret;
304
305	len = min(count, sizeof(buf) - 1);
306	if (copy_from_user(buf, user_buf, len))
307		return -EFAULT;
308
309	buf[len] = '\0';
310
311	mutex_lock(&ar->conf_mutex);
312
313	if (strncmp("trigger", buf, 7) == 0) {
314		if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL ||
315		    ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) {
316			/* reset the configuration to adopt possibly changed
317			 * debugfs parameters
318			 */
319			ret = ath11k_spectral_scan_config(ar, ar->spectral.mode);
320			if (ret) {
321				ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n",
322					    ret);
323				goto unlock;
324			}
325
326			ret = ath11k_spectral_scan_trigger(ar);
327			if (ret) {
328				ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n",
329					    ret);
330			}
331		} else {
332			ret = -EINVAL;
333		}
334	} else if (strncmp("background", buf, 10) == 0) {
335		ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND);
336	} else if (strncmp("manual", buf, 6) == 0) {
337		ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL);
338	} else if (strncmp("disable", buf, 7) == 0) {
339		ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
340	} else {
341		ret = -EINVAL;
342	}
343
344unlock:
345	mutex_unlock(&ar->conf_mutex);
346
347	if (ret)
348		return ret;
349
350	return count;
351}
352
353static const struct file_operations fops_scan_ctl = {
354	.read = ath11k_read_file_spec_scan_ctl,
355	.write = ath11k_write_file_spec_scan_ctl,
356	.open = simple_open,
357	.owner = THIS_MODULE,
358	.llseek = default_llseek,
359};
360
361static ssize_t ath11k_read_file_spectral_count(struct file *file,
362					       char __user *user_buf,
363					       size_t count, loff_t *ppos)
364{
365	struct ath11k *ar = file->private_data;
366	char buf[32];
367	size_t len;
368	u16 spectral_count;
369
370	mutex_lock(&ar->conf_mutex);
371	spectral_count = ar->spectral.count;
372	mutex_unlock(&ar->conf_mutex);
373
374	len = sprintf(buf, "%d\n", spectral_count);
375	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
376}
377
378static ssize_t ath11k_write_file_spectral_count(struct file *file,
379						const char __user *user_buf,
380						size_t count, loff_t *ppos)
381{
382	struct ath11k *ar = file->private_data;
383	unsigned long val;
384	char buf[32];
385	ssize_t len;
386
387	len = min(count, sizeof(buf) - 1);
388	if (copy_from_user(buf, user_buf, len))
389		return -EFAULT;
390
391	buf[len] = '\0';
392	if (kstrtoul(buf, 0, &val))
393		return -EINVAL;
394
395	if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX)
396		return -EINVAL;
397
398	mutex_lock(&ar->conf_mutex);
399	ar->spectral.count = val;
400	mutex_unlock(&ar->conf_mutex);
401
402	return count;
403}
404
405static const struct file_operations fops_scan_count = {
406	.read = ath11k_read_file_spectral_count,
407	.write = ath11k_write_file_spectral_count,
408	.open = simple_open,
409	.owner = THIS_MODULE,
410	.llseek = default_llseek,
411};
412
413static ssize_t ath11k_read_file_spectral_bins(struct file *file,
414					      char __user *user_buf,
415					      size_t count, loff_t *ppos)
416{
417	struct ath11k *ar = file->private_data;
418	char buf[32];
419	unsigned int bins, fft_size;
420	size_t len;
421
422	mutex_lock(&ar->conf_mutex);
423
424	fft_size = ar->spectral.fft_size;
425	bins = 1 << fft_size;
426
427	mutex_unlock(&ar->conf_mutex);
428
429	len = sprintf(buf, "%d\n", bins);
430	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
431}
432
433static ssize_t ath11k_write_file_spectral_bins(struct file *file,
434					       const char __user *user_buf,
435					       size_t count, loff_t *ppos)
436{
437	struct ath11k *ar = file->private_data;
438	unsigned long val;
439	char buf[32];
440	ssize_t len;
441
442	len = min(count, sizeof(buf) - 1);
443	if (copy_from_user(buf, user_buf, len))
444		return -EFAULT;
445
446	buf[len] = '\0';
447	if (kstrtoul(buf, 0, &val))
448		return -EINVAL;
449
450	if (val < ATH11K_SPECTRAL_ATH11K_MIN_BINS ||
451	    val > SPECTRAL_ATH11K_MAX_NUM_BINS)
452		return -EINVAL;
453
454	if (!is_power_of_2(val))
455		return -EINVAL;
456
457	mutex_lock(&ar->conf_mutex);
458	ar->spectral.fft_size = ilog2(val);
459	mutex_unlock(&ar->conf_mutex);
460
461	return count;
462}
463
464static const struct file_operations fops_scan_bins = {
465	.read = ath11k_read_file_spectral_bins,
466	.write = ath11k_write_file_spectral_bins,
467	.open = simple_open,
468	.owner = THIS_MODULE,
469	.llseek = default_llseek,
470};
471
472static int ath11k_spectral_pull_summary(struct ath11k *ar,
473					struct wmi_dma_buf_release_meta_data *meta,
474					struct spectral_summary_fft_report *summary,
475					struct ath11k_spectral_summary_report *report)
476{
477	report->timestamp = __le32_to_cpu(summary->timestamp);
478	report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN,
479					   __le32_to_cpu(summary->info0));
480	report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG,
481					     __le32_to_cpu(summary->info0));
482	report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX,
483				    __le32_to_cpu(summary->info0));
484	report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT,
485					  __le32_to_cpu(summary->info0));
486	report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB,
487				       __le32_to_cpu(summary->info0));
488	report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN,
489				       __le32_to_cpu(summary->info0));
490	report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID,
491					__le32_to_cpu(summary->info0));
492	report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80,
493				      __le32_to_cpu(summary->info0));
494	report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX,
495				     __le32_to_cpu(summary->info2));
496	report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE,
497				     __le32_to_cpu(summary->info2));
498	report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE,
499					__le32_to_cpu(summary->info2));
500
501	memcpy(&report->meta, meta, sizeof(*meta));
502
503	return 0;
504}
505
506static int ath11k_spectral_pull_search(struct ath11k *ar,
507				       struct spectral_search_fft_report *search,
508				       struct ath11k_spectral_search_report *report)
509{
510	report->timestamp = __le32_to_cpu(search->timestamp);
511	report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID,
512					__le32_to_cpu(search->info0));
513	report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM,
514				      __le32_to_cpu(search->info0));
515	report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK,
516					__le32_to_cpu(search->info0));
517	report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
518				     __le32_to_cpu(search->info0));
519	report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX,
520				      __le32_to_cpu(search->info0));
521	report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB,
522					__le32_to_cpu(search->info1));
523	report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB,
524					  __le32_to_cpu(search->info1));
525	report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS,
526					     __le32_to_cpu(search->info2));
527	report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE,
528				     __le32_to_cpu(search->info2));
529	report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB,
530				       __le32_to_cpu(search->info2));
531	report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB,
532				       __le32_to_cpu(search->info2));
533
534	return 0;
535}
536
537static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude,
538				      int bin_len, u8 *bins)
539{
540	int dc_pos;
541	u8 max_exp;
542
543	dc_pos = bin_len / 2;
544
545	/* peak index outside of bins */
546	if (dc_pos <= max_index || -dc_pos >= max_index)
547		return 0;
548
549	for (max_exp = 0; max_exp < 8; max_exp++) {
550		if (bins[dc_pos + max_index] == (max_magnitude >> max_exp))
551			break;
552	}
553
554	/* max_exp not found */
555	if (bins[dc_pos + max_index] != (max_magnitude >> max_exp))
556		return 0;
557
558	return max_exp;
559}
560
561static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz)
562{
563	int i, j;
564
565	i = 0;
566	j = 0;
567	while (i < num_bins) {
568		outbins[i] = inbins[j];
569		i++;
570		j += fft_sz;
571	}
572}
573
574static
575int ath11k_spectral_process_fft(struct ath11k *ar,
576				struct ath11k_spectral_summary_report *summary,
577				void *data,
578				struct fft_sample_ath11k *fft_sample,
579				u32 data_len)
580{
581	struct ath11k_base *ab = ar->ab;
582	struct spectral_search_fft_report *fft_report = data;
583	struct ath11k_spectral_search_report search;
584	struct spectral_tlv *tlv;
585	int tlv_len, bin_len, num_bins;
586	u16 length, freq;
587	u8 chan_width_mhz;
588	int ret;
589
590	lockdep_assert_held(&ar->spectral.lock);
591
592	if (!ab->hw_params.spectral_fft_sz) {
593		ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
594			    ab->hw_rev);
595		return -EINVAL;
596	}
597
598	tlv = (struct spectral_tlv *)data;
599	tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header));
600	/* convert Dword into bytes */
601	tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
602	bin_len = tlv_len - (sizeof(*fft_report) - sizeof(*tlv));
603
604	if (data_len < (bin_len + sizeof(*fft_report))) {
605		ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n",
606			    bin_len, data_len);
607		return -EINVAL;
608	}
609
610	num_bins = bin_len / ATH11K_SPECTRAL_BIN_SIZE;
611	/* Only In-band bins are useful to user for visualize */
612	num_bins >>= 1;
613
614	if (num_bins < ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS ||
615	    num_bins > ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS ||
616	    !is_power_of_2(num_bins)) {
617		ath11k_warn(ab, "Invalid num of bins %d\n", num_bins);
618		return -EINVAL;
619	}
620
621	ret = ath11k_spectral_pull_search(ar, data, &search);
622	if (ret) {
623		ath11k_warn(ab, "failed to pull search report %d\n", ret);
624		return ret;
625	}
626
627	chan_width_mhz = summary->meta.ch_width;
628
629	switch (chan_width_mhz) {
630	case ATH11K_SPECTRAL_20MHZ:
631	case ATH11K_SPECTRAL_40MHZ:
632	case ATH11K_SPECTRAL_80MHZ:
633		fft_sample->chan_width_mhz = chan_width_mhz;
634		break;
635	default:
636		ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
637		return -EINVAL;
638	}
639
640	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins;
641	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K;
642	fft_sample->tlv.length = __cpu_to_be16(length);
643
644	fft_sample->tsf = __cpu_to_be32(search.timestamp);
645	fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag);
646	fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
647					  __le32_to_cpu(fft_report->info0));
648
649	summary->inb_pwr_db >>= 1;
650	fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db);
651	fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]);
652
653	freq = summary->meta.freq1;
654	fft_sample->freq1 = __cpu_to_be16(freq);
655
656	freq = summary->meta.freq2;
657	fft_sample->freq2 = __cpu_to_be16(freq);
658
659	ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
660				  ab->hw_params.spectral_fft_sz);
661
662	fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
663							  search.peak_mag,
664							  num_bins,
665							  fft_sample->data);
666
667	if (ar->spectral.rfs_scan)
668		relay_write(ar->spectral.rfs_scan, fft_sample,
669			    length + sizeof(struct fft_sample_tlv));
670
671	return 0;
672}
673
674static int ath11k_spectral_process_data(struct ath11k *ar,
675					struct ath11k_dbring_data *param)
676{
677	struct ath11k_base *ab = ar->ab;
678	struct spectral_tlv *tlv;
679	struct spectral_summary_fft_report *summary = NULL;
680	struct ath11k_spectral_summary_report summ_rpt;
681	struct fft_sample_ath11k *fft_sample = NULL;
682	u8 *data;
683	u32 data_len, i;
684	u8 sign, tag;
685	int tlv_len, sample_sz;
686	int ret;
687	bool quit = false;
688
689	spin_lock_bh(&ar->spectral.lock);
690
691	if (!ar->spectral.enabled) {
692		ret = -EINVAL;
693		goto unlock;
694	}
695
696	sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS;
697	fft_sample = kmalloc(sample_sz, GFP_ATOMIC);
698	if (!fft_sample) {
699		ret = -ENOBUFS;
700		goto unlock;
701	}
702
703	data = param->data;
704	data_len = param->data_sz;
705	i = 0;
706	while (!quit && (i < data_len)) {
707		if ((i + sizeof(*tlv)) > data_len) {
708			ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n",
709				    i);
710			ret = -EINVAL;
711			goto err;
712		}
713
714		tlv = (struct spectral_tlv *)&data[i];
715		sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN,
716				 __le32_to_cpu(tlv->header));
717		if (sign != ATH11K_SPECTRAL_SIGNATURE) {
718			ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n",
719				    sign, i);
720			ret = -EINVAL;
721			goto err;
722		}
723
724		tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN,
725				    __le32_to_cpu(tlv->header));
726		/* convert Dword into bytes */
727		tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
728		if ((i + sizeof(*tlv) + tlv_len) > data_len) {
729			ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n",
730				    i, tlv_len, data_len);
731			ret = -EINVAL;
732			goto err;
733		}
734
735		tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG,
736				__le32_to_cpu(tlv->header));
737		switch (tag) {
738		case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY:
739			/* HW bug in tlv length of summary report,
740			 * HW report 3 DWORD size but the data payload
741			 * is 4 DWORD size (16 bytes).
742			 * Need to remove this workaround once HW bug fixed
743			 */
744			tlv_len = sizeof(*summary) - sizeof(*tlv);
745
746			if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) {
747				ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
748					    i, tlv_len);
749				ret = -EINVAL;
750				goto err;
751			}
752
753			summary = (struct spectral_summary_fft_report *)tlv;
754			ath11k_spectral_pull_summary(ar, &param->meta,
755						     summary, &summ_rpt);
756			break;
757		case ATH11K_SPECTRAL_TAG_SCAN_SEARCH:
758			if (tlv_len < (sizeof(struct spectral_search_fft_report) -
759				       sizeof(*tlv))) {
760				ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n",
761					    i);
762				ret = -EINVAL;
763				goto err;
764			}
765
766			memset(fft_sample, 0, sample_sz);
767			ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv,
768							  fft_sample,
769							  data_len - i);
770			if (ret) {
771				ath11k_warn(ab, "failed to process spectral fft at bytes %d\n",
772					    i);
773				goto err;
774			}
775			quit = true;
776			break;
777		}
778
779		i += sizeof(*tlv) + tlv_len;
780	}
781
782	ret = 0;
783
784err:
785	kfree(fft_sample);
786unlock:
787	spin_unlock_bh(&ar->spectral.lock);
788	return ret;
789}
790
791static int ath11k_spectral_ring_alloc(struct ath11k *ar,
792				      struct ath11k_dbring_cap *db_cap)
793{
794	struct ath11k_spectral *sp = &ar->spectral;
795	int ret;
796
797	ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring,
798				       0, db_cap->min_elem);
799	if (ret) {
800		ath11k_warn(ar->ab, "failed to setup db ring\n");
801		return ret;
802	}
803
804	ath11k_dbring_set_cfg(ar, &sp->rx_ring,
805			      ATH11K_SPECTRAL_NUM_RESP_PER_EVENT,
806			      ATH11K_SPECTRAL_EVENT_TIMEOUT_MS,
807			      ath11k_spectral_process_data);
808
809	ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap);
810	if (ret) {
811		ath11k_warn(ar->ab, "failed to setup db ring buffer\n");
812		goto srng_cleanup;
813	}
814
815	ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring,
816					  WMI_DIRECT_BUF_SPECTRAL);
817	if (ret) {
818		ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
819		goto buffer_cleanup;
820	}
821
822	return 0;
823
824buffer_cleanup:
825	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
826srng_cleanup:
827	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
828	return ret;
829}
830
831static inline void ath11k_spectral_ring_free(struct ath11k *ar)
832{
833	struct ath11k_spectral *sp = &ar->spectral;
834
835	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
836	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
837}
838
839static inline void ath11k_spectral_debug_unregister(struct ath11k *ar)
840{
841	debugfs_remove(ar->spectral.scan_bins);
842	ar->spectral.scan_bins = NULL;
843
844	debugfs_remove(ar->spectral.scan_count);
845	ar->spectral.scan_count = NULL;
846
847	debugfs_remove(ar->spectral.scan_ctl);
848	ar->spectral.scan_ctl = NULL;
849
850	if (ar->spectral.rfs_scan) {
851		relay_close(ar->spectral.rfs_scan);
852		ar->spectral.rfs_scan = NULL;
853	}
854}
855
856int ath11k_spectral_vif_stop(struct ath11k_vif *arvif)
857{
858	if (!arvif->spectral_enabled)
859		return 0;
860
861	return ath11k_spectral_scan_config(arvif->ar, ATH11K_SPECTRAL_DISABLED);
862}
863
864void ath11k_spectral_reset_buffer(struct ath11k *ar)
865{
866	if (!ar->spectral.enabled)
867		return;
868
869	if (ar->spectral.rfs_scan)
870		relay_reset(ar->spectral.rfs_scan);
871}
872
873void ath11k_spectral_deinit(struct ath11k_base *ab)
874{
875	struct ath11k *ar;
876	struct ath11k_spectral *sp;
877	int i;
878
879	for (i = 0; i <  ab->num_radios; i++) {
880		ar = ab->pdevs[i].ar;
881		sp = &ar->spectral;
882
883		if (!sp->enabled)
884			continue;
885
886		mutex_lock(&ar->conf_mutex);
887		ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
888		mutex_unlock(&ar->conf_mutex);
889
890		spin_lock_bh(&sp->lock);
891		sp->enabled = false;
892		spin_unlock_bh(&sp->lock);
893
894		ath11k_spectral_debug_unregister(ar);
895		ath11k_spectral_ring_free(ar);
896	}
897}
898
899static inline int ath11k_spectral_debug_register(struct ath11k *ar)
900{
901	int ret;
902
903	ar->spectral.rfs_scan = relay_open("spectral_scan",
904					   ar->debug.debugfs_pdev,
905					   ATH11K_SPECTRAL_SUB_BUFF_SIZE,
906					   ATH11K_SPECTRAL_NUM_SUB_BUF,
907					   &rfs_scan_cb, NULL);
908	if (!ar->spectral.rfs_scan) {
909		ath11k_warn(ar->ab, "failed to open relay in pdev %d\n",
910			    ar->pdev_idx);
911		return -EINVAL;
912	}
913
914	ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl",
915						    0600,
916						    ar->debug.debugfs_pdev, ar,
917						    &fops_scan_ctl);
918	if (!ar->spectral.scan_ctl) {
919		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
920			    ar->pdev_idx);
921		ret = -EINVAL;
922		goto debug_unregister;
923	}
924
925	ar->spectral.scan_count = debugfs_create_file("spectral_count",
926						      0600,
927						      ar->debug.debugfs_pdev, ar,
928						      &fops_scan_count);
929	if (!ar->spectral.scan_count) {
930		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
931			    ar->pdev_idx);
932		ret = -EINVAL;
933		goto debug_unregister;
934	}
935
936	ar->spectral.scan_bins = debugfs_create_file("spectral_bins",
937						     0600,
938						     ar->debug.debugfs_pdev, ar,
939						     &fops_scan_bins);
940	if (!ar->spectral.scan_bins) {
941		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
942			    ar->pdev_idx);
943		ret = -EINVAL;
944		goto debug_unregister;
945	}
946
947	return 0;
948
949debug_unregister:
950	ath11k_spectral_debug_unregister(ar);
951	return ret;
952}
953
954int ath11k_spectral_init(struct ath11k_base *ab)
955{
956	struct ath11k *ar;
957	struct ath11k_spectral *sp;
958	struct ath11k_dbring_cap db_cap;
959	int ret;
960	int i;
961
962	if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA,
963		      ab->wmi_ab.svc_map))
964		return 0;
965
966	if (!ab->hw_params.spectral_fft_sz)
967		return 0;
968
969	for (i = 0; i < ab->num_radios; i++) {
970		ar = ab->pdevs[i].ar;
971		sp = &ar->spectral;
972
973		ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
974					    WMI_DIRECT_BUF_SPECTRAL,
975					    &db_cap);
976		if (ret)
977			continue;
978
979		idr_init(&sp->rx_ring.bufs_idr);
980		spin_lock_init(&sp->rx_ring.idr_lock);
981		spin_lock_init(&sp->lock);
982
983		ret = ath11k_spectral_ring_alloc(ar, &db_cap);
984		if (ret) {
985			ath11k_warn(ab, "failed to init spectral ring for pdev %d\n",
986				    i);
987			goto deinit;
988		}
989
990		spin_lock_bh(&sp->lock);
991
992		sp->mode = ATH11K_SPECTRAL_DISABLED;
993		sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
994		sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT;
995		sp->enabled = true;
996
997		spin_unlock_bh(&sp->lock);
998
999		ret = ath11k_spectral_debug_register(ar);
1000		if (ret) {
1001			ath11k_warn(ab, "failed to register spectral for pdev %d\n",
1002				    i);
1003			goto deinit;
1004		}
1005	}
1006
1007	return 0;
1008
1009deinit:
1010	ath11k_spectral_deinit(ab);
1011	return ret;
1012}
1013
1014enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar)
1015{
1016	if (ar->spectral.enabled)
1017		return ar->spectral.mode;
1018	else
1019		return ATH11K_SPECTRAL_DISABLED;
1020}
1021
1022struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar)
1023{
1024	if (ar->spectral.enabled)
1025		return &ar->spectral.rx_ring;
1026	else
1027		return NULL;
1028}
1029