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