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