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