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}
v5.14.15
   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
  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[0];
 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	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
 203static 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	ar->spectral.mode = mode;
 
 218
 219	ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
 220					      ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
 221					      ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE);
 222	if (ret) {
 223		ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret);
 224		return ret;
 225	}
 226
 227	if (mode == ATH11K_SPECTRAL_DISABLED)
 228		return 0;
 229
 230	if (mode == ATH11K_SPECTRAL_BACKGROUND)
 231		count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
 232	else
 233		count = max_t(u16, 1, ar->spectral.count);
 234
 235	param.vdev_id = arvif->vdev_id;
 236	param.scan_count = count;
 237	param.scan_fft_size = ar->spectral.fft_size;
 238	param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT;
 239	param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT;
 240	param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT;
 241	param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT;
 242	param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
 243	param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT;
 244	param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
 245	param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
 246	param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
 247	param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
 248	param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT;
 249	param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
 250	param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT;
 251	param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT;
 252	param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT;
 253	param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT;
 254
 255	ret = ath11k_wmi_vdev_spectral_conf(ar, &param);
 256	if (ret) {
 257		ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret);
 258		return ret;
 259	}
 260
 261	return 0;
 262}
 263
 264static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file,
 265					      char __user *user_buf,
 266					      size_t count, loff_t *ppos)
 267{
 268	struct ath11k *ar = file->private_data;
 269	char *mode = "";
 270	size_t len;
 271	enum ath11k_spectral_mode spectral_mode;
 272
 273	mutex_lock(&ar->conf_mutex);
 274	spectral_mode = ar->spectral.mode;
 275	mutex_unlock(&ar->conf_mutex);
 276
 277	switch (spectral_mode) {
 278	case ATH11K_SPECTRAL_DISABLED:
 279		mode = "disable";
 280		break;
 281	case ATH11K_SPECTRAL_BACKGROUND:
 282		mode = "background";
 283		break;
 284	case ATH11K_SPECTRAL_MANUAL:
 285		mode = "manual";
 286		break;
 287	}
 288
 289	len = strlen(mode);
 290	return simple_read_from_buffer(user_buf, count, ppos, mode, len);
 291}
 292
 293static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file,
 294					       const char __user *user_buf,
 295					       size_t count, loff_t *ppos)
 296{
 297	struct ath11k *ar = file->private_data;
 298	char buf[32];
 299	ssize_t len;
 300	int ret;
 301
 302	len = min(count, sizeof(buf) - 1);
 303	if (copy_from_user(buf, user_buf, len))
 304		return -EFAULT;
 305
 306	buf[len] = '\0';
 307
 308	mutex_lock(&ar->conf_mutex);
 309
 310	if (strncmp("trigger", buf, 7) == 0) {
 311		if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL ||
 312		    ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) {
 313			/* reset the configuration to adopt possibly changed
 314			 * debugfs parameters
 315			 */
 316			ret = ath11k_spectral_scan_config(ar, ar->spectral.mode);
 317			if (ret) {
 318				ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n",
 319					    ret);
 320				goto unlock;
 321			}
 322
 323			ret = ath11k_spectral_scan_trigger(ar);
 324			if (ret) {
 325				ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n",
 326					    ret);
 327			}
 328		} else {
 329			ret = -EINVAL;
 330		}
 331	} else if (strncmp("background", buf, 10) == 0) {
 332		ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND);
 333	} else if (strncmp("manual", buf, 6) == 0) {
 334		ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL);
 335	} else if (strncmp("disable", buf, 7) == 0) {
 336		ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
 337	} else {
 338		ret = -EINVAL;
 339	}
 340
 341unlock:
 342	mutex_unlock(&ar->conf_mutex);
 343
 344	if (ret)
 345		return ret;
 346
 347	return count;
 348}
 349
 350static const struct file_operations fops_scan_ctl = {
 351	.read = ath11k_read_file_spec_scan_ctl,
 352	.write = ath11k_write_file_spec_scan_ctl,
 353	.open = simple_open,
 354	.owner = THIS_MODULE,
 355	.llseek = default_llseek,
 356};
 357
 358static ssize_t ath11k_read_file_spectral_count(struct file *file,
 359					       char __user *user_buf,
 360					       size_t count, loff_t *ppos)
 361{
 362	struct ath11k *ar = file->private_data;
 363	char buf[32];
 364	size_t len;
 365	u16 spectral_count;
 366
 367	mutex_lock(&ar->conf_mutex);
 368	spectral_count = ar->spectral.count;
 369	mutex_unlock(&ar->conf_mutex);
 370
 371	len = sprintf(buf, "%d\n", spectral_count);
 372	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 373}
 374
 375static ssize_t ath11k_write_file_spectral_count(struct file *file,
 376						const char __user *user_buf,
 377						size_t count, loff_t *ppos)
 378{
 379	struct ath11k *ar = file->private_data;
 380	unsigned long val;
 381	char buf[32];
 382	ssize_t len;
 383
 384	len = min(count, sizeof(buf) - 1);
 385	if (copy_from_user(buf, user_buf, len))
 386		return -EFAULT;
 387
 388	buf[len] = '\0';
 389	if (kstrtoul(buf, 0, &val))
 390		return -EINVAL;
 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	char buf[32];
 437	ssize_t len;
 438
 439	len = min(count, sizeof(buf) - 1);
 440	if (copy_from_user(buf, user_buf, len))
 441		return -EFAULT;
 442
 443	buf[len] = '\0';
 444	if (kstrtoul(buf, 0, &val))
 445		return -EINVAL;
 446
 447	if (val < ATH11K_SPECTRAL_ATH11K_MIN_BINS ||
 448	    val > SPECTRAL_ATH11K_MAX_NUM_BINS)
 449		return -EINVAL;
 450
 451	if (!is_power_of_2(val))
 452		return -EINVAL;
 453
 454	mutex_lock(&ar->conf_mutex);
 455	ar->spectral.fft_size = ilog2(val);
 456	mutex_unlock(&ar->conf_mutex);
 457
 458	return count;
 459}
 460
 461static const struct file_operations fops_scan_bins = {
 462	.read = ath11k_read_file_spectral_bins,
 463	.write = ath11k_write_file_spectral_bins,
 464	.open = simple_open,
 465	.owner = THIS_MODULE,
 466	.llseek = default_llseek,
 467};
 468
 469static int ath11k_spectral_pull_summary(struct ath11k *ar,
 470					struct wmi_dma_buf_release_meta_data *meta,
 471					struct spectral_summary_fft_report *summary,
 472					struct ath11k_spectral_summary_report *report)
 473{
 474	report->timestamp = __le32_to_cpu(summary->timestamp);
 475	report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN,
 476					   __le32_to_cpu(summary->info0));
 477	report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG,
 478					     __le32_to_cpu(summary->info0));
 479	report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX,
 480				    __le32_to_cpu(summary->info0));
 481	report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT,
 482					  __le32_to_cpu(summary->info0));
 483	report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB,
 484				       __le32_to_cpu(summary->info0));
 485	report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN,
 486				       __le32_to_cpu(summary->info0));
 487	report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID,
 488					__le32_to_cpu(summary->info0));
 489	report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80,
 490				      __le32_to_cpu(summary->info0));
 491	report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX,
 492				     __le32_to_cpu(summary->info2));
 493	report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE,
 494				     __le32_to_cpu(summary->info2));
 495	report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE,
 496					__le32_to_cpu(summary->info2));
 497
 498	memcpy(&report->meta, meta, sizeof(*meta));
 499
 500	return 0;
 501}
 502
 503static int ath11k_spectral_pull_search(struct ath11k *ar,
 504				       struct spectral_search_fft_report *search,
 505				       struct ath11k_spectral_search_report *report)
 506{
 507	report->timestamp = __le32_to_cpu(search->timestamp);
 508	report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID,
 509					__le32_to_cpu(search->info0));
 510	report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM,
 511				      __le32_to_cpu(search->info0));
 512	report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK,
 513					__le32_to_cpu(search->info0));
 514	report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
 515				     __le32_to_cpu(search->info0));
 516	report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX,
 517				      __le32_to_cpu(search->info0));
 518	report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB,
 519					__le32_to_cpu(search->info1));
 520	report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB,
 521					  __le32_to_cpu(search->info1));
 522	report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS,
 523					     __le32_to_cpu(search->info2));
 524	report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE,
 525				     __le32_to_cpu(search->info2));
 526	report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB,
 527				       __le32_to_cpu(search->info2));
 528	report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB,
 529				       __le32_to_cpu(search->info2));
 530
 531	return 0;
 532}
 533
 534static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude,
 535				      int bin_len, u8 *bins)
 536{
 537	int dc_pos;
 538	u8 max_exp;
 539
 540	dc_pos = bin_len / 2;
 541
 542	/* peak index outside of bins */
 543	if (dc_pos <= max_index || -dc_pos >= max_index)
 544		return 0;
 545
 546	for (max_exp = 0; max_exp < 8; max_exp++) {
 547		if (bins[dc_pos + max_index] == (max_magnitude >> max_exp))
 548			break;
 549	}
 550
 551	/* max_exp not found */
 552	if (bins[dc_pos + max_index] != (max_magnitude >> max_exp))
 553		return 0;
 554
 555	return max_exp;
 556}
 557
 558static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz)
 559{
 560	int i, j;
 561
 562	i = 0;
 563	j = 0;
 564	while (i < num_bins) {
 565		outbins[i] = inbins[j];
 566		i++;
 567		j += fft_sz;
 568	}
 569}
 570
 571static
 572int ath11k_spectral_process_fft(struct ath11k *ar,
 573				struct ath11k_spectral_summary_report *summary,
 574				void *data,
 575				struct fft_sample_ath11k *fft_sample,
 576				u32 data_len)
 577{
 578	struct ath11k_base *ab = ar->ab;
 579	struct spectral_search_fft_report *fft_report = data;
 580	struct ath11k_spectral_search_report search;
 581	struct spectral_tlv *tlv;
 582	int tlv_len, bin_len, num_bins;
 583	u16 length, freq;
 584	u8 chan_width_mhz;
 585	int ret;
 
 
 586
 587	lockdep_assert_held(&ar->spectral.lock);
 588
 589	if (!ab->hw_params.spectral_fft_sz) {
 590		ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
 591			    ab->hw_rev);
 592		return -EINVAL;
 593	}
 594
 595	tlv = (struct spectral_tlv *)data;
 596	tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header));
 597	/* convert Dword into bytes */
 598	tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
 599	bin_len = tlv_len - (sizeof(*fft_report) - sizeof(*tlv));
 600
 601	if (data_len < (bin_len + sizeof(*fft_report))) {
 602		ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n",
 603			    bin_len, data_len);
 604		return -EINVAL;
 605	}
 606
 607	num_bins = bin_len / ATH11K_SPECTRAL_BIN_SIZE;
 
 608	/* Only In-band bins are useful to user for visualize */
 609	num_bins >>= 1;
 610
 611	if (num_bins < ATH11K_SPECTRAL_ATH11K_MIN_IB_BINS ||
 612	    num_bins > ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS ||
 613	    !is_power_of_2(num_bins)) {
 614		ath11k_warn(ab, "Invalid num of bins %d\n", num_bins);
 615		return -EINVAL;
 616	}
 617
 
 
 
 
 
 
 
 618	ret = ath11k_spectral_pull_search(ar, data, &search);
 619	if (ret) {
 620		ath11k_warn(ab, "failed to pull search report %d\n", ret);
 621		return ret;
 622	}
 623
 624	chan_width_mhz = summary->meta.ch_width;
 625
 626	switch (chan_width_mhz) {
 627	case ATH11K_SPECTRAL_20MHZ:
 628	case ATH11K_SPECTRAL_40MHZ:
 629	case ATH11K_SPECTRAL_80MHZ:
 630		fft_sample->chan_width_mhz = chan_width_mhz;
 631		break;
 
 
 
 
 
 
 
 632	default:
 633		ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
 634		return -EINVAL;
 635	}
 636
 637	length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins;
 638	fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K;
 639	fft_sample->tlv.length = __cpu_to_be16(length);
 640
 641	fft_sample->tsf = __cpu_to_be32(search.timestamp);
 642	fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag);
 643	fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
 644					  __le32_to_cpu(fft_report->info0));
 645
 646	summary->inb_pwr_db >>= 1;
 647	fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db);
 648	fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]);
 649
 650	freq = summary->meta.freq1;
 651	fft_sample->freq1 = __cpu_to_be16(freq);
 652
 653	freq = summary->meta.freq2;
 654	fft_sample->freq2 = __cpu_to_be16(freq);
 655
 
 
 
 
 
 
 
 
 
 
 
 656	ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
 657				  ab->hw_params.spectral_fft_sz);
 658
 659	fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
 660							  search.peak_mag,
 661							  num_bins,
 662							  fft_sample->data);
 663
 664	if (ar->spectral.rfs_scan)
 665		relay_write(ar->spectral.rfs_scan, fft_sample,
 666			    length + sizeof(struct fft_sample_tlv));
 667
 668	return 0;
 669}
 670
 671static int ath11k_spectral_process_data(struct ath11k *ar,
 672					struct ath11k_dbring_data *param)
 673{
 674	struct ath11k_base *ab = ar->ab;
 675	struct spectral_tlv *tlv;
 676	struct spectral_summary_fft_report *summary = NULL;
 677	struct ath11k_spectral_summary_report summ_rpt;
 678	struct fft_sample_ath11k *fft_sample = NULL;
 679	u8 *data;
 680	u32 data_len, i;
 681	u8 sign, tag;
 682	int tlv_len, sample_sz;
 683	int ret;
 684	bool quit = false;
 685
 686	spin_lock_bh(&ar->spectral.lock);
 687
 688	if (!ar->spectral.enabled) {
 689		ret = -EINVAL;
 690		goto unlock;
 691	}
 692
 693	sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_ATH11K_MAX_IB_BINS;
 694	fft_sample = kmalloc(sample_sz, GFP_ATOMIC);
 695	if (!fft_sample) {
 696		ret = -ENOBUFS;
 697		goto unlock;
 698	}
 699
 700	data = param->data;
 701	data_len = param->data_sz;
 702	i = 0;
 703	while (!quit && (i < data_len)) {
 704		if ((i + sizeof(*tlv)) > data_len) {
 705			ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n",
 706				    i);
 707			ret = -EINVAL;
 708			goto err;
 709		}
 710
 711		tlv = (struct spectral_tlv *)&data[i];
 712		sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN,
 713				 __le32_to_cpu(tlv->header));
 714		if (sign != ATH11K_SPECTRAL_SIGNATURE) {
 715			ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n",
 716				    sign, i);
 717			ret = -EINVAL;
 718			goto err;
 719		}
 720
 721		tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN,
 722				    __le32_to_cpu(tlv->header));
 723		/* convert Dword into bytes */
 724		tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
 725		if ((i + sizeof(*tlv) + tlv_len) > data_len) {
 726			ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n",
 727				    i, tlv_len, data_len);
 728			ret = -EINVAL;
 729			goto err;
 730		}
 731
 732		tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG,
 733				__le32_to_cpu(tlv->header));
 734		switch (tag) {
 735		case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY:
 736			/* HW bug in tlv length of summary report,
 737			 * HW report 3 DWORD size but the data payload
 738			 * is 4 DWORD size (16 bytes).
 739			 * Need to remove this workaround once HW bug fixed
 740			 */
 741			tlv_len = sizeof(*summary) - sizeof(*tlv);
 
 742
 743			if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) {
 744				ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
 745					    i, tlv_len);
 746				ret = -EINVAL;
 747				goto err;
 748			}
 749
 
 
 
 
 
 
 750			summary = (struct spectral_summary_fft_report *)tlv;
 751			ath11k_spectral_pull_summary(ar, &param->meta,
 752						     summary, &summ_rpt);
 753			break;
 754		case ATH11K_SPECTRAL_TAG_SCAN_SEARCH:
 755			if (tlv_len < (sizeof(struct spectral_search_fft_report) -
 756				       sizeof(*tlv))) {
 757				ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n",
 758					    i);
 759				ret = -EINVAL;
 760				goto err;
 761			}
 762
 763			memset(fft_sample, 0, sample_sz);
 764			ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv,
 765							  fft_sample,
 766							  data_len - i);
 767			if (ret) {
 768				ath11k_warn(ab, "failed to process spectral fft at bytes %d\n",
 769					    i);
 770				goto err;
 771			}
 772			quit = true;
 773			break;
 774		}
 775
 776		i += sizeof(*tlv) + tlv_len;
 777	}
 778
 779	ret = 0;
 780
 781err:
 782	kfree(fft_sample);
 783unlock:
 784	spin_unlock_bh(&ar->spectral.lock);
 785	return ret;
 786}
 787
 788static int ath11k_spectral_ring_alloc(struct ath11k *ar,
 789				      struct ath11k_dbring_cap *db_cap)
 790{
 791	struct ath11k_spectral *sp = &ar->spectral;
 792	int ret;
 793
 794	ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring,
 795				       0, db_cap->min_elem);
 796	if (ret) {
 797		ath11k_warn(ar->ab, "failed to setup db ring\n");
 798		return ret;
 799	}
 800
 801	ath11k_dbring_set_cfg(ar, &sp->rx_ring,
 802			      ATH11K_SPECTRAL_NUM_RESP_PER_EVENT,
 803			      ATH11K_SPECTRAL_EVENT_TIMEOUT_MS,
 804			      ath11k_spectral_process_data);
 805
 806	ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap);
 807	if (ret) {
 808		ath11k_warn(ar->ab, "failed to setup db ring buffer\n");
 809		goto srng_cleanup;
 810	}
 811
 812	ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring,
 813					  WMI_DIRECT_BUF_SPECTRAL);
 814	if (ret) {
 815		ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
 816		goto buffer_cleanup;
 817	}
 818
 819	return 0;
 820
 821buffer_cleanup:
 822	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
 823srng_cleanup:
 824	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
 825	return ret;
 826}
 827
 828static inline void ath11k_spectral_ring_free(struct ath11k *ar)
 829{
 830	struct ath11k_spectral *sp = &ar->spectral;
 831
 832	if (!sp->enabled)
 833		return;
 834
 835	ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
 836	ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
 837}
 838
 839static 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
 856int 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
 864void 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
 873void 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		ath11k_spectral_debug_unregister(ar);
 887		ath11k_spectral_ring_free(ar);
 
 888
 889		spin_lock_bh(&sp->lock);
 890
 891		sp->mode = ATH11K_SPECTRAL_DISABLED;
 892		sp->enabled = false;
 
 893
 894		spin_unlock_bh(&sp->lock);
 
 895	}
 896}
 897
 898static inline int ath11k_spectral_debug_register(struct ath11k *ar)
 899{
 900	int ret;
 901
 902	ar->spectral.rfs_scan = relay_open("spectral_scan",
 903					   ar->debug.debugfs_pdev,
 904					   ATH11K_SPECTRAL_SUB_BUFF_SIZE,
 905					   ATH11K_SPECTRAL_NUM_SUB_BUF,
 906					   &rfs_scan_cb, NULL);
 907	if (!ar->spectral.rfs_scan) {
 908		ath11k_warn(ar->ab, "failed to open relay in pdev %d\n",
 909			    ar->pdev_idx);
 910		return -EINVAL;
 911	}
 912
 913	ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl",
 914						    0600,
 915						    ar->debug.debugfs_pdev, ar,
 916						    &fops_scan_ctl);
 917	if (!ar->spectral.scan_ctl) {
 918		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
 919			    ar->pdev_idx);
 920		ret = -EINVAL;
 921		goto debug_unregister;
 922	}
 923
 924	ar->spectral.scan_count = debugfs_create_file("spectral_count",
 925						      0600,
 926						      ar->debug.debugfs_pdev, ar,
 927						      &fops_scan_count);
 928	if (!ar->spectral.scan_count) {
 929		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
 930			    ar->pdev_idx);
 931		ret = -EINVAL;
 932		goto debug_unregister;
 933	}
 934
 935	ar->spectral.scan_bins = debugfs_create_file("spectral_bins",
 936						     0600,
 937						     ar->debug.debugfs_pdev, ar,
 938						     &fops_scan_bins);
 939	if (!ar->spectral.scan_bins) {
 940		ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
 941			    ar->pdev_idx);
 942		ret = -EINVAL;
 943		goto debug_unregister;
 944	}
 945
 946	return 0;
 947
 948debug_unregister:
 949	ath11k_spectral_debug_unregister(ar);
 950	return ret;
 951}
 952
 953int ath11k_spectral_init(struct ath11k_base *ab)
 954{
 955	struct ath11k *ar;
 956	struct ath11k_spectral *sp;
 957	struct ath11k_dbring_cap db_cap;
 958	int ret;
 959	int i;
 960
 961	if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA,
 962		      ab->wmi_ab.svc_map))
 963		return 0;
 964
 965	if (!ab->hw_params.spectral_fft_sz)
 966		return 0;
 967
 968	for (i = 0; i < ab->num_radios; i++) {
 969		ar = ab->pdevs[i].ar;
 970		sp = &ar->spectral;
 971
 972		ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
 973					    WMI_DIRECT_BUF_SPECTRAL,
 974					    &db_cap);
 975		if (ret)
 976			continue;
 977
 978		idr_init(&sp->rx_ring.bufs_idr);
 979		spin_lock_init(&sp->rx_ring.idr_lock);
 980		spin_lock_init(&sp->lock);
 981
 982		ret = ath11k_spectral_ring_alloc(ar, &db_cap);
 983		if (ret) {
 984			ath11k_warn(ab, "failed to init spectral ring for pdev %d\n",
 985				    i);
 986			goto deinit;
 987		}
 988
 989		spin_lock_bh(&sp->lock);
 990
 991		sp->mode = ATH11K_SPECTRAL_DISABLED;
 992		sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
 993		sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT;
 994		sp->enabled = true;
 995
 996		spin_unlock_bh(&sp->lock);
 997
 998		ret = ath11k_spectral_debug_register(ar);
 999		if (ret) {
1000			ath11k_warn(ab, "failed to register spectral for pdev %d\n",
1001				    i);
1002			goto deinit;
1003		}
1004	}
1005
1006	return 0;
1007
1008deinit:
1009	ath11k_spectral_deinit(ab);
1010	return ret;
1011}
1012
1013enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar)
1014{
1015	if (ar->spectral.enabled)
1016		return ar->spectral.mode;
1017	else
1018		return ATH11K_SPECTRAL_DISABLED;
1019}
1020
1021struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar)
1022{
1023	if (ar->spectral.enabled)
1024		return &ar->spectral.rx_ring;
1025	else
1026		return NULL;
1027}