cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

debugfs.c (42656B)


      1// SPDX-License-Identifier: BSD-3-Clause-Clear
      2/*
      3 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/vmalloc.h>
      7
      8#include "debugfs.h"
      9
     10#include "core.h"
     11#include "debug.h"
     12#include "wmi.h"
     13#include "hal_rx.h"
     14#include "dp_tx.h"
     15#include "debugfs_htt_stats.h"
     16#include "peer.h"
     17
     18static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
     19	"REO2SW1_RING",
     20	"REO2SW2_RING",
     21	"REO2SW3_RING",
     22	"REO2SW4_RING",
     23	"WBM2REO_LINK_RING",
     24	"REO2TCL_RING",
     25	"REO2FW_RING",
     26	"RELEASE_RING",
     27	"PPE_RELEASE_RING",
     28	"TCL2TQM_RING",
     29	"TQM_RELEASE_RING",
     30	"REO_RELEASE_RING",
     31	"WBM2SW0_RELEASE_RING",
     32	"WBM2SW1_RELEASE_RING",
     33	"WBM2SW2_RELEASE_RING",
     34	"WBM2SW3_RELEASE_RING",
     35	"REO_CMD_RING",
     36	"REO_STATUS_RING",
     37};
     38
     39static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
     40	"FW2RXDMA_BUF_RING",
     41	"FW2RXDMA_STATUS_RING",
     42	"FW2RXDMA_LINK_RING",
     43	"SW2RXDMA_BUF_RING",
     44	"WBM2RXDMA_LINK_RING",
     45	"RXDMA2FW_RING",
     46	"RXDMA2SW_RING",
     47	"RXDMA2RELEASE_RING",
     48	"RXDMA2REO_RING",
     49	"MONITOR_STATUS_RING",
     50	"MONITOR_BUF_RING",
     51	"MONITOR_DESC_RING",
     52	"MONITOR_DEST_RING",
     53};
     54
     55void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
     56				     enum wmi_direct_buffer_module id,
     57				     enum ath11k_dbg_dbr_event event,
     58				     struct hal_srng *srng)
     59{
     60	struct ath11k_debug_dbr *dbr_debug;
     61	struct ath11k_dbg_dbr_data *dbr_data;
     62	struct ath11k_dbg_dbr_entry *entry;
     63
     64	if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
     65		return;
     66
     67	dbr_debug = ar->debug.dbr_debug[id];
     68	if (!dbr_debug)
     69		return;
     70
     71	if (!dbr_debug->dbr_debug_enabled)
     72		return;
     73
     74	dbr_data = &dbr_debug->dbr_dbg_data;
     75
     76	spin_lock_bh(&dbr_data->lock);
     77
     78	if (dbr_data->entries) {
     79		entry = &dbr_data->entries[dbr_data->dbr_debug_idx];
     80		entry->hp = srng->u.src_ring.hp;
     81		entry->tp = *srng->u.src_ring.tp_addr;
     82		entry->timestamp = jiffies;
     83		entry->event = event;
     84
     85		dbr_data->dbr_debug_idx++;
     86		if (dbr_data->dbr_debug_idx ==
     87		    dbr_data->num_ring_debug_entries)
     88			dbr_data->dbr_debug_idx = 0;
     89	}
     90
     91	spin_unlock_bh(&dbr_data->lock);
     92}
     93
     94static void ath11k_fw_stats_pdevs_free(struct list_head *head)
     95{
     96	struct ath11k_fw_stats_pdev *i, *tmp;
     97
     98	list_for_each_entry_safe(i, tmp, head, list) {
     99		list_del(&i->list);
    100		kfree(i);
    101	}
    102}
    103
    104static void ath11k_fw_stats_vdevs_free(struct list_head *head)
    105{
    106	struct ath11k_fw_stats_vdev *i, *tmp;
    107
    108	list_for_each_entry_safe(i, tmp, head, list) {
    109		list_del(&i->list);
    110		kfree(i);
    111	}
    112}
    113
    114static void ath11k_fw_stats_bcn_free(struct list_head *head)
    115{
    116	struct ath11k_fw_stats_bcn *i, *tmp;
    117
    118	list_for_each_entry_safe(i, tmp, head, list) {
    119		list_del(&i->list);
    120		kfree(i);
    121	}
    122}
    123
    124static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar)
    125{
    126	spin_lock_bh(&ar->data_lock);
    127	ar->debug.fw_stats_done = false;
    128	ath11k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
    129	ath11k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
    130	spin_unlock_bh(&ar->data_lock);
    131}
    132
    133void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb)
    134{
    135	struct ath11k_fw_stats stats = {};
    136	struct ath11k *ar;
    137	struct ath11k_pdev *pdev;
    138	bool is_end;
    139	static unsigned int num_vdev, num_bcn;
    140	size_t total_vdevs_started = 0;
    141	int i, ret;
    142
    143	INIT_LIST_HEAD(&stats.pdevs);
    144	INIT_LIST_HEAD(&stats.vdevs);
    145	INIT_LIST_HEAD(&stats.bcn);
    146
    147	ret = ath11k_wmi_pull_fw_stats(ab, skb, &stats);
    148	if (ret) {
    149		ath11k_warn(ab, "failed to pull fw stats: %d\n", ret);
    150		goto free;
    151	}
    152
    153	rcu_read_lock();
    154	ar = ath11k_mac_get_ar_by_pdev_id(ab, stats.pdev_id);
    155	if (!ar) {
    156		rcu_read_unlock();
    157		ath11k_warn(ab, "failed to get ar for pdev_id %d: %d\n",
    158			    stats.pdev_id, ret);
    159		goto free;
    160	}
    161
    162	spin_lock_bh(&ar->data_lock);
    163
    164	if (stats.stats_id == WMI_REQUEST_PDEV_STAT) {
    165		list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
    166		ar->debug.fw_stats_done = true;
    167		goto complete;
    168	}
    169
    170	if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
    171		ar->debug.fw_stats_done = true;
    172		goto complete;
    173	}
    174
    175	if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
    176		if (list_empty(&stats.vdevs)) {
    177			ath11k_warn(ab, "empty vdev stats");
    178			goto complete;
    179		}
    180		/* FW sends all the active VDEV stats irrespective of PDEV,
    181		 * hence limit until the count of all VDEVs started
    182		 */
    183		for (i = 0; i < ab->num_radios; i++) {
    184			pdev = rcu_dereference(ab->pdevs_active[i]);
    185			if (pdev && pdev->ar)
    186				total_vdevs_started += ar->num_started_vdevs;
    187		}
    188
    189		is_end = ((++num_vdev) == total_vdevs_started);
    190
    191		list_splice_tail_init(&stats.vdevs,
    192				      &ar->debug.fw_stats.vdevs);
    193
    194		if (is_end) {
    195			ar->debug.fw_stats_done = true;
    196			num_vdev = 0;
    197		}
    198		goto complete;
    199	}
    200
    201	if (stats.stats_id == WMI_REQUEST_BCN_STAT) {
    202		if (list_empty(&stats.bcn)) {
    203			ath11k_warn(ab, "empty bcn stats");
    204			goto complete;
    205		}
    206		/* Mark end until we reached the count of all started VDEVs
    207		 * within the PDEV
    208		 */
    209		is_end = ((++num_bcn) == ar->num_started_vdevs);
    210
    211		list_splice_tail_init(&stats.bcn,
    212				      &ar->debug.fw_stats.bcn);
    213
    214		if (is_end) {
    215			ar->debug.fw_stats_done = true;
    216			num_bcn = 0;
    217		}
    218	}
    219complete:
    220	complete(&ar->debug.fw_stats_complete);
    221	rcu_read_unlock();
    222	spin_unlock_bh(&ar->data_lock);
    223
    224free:
    225	ath11k_fw_stats_pdevs_free(&stats.pdevs);
    226	ath11k_fw_stats_vdevs_free(&stats.vdevs);
    227	ath11k_fw_stats_bcn_free(&stats.bcn);
    228}
    229
    230static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
    231					   struct stats_request_params *req_param)
    232{
    233	struct ath11k_base *ab = ar->ab;
    234	unsigned long timeout, time_left;
    235	int ret;
    236
    237	lockdep_assert_held(&ar->conf_mutex);
    238
    239	/* FW stats can get split when exceeding the stats data buffer limit.
    240	 * In that case, since there is no end marking for the back-to-back
    241	 * received 'update stats' event, we keep a 3 seconds timeout in case,
    242	 * fw_stats_done is not marked yet
    243	 */
    244	timeout = jiffies + msecs_to_jiffies(3 * 1000);
    245
    246	ath11k_debugfs_fw_stats_reset(ar);
    247
    248	reinit_completion(&ar->debug.fw_stats_complete);
    249
    250	ret = ath11k_wmi_send_stats_request_cmd(ar, req_param);
    251
    252	if (ret) {
    253		ath11k_warn(ab, "could not request fw stats (%d)\n",
    254			    ret);
    255		return ret;
    256	}
    257
    258	time_left =
    259	wait_for_completion_timeout(&ar->debug.fw_stats_complete,
    260				    1 * HZ);
    261	if (!time_left)
    262		return -ETIMEDOUT;
    263
    264	for (;;) {
    265		if (time_after(jiffies, timeout))
    266			break;
    267
    268		spin_lock_bh(&ar->data_lock);
    269		if (ar->debug.fw_stats_done) {
    270			spin_unlock_bh(&ar->data_lock);
    271			break;
    272		}
    273		spin_unlock_bh(&ar->data_lock);
    274	}
    275	return 0;
    276}
    277
    278int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
    279				u32 vdev_id, u32 stats_id)
    280{
    281	struct ath11k_base *ab = ar->ab;
    282	struct stats_request_params req_param;
    283	int ret;
    284
    285	mutex_lock(&ar->conf_mutex);
    286
    287	if (ar->state != ATH11K_STATE_ON) {
    288		ret = -ENETDOWN;
    289		goto err_unlock;
    290	}
    291
    292	req_param.pdev_id = pdev_id;
    293	req_param.vdev_id = vdev_id;
    294	req_param.stats_id = stats_id;
    295
    296	ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
    297	if (ret)
    298		ath11k_warn(ab, "failed to request fw stats: %d\n", ret);
    299
    300	ath11k_dbg(ab, ATH11K_DBG_WMI,
    301		   "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
    302		   pdev_id, vdev_id, stats_id);
    303
    304err_unlock:
    305	mutex_unlock(&ar->conf_mutex);
    306
    307	return ret;
    308}
    309
    310static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
    311{
    312	struct ath11k *ar = inode->i_private;
    313	struct ath11k_base *ab = ar->ab;
    314	struct stats_request_params req_param;
    315	void *buf = NULL;
    316	int ret;
    317
    318	mutex_lock(&ar->conf_mutex);
    319
    320	if (ar->state != ATH11K_STATE_ON) {
    321		ret = -ENETDOWN;
    322		goto err_unlock;
    323	}
    324
    325	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
    326	if (!buf) {
    327		ret = -ENOMEM;
    328		goto err_unlock;
    329	}
    330
    331	req_param.pdev_id = ar->pdev->pdev_id;
    332	req_param.vdev_id = 0;
    333	req_param.stats_id = WMI_REQUEST_PDEV_STAT;
    334
    335	ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
    336	if (ret) {
    337		ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
    338		goto err_free;
    339	}
    340
    341	ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
    342				 buf);
    343
    344	file->private_data = buf;
    345
    346	mutex_unlock(&ar->conf_mutex);
    347	return 0;
    348
    349err_free:
    350	vfree(buf);
    351
    352err_unlock:
    353	mutex_unlock(&ar->conf_mutex);
    354	return ret;
    355}
    356
    357static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
    358{
    359	vfree(file->private_data);
    360
    361	return 0;
    362}
    363
    364static ssize_t ath11k_read_pdev_stats(struct file *file,
    365				      char __user *user_buf,
    366				      size_t count, loff_t *ppos)
    367{
    368	const char *buf = file->private_data;
    369	size_t len = strlen(buf);
    370
    371	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    372}
    373
    374static const struct file_operations fops_pdev_stats = {
    375	.open = ath11k_open_pdev_stats,
    376	.release = ath11k_release_pdev_stats,
    377	.read = ath11k_read_pdev_stats,
    378	.owner = THIS_MODULE,
    379	.llseek = default_llseek,
    380};
    381
    382static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
    383{
    384	struct ath11k *ar = inode->i_private;
    385	struct stats_request_params req_param;
    386	void *buf = NULL;
    387	int ret;
    388
    389	mutex_lock(&ar->conf_mutex);
    390
    391	if (ar->state != ATH11K_STATE_ON) {
    392		ret = -ENETDOWN;
    393		goto err_unlock;
    394	}
    395
    396	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
    397	if (!buf) {
    398		ret = -ENOMEM;
    399		goto err_unlock;
    400	}
    401
    402	req_param.pdev_id = ar->pdev->pdev_id;
    403	/* VDEV stats is always sent for all active VDEVs from FW */
    404	req_param.vdev_id = 0;
    405	req_param.stats_id = WMI_REQUEST_VDEV_STAT;
    406
    407	ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
    408	if (ret) {
    409		ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
    410		goto err_free;
    411	}
    412
    413	ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
    414				 buf);
    415
    416	file->private_data = buf;
    417
    418	mutex_unlock(&ar->conf_mutex);
    419	return 0;
    420
    421err_free:
    422	vfree(buf);
    423
    424err_unlock:
    425	mutex_unlock(&ar->conf_mutex);
    426	return ret;
    427}
    428
    429static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
    430{
    431	vfree(file->private_data);
    432
    433	return 0;
    434}
    435
    436static ssize_t ath11k_read_vdev_stats(struct file *file,
    437				      char __user *user_buf,
    438				      size_t count, loff_t *ppos)
    439{
    440	const char *buf = file->private_data;
    441	size_t len = strlen(buf);
    442
    443	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    444}
    445
    446static const struct file_operations fops_vdev_stats = {
    447	.open = ath11k_open_vdev_stats,
    448	.release = ath11k_release_vdev_stats,
    449	.read = ath11k_read_vdev_stats,
    450	.owner = THIS_MODULE,
    451	.llseek = default_llseek,
    452};
    453
    454static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
    455{
    456	struct ath11k *ar = inode->i_private;
    457	struct ath11k_vif *arvif;
    458	struct stats_request_params req_param;
    459	void *buf = NULL;
    460	int ret;
    461
    462	mutex_lock(&ar->conf_mutex);
    463
    464	if (ar->state != ATH11K_STATE_ON) {
    465		ret = -ENETDOWN;
    466		goto err_unlock;
    467	}
    468
    469	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
    470	if (!buf) {
    471		ret = -ENOMEM;
    472		goto err_unlock;
    473	}
    474
    475	req_param.stats_id = WMI_REQUEST_BCN_STAT;
    476	req_param.pdev_id = ar->pdev->pdev_id;
    477
    478	/* loop all active VDEVs for bcn stats */
    479	list_for_each_entry(arvif, &ar->arvifs, list) {
    480		if (!arvif->is_up)
    481			continue;
    482
    483		req_param.vdev_id = arvif->vdev_id;
    484		ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
    485		if (ret) {
    486			ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
    487			goto err_free;
    488		}
    489	}
    490
    491	ath11k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, req_param.stats_id,
    492				 buf);
    493
    494	/* since beacon stats request is looped for all active VDEVs, saved fw
    495	 * stats is not freed for each request until done for all active VDEVs
    496	 */
    497	spin_lock_bh(&ar->data_lock);
    498	ath11k_fw_stats_bcn_free(&ar->debug.fw_stats.bcn);
    499	spin_unlock_bh(&ar->data_lock);
    500
    501	file->private_data = buf;
    502
    503	mutex_unlock(&ar->conf_mutex);
    504	return 0;
    505
    506err_free:
    507	vfree(buf);
    508
    509err_unlock:
    510	mutex_unlock(&ar->conf_mutex);
    511	return ret;
    512}
    513
    514static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
    515{
    516	vfree(file->private_data);
    517
    518	return 0;
    519}
    520
    521static ssize_t ath11k_read_bcn_stats(struct file *file,
    522				     char __user *user_buf,
    523				     size_t count, loff_t *ppos)
    524{
    525	const char *buf = file->private_data;
    526	size_t len = strlen(buf);
    527
    528	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
    529}
    530
    531static const struct file_operations fops_bcn_stats = {
    532	.open = ath11k_open_bcn_stats,
    533	.release = ath11k_release_bcn_stats,
    534	.read = ath11k_read_bcn_stats,
    535	.owner = THIS_MODULE,
    536	.llseek = default_llseek,
    537};
    538
    539static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
    540					     char __user *user_buf,
    541					     size_t count, loff_t *ppos)
    542{
    543	const char buf[] =
    544		"To simulate firmware crash write one of the keywords to this file:\n"
    545		"`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
    546		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
    547
    548	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
    549}
    550
    551/* Simulate firmware crash:
    552 * 'soft': Call wmi command causing firmware hang. This firmware hang is
    553 * recoverable by warm firmware reset.
    554 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
    555 * vdev id. This is hard firmware crash because it is recoverable only by cold
    556 * firmware reset.
    557 */
    558static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
    559					      const char __user *user_buf,
    560					      size_t count, loff_t *ppos)
    561{
    562	struct ath11k_base *ab = file->private_data;
    563	struct ath11k_pdev *pdev;
    564	struct ath11k *ar = ab->pdevs[0].ar;
    565	char buf[32] = {0};
    566	ssize_t rc;
    567	int i, ret, radioup = 0;
    568
    569	for (i = 0; i < ab->num_radios; i++) {
    570		pdev = &ab->pdevs[i];
    571		ar = pdev->ar;
    572		if (ar && ar->state == ATH11K_STATE_ON) {
    573			radioup = 1;
    574			break;
    575		}
    576	}
    577	/* filter partial writes and invalid commands */
    578	if (*ppos != 0 || count >= sizeof(buf) || count == 0)
    579		return -EINVAL;
    580
    581	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
    582	if (rc < 0)
    583		return rc;
    584
    585	/* drop the possible '\n' from the end */
    586	if (buf[*ppos - 1] == '\n')
    587		buf[*ppos - 1] = '\0';
    588
    589	if (radioup == 0) {
    590		ret = -ENETDOWN;
    591		goto exit;
    592	}
    593
    594	if (!strcmp(buf, "assert")) {
    595		ath11k_info(ab, "simulating firmware assert crash\n");
    596		ret = ath11k_wmi_force_fw_hang_cmd(ar,
    597						   ATH11K_WMI_FW_HANG_ASSERT_TYPE,
    598						   ATH11K_WMI_FW_HANG_DELAY);
    599	} else if (!strcmp(buf, "hw-restart")) {
    600		ath11k_info(ab, "user requested hw restart\n");
    601		queue_work(ab->workqueue_aux, &ab->reset_work);
    602		ret = 0;
    603	} else {
    604		ret = -EINVAL;
    605		goto exit;
    606	}
    607
    608	if (ret) {
    609		ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
    610		goto exit;
    611	}
    612
    613	ret = count;
    614
    615exit:
    616	return ret;
    617}
    618
    619static const struct file_operations fops_simulate_fw_crash = {
    620	.read = ath11k_read_simulate_fw_crash,
    621	.write = ath11k_write_simulate_fw_crash,
    622	.open = simple_open,
    623	.owner = THIS_MODULE,
    624	.llseek = default_llseek,
    625};
    626
    627static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
    628						 const char __user *ubuf,
    629						 size_t count, loff_t *ppos)
    630{
    631	struct ath11k *ar = file->private_data;
    632	u32 filter;
    633	int ret;
    634
    635	if (kstrtouint_from_user(ubuf, count, 0, &filter))
    636		return -EINVAL;
    637
    638	mutex_lock(&ar->conf_mutex);
    639
    640	if (ar->state != ATH11K_STATE_ON) {
    641		ret = -ENETDOWN;
    642		goto out;
    643	}
    644
    645	if (filter == ar->debug.extd_tx_stats) {
    646		ret = count;
    647		goto out;
    648	}
    649
    650	ar->debug.extd_tx_stats = filter;
    651	ret = count;
    652
    653out:
    654	mutex_unlock(&ar->conf_mutex);
    655	return ret;
    656}
    657
    658static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
    659						char __user *ubuf,
    660						size_t count, loff_t *ppos)
    661
    662{
    663	char buf[32] = {0};
    664	struct ath11k *ar = file->private_data;
    665	int len = 0;
    666
    667	mutex_lock(&ar->conf_mutex);
    668	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
    669			ar->debug.extd_tx_stats);
    670	mutex_unlock(&ar->conf_mutex);
    671
    672	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
    673}
    674
    675static const struct file_operations fops_extd_tx_stats = {
    676	.read = ath11k_read_enable_extd_tx_stats,
    677	.write = ath11k_write_enable_extd_tx_stats,
    678	.open = simple_open
    679};
    680
    681static ssize_t ath11k_write_extd_rx_stats(struct file *file,
    682					  const char __user *ubuf,
    683					  size_t count, loff_t *ppos)
    684{
    685	struct ath11k *ar = file->private_data;
    686	struct ath11k_base *ab = ar->ab;
    687	struct htt_rx_ring_tlv_filter tlv_filter = {0};
    688	u32 enable, rx_filter = 0, ring_id;
    689	int i;
    690	int ret;
    691
    692	if (kstrtouint_from_user(ubuf, count, 0, &enable))
    693		return -EINVAL;
    694
    695	mutex_lock(&ar->conf_mutex);
    696
    697	if (ar->state != ATH11K_STATE_ON) {
    698		ret = -ENETDOWN;
    699		goto exit;
    700	}
    701
    702	if (enable > 1) {
    703		ret = -EINVAL;
    704		goto exit;
    705	}
    706
    707	if (enable == ar->debug.extd_rx_stats) {
    708		ret = count;
    709		goto exit;
    710	}
    711
    712	if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
    713		ar->debug.extd_rx_stats = enable;
    714		ret = count;
    715		goto exit;
    716	}
    717
    718	if (enable) {
    719		rx_filter =  HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
    720		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
    721		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
    722		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
    723		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
    724		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
    725
    726		tlv_filter.rx_filter = rx_filter;
    727		tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
    728		tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
    729		tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
    730		tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
    731			HTT_RX_FP_DATA_FILTER_FLASG3;
    732	} else {
    733		tlv_filter = ath11k_mac_mon_status_filter_default;
    734	}
    735
    736	ar->debug.rx_filter = tlv_filter.rx_filter;
    737
    738	for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
    739		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
    740		ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
    741						       HAL_RXDMA_MONITOR_STATUS,
    742						       DP_RX_BUFFER_SIZE, &tlv_filter);
    743
    744		if (ret) {
    745			ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
    746			goto exit;
    747		}
    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_debugfs_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_debugfs_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 < ab->hw_params.max_tx_ring; 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_debugfs_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_debugfs_dump_soc_dp_stats,
    917	.open = simple_open,
    918	.owner = THIS_MODULE,
    919	.llseek = default_llseek,
    920};
    921
    922static ssize_t ath11k_write_fw_dbglog(struct file *file,
    923				      const char __user *user_buf,
    924				      size_t count, loff_t *ppos)
    925{
    926	struct ath11k *ar = file->private_data;
    927	char buf[128] = {0};
    928	struct ath11k_fw_dbglog dbglog;
    929	unsigned int param, mod_id_index, is_end;
    930	u64 value;
    931	int ret, num;
    932
    933	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
    934				     user_buf, count);
    935	if (ret <= 0)
    936		return ret;
    937
    938	num = sscanf(buf, "%u %llx %u %u", &param, &value, &mod_id_index, &is_end);
    939
    940	if (num < 2)
    941		return -EINVAL;
    942
    943	mutex_lock(&ar->conf_mutex);
    944	if (param == WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP ||
    945	    param == WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP) {
    946		if (num != 4 || mod_id_index > (MAX_MODULE_ID_BITMAP_WORDS - 1)) {
    947			ret = -EINVAL;
    948			goto out;
    949		}
    950		ar->debug.module_id_bitmap[mod_id_index] = upper_32_bits(value);
    951		if (!is_end) {
    952			ret = count;
    953			goto out;
    954		}
    955	} else {
    956		if (num != 2) {
    957			ret = -EINVAL;
    958			goto out;
    959		}
    960	}
    961
    962	dbglog.param = param;
    963	dbglog.value = lower_32_bits(value);
    964	ret = ath11k_wmi_fw_dbglog_cfg(ar, ar->debug.module_id_bitmap, &dbglog);
    965	if (ret) {
    966		ath11k_warn(ar->ab, "fw dbglog config failed from debugfs: %d\n",
    967			    ret);
    968		goto out;
    969	}
    970
    971	ret = count;
    972
    973out:
    974	mutex_unlock(&ar->conf_mutex);
    975	return ret;
    976}
    977
    978static const struct file_operations fops_fw_dbglog = {
    979	.write = ath11k_write_fw_dbglog,
    980	.open = simple_open,
    981	.owner = THIS_MODULE,
    982	.llseek = default_llseek,
    983};
    984
    985int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
    986{
    987	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
    988		return 0;
    989
    990	ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
    991	if (IS_ERR(ab->debugfs_soc))
    992		return PTR_ERR(ab->debugfs_soc);
    993
    994	debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
    995			    &fops_simulate_fw_crash);
    996
    997	debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
    998			    &fops_soc_dp_stats);
    999
   1000	return 0;
   1001}
   1002
   1003void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
   1004{
   1005	debugfs_remove_recursive(ab->debugfs_soc);
   1006	ab->debugfs_soc = NULL;
   1007}
   1008
   1009int ath11k_debugfs_soc_create(struct ath11k_base *ab)
   1010{
   1011	ab->debugfs_ath11k = debugfs_create_dir("ath11k", NULL);
   1012
   1013	return PTR_ERR_OR_ZERO(ab->debugfs_ath11k);
   1014}
   1015
   1016void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
   1017{
   1018	debugfs_remove_recursive(ab->debugfs_ath11k);
   1019	ab->debugfs_ath11k = NULL;
   1020}
   1021EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
   1022
   1023void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
   1024{
   1025	struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
   1026							ar->debug.debugfs_pdev);
   1027
   1028	ar->debug.fw_stats.debugfs_fwstats = fwstats_dir;
   1029
   1030	/* all stats debugfs files created are under "fw_stats" directory
   1031	 * created per PDEV
   1032	 */
   1033	debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
   1034			    &fops_pdev_stats);
   1035	debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
   1036			    &fops_vdev_stats);
   1037	debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
   1038			    &fops_bcn_stats);
   1039
   1040	INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
   1041	INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
   1042	INIT_LIST_HEAD(&ar->debug.fw_stats.bcn);
   1043
   1044	init_completion(&ar->debug.fw_stats_complete);
   1045}
   1046
   1047static ssize_t ath11k_write_pktlog_filter(struct file *file,
   1048					  const char __user *ubuf,
   1049					  size_t count, loff_t *ppos)
   1050{
   1051	struct ath11k *ar = file->private_data;
   1052	struct ath11k_base *ab = ar->ab;
   1053	struct htt_rx_ring_tlv_filter tlv_filter = {0};
   1054	u32 rx_filter = 0, ring_id, filter, mode;
   1055	u8 buf[128] = {0};
   1056	int i, ret, rx_buf_sz = 0;
   1057	ssize_t rc;
   1058
   1059	mutex_lock(&ar->conf_mutex);
   1060	if (ar->state != ATH11K_STATE_ON) {
   1061		ret = -ENETDOWN;
   1062		goto out;
   1063	}
   1064
   1065	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
   1066	if (rc < 0) {
   1067		ret = rc;
   1068		goto out;
   1069	}
   1070	buf[rc] = '\0';
   1071
   1072	ret = sscanf(buf, "0x%x %u", &filter, &mode);
   1073	if (ret != 2) {
   1074		ret = -EINVAL;
   1075		goto out;
   1076	}
   1077
   1078	if (filter) {
   1079		ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
   1080		if (ret) {
   1081			ath11k_warn(ar->ab,
   1082				    "failed to enable pktlog filter %x: %d\n",
   1083				    ar->debug.pktlog_filter, ret);
   1084			goto out;
   1085		}
   1086	} else {
   1087		ret = ath11k_wmi_pdev_pktlog_disable(ar);
   1088		if (ret) {
   1089			ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
   1090			goto out;
   1091		}
   1092	}
   1093
   1094	/* Clear rx filter set for monitor mode and rx status */
   1095	for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
   1096		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
   1097		ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
   1098						       HAL_RXDMA_MONITOR_STATUS,
   1099						       rx_buf_sz, &tlv_filter);
   1100		if (ret) {
   1101			ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
   1102			goto out;
   1103		}
   1104	}
   1105#define HTT_RX_FILTER_TLV_LITE_MODE \
   1106			(HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
   1107			HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
   1108			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
   1109			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
   1110			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
   1111			HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
   1112
   1113	if (mode == ATH11K_PKTLOG_MODE_FULL) {
   1114		rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
   1115			    HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
   1116			    HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
   1117			    HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
   1118			    HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
   1119			    HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
   1120		rx_buf_sz = DP_RX_BUFFER_SIZE;
   1121	} else if (mode == ATH11K_PKTLOG_MODE_LITE) {
   1122		ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
   1123							  HTT_PPDU_STATS_TAG_PKTLOG);
   1124		if (ret) {
   1125			ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
   1126			goto out;
   1127		}
   1128
   1129		rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
   1130		rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
   1131	} else {
   1132		rx_buf_sz = DP_RX_BUFFER_SIZE;
   1133		tlv_filter = ath11k_mac_mon_status_filter_default;
   1134		rx_filter = tlv_filter.rx_filter;
   1135
   1136		ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
   1137							  HTT_PPDU_STATS_TAG_DEFAULT);
   1138		if (ret) {
   1139			ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
   1140				   ret);
   1141			goto out;
   1142		}
   1143	}
   1144
   1145	tlv_filter.rx_filter = rx_filter;
   1146	if (rx_filter) {
   1147		tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
   1148		tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
   1149		tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
   1150		tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
   1151					       HTT_RX_FP_DATA_FILTER_FLASG3;
   1152	}
   1153
   1154	for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
   1155		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
   1156		ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
   1157						       ar->dp.mac_id + i,
   1158						       HAL_RXDMA_MONITOR_STATUS,
   1159						       rx_buf_sz, &tlv_filter);
   1160
   1161		if (ret) {
   1162			ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
   1163			goto out;
   1164		}
   1165	}
   1166
   1167	ath11k_info(ab, "pktlog mode %s\n",
   1168		    ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
   1169
   1170	ar->debug.pktlog_filter = filter;
   1171	ar->debug.pktlog_mode = mode;
   1172	ret = count;
   1173
   1174out:
   1175	mutex_unlock(&ar->conf_mutex);
   1176	return ret;
   1177}
   1178
   1179static ssize_t ath11k_read_pktlog_filter(struct file *file,
   1180					 char __user *ubuf,
   1181					 size_t count, loff_t *ppos)
   1182
   1183{
   1184	char buf[32] = {0};
   1185	struct ath11k *ar = file->private_data;
   1186	int len = 0;
   1187
   1188	mutex_lock(&ar->conf_mutex);
   1189	len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
   1190			ar->debug.pktlog_filter,
   1191			ar->debug.pktlog_mode);
   1192	mutex_unlock(&ar->conf_mutex);
   1193
   1194	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
   1195}
   1196
   1197static const struct file_operations fops_pktlog_filter = {
   1198	.read = ath11k_read_pktlog_filter,
   1199	.write = ath11k_write_pktlog_filter,
   1200	.open = simple_open
   1201};
   1202
   1203static ssize_t ath11k_write_simulate_radar(struct file *file,
   1204					   const char __user *user_buf,
   1205					   size_t count, loff_t *ppos)
   1206{
   1207	struct ath11k *ar = file->private_data;
   1208	int ret;
   1209
   1210	ret = ath11k_wmi_simulate_radar(ar);
   1211	if (ret)
   1212		return ret;
   1213
   1214	return count;
   1215}
   1216
   1217static const struct file_operations fops_simulate_radar = {
   1218	.write = ath11k_write_simulate_radar,
   1219	.open = simple_open
   1220};
   1221
   1222static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
   1223					     char __user *user_buf,
   1224					     size_t count, loff_t *ppos)
   1225{
   1226	struct ath11k_dbg_dbr_data *dbr_dbg_data = file->private_data;
   1227	static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"};
   1228	int size = ATH11K_DEBUG_DBR_ENTRIES_MAX * 100;
   1229	char *buf;
   1230	int i, ret;
   1231	int len = 0;
   1232
   1233	buf = kzalloc(size, GFP_KERNEL);
   1234	if (!buf)
   1235		return -ENOMEM;
   1236
   1237	len += scnprintf(buf + len, size - len,
   1238			 "-----------------------------------------\n");
   1239	len += scnprintf(buf + len, size - len,
   1240			 "| idx |  hp  |  tp  | timestamp |  event |\n");
   1241	len += scnprintf(buf + len, size - len,
   1242			 "-----------------------------------------\n");
   1243
   1244	spin_lock_bh(&dbr_dbg_data->lock);
   1245
   1246	for (i = 0; i < dbr_dbg_data->num_ring_debug_entries; i++) {
   1247		len += scnprintf(buf + len, size - len,
   1248				 "|%4u|%8u|%8u|%11llu|%8s|\n", i,
   1249				 dbr_dbg_data->entries[i].hp,
   1250				 dbr_dbg_data->entries[i].tp,
   1251				 dbr_dbg_data->entries[i].timestamp,
   1252				 event_id_to_string[dbr_dbg_data->entries[i].event]);
   1253	}
   1254
   1255	spin_unlock_bh(&dbr_dbg_data->lock);
   1256
   1257	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
   1258	kfree(buf);
   1259
   1260	return ret;
   1261}
   1262
   1263static const struct file_operations fops_debug_dump_dbr_entries = {
   1264	.read = ath11k_debug_dump_dbr_entries,
   1265	.open = simple_open,
   1266	.owner = THIS_MODULE,
   1267	.llseek = default_llseek,
   1268};
   1269
   1270static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
   1271{
   1272	struct ath11k_debug_dbr *dbr_debug;
   1273	struct ath11k_dbg_dbr_data *dbr_dbg_data;
   1274
   1275	if (!ar->debug.dbr_debug[dbr_id])
   1276		return;
   1277
   1278	dbr_debug = ar->debug.dbr_debug[dbr_id];
   1279	dbr_dbg_data = &dbr_debug->dbr_dbg_data;
   1280
   1281	debugfs_remove_recursive(dbr_debug->dbr_debugfs);
   1282	kfree(dbr_dbg_data->entries);
   1283	kfree(dbr_debug);
   1284	ar->debug.dbr_debug[dbr_id] = NULL;
   1285}
   1286
   1287static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
   1288{
   1289	struct ath11k_debug_dbr *dbr_debug;
   1290	struct ath11k_dbg_dbr_data *dbr_dbg_data;
   1291	static const char * const dbr_id_to_str[] = {"spectral", "CFR"};
   1292
   1293	if (ar->debug.dbr_debug[dbr_id])
   1294		return 0;
   1295
   1296	ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
   1297					      GFP_KERNEL);
   1298
   1299	if (!ar->debug.dbr_debug[dbr_id])
   1300		return -ENOMEM;
   1301
   1302	dbr_debug = ar->debug.dbr_debug[dbr_id];
   1303	dbr_dbg_data = &dbr_debug->dbr_dbg_data;
   1304
   1305	if (dbr_debug->dbr_debugfs)
   1306		return 0;
   1307
   1308	dbr_debug->dbr_debugfs = debugfs_create_dir(dbr_id_to_str[dbr_id],
   1309						    ar->debug.debugfs_pdev);
   1310	if (IS_ERR_OR_NULL(dbr_debug->dbr_debugfs)) {
   1311		if (IS_ERR(dbr_debug->dbr_debugfs))
   1312			return PTR_ERR(dbr_debug->dbr_debugfs);
   1313		return -ENOMEM;
   1314	}
   1315
   1316	dbr_debug->dbr_debug_enabled = true;
   1317	dbr_dbg_data->num_ring_debug_entries = ATH11K_DEBUG_DBR_ENTRIES_MAX;
   1318	dbr_dbg_data->dbr_debug_idx = 0;
   1319	dbr_dbg_data->entries = kcalloc(ATH11K_DEBUG_DBR_ENTRIES_MAX,
   1320					sizeof(struct ath11k_dbg_dbr_entry),
   1321					GFP_KERNEL);
   1322	if (!dbr_dbg_data->entries)
   1323		return -ENOMEM;
   1324
   1325	spin_lock_init(&dbr_dbg_data->lock);
   1326
   1327	debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
   1328			    dbr_dbg_data, &fops_debug_dump_dbr_entries);
   1329
   1330	return 0;
   1331}
   1332
   1333static ssize_t ath11k_debugfs_write_enable_dbr_dbg(struct file *file,
   1334						   const char __user *ubuf,
   1335						   size_t count, loff_t *ppos)
   1336{
   1337	struct ath11k *ar = file->private_data;
   1338	char buf[32] = {0};
   1339	u32 dbr_id, enable;
   1340	int ret;
   1341
   1342	mutex_lock(&ar->conf_mutex);
   1343
   1344	if (ar->state != ATH11K_STATE_ON) {
   1345		ret = -ENETDOWN;
   1346		goto out;
   1347	}
   1348
   1349	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
   1350	if (ret < 0)
   1351		goto out;
   1352
   1353	buf[ret] = '\0';
   1354	ret = sscanf(buf, "%u %u", &dbr_id, &enable);
   1355	if (ret != 2 || dbr_id > 1 || enable > 1) {
   1356		ret = -EINVAL;
   1357		ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
   1358		goto out;
   1359	}
   1360
   1361	if (enable) {
   1362		ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
   1363		if (ret) {
   1364			ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
   1365				    ret);
   1366			goto out;
   1367		}
   1368	} else {
   1369		ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
   1370	}
   1371
   1372	ret = count;
   1373out:
   1374	mutex_unlock(&ar->conf_mutex);
   1375	return ret;
   1376}
   1377
   1378static const struct file_operations fops_dbr_debug = {
   1379	.write = ath11k_debugfs_write_enable_dbr_dbg,
   1380	.open = simple_open,
   1381	.owner = THIS_MODULE,
   1382	.llseek = default_llseek,
   1383};
   1384
   1385int ath11k_debugfs_register(struct ath11k *ar)
   1386{
   1387	struct ath11k_base *ab = ar->ab;
   1388	char pdev_name[5];
   1389	char buf[100] = {0};
   1390
   1391	snprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
   1392
   1393	ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
   1394	if (IS_ERR(ar->debug.debugfs_pdev))
   1395		return PTR_ERR(ar->debug.debugfs_pdev);
   1396
   1397	/* Create a symlink under ieee80211/phy* */
   1398	snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
   1399	debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
   1400
   1401	ath11k_debugfs_htt_stats_init(ar);
   1402
   1403	ath11k_debugfs_fw_stats_init(ar);
   1404
   1405	debugfs_create_file("ext_tx_stats", 0644,
   1406			    ar->debug.debugfs_pdev, ar,
   1407			    &fops_extd_tx_stats);
   1408	debugfs_create_file("ext_rx_stats", 0644,
   1409			    ar->debug.debugfs_pdev, ar,
   1410			    &fops_extd_rx_stats);
   1411	debugfs_create_file("pktlog_filter", 0644,
   1412			    ar->debug.debugfs_pdev, ar,
   1413			    &fops_pktlog_filter);
   1414	debugfs_create_file("fw_dbglog_config", 0600,
   1415			    ar->debug.debugfs_pdev, ar,
   1416			    &fops_fw_dbglog);
   1417
   1418	if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
   1419		debugfs_create_file("dfs_simulate_radar", 0200,
   1420				    ar->debug.debugfs_pdev, ar,
   1421				    &fops_simulate_radar);
   1422		debugfs_create_bool("dfs_block_radar_events", 0200,
   1423				    ar->debug.debugfs_pdev,
   1424				    &ar->dfs_block_radar_events);
   1425	}
   1426
   1427	if (ab->hw_params.dbr_debug_support)
   1428		debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
   1429				    ar, &fops_dbr_debug);
   1430
   1431	return 0;
   1432}
   1433
   1434void ath11k_debugfs_unregister(struct ath11k *ar)
   1435{
   1436	struct ath11k_debug_dbr *dbr_debug;
   1437	struct ath11k_dbg_dbr_data *dbr_dbg_data;
   1438	int i;
   1439
   1440	for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
   1441		dbr_debug = ar->debug.dbr_debug[i];
   1442		if (!dbr_debug)
   1443			continue;
   1444
   1445		dbr_dbg_data = &dbr_debug->dbr_dbg_data;
   1446		kfree(dbr_dbg_data->entries);
   1447		debugfs_remove_recursive(dbr_debug->dbr_debugfs);
   1448		kfree(dbr_debug);
   1449		ar->debug.dbr_debug[i] = NULL;
   1450	}
   1451}
   1452
   1453static ssize_t ath11k_write_twt_add_dialog(struct file *file,
   1454					   const char __user *ubuf,
   1455					   size_t count, loff_t *ppos)
   1456{
   1457	struct ath11k_vif *arvif = file->private_data;
   1458	struct wmi_twt_add_dialog_params params = { 0 };
   1459	u8 buf[128] = {0};
   1460	int ret;
   1461
   1462	if (arvif->ar->twt_enabled == 0) {
   1463		ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
   1464		return -EOPNOTSUPP;
   1465	}
   1466
   1467	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
   1468	if (ret < 0)
   1469		return ret;
   1470
   1471	buf[ret] = '\0';
   1472	ret = sscanf(buf,
   1473		     "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu",
   1474		     &params.peer_macaddr[0],
   1475		     &params.peer_macaddr[1],
   1476		     &params.peer_macaddr[2],
   1477		     &params.peer_macaddr[3],
   1478		     &params.peer_macaddr[4],
   1479		     &params.peer_macaddr[5],
   1480		     &params.dialog_id,
   1481		     &params.wake_intvl_us,
   1482		     &params.wake_intvl_mantis,
   1483		     &params.wake_dura_us,
   1484		     &params.sp_offset_us,
   1485		     &params.twt_cmd,
   1486		     &params.flag_bcast,
   1487		     &params.flag_trigger,
   1488		     &params.flag_flow_type,
   1489		     &params.flag_protection);
   1490	if (ret != 16)
   1491		return -EINVAL;
   1492
   1493	params.vdev_id = arvif->vdev_id;
   1494
   1495	ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, &params);
   1496	if (ret)
   1497		return ret;
   1498
   1499	return count;
   1500}
   1501
   1502static ssize_t ath11k_write_twt_del_dialog(struct file *file,
   1503					   const char __user *ubuf,
   1504					   size_t count, loff_t *ppos)
   1505{
   1506	struct ath11k_vif *arvif = file->private_data;
   1507	struct wmi_twt_del_dialog_params params = { 0 };
   1508	u8 buf[64] = {0};
   1509	int ret;
   1510
   1511	if (arvif->ar->twt_enabled == 0) {
   1512		ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
   1513		return -EOPNOTSUPP;
   1514	}
   1515
   1516	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
   1517	if (ret < 0)
   1518		return ret;
   1519
   1520	buf[ret] = '\0';
   1521	ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
   1522		     &params.peer_macaddr[0],
   1523		     &params.peer_macaddr[1],
   1524		     &params.peer_macaddr[2],
   1525		     &params.peer_macaddr[3],
   1526		     &params.peer_macaddr[4],
   1527		     &params.peer_macaddr[5],
   1528		     &params.dialog_id);
   1529	if (ret != 7)
   1530		return -EINVAL;
   1531
   1532	params.vdev_id = arvif->vdev_id;
   1533
   1534	ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, &params);
   1535	if (ret)
   1536		return ret;
   1537
   1538	return count;
   1539}
   1540
   1541static ssize_t ath11k_write_twt_pause_dialog(struct file *file,
   1542					     const char __user *ubuf,
   1543					     size_t count, loff_t *ppos)
   1544{
   1545	struct ath11k_vif *arvif = file->private_data;
   1546	struct wmi_twt_pause_dialog_params params = { 0 };
   1547	u8 buf[64] = {0};
   1548	int ret;
   1549
   1550	if (arvif->ar->twt_enabled == 0) {
   1551		ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
   1552		return -EOPNOTSUPP;
   1553	}
   1554
   1555	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
   1556	if (ret < 0)
   1557		return ret;
   1558
   1559	buf[ret] = '\0';
   1560	ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
   1561		     &params.peer_macaddr[0],
   1562		     &params.peer_macaddr[1],
   1563		     &params.peer_macaddr[2],
   1564		     &params.peer_macaddr[3],
   1565		     &params.peer_macaddr[4],
   1566		     &params.peer_macaddr[5],
   1567		     &params.dialog_id);
   1568	if (ret != 7)
   1569		return -EINVAL;
   1570
   1571	params.vdev_id = arvif->vdev_id;
   1572
   1573	ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, &params);
   1574	if (ret)
   1575		return ret;
   1576
   1577	return count;
   1578}
   1579
   1580static ssize_t ath11k_write_twt_resume_dialog(struct file *file,
   1581					      const char __user *ubuf,
   1582					      size_t count, loff_t *ppos)
   1583{
   1584	struct ath11k_vif *arvif = file->private_data;
   1585	struct wmi_twt_resume_dialog_params params = { 0 };
   1586	u8 buf[64] = {0};
   1587	int ret;
   1588
   1589	if (arvif->ar->twt_enabled == 0) {
   1590		ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
   1591		return -EOPNOTSUPP;
   1592	}
   1593
   1594	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
   1595	if (ret < 0)
   1596		return ret;
   1597
   1598	buf[ret] = '\0';
   1599	ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u",
   1600		     &params.peer_macaddr[0],
   1601		     &params.peer_macaddr[1],
   1602		     &params.peer_macaddr[2],
   1603		     &params.peer_macaddr[3],
   1604		     &params.peer_macaddr[4],
   1605		     &params.peer_macaddr[5],
   1606		     &params.dialog_id,
   1607		     &params.sp_offset_us,
   1608		     &params.next_twt_size);
   1609	if (ret != 9)
   1610		return -EINVAL;
   1611
   1612	params.vdev_id = arvif->vdev_id;
   1613
   1614	ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, &params);
   1615	if (ret)
   1616		return ret;
   1617
   1618	return count;
   1619}
   1620
   1621static const struct file_operations ath11k_fops_twt_add_dialog = {
   1622	.write = ath11k_write_twt_add_dialog,
   1623	.open = simple_open
   1624};
   1625
   1626static const struct file_operations ath11k_fops_twt_del_dialog = {
   1627	.write = ath11k_write_twt_del_dialog,
   1628	.open = simple_open
   1629};
   1630
   1631static const struct file_operations ath11k_fops_twt_pause_dialog = {
   1632	.write = ath11k_write_twt_pause_dialog,
   1633	.open = simple_open
   1634};
   1635
   1636static const struct file_operations ath11k_fops_twt_resume_dialog = {
   1637	.write = ath11k_write_twt_resume_dialog,
   1638	.open = simple_open
   1639};
   1640
   1641int ath11k_debugfs_add_interface(struct ath11k_vif *arvif)
   1642{
   1643	if (arvif->vif->type == NL80211_IFTYPE_AP && !arvif->debugfs_twt) {
   1644		arvif->debugfs_twt = debugfs_create_dir("twt",
   1645							arvif->vif->debugfs_dir);
   1646		if (!arvif->debugfs_twt || IS_ERR(arvif->debugfs_twt)) {
   1647			ath11k_warn(arvif->ar->ab,
   1648				    "failed to create directory %p\n",
   1649				    arvif->debugfs_twt);
   1650			arvif->debugfs_twt = NULL;
   1651			return -1;
   1652		}
   1653
   1654		debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt,
   1655				    arvif, &ath11k_fops_twt_add_dialog);
   1656
   1657		debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt,
   1658				    arvif, &ath11k_fops_twt_del_dialog);
   1659
   1660		debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt,
   1661				    arvif, &ath11k_fops_twt_pause_dialog);
   1662
   1663		debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt,
   1664				    arvif, &ath11k_fops_twt_resume_dialog);
   1665	}
   1666	return 0;
   1667}
   1668
   1669void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif)
   1670{
   1671	debugfs_remove_recursive(arvif->debugfs_twt);
   1672	arvif->debugfs_twt = NULL;
   1673}