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