xref: /linux/drivers/net/wireless/ath/ath11k/spectral.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
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