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