Linux Audio

Check our new training course

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