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  
61  struct spectral_tlv {
62  	__le32 timestamp;
63  	__le32 header;
64  } __packed;
65  
66  struct 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  
75  struct 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  
105  struct 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  
115  struct 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  
create_buf_file_handler(const char * filename,struct dentry * parent,umode_t mode,struct rchan_buf * buf,int * is_global)130  static 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  
remove_buf_file_handler(struct dentry * dentry)144  static int remove_buf_file_handler(struct dentry *dentry)
145  {
146  	debugfs_remove(dentry);
147  
148  	return 0;
149  }
150  
151  static const struct rchan_callbacks rfs_scan_cb = {
152  	.create_buf_file = create_buf_file_handler,
153  	.remove_buf_file = remove_buf_file_handler,
154  };
155  
ath11k_spectral_get_vdev(struct ath11k * ar)156  static 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  
ath11k_spectral_scan_trigger(struct ath11k * ar)174  static 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  
ath11k_spectral_scan_config(struct ath11k * ar,enum ath11k_spectral_mode mode)205  static 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  
ath11k_read_file_spec_scan_ctl(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)269  static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file,
270  					      char __user *user_buf,
271  					      size_t count, loff_t *ppos)
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  
ath11k_write_file_spec_scan_ctl(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)298  static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file,
299  					       const char __user *user_buf,
300  					       size_t count, loff_t *ppos)
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  
346  unlock:
347  	mutex_unlock(&ar->conf_mutex);
348  
349  	if (ret)
350  		return ret;
351  
352  	return count;
353  }
354  
355  static const struct file_operations fops_scan_ctl = {
356  	.read = ath11k_read_file_spec_scan_ctl,
357  	.write = ath11k_write_file_spec_scan_ctl,
358  	.open = simple_open,
359  	.owner = THIS_MODULE,
360  	.llseek = default_llseek,
361  };
362  
ath11k_read_file_spectral_count(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)363  static 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  
ath11k_write_file_spectral_count(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)380  static ssize_t ath11k_write_file_spectral_count(struct file *file,
381  						const char __user *user_buf,
382  						size_t count, loff_t *ppos)
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  
402  static 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  
ath11k_read_file_spectral_bins(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)410  static 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  
ath11k_write_file_spectral_bins(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)430  static ssize_t ath11k_write_file_spectral_bins(struct file *file,
431  					       const char __user *user_buf,
432  					       size_t count, loff_t *ppos)
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  
456  static 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  
ath11k_spectral_pull_summary(struct ath11k * ar,struct wmi_dma_buf_release_meta_data * meta,struct spectral_summary_fft_report * summary,struct ath11k_spectral_summary_report * report)464  static int ath11k_spectral_pull_summary(struct ath11k *ar,
465  					struct wmi_dma_buf_release_meta_data *meta,
466  					struct spectral_summary_fft_report *summary,
467  					struct ath11k_spectral_summary_report *report)
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  
ath11k_spectral_pull_search(struct ath11k * ar,struct spectral_search_fft_report * search,struct ath11k_spectral_search_report * report)498  static 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  
ath11k_spectral_get_max_exp(s8 max_index,u8 max_magnitude,int bin_len,u8 * bins)529  static 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  
ath11k_spectral_parse_fft(u8 * outbins,u8 * inbins,int num_bins,u8 fft_sz)553  static 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  
566  static
ath11k_spectral_process_fft(struct ath11k * ar,struct ath11k_spectral_summary_report * summary,void * data,struct fft_sample_ath11k * fft_sample,u32 data_len)567  int 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  
ath11k_spectral_process_data(struct ath11k * ar,struct ath11k_dbring_data * param)694  static 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  
811  err:
812  	kfree(fft_sample);
813  unlock:
814  	spin_unlock_bh(&ar->spectral.lock);
815  	return ret;
816  }
817  
ath11k_spectral_ring_alloc(struct ath11k * ar,struct ath11k_dbring_cap * db_cap)818  static 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  
851  buffer_cleanup:
852  	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
853  srng_cleanup:
854  	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
855  	return ret;
856  }
857  
ath11k_spectral_ring_free(struct ath11k * ar)858  static 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  
ath11k_spectral_debug_unregister(struct ath11k * ar)866  static 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  
ath11k_spectral_vif_stop(struct ath11k_vif * arvif)883  int 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  
ath11k_spectral_reset_buffer(struct ath11k * ar)891  void 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  
ath11k_spectral_deinit(struct ath11k_base * ab)900  void 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  
ath11k_spectral_debug_register(struct ath11k * ar)926  static 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  
976  debug_unregister:
977  	ath11k_spectral_debug_unregister(ar);
978  	return ret;
979  }
980  
ath11k_spectral_init(struct ath11k_base * ab)981  int 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  
1036  deinit:
1037  	ath11k_spectral_deinit(ab);
1038  	return ret;
1039  }
1040  
ath11k_spectral_get_mode(struct ath11k * ar)1041  enum 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  
ath11k_spectral_get_dbring(struct ath11k * ar)1049  struct 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