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