Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: BSD-3-Clause-Clear
  2/*
  3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  4 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5 */
  6
  7#include <linux/vmalloc.h>
  8#include "core.h"
  9#include "debug.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 10
 11void ath11k_info(struct ath11k_base *ab, const char *fmt, ...)
 12{
 13	struct va_format vaf = {
 14		.fmt = fmt,
 15	};
 16	va_list args;
 17
 18	va_start(args, fmt);
 19	vaf.va = &args;
 20	dev_info(ab->dev, "%pV", &vaf);
 21	trace_ath11k_log_info(ab, &vaf);
 22	va_end(args);
 23}
 24EXPORT_SYMBOL(ath11k_info);
 25
 26void ath11k_err(struct ath11k_base *ab, const char *fmt, ...)
 27{
 28	struct va_format vaf = {
 29		.fmt = fmt,
 30	};
 31	va_list args;
 32
 33	va_start(args, fmt);
 34	vaf.va = &args;
 35	dev_err(ab->dev, "%pV", &vaf);
 36	trace_ath11k_log_err(ab, &vaf);
 37	va_end(args);
 38}
 39EXPORT_SYMBOL(ath11k_err);
 40
 41void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...)
 42{
 43	struct va_format vaf = {
 44		.fmt = fmt,
 45	};
 46	va_list args;
 47
 48	va_start(args, fmt);
 49	vaf.va = &args;
 50	dev_warn_ratelimited(ab->dev, "%pV", &vaf);
 51	trace_ath11k_log_warn(ab, &vaf);
 52	va_end(args);
 53}
 54EXPORT_SYMBOL(ath11k_warn);
 55
 56#ifdef CONFIG_ATH11K_DEBUG
 57
 58void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,
 59		  const char *fmt, ...)
 60{
 61	struct va_format vaf;
 62	va_list args;
 63
 64	va_start(args, fmt);
 65
 66	vaf.fmt = fmt;
 67	vaf.va = &args;
 68
 69	if (ath11k_debug_mask & mask)
 70		dev_printk(KERN_DEBUG, ab->dev, "%s %pV", ath11k_dbg_str(mask), &vaf);
 71
 72	trace_ath11k_log_dbg(ab, mask, &vaf);
 73
 74	va_end(args);
 75}
 76EXPORT_SYMBOL(__ath11k_dbg);
 77
 78void ath11k_dbg_dump(struct ath11k_base *ab,
 79		     enum ath11k_debug_mask mask,
 80		     const char *msg, const char *prefix,
 81		     const void *buf, size_t len)
 82{
 83	char linebuf[256];
 84	size_t linebuflen;
 85	const void *ptr;
 86
 87	if (ath11k_debug_mask & mask) {
 88		if (msg)
 89			__ath11k_dbg(ab, mask, "%s\n", msg);
 90
 91		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
 92			linebuflen = 0;
 93			linebuflen += scnprintf(linebuf + linebuflen,
 94						sizeof(linebuf) - linebuflen,
 95						"%s%08x: ",
 96						(prefix ? prefix : ""),
 97						(unsigned int)(ptr - buf));
 98			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
 99					   linebuf + linebuflen,
100					   sizeof(linebuf) - linebuflen, true);
101			dev_printk(KERN_DEBUG, ab->dev, "%s\n", linebuf);
102		}
103	}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
105	/* tracing code doesn't like null strings */
106	trace_ath11k_log_dbg_dump(ab, msg ? msg : "", prefix ? prefix : "",
107				  buf, len);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108}
109EXPORT_SYMBOL(ath11k_dbg_dump);
110
111#endif /* CONFIG_ATH11K_DEBUG */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v5.9
   1// SPDX-License-Identifier: BSD-3-Clause-Clear
   2/*
   3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 
   4 */
   5
   6#include <linux/vmalloc.h>
   7#include "core.h"
   8#include "debug.h"
   9#include "wmi.h"
  10#include "hal_rx.h"
  11#include "dp_tx.h"
  12#include "debug_htt_stats.h"
  13#include "peer.h"
  14
  15static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
  16	"REO2SW1_RING",
  17	"REO2SW2_RING",
  18	"REO2SW3_RING",
  19	"REO2SW4_RING",
  20	"WBM2REO_LINK_RING",
  21	"REO2TCL_RING",
  22	"REO2FW_RING",
  23	"RELEASE_RING",
  24	"PPE_RELEASE_RING",
  25	"TCL2TQM_RING",
  26	"TQM_RELEASE_RING",
  27	"REO_RELEASE_RING",
  28	"WBM2SW0_RELEASE_RING",
  29	"WBM2SW1_RELEASE_RING",
  30	"WBM2SW2_RELEASE_RING",
  31	"WBM2SW3_RELEASE_RING",
  32	"REO_CMD_RING",
  33	"REO_STATUS_RING",
  34};
  35
  36static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
  37	"FW2RXDMA_BUF_RING",
  38	"FW2RXDMA_STATUS_RING",
  39	"FW2RXDMA_LINK_RING",
  40	"SW2RXDMA_BUF_RING",
  41	"WBM2RXDMA_LINK_RING",
  42	"RXDMA2FW_RING",
  43	"RXDMA2SW_RING",
  44	"RXDMA2RELEASE_RING",
  45	"RXDMA2REO_RING",
  46	"MONITOR_STATUS_RING",
  47	"MONITOR_BUF_RING",
  48	"MONITOR_DESC_RING",
  49	"MONITOR_DEST_RING",
  50};
  51
  52void ath11k_info(struct ath11k_base *ab, const char *fmt, ...)
  53{
  54	struct va_format vaf = {
  55		.fmt = fmt,
  56	};
  57	va_list args;
  58
  59	va_start(args, fmt);
  60	vaf.va = &args;
  61	dev_info(ab->dev, "%pV", &vaf);
  62	/* TODO: Trace the log */
  63	va_end(args);
  64}
 
  65
  66void ath11k_err(struct ath11k_base *ab, const char *fmt, ...)
  67{
  68	struct va_format vaf = {
  69		.fmt = fmt,
  70	};
  71	va_list args;
  72
  73	va_start(args, fmt);
  74	vaf.va = &args;
  75	dev_err(ab->dev, "%pV", &vaf);
  76	/* TODO: Trace the log */
  77	va_end(args);
  78}
 
  79
  80void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...)
  81{
  82	struct va_format vaf = {
  83		.fmt = fmt,
  84	};
  85	va_list args;
  86
  87	va_start(args, fmt);
  88	vaf.va = &args;
  89	dev_warn_ratelimited(ab->dev, "%pV", &vaf);
  90	/* TODO: Trace the log */
  91	va_end(args);
  92}
 
  93
  94#ifdef CONFIG_ATH11K_DEBUG
 
  95void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,
  96		  const char *fmt, ...)
  97{
  98	struct va_format vaf;
  99	va_list args;
 100
 101	va_start(args, fmt);
 102
 103	vaf.fmt = fmt;
 104	vaf.va = &args;
 105
 106	if (ath11k_debug_mask & mask)
 107		dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf);
 108
 109	/* TODO: trace log */
 110
 111	va_end(args);
 112}
 
 113
 114void ath11k_dbg_dump(struct ath11k_base *ab,
 115		     enum ath11k_debug_mask mask,
 116		     const char *msg, const char *prefix,
 117		     const void *buf, size_t len)
 118{
 119	char linebuf[256];
 120	size_t linebuflen;
 121	const void *ptr;
 122
 123	if (ath11k_debug_mask & mask) {
 124		if (msg)
 125			__ath11k_dbg(ab, mask, "%s\n", msg);
 126
 127		for (ptr = buf; (ptr - buf) < len; ptr += 16) {
 128			linebuflen = 0;
 129			linebuflen += scnprintf(linebuf + linebuflen,
 130						sizeof(linebuf) - linebuflen,
 131						"%s%08x: ",
 132						(prefix ? prefix : ""),
 133						(unsigned int)(ptr - buf));
 134			hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
 135					   linebuf + linebuflen,
 136					   sizeof(linebuf) - linebuflen, true);
 137			dev_printk(KERN_DEBUG, ab->dev, "%s\n", linebuf);
 138		}
 139	}
 140}
 141
 142#endif
 143
 144#ifdef CONFIG_ATH11K_DEBUGFS
 145static void ath11k_fw_stats_pdevs_free(struct list_head *head)
 146{
 147	struct ath11k_fw_stats_pdev *i, *tmp;
 148
 149	list_for_each_entry_safe(i, tmp, head, list) {
 150		list_del(&i->list);
 151		kfree(i);
 152	}
 153}
 154
 155static void ath11k_fw_stats_vdevs_free(struct list_head *head)
 156{
 157	struct ath11k_fw_stats_vdev *i, *tmp;
 158
 159	list_for_each_entry_safe(i, tmp, head, list) {
 160		list_del(&i->list);
 161		kfree(i);
 162	}
 163}
 164
 165static void ath11k_fw_stats_bcn_free(struct list_head *head)
 166{
 167	struct ath11k_fw_stats_bcn *i, *tmp;
 168
 169	list_for_each_entry_safe(i, tmp, head, list) {
 170		list_del(&i->list);
 171		kfree(i);
 172	}
 173}
 174
 175static void ath11k_debug_fw_stats_reset(struct ath11k *ar)
 176{
 177	spin_lock_bh(&ar->data_lock);
 178	ar->debug.fw_stats_done = false;
 179	ath11k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
 180	ath11k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
 181	spin_unlock_bh(&ar->data_lock);
 182}
 183
 184void ath11k_debug_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
 185{
 186	struct ath11k_fw_stats stats = {};
 187	struct ath11k *ar;
 188	struct ath11k_pdev *pdev;
 189	bool is_end;
 190	static unsigned int num_vdev, num_bcn;
 191	size_t total_vdevs_started = 0;
 192	int i, ret;
 193
 194	INIT_LIST_HEAD(&stats.pdevs);
 195	INIT_LIST_HEAD(&stats.vdevs);
 196	INIT_LIST_HEAD(&stats.bcn);
 197
 198	ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
 199	if (ret) {
 200		ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
 201		goto free;
 202	}
 203
 204	rcu_read_lock();
 205	ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
 206	if (!ar) {
 207		rcu_read_unlock();
 208		ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
 209			    stats.pdev_id, ret);
 210		goto free;
 211	}
 212
 213	spin_lock_bh(&ar->data_lock);
 214
 215	if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
 216		list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
 217		ar->debug.fw_stats_done = true;
 218		goto complete;
 219	}
 220
 221	if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
 222		if (list_empty(&stats.vdevs)) {
 223			ath11k_warn(ab, "empty vdev stats");
 224			goto complete;
 225		}
 226		/* FW sends all the active VDEV stats irrespective of PDEV,
 227		 * hence limit until the count of all VDEVs started
 228		 */
 229		for (i = 0; i < ab->num_radios; i++) {
 230			pdev = rcu_dereference(ab->pdevs_active[i]);
 231			if (pdev && pdev->ar)
 232				total_vdevs_started += ar->num_started_vdevs;
 233		}
 234
 235		is_end = ((++num_vdev) == total_vdevs_started);
 236
 237		list_splice_tail_init(&stats.vdevs,
 238				      &ar->debug.fw_stats.vdevs);
 239
 240		if (is_end) {
 241			ar->debug.fw_stats_done = true;
 242			num_vdev = 0;
 243		}
 244		goto complete;
 245	}
 246
 247	if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
 248		if (list_empty(&stats.bcn)) {
 249			ath11k_warn(ab, "empty bcn stats");
 250			goto complete;
 251		}
 252		/* Mark end until we reached the count of all started VDEVs
 253		 * within the PDEV
 254		 */
 255		is_end = ((++num_bcn) == ar->num_started_vdevs);
 256
 257		list_splice_tail_init(&stats.bcn,
 258				      &ar->debug.fw_stats.bcn);
 259
 260		if (is_end) {
 261			ar->debug.fw_stats_done = true;
 262			num_bcn = 0;
 263		}
 264	}
 265complete:
 266	complete(&ar->debug.fw_stats_complete);
 267	rcu_read_unlock();
 268	spin_unlock_bh(&ar->data_lock);
 269
 270free:
 271	ath11k_fw_stats_pdevs_free(&stats.pdevs);
 272	ath11k_fw_stats_vdevs_free(&stats.vdevs);
 273	ath11k_fw_stats_bcn_free(&stats.bcn);
 274}
 275
 276static int ath11k_debug_fw_stats_request(struct ath11k *ar,
 277					 struct stats_request_params *req_param)
 278{
 279	struct ath11k_base *ab = ar->ab;
 280	unsigned long timeout, time_left;
 281	int ret;
 282
 283	lockdep_assert_held(&ar->conf_mutex);
 284
 285	/* FW stats can get split when exceeding the stats data buffer limit.
 286	 * In that case, since there is no end marking for the back-to-back
 287	 * received 'update stats' event, we keep a 3 seconds timeout in case,
 288	 * fw_stats_done is not marked yet
 289	 */
 290	timeout = jiffies + msecs_to_jiffies(3 * HZ);
 291
 292	ath11k_debug_fw_stats_reset(ar);
 293
 294	reinit_completion(&ar->debug.fw_stats_complete);
 295
 296	ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
 297
 298	if (ret) {
 299		ath11k_warn(ab, "could not request fw stats (%d)\n",
 300			    ret);
 301		return ret;
 302	}
 303
 304	time_left =
 305	wait_for_completion_timeout(&ar->debug.fw_stats_complete,
 306				    1 * HZ);
 307	if (!time_left)
 308		return -ETIMEDOUT;
 309
 310	for (;;) {
 311		if (time_after(jiffies, timeout))
 312			break;
 313
 314		spin_lock_bh(&ar->data_lock);
 315		if (ar->debug.fw_stats_done) {
 316			spin_unlock_bh(&ar->data_lock);
 317			break;
 318		}
 319		spin_unlock_bh(&ar->data_lock);
 320	}
 321	return 0;
 322}
 323
 324static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
 325{
 326	struct ath11k *ar = inode->i_private;
 327	struct ath11k_base *ab = ar->ab;
 328	struct stats_request_params req_param;
 329	void *buf = NULL;
 330	int ret;
 331
 332	mutex_lock(&ar->conf_mutex);
 333
 334	if (ar->state != ATH11K_STATE_ON) {
 335		ret = -ENETDOWN;
 336		goto err_unlock;
 337	}
 338
 339	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
 340	if (!buf) {
 341		ret = -ENOMEM;
 342		goto err_unlock;
 343	}
 344
 345	req_param.pdev_id = ar->pdev->pdev_id;
 346	req_param.vdev_id = 0;
 347	req_param.stats_id = WMI_REQUEST_PDEV_STAT;
 348
 349	ret = ath11k_debug_fw_stats_request(ar, &req_param);
 350	if (ret) {
 351		ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
 352		goto err_free;
 353	}
 354
 355	ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
 356				 buf);
 357
 358	file->private_data = buf;
 359
 360	mutex_unlock(&ar->conf_mutex);
 361	return 0;
 362
 363err_free:
 364	vfree(buf);
 365
 366err_unlock:
 367	mutex_unlock(&ar->conf_mutex);
 368	return ret;
 369}
 370
 371static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
 372{
 373	vfree(file->private_data);
 374
 375	return 0;
 376}
 377
 378static ssize_t ath11k_read_pdev_stats(struct file *file,
 379				      char __user *user_buf,
 380				      size_t count, loff_t *ppos)
 381{
 382	const char *buf = file->private_data;
 383	size_t len = strlen(buf);
 384
 385	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 386}
 387
 388static const struct file_operations fops_pdev_stats = {
 389	.open = ath11k_open_pdev_stats,
 390	.release = ath11k_release_pdev_stats,
 391	.read = ath11k_read_pdev_stats,
 392	.owner = THIS_MODULE,
 393	.llseek = default_llseek,
 394};
 395
 396static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
 397{
 398	struct ath11k *ar = inode->i_private;
 399	struct stats_request_params req_param;
 400	void *buf = NULL;
 401	int ret;
 402
 403	mutex_lock(&ar->conf_mutex);
 404
 405	if (ar->state != ATH11K_STATE_ON) {
 406		ret = -ENETDOWN;
 407		goto err_unlock;
 408	}
 409
 410	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
 411	if (!buf) {
 412		ret = -ENOMEM;
 413		goto err_unlock;
 414	}
 415
 416	req_param.pdev_id = ar->pdev->pdev_id;
 417	/* VDEV stats is always sent for all active VDEVs from FW */
 418	req_param.vdev_id = 0;
 419	req_param.stats_id = WMI_REQUEST_VDEV_STAT;
 420
 421	ret = ath11k_debug_fw_stats_request(ar, &req_param);
 422	if (ret) {
 423		ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
 424		goto err_free;
 425	}
 426
 427	ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
 428				 buf);
 429
 430	file->private_data = buf;
 431
 432	mutex_unlock(&ar->conf_mutex);
 433	return 0;
 434
 435err_free:
 436	vfree(buf);
 437
 438err_unlock:
 439	mutex_unlock(&ar->conf_mutex);
 440	return ret;
 441}
 442
 443static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
 444{
 445	vfree(file->private_data);
 446
 447	return 0;
 448}
 449
 450static ssize_t ath11k_read_vdev_stats(struct file *file,
 451				      char __user *user_buf,
 452				      size_t count, loff_t *ppos)
 453{
 454	const char *buf = file->private_data;
 455	size_t len = strlen(buf);
 456
 457	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 458}
 459
 460static const struct file_operations fops_vdev_stats = {
 461	.open = ath11k_open_vdev_stats,
 462	.release = ath11k_release_vdev_stats,
 463	.read = ath11k_read_vdev_stats,
 464	.owner = THIS_MODULE,
 465	.llseek = default_llseek,
 466};
 467
 468static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
 469{
 470	struct ath11k *ar = inode->i_private;
 471	struct ath11k_vif *arvif;
 472	struct stats_request_params req_param;
 473	void *buf = NULL;
 474	int ret;
 475
 476	mutex_lock(&ar->conf_mutex);
 477
 478	if (ar->state != ATH11K_STATE_ON) {
 479		ret = -ENETDOWN;
 480		goto err_unlock;
 481	}
 482
 483	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
 484	if (!buf) {
 485		ret = -ENOMEM;
 486		goto err_unlock;
 487	}
 488
 489	req_param.stats_id = WMI_REQUEST_BCN_STAT;
 490	req_param.pdev_id = ar->pdev->pdev_id;
 491
 492	/* loop all active VDEVs for bcn stats */
 493	list_for_each_entry(arvif, &ar->arvifs, list) {
 494		if (!arvif->is_up)
 495			continue;
 496
 497		req_param.vdev_id = arvif->vdev_id;
 498		ret = ath11k_debug_fw_stats_request(ar, &req_param);
 499		if (ret) {
 500			ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
 501			goto err_free;
 502		}
 503	}
 504
 505	ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
 506				 buf);
 507
 508	/* since beacon stats request is looped for all active VDEVs, saved fw
 509	 * stats is not freed for each request until done for all active VDEVs
 510	 */
 511	spin_lock_bh(&ar->data_lock);
 512	ath11k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn);
 513	spin_unlock_bh(&ar->data_lock);
 514
 515	file->private_data = buf;
 516
 517	mutex_unlock(&ar->conf_mutex);
 518	return 0;
 519
 520err_free:
 521	vfree(buf);
 522
 523err_unlock:
 524	mutex_unlock(&ar->conf_mutex);
 525	return ret;
 526}
 527
 528static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
 529{
 530	vfree(file->private_data);
 531
 532	return 0;
 533}
 534
 535static ssize_t ath11k_read_bcn_stats(struct file *file,
 536				     char __user *user_buf,
 537				     size_t count, loff_t *ppos)
 538{
 539	const char *buf = file->private_data;
 540	size_t len = strlen(buf);
 541
 542	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 543}
 544
 545static const struct file_operations fops_bcn_stats = {
 546	.open = ath11k_open_bcn_stats,
 547	.release = ath11k_release_bcn_stats,
 548	.read = ath11k_read_bcn_stats,
 549	.owner = THIS_MODULE,
 550	.llseek = default_llseek,
 551};
 552
 553static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
 554					     char __user *user_buf,
 555					     size_t count, loff_t *ppos)
 556{
 557	const char buf[] =
 558		"To simulate firmware crash write one of the keywords to this file:\n"
 559		"`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
 560		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
 561
 562	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 563}
 564
 565/* Simulate firmware crash:
 566 * 'soft': Call wmi command causing firmware hang. This firmware hang is
 567 * recoverable by warm firmware reset.
 568 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
 569 * vdev id. This is hard firmware crash because it is recoverable only by cold
 570 * firmware reset.
 571 */
 572static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
 573					      const char __user *user_buf,
 574					      size_t count, loff_t *ppos)
 575{
 576	struct ath11k_base *ab = file->private_data;
 577	struct ath11k_pdev *pdev;
 578	struct ath11k *ar = ab->pdevs[0].ar;
 579	char buf[32] = {0};
 580	ssize_t rc;
 581	int i, ret, radioup = 0;
 582
 583	for (i = 0; i < ab->num_radios; i++) {
 584		pdev = &ab->pdevs[i];
 585		ar = pdev->ar;
 586		if (ar && ar->state == ATH11K_STATE_ON) {
 587			radioup = 1;
 588			break;
 589		}
 590	}
 591	/* filter partial writes and invalid commands */
 592	if (*ppos != 0 || count >= sizeof(buf) || count == 0)
 593		return -EINVAL;
 594
 595	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
 596	if (rc < 0)
 597		return rc;
 598
 599	/* drop the possible '\n' from the end */
 600	if (buf[*ppos - 1] == '\n')
 601		buf[*ppos - 1] = '\0';
 602
 603	if (radioup == 0) {
 604		ret = -ENETDOWN;
 605		goto exit;
 606	}
 607
 608	if (!strcmp(buf, "assert")) {
 609		ath11k_info(ab, "simulating firmware assert crash\n");
 610		ret = ath11k_wmi_force_fw_hang_cmd(ar,
 611						   ATH11K_WMI_FW_HANG_ASSERT_TYPE,
 612						   ATH11K_WMI_FW_HANG_DELAY);
 613	} else {
 614		ret = -EINVAL;
 615		goto exit;
 616	}
 617
 618	if (ret) {
 619		ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
 620		goto exit;
 621	}
 622
 623	ret = count;
 624
 625exit:
 626	return ret;
 627}
 
 628
 629static const struct file_operations fops_simulate_fw_crash = {
 630	.read = ath11k_read_simulate_fw_crash,
 631	.write = ath11k_write_simulate_fw_crash,
 632	.open = simple_open,
 633	.owner = THIS_MODULE,
 634	.llseek = default_llseek,
 635};
 636
 637static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
 638						 const char __user *ubuf,
 639						 size_t count, loff_t *ppos)
 640{
 641	struct ath11k *ar = file->private_data;
 642	u32 filter;
 643	int ret;
 644
 645	if (kstrtouint_from_user(ubuf, count, 0, &filter))
 646		return -EINVAL;
 647
 648	mutex_lock(&ar->conf_mutex);
 649
 650	if (ar->state != ATH11K_STATE_ON) {
 651		ret = -ENETDOWN;
 652		goto out;
 653	}
 654
 655	if (filter == ar->debug.extd_tx_stats) {
 656		ret = count;
 657		goto out;
 658	}
 659
 660	ar->debug.extd_tx_stats = filter;
 661	ret = count;
 662
 663out:
 664	mutex_unlock(&ar->conf_mutex);
 665	return ret;
 666}
 667
 668static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
 669						char __user *ubuf,
 670						size_t count, loff_t *ppos)
 671
 672{
 673	char buf[32] = {0};
 674	struct ath11k *ar = file->private_data;
 675	int len = 0;
 676
 677	mutex_lock(&ar->conf_mutex);
 678	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
 679			ar->debug.extd_tx_stats);
 680	mutex_unlock(&ar->conf_mutex);
 681
 682	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
 683}
 684
 685static const struct file_operations fops_extd_tx_stats = {
 686	.read = ath11k_read_enable_extd_tx_stats,
 687	.write = ath11k_write_enable_extd_tx_stats,
 688	.open = simple_open
 689};
 690
 691static ssize_t ath11k_write_extd_rx_stats(struct file *file,
 692					  const char __user *ubuf,
 693					  size_t count, loff_t *ppos)
 694{
 695	struct ath11k *ar = file->private_data;
 696	struct htt_rx_ring_tlv_filter tlv_filter = {0};
 697	u32 enable, rx_filter = 0, ring_id;
 698	int ret;
 699
 700	if (kstrtouint_from_user(ubuf, count, 0, &enable))
 701		return -EINVAL;
 702
 703	mutex_lock(&ar->conf_mutex);
 704
 705	if (ar->state != ATH11K_STATE_ON) {
 706		ret = -ENETDOWN;
 707		goto exit;
 708	}
 709
 710	if (enable > 1) {
 711		ret = -EINVAL;
 712		goto exit;
 713	}
 714
 715	if (enable == ar->debug.extd_rx_stats) {
 716		ret = count;
 717		goto exit;
 718	}
 719
 720	if (enable) {
 721		rx_filter =  HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
 722		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
 723		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
 724		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
 725		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
 726		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
 727
 728		tlv_filter.rx_filter = rx_filter;
 729		tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
 730		tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
 731		tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
 732		tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
 733			HTT_RX_FP_DATA_FILTER_FLASG3;
 734	} else {
 735		tlv_filter = ath11k_mac_mon_status_filter_default;
 736	}
 737
 738	ar->debug.rx_filter = tlv_filter.rx_filter;
 739
 740	ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id;
 741	ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
 742					       HAL_RXDMA_MONITOR_STATUS,
 743					       DP_RX_BUFFER_SIZE, &tlv_filter);
 744
 745	if (ret) {
 746		ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
 747		goto exit;
 748	}
 749
 750	ar->debug.extd_rx_stats = enable;
 751	ret = count;
 752exit:
 753	mutex_unlock(&ar->conf_mutex);
 754	return ret;
 755}
 756
 757static ssize_t ath11k_read_extd_rx_stats(struct file *file,
 758					 char __user *ubuf,
 759					 size_t count, loff_t *ppos)
 760{
 761	struct ath11k *ar = file->private_data;
 762	char buf[32];
 763	int len = 0;
 764
 765	mutex_lock(&ar->conf_mutex);
 766	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
 767			ar->debug.extd_rx_stats);
 768	mutex_unlock(&ar->conf_mutex);
 769
 770	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
 771}
 772
 773static const struct file_operations fops_extd_rx_stats = {
 774	.read = ath11k_read_extd_rx_stats,
 775	.write = ath11k_write_extd_rx_stats,
 776	.open = simple_open,
 777};
 778
 779static int ath11k_fill_bp_stats(struct ath11k_base *ab,
 780				struct ath11k_bp_stats *bp_stats,
 781				char *buf, int len, int size)
 782{
 783	lockdep_assert_held(&ab->base_lock);
 784
 785	len += scnprintf(buf + len, size - len, "count: %u\n",
 786			 bp_stats->count);
 787	len += scnprintf(buf + len, size - len, "hp: %u\n",
 788			 bp_stats->hp);
 789	len += scnprintf(buf + len, size - len, "tp: %u\n",
 790			 bp_stats->tp);
 791	len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
 792			 jiffies_to_msecs(jiffies - bp_stats->jiffies));
 793	return len;
 794}
 795
 796static ssize_t ath11k_debug_dump_soc_ring_bp_stats(struct ath11k_base *ab,
 797						   char *buf, int size)
 798{
 799	struct ath11k_bp_stats *bp_stats;
 800	bool stats_rxd = false;
 801	u8 i, pdev_idx;
 802	int len = 0;
 803
 804	len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
 805	len += scnprintf(buf + len, size - len, "==================\n");
 806
 807	spin_lock_bh(&ab->base_lock);
 808	for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
 809		bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
 810
 811		if (!bp_stats->count)
 812			continue;
 813
 814		len += scnprintf(buf + len, size - len, "Ring: %s\n",
 815				 htt_bp_umac_ring[i]);
 816		len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
 817		stats_rxd = true;
 818	}
 819
 820	for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
 821		for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
 822			bp_stats =
 823				&ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
 824
 825			if (!bp_stats->count)
 826				continue;
 827
 828			len += scnprintf(buf + len, size - len, "Ring: %s\n",
 829					 htt_bp_lmac_ring[i]);
 830			len += scnprintf(buf + len, size - len, "pdev: %d\n",
 831					 pdev_idx);
 832			len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
 833			stats_rxd = true;
 834		}
 835	}
 836	spin_unlock_bh(&ab->base_lock);
 837
 838	if (!stats_rxd)
 839		len += scnprintf(buf + len, size - len,
 840				 "No Ring Backpressure stats received\n\n");
 841
 842	return len;
 843}
 844
 845static ssize_t ath11k_debug_dump_soc_dp_stats(struct file *file,
 846					      char __user *user_buf,
 847					      size_t count, loff_t *ppos)
 848{
 849	struct ath11k_base *ab = file->private_data;
 850	struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
 851	int len = 0, i, retval;
 852	const int size = 4096;
 853	static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
 854			"Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
 855			"Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
 856			"AMSDU parse", "SA timeout", "DA timeout",
 857			"Flow timeout", "Flush req"};
 858	static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
 859			"Desc addr zero", "Desc inval", "AMPDU in non BA",
 860			"Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
 861			"Frame OOR", "BAR OOR", "No BA session",
 862			"Frame SN equal SSN", "PN check fail", "2k err",
 863			"PN err", "Desc blocked"};
 864
 865	char *buf;
 866
 867	buf = kzalloc(size, GFP_KERNEL);
 868	if (!buf)
 869		return -ENOMEM;
 870
 871	len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
 872	len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
 873			 soc_stats->err_ring_pkts);
 874	len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
 875			 soc_stats->invalid_rbm);
 876	len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
 877	for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
 878		len += scnprintf(buf + len, size - len, "%s: %u\n",
 879				 rxdma_err[i], soc_stats->rxdma_error[i]);
 880
 881	len += scnprintf(buf + len, size - len, "\nREO errors:\n");
 882	for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
 883		len += scnprintf(buf + len, size - len, "%s: %u\n",
 884				 reo_err[i], soc_stats->reo_error[i]);
 885
 886	len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
 887	len += scnprintf(buf + len, size - len,
 888			 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
 889			 soc_stats->hal_reo_error[0],
 890			 soc_stats->hal_reo_error[1],
 891			 soc_stats->hal_reo_error[2],
 892			 soc_stats->hal_reo_error[3]);
 893
 894	len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
 895	len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
 896
 897	for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
 898		len += scnprintf(buf + len, size - len, "ring%d: %u\n",
 899				 i, soc_stats->tx_err.desc_na[i]);
 900
 901	len += scnprintf(buf + len, size - len,
 902			 "\nMisc Transmit Failures: %d\n",
 903			 atomic_read(&soc_stats->tx_err.misc_fail));
 904
 905	len += ath11k_debug_dump_soc_ring_bp_stats(ab, buf + len, size - len);
 906
 907	if (len > size)
 908		len = size;
 909	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
 910	kfree(buf);
 911
 912	return retval;
 913}
 914
 915static const struct file_operations fops_soc_dp_stats = {
 916	.read = ath11k_debug_dump_soc_dp_stats,
 917	.open = simple_open,
 918	.owner = THIS_MODULE,
 919	.llseek = default_llseek,
 920};
 921
 922int ath11k_debug_pdev_create(struct ath11k_base *ab)
 923{
 924	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
 925		return 0;
 926
 927	ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
 928
 929	if (IS_ERR_OR_NULL(ab->debugfs_soc)) {
 930		if (IS_ERR(ab->debugfs_soc))
 931			return PTR_ERR(ab->debugfs_soc);
 932		return -ENOMEM;
 933	}
 934
 935	debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
 936			    &fops_simulate_fw_crash);
 937
 938	debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
 939			    &fops_soc_dp_stats);
 940
 941	return 0;
 942}
 943
 944void ath11k_debug_pdev_destroy(struct ath11k_base *ab)
 945{
 946	debugfs_remove_recursive(ab->debugfs_ath11k);
 947	ab->debugfs_ath11k = NULL;
 948}
 949
 950int ath11k_debug_soc_create(struct ath11k_base *ab)
 951{
 952	ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
 953
 954	if (IS_ERR_OR_NULL(ab->debugfs_ath11k)) {
 955		if (IS_ERR(ab->debugfs_ath11k))
 956			return PTR_ERR(ab->debugfs_ath11k);
 957		return -ENOMEM;
 958	}
 959
 960	return 0;
 961}
 962
 963void ath11k_debug_soc_destroy(struct ath11k_base *ab)
 964{
 965	debugfs_remove_recursive(ab->debugfs_soc);
 966	ab->debugfs_soc = NULL;
 967}
 968
 969void ath11k_debug_fw_stats_init(struct ath11k *ar)
 970{
 971	struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
 972							ar->debug.debugfs_pdev);
 973
 974	ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
 975
 976	/* all stats debugfs files created are under "fw_stats" directory
 977	 * created per PDEV
 978	 */
 979	debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
 980			    &fops_pdev_stats);
 981	debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
 982			    &fops_vdev_stats);
 983	debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
 984			    &fops_bcn_stats);
 985
 986	INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
 987	INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
 988	INIT_LIST_HEAD(&ar->debug.fw_stats.bcn);
 989
 990	init_completion(&ar->debug.fw_stats_complete);
 991}
 992
 993static ssize_t ath11k_write_pktlog_filter(struct file *file,
 994					  const char __user *ubuf,
 995					  size_t count, loff_t *ppos)
 996{
 997	struct ath11k *ar = file->private_data;
 998	struct htt_rx_ring_tlv_filter tlv_filter = {0};
 999	u32 rx_filter = 0, ring_id, filter, mode;
1000	u8 buf[128] = {0};
1001	int ret;
1002	ssize_t rc;
1003
1004	mutex_lock(&ar->conf_mutex);
1005	if (ar->state != ATH11K_STATE_ON) {
1006		ret = -ENETDOWN;
1007		goto out;
1008	}
1009
1010	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1011	if (rc < 0) {
1012		ret = rc;
1013		goto out;
1014	}
1015	buf[rc] = '\0';
1016
1017	ret = sscanf(buf, "0x%x %u", &filter, &mode);
1018	if (ret != 2) {
1019		ret = -EINVAL;
1020		goto out;
1021	}
1022
1023	if (filter) {
1024		ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
1025		if (ret) {
1026			ath11k_warn(ar->ab,
1027				    "failed to enable pktlog filter %x: %d\n",
1028				    ar->debug.pktlog_filter, ret);
1029			goto out;
1030		}
1031	} else {
1032		ret = ath11k_wmi_pdev_pktlog_disable(ar);
1033		if (ret) {
1034			ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
1035			goto out;
1036		}
1037	}
1038
1039#define HTT_RX_FILTER_TLV_LITE_MODE \
1040			(HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
1041			HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
1042			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
1043			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
1044			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
1045			HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
1046
1047	if (mode == ATH11K_PKTLOG_MODE_FULL) {
1048		rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
1049			    HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
1050			    HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
1051			    HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
1052			    HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
1053			    HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
1054	} else if (mode == ATH11K_PKTLOG_MODE_LITE) {
1055		ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1056							  HTT_PPDU_STATS_TAG_PKTLOG);
1057		if (ret) {
1058			ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
1059			goto out;
1060		}
1061
1062		rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
1063	} else {
1064		ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1065							  HTT_PPDU_STATS_TAG_DEFAULT);
1066		if (ret) {
1067			ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1068				   ret);
1069			goto out;
1070		}
1071	}
1072
1073	tlv_filter.rx_filter = rx_filter;
1074	if (rx_filter) {
1075		tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
1076		tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
1077		tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
1078		tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1079					       HTT_RX_FP_DATA_FILTER_FLASG3;
1080	}
1081
1082	ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id;
1083	ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
1084					       HAL_RXDMA_MONITOR_STATUS,
1085					       DP_RX_BUFFER_SIZE, &tlv_filter);
1086	if (ret) {
1087		ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
1088		goto out;
1089	}
1090
1091	ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n",
1092		   filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1093
1094	ar->debug.pktlog_filter = filter;
1095	ar->debug.pktlog_mode = mode;
1096	ret = count;
1097
1098out:
1099	mutex_unlock(&ar->conf_mutex);
1100	return ret;
1101}
1102
1103static ssize_t ath11k_read_pktlog_filter(struct file *file,
1104					 char __user *ubuf,
1105					 size_t count, loff_t *ppos)
1106
1107{
1108	char buf[32] = {0};
1109	struct ath11k *ar = file->private_data;
1110	int len = 0;
1111
1112	mutex_lock(&ar->conf_mutex);
1113	len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1114			ar->debug.pktlog_filter,
1115			ar->debug.pktlog_mode);
1116	mutex_unlock(&ar->conf_mutex);
1117
1118	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1119}
1120
1121static const struct file_operations fops_pktlog_filter = {
1122	.read = ath11k_read_pktlog_filter,
1123	.write = ath11k_write_pktlog_filter,
1124	.open = simple_open
1125};
1126
1127static ssize_t ath11k_write_simulate_radar(struct file *file,
1128					   const char __user *user_buf,
1129					   size_t count, loff_t *ppos)
1130{
1131	struct ath11k *ar = file->private_data;
1132	int ret;
1133
1134	ret = ath11k_wmi_simulate_radar(ar);
1135	if (ret)
1136		return ret;
1137
1138	return count;
1139}
1140
1141static const struct file_operations fops_simulate_radar = {
1142	.write = ath11k_write_simulate_radar,
1143	.open = simple_open
1144};
1145
1146int ath11k_debug_register(struct ath11k *ar)
1147{
1148	struct ath11k_base *ab = ar->ab;
1149	char pdev_name[5];
1150	char buf[100] = {0};
1151
1152	snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1153
1154	ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1155
1156	if (IS_ERR_OR_NULL(ar->debug.debugfs_pdev)) {
1157		if (IS_ERR(ar->debug.debugfs_pdev))
1158			return PTR_ERR(ar->debug.debugfs_pdev);
1159
1160		return -ENOMEM;
1161	}
1162
1163	/* Create a symlink under ieee80211/phy* */
1164	snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1165	debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1166
1167	ath11k_debug_htt_stats_init(ar);
1168
1169	ath11k_debug_fw_stats_init(ar);
1170
1171	debugfs_create_file("ext_tx_stats", 0644,
1172			    ar->debug.debugfs_pdev, ar,
1173			    &fops_extd_tx_stats);
1174	debugfs_create_file("ext_rx_stats", 0644,
1175			    ar->debug.debugfs_pdev, ar,
1176			    &fops_extd_rx_stats);
1177	debugfs_create_file("pktlog_filter", 0644,
1178			    ar->debug.debugfs_pdev, ar,
1179			    &fops_pktlog_filter);
1180
1181	if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1182		debugfs_create_file("dfs_simulate_radar", 0200,
1183				    ar->debug.debugfs_pdev, ar,
1184				    &fops_simulate_radar);
1185		debugfs_create_bool("dfs_block_radar_events", 0200,
1186				    ar->debug.debugfs_pdev,
1187				    &ar->dfs_block_radar_events);
1188	}
1189
1190	return 0;
1191}
1192
1193void ath11k_debug_unregister(struct ath11k *ar)
1194{
1195}
1196#endif /* CONFIG_ATH11K_DEBUGFS */