File Index
Files and directories
Sign in
FILE

debugfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/ath/ath11k/debugfs.c C
   1// SPDX-License-Identifier: BSD-3-Clause-Clear
   2/*
   3 * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
   4 * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
   5 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
   6 */
   7
   8#include <linux/export.h>
   9#include <linux/vmalloc.h>
  10
  11#include "debugfs.h"
  12
  13#include "core.h"
  14#include "debug.h"
  15#include "wmi.h"
  16#include "hal_rx.h"
  17#include "dp_tx.h"
  18#include "debugfs_htt_stats.h"
  19#include "peer.h"
  20#include "hif.h"
  21
  22static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
  23	"REO2SW1_RING",
  24	"REO2SW2_RING",
  25	"REO2SW3_RING",
  26	"REO2SW4_RING",
  27	"WBM2REO_LINK_RING",
  28	"REO2TCL_RING",
  29	"REO2FW_RING",
  30	"RELEASE_RING",
  31	"PPE_RELEASE_RING",
  32	"TCL2TQM_RING",
  33	"TQM_RELEASE_RING",
  34	"REO_RELEASE_RING",
  35	"WBM2SW0_RELEASE_RING",
  36	"WBM2SW1_RELEASE_RING",
  37	"WBM2SW2_RELEASE_RING",
  38	"WBM2SW3_RELEASE_RING",
  39	"REO_CMD_RING",
  40	"REO_STATUS_RING",
  41};
  42
  43static const char *htt_bp_lmac_ring[HTT_SW_LMAC_RING_IDX_MAX] = {
  44	"FW2RXDMA_BUF_RING",
  45	"FW2RXDMA_STATUS_RING",
  46	"FW2RXDMA_LINK_RING",
  47	"SW2RXDMA_BUF_RING",
  48	"WBM2RXDMA_LINK_RING",
  49	"RXDMA2FW_RING",
  50	"RXDMA2SW_RING",
  51	"RXDMA2RELEASE_RING",
  52	"RXDMA2REO_RING",
  53	"MONITOR_STATUS_RING",
  54	"MONITOR_BUF_RING",
  55	"MONITOR_DESC_RING",
  56	"MONITOR_DEST_RING",
  57};
  58
  59void ath11k_debugfs_add_dbring_entry(struct ath11k *ar,
  60				     enum wmi_direct_buffer_module id,
  61				     enum ath11k_dbg_dbr_event event,
  62				     struct hal_srng *srng)
  63{
  64	struct ath11k_debug_dbr *dbr_debug;
  65	struct ath11k_dbg_dbr_data *dbr_data;
  66	struct ath11k_dbg_dbr_entry *entry;
  67
  68	if (id >= WMI_DIRECT_BUF_MAX || event >= ATH11K_DBG_DBR_EVENT_MAX)
  69		return;
  70
  71	dbr_debug = ar->debug.dbr_debug[id];
  72	if (!dbr_debug)
  73		return;
  74
  75	if (!dbr_debug->dbr_debug_enabled)
  76		return;
  77
  78	dbr_data = &dbr_debug->dbr_dbg_data;
  79
  80	spin_lock_bh(&dbr_data->lock);
  81
  82	if (dbr_data->entries) {
  83		entry = &dbr_data->entries[dbr_data->dbr_debug_idx];
  84		entry->hp = srng->u.src_ring.hp;
  85		entry->tp = *srng->u.src_ring.tp_addr;
  86		entry->timestamp = jiffies;
  87		entry->event = event;
  88
  89		dbr_data->dbr_debug_idx++;
  90		if (dbr_data->dbr_debug_idx ==
  91		    dbr_data->num_ring_debug_entries)
  92			dbr_data->dbr_debug_idx = 0;
  93	}
  94
  95	spin_unlock_bh(&dbr_data->lock);
  96}
  97
  98void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats)
  99{
 100	struct ath11k_base *ab = ar->ab;
 101	bool is_end = true;
 102
 103	/* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_RSSI_PER_CHAIN_STAT and
 104	 * WMI_REQUEST_VDEV_STAT requests have been already processed.
 105	 */
 106	if (stats->stats_id == WMI_REQUEST_BCN_STAT) {
 107		if (list_empty(&stats->bcn)) {
 108			ath11k_warn(ab, "empty bcn stats");
 109			return;
 110		}
 111		/* Mark end until we reached the count of all started VDEVs
 112		 * within the PDEV
 113		 */
 114		if (ar->num_started_vdevs)
 115			is_end = ((++ar->fw_stats.num_bcn_recvd) ==
 116				  ar->num_started_vdevs);
 117
 118		list_splice_tail_init(&stats->bcn,
 119				      &ar->fw_stats.bcn);
 120
 121		if (is_end)
 122			complete(&ar->fw_stats_done);
 123	}
 124}
 125
 126static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
 127{
 128	struct ath11k *ar = inode->i_private;
 129	struct ath11k_base *ab = ar->ab;
 130	struct stats_request_params req_param;
 131	void *buf = NULL;
 132	int ret;
 133
 134	mutex_lock(&ar->conf_mutex);
 135
 136	if (ar->state != ATH11K_STATE_ON) {
 137		ret = -ENETDOWN;
 138		goto err_unlock;
 139	}
 140
 141	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
 142	if (!buf) {
 143		ret = -ENOMEM;
 144		goto err_unlock;
 145	}
 146
 147	req_param.pdev_id = ar->pdev->pdev_id;
 148	req_param.vdev_id = 0;
 149	req_param.stats_id = WMI_REQUEST_PDEV_STAT;
 150
 151	ret = ath11k_mac_fw_stats_request(ar, &req_param);
 152	if (ret) {
 153		ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
 154		goto err_free;
 155	}
 156
 157	ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
 158
 159	file->private_data = buf;
 160
 161	mutex_unlock(&ar->conf_mutex);
 162	return 0;
 163
 164err_free:
 165	vfree(buf);
 166
 167err_unlock:
 168	mutex_unlock(&ar->conf_mutex);
 169	return ret;
 170}
 171
 172static int ath11k_release_pdev_stats(struct inode *inode, struct file *file)
 173{
 174	vfree(file->private_data);
 175
 176	return 0;
 177}
 178
 179static ssize_t ath11k_read_pdev_stats(struct file *file,
 180				      char __user *user_buf,
 181				      size_t count, loff_t *ppos)
 182{
 183	const char *buf = file->private_data;
 184	size_t len = strlen(buf);
 185
 186	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 187}
 188
 189static const struct file_operations fops_pdev_stats = {
 190	.open = ath11k_open_pdev_stats,
 191	.release = ath11k_release_pdev_stats,
 192	.read = ath11k_read_pdev_stats,
 193	.owner = THIS_MODULE,
 194	.llseek = default_llseek,
 195};
 196
 197static int ath11k_open_vdev_stats(struct inode *inode, struct file *file)
 198{
 199	struct ath11k *ar = inode->i_private;
 200	struct stats_request_params req_param;
 201	void *buf = NULL;
 202	int ret;
 203
 204	mutex_lock(&ar->conf_mutex);
 205
 206	if (ar->state != ATH11K_STATE_ON) {
 207		ret = -ENETDOWN;
 208		goto err_unlock;
 209	}
 210
 211	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
 212	if (!buf) {
 213		ret = -ENOMEM;
 214		goto err_unlock;
 215	}
 216
 217	req_param.pdev_id = ar->pdev->pdev_id;
 218	/* VDEV stats is always sent for all active VDEVs from FW */
 219	req_param.vdev_id = 0;
 220	req_param.stats_id = WMI_REQUEST_VDEV_STAT;
 221
 222	ret = ath11k_mac_fw_stats_request(ar, &req_param);
 223	if (ret) {
 224		ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
 225		goto err_free;
 226	}
 227
 228	ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
 229
 230	file->private_data = buf;
 231
 232	mutex_unlock(&ar->conf_mutex);
 233	return 0;
 234
 235err_free:
 236	vfree(buf);
 237
 238err_unlock:
 239	mutex_unlock(&ar->conf_mutex);
 240	return ret;
 241}
 242
 243static int ath11k_release_vdev_stats(struct inode *inode, struct file *file)
 244{
 245	vfree(file->private_data);
 246
 247	return 0;
 248}
 249
 250static ssize_t ath11k_read_vdev_stats(struct file *file,
 251				      char __user *user_buf,
 252				      size_t count, loff_t *ppos)
 253{
 254	const char *buf = file->private_data;
 255	size_t len = strlen(buf);
 256
 257	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 258}
 259
 260static const struct file_operations fops_vdev_stats = {
 261	.open = ath11k_open_vdev_stats,
 262	.release = ath11k_release_vdev_stats,
 263	.read = ath11k_read_vdev_stats,
 264	.owner = THIS_MODULE,
 265	.llseek = default_llseek,
 266};
 267
 268static int ath11k_open_bcn_stats(struct inode *inode, struct file *file)
 269{
 270	struct ath11k *ar = inode->i_private;
 271	struct ath11k_vif *arvif;
 272	struct stats_request_params req_param;
 273	void *buf = NULL;
 274	int ret;
 275
 276	mutex_lock(&ar->conf_mutex);
 277
 278	if (ar->state != ATH11K_STATE_ON) {
 279		ret = -ENETDOWN;
 280		goto err_unlock;
 281	}
 282
 283	buf = vmalloc(ATH11K_FW_STATS_BUF_SIZE);
 284	if (!buf) {
 285		ret = -ENOMEM;
 286		goto err_unlock;
 287	}
 288
 289	req_param.stats_id = WMI_REQUEST_BCN_STAT;
 290	req_param.pdev_id = ar->pdev->pdev_id;
 291
 292	/* loop all active VDEVs for bcn stats */
 293	list_for_each_entry(arvif, &ar->arvifs, list) {
 294		if (!arvif->is_up)
 295			continue;
 296
 297		req_param.vdev_id = arvif->vdev_id;
 298		ret = ath11k_mac_fw_stats_request(ar, &req_param);
 299		if (ret) {
 300			ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
 301			goto err_free;
 302		}
 303	}
 304
 305	ath11k_wmi_fw_stats_fill(ar, &ar->fw_stats, req_param.stats_id, buf);
 306
 307	/* since beacon stats request is looped for all active VDEVs, saved fw
 308	 * stats is not freed for each request until done for all active VDEVs
 309	 */
 310	spin_lock_bh(&ar->data_lock);
 311	ath11k_fw_stats_bcn_free(&ar->fw_stats.bcn);
 312	spin_unlock_bh(&ar->data_lock);
 313
 314	file->private_data = buf;
 315
 316	mutex_unlock(&ar->conf_mutex);
 317	return 0;
 318
 319err_free:
 320	vfree(buf);
 321
 322err_unlock:
 323	mutex_unlock(&ar->conf_mutex);
 324	return ret;
 325}
 326
 327static int ath11k_release_bcn_stats(struct inode *inode, struct file *file)
 328{
 329	vfree(file->private_data);
 330
 331	return 0;
 332}
 333
 334static ssize_t ath11k_read_bcn_stats(struct file *file,
 335				     char __user *user_buf,
 336				     size_t count, loff_t *ppos)
 337{
 338	const char *buf = file->private_data;
 339	size_t len = strlen(buf);
 340
 341	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 342}
 343
 344static const struct file_operations fops_bcn_stats = {
 345	.open = ath11k_open_bcn_stats,
 346	.release = ath11k_release_bcn_stats,
 347	.read = ath11k_read_bcn_stats,
 348	.owner = THIS_MODULE,
 349	.llseek = default_llseek,
 350};
 351
 352static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
 353					     char __user *user_buf,
 354					     size_t count, loff_t *ppos)
 355{
 356	const char buf[] =
 357		"To simulate firmware crash write one of the keywords to this file:\n"
 358		"`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
 359		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
 360
 361	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 362}
 363
 364/* Simulate firmware crash:
 365 * 'soft': Call wmi command causing firmware hang. This firmware hang is
 366 * recoverable by warm firmware reset.
 367 * 'hard': Force firmware crash by setting any vdev parameter for not allowed
 368 * vdev id. This is hard firmware crash because it is recoverable only by cold
 369 * firmware reset.
 370 */
 371static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
 372					      const char __user *user_buf,
 373					      size_t count, loff_t *ppos)
 374{
 375	struct ath11k_base *ab = file->private_data;
 376	struct ath11k_pdev *pdev;
 377	struct ath11k *ar = ab->pdevs[0].ar;
 378	char buf[32] = {};
 379	ssize_t rc;
 380	int i, ret, radioup = 0;
 381
 382	for (i = 0; i < ab->num_radios; i++) {
 383		pdev = &ab->pdevs[i];
 384		ar = pdev->ar;
 385		if (ar && ar->state == ATH11K_STATE_ON) {
 386			radioup = 1;
 387			break;
 388		}
 389	}
 390	/* filter partial writes and invalid commands */
 391	if (*ppos != 0 || count >= sizeof(buf) || count == 0)
 392		return -EINVAL;
 393
 394	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
 395	if (rc < 0)
 396		return rc;
 397
 398	/* drop the possible '\n' from the end */
 399	if (buf[*ppos - 1] == '\n')
 400		buf[*ppos - 1] = '\0';
 401
 402	if (radioup == 0) {
 403		ret = -ENETDOWN;
 404		goto exit;
 405	}
 406
 407	if (!strcmp(buf, "assert")) {
 408		ath11k_info(ab, "simulating firmware assert crash\n");
 409		ret = ath11k_wmi_force_fw_hang_cmd(ar,
 410						   ATH11K_WMI_FW_HANG_ASSERT_TYPE,
 411						   ATH11K_WMI_FW_HANG_DELAY);
 412	} else if (!strcmp(buf, "hw-restart")) {
 413		ath11k_info(ab, "user requested hw restart\n");
 414		queue_work(ab->workqueue_aux, &ab->reset_work);
 415		ret = 0;
 416	} else {
 417		ret = -EINVAL;
 418		goto exit;
 419	}
 420
 421	if (ret) {
 422		ath11k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
 423		goto exit;
 424	}
 425
 426	ret = count;
 427
 428exit:
 429	return ret;
 430}
 431
 432static const struct file_operations fops_simulate_fw_crash = {
 433	.read = ath11k_read_simulate_fw_crash,
 434	.write = ath11k_write_simulate_fw_crash,
 435	.open = simple_open,
 436	.owner = THIS_MODULE,
 437	.llseek = default_llseek,
 438};
 439
 440static ssize_t ath11k_write_enable_extd_tx_stats(struct file *file,
 441						 const char __user *ubuf,
 442						 size_t count, loff_t *ppos)
 443{
 444	struct ath11k *ar = file->private_data;
 445	u32 filter;
 446	int ret;
 447
 448	if (kstrtouint_from_user(ubuf, count, 0, &filter))
 449		return -EINVAL;
 450
 451	mutex_lock(&ar->conf_mutex);
 452
 453	if (ar->state != ATH11K_STATE_ON) {
 454		ret = -ENETDOWN;
 455		goto out;
 456	}
 457
 458	if (filter == ar->debug.extd_tx_stats) {
 459		ret = count;
 460		goto out;
 461	}
 462
 463	ar->debug.extd_tx_stats = filter;
 464	ret = count;
 465
 466out:
 467	mutex_unlock(&ar->conf_mutex);
 468	return ret;
 469}
 470
 471static ssize_t ath11k_read_enable_extd_tx_stats(struct file *file,
 472						char __user *ubuf,
 473						size_t count, loff_t *ppos)
 474
 475{
 476	char buf[32] = {};
 477	struct ath11k *ar = file->private_data;
 478	int len = 0;
 479
 480	mutex_lock(&ar->conf_mutex);
 481	len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
 482			ar->debug.extd_tx_stats);
 483	mutex_unlock(&ar->conf_mutex);
 484
 485	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
 486}
 487
 488static const struct file_operations fops_extd_tx_stats = {
 489	.read = ath11k_read_enable_extd_tx_stats,
 490	.write = ath11k_write_enable_extd_tx_stats,
 491	.open = simple_open
 492};
 493
 494static ssize_t ath11k_write_extd_rx_stats(struct file *file,
 495					  const char __user *ubuf,
 496					  size_t count, loff_t *ppos)
 497{
 498	struct ath11k *ar = file->private_data;
 499	struct ath11k_base *ab = ar->ab;
 500	struct htt_rx_ring_tlv_filter tlv_filter = {};
 501	u32 enable, rx_filter = 0, ring_id;
 502	int i;
 503	int ret;
 504
 505	if (kstrtouint_from_user(ubuf, count, 0, &enable))
 506		return -EINVAL;
 507
 508	mutex_lock(&ar->conf_mutex);
 509
 510	if (ar->state != ATH11K_STATE_ON) {
 511		ret = -ENETDOWN;
 512		goto exit;
 513	}
 514
 515	if (enable > 1) {
 516		ret = -EINVAL;
 517		goto exit;
 518	}
 519
 520	if (enable == ar->debug.extd_rx_stats) {
 521		ret = count;
 522		goto exit;
 523	}
 524
 525	if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags)) {
 526		ar->debug.extd_rx_stats = enable;
 527		ret = count;
 528		goto exit;
 529	}
 530
 531	if (enable) {
 532		rx_filter =  HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
 533		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
 534		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
 535		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
 536		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
 537		rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
 538
 539		tlv_filter.rx_filter = rx_filter;
 540		tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
 541		tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
 542		tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
 543		tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
 544			HTT_RX_FP_DATA_FILTER_FLASG3;
 545	} else {
 546		tlv_filter = ath11k_mac_mon_status_filter_default;
 547	}
 548
 549	ar->debug.rx_filter = tlv_filter.rx_filter;
 550
 551	for (i = 0; i < ab->hw_params.num_rxdma_per_pdev; i++) {
 552		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
 553		ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
 554						       HAL_RXDMA_MONITOR_STATUS,
 555						       DP_RX_BUFFER_SIZE, &tlv_filter);
 556
 557		if (ret) {
 558			ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
 559			goto exit;
 560		}
 561	}
 562
 563	ar->debug.extd_rx_stats = enable;
 564	ret = count;
 565exit:
 566	mutex_unlock(&ar->conf_mutex);
 567	return ret;
 568}
 569
 570static ssize_t ath11k_read_extd_rx_stats(struct file *file,
 571					 char __user *ubuf,
 572					 size_t count, loff_t *ppos)
 573{
 574	struct ath11k *ar = file->private_data;
 575	char buf[32];
 576	int len = 0;
 577
 578	mutex_lock(&ar->conf_mutex);
 579	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
 580			ar->debug.extd_rx_stats);
 581	mutex_unlock(&ar->conf_mutex);
 582
 583	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
 584}
 585
 586static const struct file_operations fops_extd_rx_stats = {
 587	.read = ath11k_read_extd_rx_stats,
 588	.write = ath11k_write_extd_rx_stats,
 589	.open = simple_open,
 590};
 591
 592static int ath11k_fill_bp_stats(struct ath11k_base *ab,
 593				struct ath11k_bp_stats *bp_stats,
 594				char *buf, int len, int size)
 595{
 596	lockdep_assert_held(&ab->base_lock);
 597
 598	len += scnprintf(buf + len, size - len, "count: %u\n",
 599			 bp_stats->count);
 600	len += scnprintf(buf + len, size - len, "hp: %u\n",
 601			 bp_stats->hp);
 602	len += scnprintf(buf + len, size - len, "tp: %u\n",
 603			 bp_stats->tp);
 604	len += scnprintf(buf + len, size - len, "seen before: %ums\n\n",
 605			 jiffies_to_msecs(jiffies - bp_stats->jiffies));
 606	return len;
 607}
 608
 609static ssize_t ath11k_debugfs_dump_soc_ring_bp_stats(struct ath11k_base *ab,
 610						     char *buf, int size)
 611{
 612	struct ath11k_bp_stats *bp_stats;
 613	bool stats_rxd = false;
 614	u8 i, pdev_idx;
 615	int len = 0;
 616
 617	len += scnprintf(buf + len, size - len, "\nBackpressure Stats\n");
 618	len += scnprintf(buf + len, size - len, "==================\n");
 619
 620	spin_lock_bh(&ab->base_lock);
 621	for (i = 0; i < HTT_SW_UMAC_RING_IDX_MAX; i++) {
 622		bp_stats = &ab->soc_stats.bp_stats.umac_ring_bp_stats[i];
 623
 624		if (!bp_stats->count)
 625			continue;
 626
 627		len += scnprintf(buf + len, size - len, "Ring: %s\n",
 628				 htt_bp_umac_ring[i]);
 629		len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
 630		stats_rxd = true;
 631	}
 632
 633	for (i = 0; i < HTT_SW_LMAC_RING_IDX_MAX; i++) {
 634		for (pdev_idx = 0; pdev_idx < MAX_RADIOS; pdev_idx++) {
 635			bp_stats =
 636				&ab->soc_stats.bp_stats.lmac_ring_bp_stats[i][pdev_idx];
 637
 638			if (!bp_stats->count)
 639				continue;
 640
 641			len += scnprintf(buf + len, size - len, "Ring: %s\n",
 642					 htt_bp_lmac_ring[i]);
 643			len += scnprintf(buf + len, size - len, "pdev: %d\n",
 644					 pdev_idx);
 645			len = ath11k_fill_bp_stats(ab, bp_stats, buf, len, size);
 646			stats_rxd = true;
 647		}
 648	}
 649	spin_unlock_bh(&ab->base_lock);
 650
 651	if (!stats_rxd)
 652		len += scnprintf(buf + len, size - len,
 653				 "No Ring Backpressure stats received\n\n");
 654
 655	return len;
 656}
 657
 658static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
 659						char __user *user_buf,
 660						size_t count, loff_t *ppos)
 661{
 662	struct ath11k_base *ab = file->private_data;
 663	struct ath11k_soc_dp_stats *soc_stats = &ab->soc_stats;
 664	int len = 0, i, retval;
 665	const int size = 4096;
 666	static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
 667			"Overflow", "MPDU len", "FCS", "Decrypt", "TKIP MIC",
 668			"Unencrypt", "MSDU len", "MSDU limit", "WiFi parse",
 669			"AMSDU parse", "SA timeout", "DA timeout",
 670			"Flow timeout", "Flush req"};
 671	static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
 672			"Desc addr zero", "Desc inval", "AMPDU in non BA",
 673			"Non BA dup", "BA dup", "Frame 2k jump", "BAR 2k jump",
 674			"Frame OOR", "BAR OOR", "No BA session",
 675			"Frame SN equal SSN", "PN check fail", "2k err",
 676			"PN err", "Desc blocked"};
 677
 678	char *buf;
 679
 680	buf = kzalloc(size, GFP_KERNEL);
 681	if (!buf)
 682		return -ENOMEM;
 683
 684	len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n");
 685	len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
 686			 soc_stats->err_ring_pkts);
 687	len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
 688			 soc_stats->invalid_rbm);
 689	len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
 690	for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
 691		len += scnprintf(buf + len, size - len, "%s: %u\n",
 692				 rxdma_err[i], soc_stats->rxdma_error[i]);
 693
 694	len += scnprintf(buf + len, size - len, "\nREO errors:\n");
 695	for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
 696		len += scnprintf(buf + len, size - len, "%s: %u\n",
 697				 reo_err[i], soc_stats->reo_error[i]);
 698
 699	len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
 700	len += scnprintf(buf + len, size - len,
 701			 "ring0: %u\nring1: %u\nring2: %u\nring3: %u\n",
 702			 soc_stats->hal_reo_error[0],
 703			 soc_stats->hal_reo_error[1],
 704			 soc_stats->hal_reo_error[2],
 705			 soc_stats->hal_reo_error[3]);
 706
 707	len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
 708	len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
 709
 710	for (i = 0; i < ab->hw_params.max_tx_ring; i++)
 711		len += scnprintf(buf + len, size - len, "ring%d: %u\n",
 712				 i, soc_stats->tx_err.desc_na[i]);
 713
 714	len += scnprintf(buf + len, size - len,
 715			 "\nMisc Transmit Failures: %d\n",
 716			 atomic_read(&soc_stats->tx_err.misc_fail));
 717
 718	len += ath11k_debugfs_dump_soc_ring_bp_stats(ab, buf + len, size - len);
 719
 720	if (len > size)
 721		len = size;
 722	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
 723	kfree(buf);
 724
 725	return retval;
 726}
 727
 728static const struct file_operations fops_soc_dp_stats = {
 729	.read = ath11k_debugfs_dump_soc_dp_stats,
 730	.open = simple_open,
 731	.owner = THIS_MODULE,
 732	.llseek = default_llseek,
 733};
 734
 735static ssize_t ath11k_write_fw_dbglog(struct file *file,
 736				      const char __user *user_buf,
 737				      size_t count, loff_t *ppos)
 738{
 739	struct ath11k *ar = file->private_data;
 740	char buf[128] = {};
 741	struct ath11k_fw_dbglog dbglog;
 742	unsigned int param, mod_id_index, is_end;
 743	u64 value;
 744	int ret, num;
 745
 746	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
 747				     user_buf, count);
 748	if (ret <= 0)
 749		return ret;
 750
 751	num = sscanf(buf, "%u %llx %u %u", &param, &value, &mod_id_index, &is_end);
 752
 753	if (num < 2)
 754		return -EINVAL;
 755
 756	mutex_lock(&ar->conf_mutex);
 757	if (param == WMI_DEBUG_LOG_PARAM_MOD_ENABLE_BITMAP ||
 758	    param == WMI_DEBUG_LOG_PARAM_WOW_MOD_ENABLE_BITMAP) {
 759		if (num != 4 || mod_id_index > (MAX_MODULE_ID_BITMAP_WORDS - 1)) {
 760			ret = -EINVAL;
 761			goto out;
 762		}
 763		ar->debug.module_id_bitmap[mod_id_index] = upper_32_bits(value);
 764		if (!is_end) {
 765			ret = count;
 766			goto out;
 767		}
 768	} else {
 769		if (num != 2) {
 770			ret = -EINVAL;
 771			goto out;
 772		}
 773	}
 774
 775	dbglog.param = param;
 776	dbglog.value = lower_32_bits(value);
 777	ret = ath11k_wmi_fw_dbglog_cfg(ar, ar->debug.module_id_bitmap, &dbglog);
 778	if (ret) {
 779		ath11k_warn(ar->ab, "fw dbglog config failed from debugfs: %d\n",
 780			    ret);
 781		goto out;
 782	}
 783
 784	ret = count;
 785
 786out:
 787	mutex_unlock(&ar->conf_mutex);
 788	return ret;
 789}
 790
 791static const struct file_operations fops_fw_dbglog = {
 792	.write = ath11k_write_fw_dbglog,
 793	.open = simple_open,
 794	.owner = THIS_MODULE,
 795	.llseek = default_llseek,
 796};
 797
 798static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
 799{
 800	struct ath11k_base *ab = inode->i_private;
 801	u8 *buf;
 802	u32 start, end;
 803	int ret;
 804
 805	start = ab->hw_params.sram_dump.start;
 806	end = ab->hw_params.sram_dump.end;
 807
 808	buf = vmalloc(end - start + 1);
 809	if (!buf)
 810		return -ENOMEM;
 811
 812	ret = ath11k_hif_read(ab, buf, start, end);
 813	if (ret) {
 814		ath11k_warn(ab, "failed to dump sram: %d\n", ret);
 815		vfree(buf);
 816		return ret;
 817	}
 818
 819	file->private_data = buf;
 820	return 0;
 821}
 822
 823static ssize_t ath11k_read_sram_dump(struct file *file,
 824				     char __user *user_buf,
 825				     size_t count, loff_t *ppos)
 826{
 827	struct ath11k_base *ab = file->f_inode->i_private;
 828	const char *buf = file->private_data;
 829	int len;
 830	u32 start, end;
 831
 832	start = ab->hw_params.sram_dump.start;
 833	end = ab->hw_params.sram_dump.end;
 834	len = end - start + 1;
 835
 836	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 837}
 838
 839static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
 840{
 841	vfree(file->private_data);
 842	file->private_data = NULL;
 843
 844	return 0;
 845}
 846
 847static const struct file_operations fops_sram_dump = {
 848	.open = ath11k_open_sram_dump,
 849	.read = ath11k_read_sram_dump,
 850	.release = ath11k_release_sram_dump,
 851	.owner = THIS_MODULE,
 852	.llseek = default_llseek,
 853};
 854
 855int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
 856{
 857	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
 858		return 0;
 859
 860	debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
 861			    &fops_simulate_fw_crash);
 862
 863	debugfs_create_file("soc_dp_stats", 0400, ab->debugfs_soc, ab,
 864			    &fops_soc_dp_stats);
 865
 866	if (ab->hw_params.sram_dump.start != 0)
 867		debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
 868				    &fops_sram_dump);
 869
 870	return 0;
 871}
 872
 873void ath11k_debugfs_pdev_destroy(struct ath11k_base *ab)
 874{
 875	debugfs_remove_recursive(ab->debugfs_soc);
 876	ab->debugfs_soc = NULL;
 877}
 878
 879int ath11k_debugfs_soc_create(struct ath11k_base *ab)
 880{
 881	struct dentry *root;
 882	bool dput_needed;
 883	char name[64];
 884	int ret;
 885
 886	root = debugfs_lookup("ath11k", NULL);
 887	if (!root) {
 888		root = debugfs_create_dir("ath11k", NULL);
 889		if (IS_ERR_OR_NULL(root))
 890			return PTR_ERR(root);
 891
 892		dput_needed = false;
 893	} else {
 894		/* a dentry from lookup() needs dput() after we don't use it */
 895		dput_needed = true;
 896	}
 897
 898	scnprintf(name, sizeof(name), "%s-%s", ath11k_bus_str(ab->hif.bus),
 899		  dev_name(ab->dev));
 900
 901	ab->debugfs_soc = debugfs_create_dir(name, root);
 902	if (IS_ERR_OR_NULL(ab->debugfs_soc)) {
 903		ret = PTR_ERR(ab->debugfs_soc);
 904		goto out;
 905	}
 906
 907	ret = 0;
 908
 909out:
 910	if (dput_needed)
 911		dput(root);
 912
 913	return ret;
 914}
 915
 916void ath11k_debugfs_soc_destroy(struct ath11k_base *ab)
 917{
 918	debugfs_remove_recursive(ab->debugfs_soc);
 919	ab->debugfs_soc = NULL;
 920
 921	/* We are not removing ath11k directory on purpose, even if it
 922	 * would be empty. This simplifies the directory handling and it's
 923	 * a minor cosmetic issue to leave an empty ath11k directory to
 924	 * debugfs.
 925	 */
 926}
 927EXPORT_SYMBOL(ath11k_debugfs_soc_destroy);
 928
 929void ath11k_debugfs_fw_stats_init(struct ath11k *ar)
 930{
 931	struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
 932							ar->debug.debugfs_pdev);
 933
 934	ar->fw_stats.debugfs_fwstats = fwstats_dir;
 935
 936	/* all stats debugfs files created are under "fw_stats" directory
 937	 * created per PDEV
 938	 */
 939	debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
 940			    &fops_pdev_stats);
 941	debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
 942			    &fops_vdev_stats);
 943	debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
 944			    &fops_bcn_stats);
 945}
 946
 947static ssize_t ath11k_write_pktlog_filter(struct file *file,
 948					  const char __user *ubuf,
 949					  size_t count, loff_t *ppos)
 950{
 951	struct ath11k *ar = file->private_data;
 952	struct ath11k_base *ab = ar->ab;
 953	struct htt_rx_ring_tlv_filter tlv_filter = {};
 954	u32 rx_filter = 0, ring_id, filter, mode;
 955	u8 buf[128] = {};
 956	int i, ret, rx_buf_sz = 0;
 957	ssize_t rc;
 958
 959	mutex_lock(&ar->conf_mutex);
 960	if (ar->state != ATH11K_STATE_ON) {
 961		ret = -ENETDOWN;
 962		goto out;
 963	}
 964
 965	rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
 966	if (rc < 0) {
 967		ret = rc;
 968		goto out;
 969	}
 970	buf[rc] = '\0';
 971
 972	ret = sscanf(buf, "0x%x %u", &filter, &mode);
 973	if (ret != 2) {
 974		ret = -EINVAL;
 975		goto out;
 976	}
 977
 978	if (filter) {
 979		ret = ath11k_wmi_pdev_pktlog_enable(ar, filter);
 980		if (ret) {
 981			ath11k_warn(ar->ab,
 982				    "failed to enable pktlog filter %x: %d\n",
 983				    ar->debug.pktlog_filter, ret);
 984			goto out;
 985		}
 986	} else {
 987		ret = ath11k_wmi_pdev_pktlog_disable(ar);
 988		if (ret) {
 989			ath11k_warn(ar->ab, "failed to disable pktlog: %d\n", ret);
 990			goto out;
 991		}
 992	}
 993
 994	/* Clear rx filter set for monitor mode and rx status */
 995	for (i = 0; i < ab->hw_params.num_rxdma_per_pdev; i++) {
 996		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
 997		ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
 998						       HAL_RXDMA_MONITOR_STATUS,
 999						       rx_buf_sz, &tlv_filter);
1000		if (ret) {
1001			ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
1002			goto out;
1003		}
1004	}
1005#define HTT_RX_FILTER_TLV_LITE_MODE \
1006			(HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
1007			HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
1008			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS | \
1009			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT | \
1010			HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE | \
1011			HTT_RX_FILTER_TLV_FLAGS_MPDU_START)
1012
1013	if (mode == ATH11K_PKTLOG_MODE_FULL) {
1014		rx_filter = HTT_RX_FILTER_TLV_LITE_MODE |
1015			    HTT_RX_FILTER_TLV_FLAGS_MSDU_START |
1016			    HTT_RX_FILTER_TLV_FLAGS_MSDU_END |
1017			    HTT_RX_FILTER_TLV_FLAGS_MPDU_END |
1018			    HTT_RX_FILTER_TLV_FLAGS_PACKET_HEADER |
1019			    HTT_RX_FILTER_TLV_FLAGS_ATTENTION;
1020		rx_buf_sz = DP_RX_BUFFER_SIZE;
1021	} else if (mode == ATH11K_PKTLOG_MODE_LITE) {
1022		ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1023							  HTT_PPDU_STATS_TAG_PKTLOG);
1024		if (ret) {
1025			ath11k_err(ar->ab, "failed to enable pktlog lite: %d\n", ret);
1026			goto out;
1027		}
1028
1029		rx_filter = HTT_RX_FILTER_TLV_LITE_MODE;
1030		rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
1031	} else {
1032		rx_buf_sz = DP_RX_BUFFER_SIZE;
1033		tlv_filter = ath11k_mac_mon_status_filter_default;
1034		rx_filter = tlv_filter.rx_filter;
1035
1036		ret = ath11k_dp_tx_htt_h2t_ppdu_stats_req(ar,
1037							  HTT_PPDU_STATS_TAG_DEFAULT);
1038		if (ret) {
1039			ath11k_err(ar->ab, "failed to send htt ppdu stats req: %d\n",
1040				   ret);
1041			goto out;
1042		}
1043	}
1044
1045	tlv_filter.rx_filter = rx_filter;
1046	if (rx_filter) {
1047		tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
1048		tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
1049		tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
1050		tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
1051					       HTT_RX_FP_DATA_FILTER_FLASG3;
1052	}
1053
1054	for (i = 0; i < ab->hw_params.num_rxdma_per_pdev; i++) {
1055		ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
1056		ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
1057						       ar->dp.mac_id + i,
1058						       HAL_RXDMA_MONITOR_STATUS,
1059						       rx_buf_sz, &tlv_filter);
1060
1061		if (ret) {
1062			ath11k_warn(ab, "failed to set rx filter for monitor status ring\n");
1063			goto out;
1064		}
1065	}
1066
1067	ath11k_info(ab, "pktlog mode %s\n",
1068		    ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
1069
1070	ar->debug.pktlog_filter = filter;
1071	ar->debug.pktlog_mode = mode;
1072	ret = count;
1073
1074out:
1075	mutex_unlock(&ar->conf_mutex);
1076	return ret;
1077}
1078
1079static ssize_t ath11k_read_pktlog_filter(struct file *file,
1080					 char __user *ubuf,
1081					 size_t count, loff_t *ppos)
1082
1083{
1084	char buf[32] = {};
1085	struct ath11k *ar = file->private_data;
1086	int len = 0;
1087
1088	mutex_lock(&ar->conf_mutex);
1089	len = scnprintf(buf, sizeof(buf) - len, "%08x %08x\n",
1090			ar->debug.pktlog_filter,
1091			ar->debug.pktlog_mode);
1092	mutex_unlock(&ar->conf_mutex);
1093
1094	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
1095}
1096
1097static const struct file_operations fops_pktlog_filter = {
1098	.read = ath11k_read_pktlog_filter,
1099	.write = ath11k_write_pktlog_filter,
1100	.open = simple_open
1101};
1102
1103static ssize_t ath11k_write_simulate_radar(struct file *file,
1104					   const char __user *user_buf,
1105					   size_t count, loff_t *ppos)
1106{
1107	struct ath11k *ar = file->private_data;
1108	int ret;
1109
1110	ret = ath11k_wmi_simulate_radar(ar);
1111	if (ret)
1112		return ret;
1113
1114	return count;
1115}
1116
1117static const struct file_operations fops_simulate_radar = {
1118	.write = ath11k_write_simulate_radar,
1119	.open = simple_open
1120};
1121
1122static ssize_t ath11k_debug_dump_dbr_entries(struct file *file,
1123					     char __user *user_buf,
1124					     size_t count, loff_t *ppos)
1125{
1126	struct ath11k_dbg_dbr_data *dbr_dbg_data = file->private_data;
1127	static const char * const event_id_to_string[] = {"empty", "Rx", "Replenish"};
1128	int size = ATH11K_DEBUG_DBR_ENTRIES_MAX * 100;
1129	char *buf;
1130	int i, ret;
1131	int len = 0;
1132
1133	buf = kzalloc(size, GFP_KERNEL);
1134	if (!buf)
1135		return -ENOMEM;
1136
1137	len += scnprintf(buf + len, size - len,
1138			 "-----------------------------------------\n");
1139	len += scnprintf(buf + len, size - len,
1140			 "| idx |  hp  |  tp  | timestamp |  event |\n");
1141	len += scnprintf(buf + len, size - len,
1142			 "-----------------------------------------\n");
1143
1144	spin_lock_bh(&dbr_dbg_data->lock);
1145
1146	for (i = 0; i < dbr_dbg_data->num_ring_debug_entries; i++) {
1147		len += scnprintf(buf + len, size - len,
1148				 "|%4u|%8u|%8u|%11llu|%8s|\n", i,
1149				 dbr_dbg_data->entries[i].hp,
1150				 dbr_dbg_data->entries[i].tp,
1151				 dbr_dbg_data->entries[i].timestamp,
1152				 event_id_to_string[dbr_dbg_data->entries[i].event]);
1153	}
1154
1155	spin_unlock_bh(&dbr_dbg_data->lock);
1156
1157	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1158	kfree(buf);
1159
1160	return ret;
1161}
1162
1163static const struct file_operations fops_debug_dump_dbr_entries = {
1164	.read = ath11k_debug_dump_dbr_entries,
1165	.open = simple_open,
1166	.owner = THIS_MODULE,
1167	.llseek = default_llseek,
1168};
1169
1170static void ath11k_debugfs_dbr_dbg_destroy(struct ath11k *ar, int dbr_id)
1171{
1172	struct ath11k_debug_dbr *dbr_debug;
1173	struct ath11k_dbg_dbr_data *dbr_dbg_data;
1174
1175	if (!ar->debug.dbr_debug[dbr_id])
1176		return;
1177
1178	dbr_debug = ar->debug.dbr_debug[dbr_id];
1179	dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1180
1181	debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1182	kfree(dbr_dbg_data->entries);
1183	kfree(dbr_debug);
1184	ar->debug.dbr_debug[dbr_id] = NULL;
1185}
1186
1187static int ath11k_debugfs_dbr_dbg_init(struct ath11k *ar, int dbr_id)
1188{
1189	struct ath11k_debug_dbr *dbr_debug;
1190	struct ath11k_dbg_dbr_data *dbr_dbg_data;
1191	static const char * const dbr_id_to_str[] = {"spectral", "CFR"};
1192
1193	if (ar->debug.dbr_debug[dbr_id])
1194		return 0;
1195
1196	ar->debug.dbr_debug[dbr_id] = kzalloc(sizeof(*dbr_debug),
1197					      GFP_KERNEL);
1198
1199	if (!ar->debug.dbr_debug[dbr_id])
1200		return -ENOMEM;
1201
1202	dbr_debug = ar->debug.dbr_debug[dbr_id];
1203	dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1204
1205	if (dbr_debug->dbr_debugfs)
1206		return 0;
1207
1208	dbr_debug->dbr_debugfs = debugfs_create_dir(dbr_id_to_str[dbr_id],
1209						    ar->debug.debugfs_pdev);
1210	if (IS_ERR_OR_NULL(dbr_debug->dbr_debugfs)) {
1211		if (IS_ERR(dbr_debug->dbr_debugfs))
1212			return PTR_ERR(dbr_debug->dbr_debugfs);
1213		return -ENOMEM;
1214	}
1215
1216	dbr_debug->dbr_debug_enabled = true;
1217	dbr_dbg_data->num_ring_debug_entries = ATH11K_DEBUG_DBR_ENTRIES_MAX;
1218	dbr_dbg_data->dbr_debug_idx = 0;
1219	dbr_dbg_data->entries = kcalloc(ATH11K_DEBUG_DBR_ENTRIES_MAX,
1220					sizeof(struct ath11k_dbg_dbr_entry),
1221					GFP_KERNEL);
1222	if (!dbr_dbg_data->entries)
1223		return -ENOMEM;
1224
1225	spin_lock_init(&dbr_dbg_data->lock);
1226
1227	debugfs_create_file("dump_dbr_debug", 0444, dbr_debug->dbr_debugfs,
1228			    dbr_dbg_data, &fops_debug_dump_dbr_entries);
1229
1230	return 0;
1231}
1232
1233static ssize_t ath11k_debugfs_write_enable_dbr_dbg(struct file *file,
1234						   const char __user *ubuf,
1235						   size_t count, loff_t *ppos)
1236{
1237	struct ath11k *ar = file->private_data;
1238	char buf[32] = {};
1239	u32 dbr_id, enable;
1240	int ret;
1241
1242	mutex_lock(&ar->conf_mutex);
1243
1244	if (ar->state != ATH11K_STATE_ON) {
1245		ret = -ENETDOWN;
1246		goto out;
1247	}
1248
1249	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1250	if (ret < 0)
1251		goto out;
1252
1253	buf[ret] = '\0';
1254	ret = sscanf(buf, "%u %u", &dbr_id, &enable);
1255	if (ret != 2 || dbr_id > 1 || enable > 1) {
1256		ret = -EINVAL;
1257		ath11k_warn(ar->ab, "usage: echo <dbr_id> <val> dbr_id:0-Spectral 1-CFR val:0-disable 1-enable\n");
1258		goto out;
1259	}
1260
1261	if (enable) {
1262		ret = ath11k_debugfs_dbr_dbg_init(ar, dbr_id);
1263		if (ret) {
1264			ath11k_warn(ar->ab, "db ring module debugfs init failed: %d\n",
1265				    ret);
1266			goto out;
1267		}
1268	} else {
1269		ath11k_debugfs_dbr_dbg_destroy(ar, dbr_id);
1270	}
1271
1272	ret = count;
1273out:
1274	mutex_unlock(&ar->conf_mutex);
1275	return ret;
1276}
1277
1278static const struct file_operations fops_dbr_debug = {
1279	.write = ath11k_debugfs_write_enable_dbr_dbg,
1280	.open = simple_open,
1281	.owner = THIS_MODULE,
1282	.llseek = default_llseek,
1283};
1284
1285static ssize_t ath11k_write_ps_timekeeper_enable(struct file *file,
1286						 const char __user *user_buf,
1287						 size_t count, loff_t *ppos)
1288{
1289	struct ath11k *ar = file->private_data;
1290	ssize_t ret;
1291	u8 ps_timekeeper_enable;
1292
1293	if (kstrtou8_from_user(user_buf, count, 0, &ps_timekeeper_enable))
1294		return -EINVAL;
1295
1296	mutex_lock(&ar->conf_mutex);
1297
1298	if (ar->state != ATH11K_STATE_ON) {
1299		ret = -ENETDOWN;
1300		goto exit;
1301	}
1302
1303	if (!ar->ps_state_enable) {
1304		ret = -EINVAL;
1305		goto exit;
1306	}
1307
1308	ar->ps_timekeeper_enable = !!ps_timekeeper_enable;
1309	ret = count;
1310exit:
1311	mutex_unlock(&ar->conf_mutex);
1312
1313	return ret;
1314}
1315
1316static ssize_t ath11k_read_ps_timekeeper_enable(struct file *file,
1317						char __user *user_buf,
1318						size_t count, loff_t *ppos)
1319{
1320	struct ath11k *ar = file->private_data;
1321	char buf[32];
1322	int len;
1323
1324	mutex_lock(&ar->conf_mutex);
1325	len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_timekeeper_enable);
1326	mutex_unlock(&ar->conf_mutex);
1327
1328	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1329}
1330
1331static const struct file_operations fops_ps_timekeeper_enable = {
1332	.read = ath11k_read_ps_timekeeper_enable,
1333	.write = ath11k_write_ps_timekeeper_enable,
1334	.open = simple_open,
1335	.owner = THIS_MODULE,
1336	.llseek = default_llseek,
1337};
1338
1339static void ath11k_reset_peer_ps_duration(void *data,
1340					  struct ieee80211_sta *sta)
1341{
1342	struct ath11k *ar = data;
1343	struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
1344
1345	spin_lock_bh(&ar->data_lock);
1346	arsta->ps_total_duration = 0;
1347	spin_unlock_bh(&ar->data_lock);
1348}
1349
1350static ssize_t ath11k_write_reset_ps_duration(struct file *file,
1351					      const  char __user *user_buf,
1352					      size_t count, loff_t *ppos)
1353{
1354	struct ath11k *ar = file->private_data;
1355	int ret;
1356	u8 reset_ps_duration;
1357
1358	if (kstrtou8_from_user(user_buf, count, 0, &reset_ps_duration))
1359		return -EINVAL;
1360
1361	mutex_lock(&ar->conf_mutex);
1362
1363	if (ar->state != ATH11K_STATE_ON) {
1364		ret = -ENETDOWN;
1365		goto exit;
1366	}
1367
1368	if (!ar->ps_state_enable) {
1369		ret = -EINVAL;
1370		goto exit;
1371	}
1372
1373	ieee80211_iterate_stations_atomic(ar->hw,
1374					  ath11k_reset_peer_ps_duration,
1375					  ar);
1376
1377	ret = count;
1378exit:
1379	mutex_unlock(&ar->conf_mutex);
1380	return ret;
1381}
1382
1383static const struct file_operations fops_reset_ps_duration = {
1384	.write = ath11k_write_reset_ps_duration,
1385	.open = simple_open,
1386	.owner = THIS_MODULE,
1387	.llseek = default_llseek,
1388};
1389
1390static void ath11k_peer_ps_state_disable(void *data,
1391					 struct ieee80211_sta *sta)
1392{
1393	struct ath11k *ar = data;
1394	struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
1395
1396	spin_lock_bh(&ar->data_lock);
1397	arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
1398	arsta->ps_start_time = 0;
1399	arsta->ps_total_duration = 0;
1400	spin_unlock_bh(&ar->data_lock);
1401}
1402
1403static ssize_t ath11k_write_ps_state_enable(struct file *file,
1404					    const char __user *user_buf,
1405					    size_t count, loff_t *ppos)
1406{
1407	struct ath11k *ar = file->private_data;
1408	struct ath11k_pdev *pdev = ar->pdev;
1409	int ret;
1410	u32 param;
1411	u8 ps_state_enable;
1412
1413	if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
1414		return -EINVAL;
1415
1416	mutex_lock(&ar->conf_mutex);
1417
1418	ps_state_enable = !!ps_state_enable;
1419
1420	if (ar->ps_state_enable == ps_state_enable) {
1421		ret = count;
1422		goto exit;
1423	}
1424
1425	param = WMI_PDEV_PEER_STA_PS_STATECHG_ENABLE;
1426	ret = ath11k_wmi_pdev_set_param(ar, param, ps_state_enable, pdev->pdev_id);
1427	if (ret) {
1428		ath11k_warn(ar->ab, "failed to enable ps_state_enable: %d\n",
1429			    ret);
1430		goto exit;
1431	}
1432	ar->ps_state_enable = ps_state_enable;
1433
1434	if (!ar->ps_state_enable) {
1435		ar->ps_timekeeper_enable = false;
1436		ieee80211_iterate_stations_atomic(ar->hw,
1437						  ath11k_peer_ps_state_disable,
1438						  ar);
1439	}
1440
1441	ret = count;
1442
1443exit:
1444	mutex_unlock(&ar->conf_mutex);
1445
1446	return ret;
1447}
1448
1449static ssize_t ath11k_read_ps_state_enable(struct file *file,
1450					   char __user *user_buf,
1451					   size_t count, loff_t *ppos)
1452{
1453	struct ath11k *ar = file->private_data;
1454	char buf[32];
1455	int len;
1456
1457	mutex_lock(&ar->conf_mutex);
1458	len = scnprintf(buf, sizeof(buf), "%d\n", ar->ps_state_enable);
1459	mutex_unlock(&ar->conf_mutex);
1460
1461	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1462}
1463
1464static const struct file_operations fops_ps_state_enable = {
1465	.read = ath11k_read_ps_state_enable,
1466	.write = ath11k_write_ps_state_enable,
1467	.open = simple_open,
1468	.owner = THIS_MODULE,
1469	.llseek = default_llseek,
1470};
1471
1472int ath11k_debugfs_register(struct ath11k *ar)
1473{
1474	struct ath11k_base *ab = ar->ab;
1475	char pdev_name[10];
1476	char buf[100] = {};
1477
1478	snprintf(pdev_name, sizeof(pdev_name), "%s%u", "mac", ar->pdev_idx);
1479
1480	ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1481	if (IS_ERR(ar->debug.debugfs_pdev))
1482		return PTR_ERR(ar->debug.debugfs_pdev);
1483
1484	/* Create a symlink under ieee80211/phy* */
1485	snprintf(buf, 100, "../../ath11k/%pd2", ar->debug.debugfs_pdev);
1486	debugfs_create_symlink("ath11k", ar->hw->wiphy->debugfsdir, buf);
1487
1488	ath11k_debugfs_htt_stats_init(ar);
1489
1490	ath11k_debugfs_fw_stats_init(ar);
1491
1492	debugfs_create_file("ext_tx_stats", 0644,
1493			    ar->debug.debugfs_pdev, ar,
1494			    &fops_extd_tx_stats);
1495	debugfs_create_file("ext_rx_stats", 0644,
1496			    ar->debug.debugfs_pdev, ar,
1497			    &fops_extd_rx_stats);
1498	debugfs_create_file("pktlog_filter", 0644,
1499			    ar->debug.debugfs_pdev, ar,
1500			    &fops_pktlog_filter);
1501	debugfs_create_file("fw_dbglog_config", 0600,
1502			    ar->debug.debugfs_pdev, ar,
1503			    &fops_fw_dbglog);
1504
1505	if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
1506		debugfs_create_file("dfs_simulate_radar", 0200,
1507				    ar->debug.debugfs_pdev, ar,
1508				    &fops_simulate_radar);
1509		debugfs_create_bool("dfs_block_radar_events", 0200,
1510				    ar->debug.debugfs_pdev,
1511				    &ar->dfs_block_radar_events);
1512	}
1513
1514	if (ab->hw_params.dbr_debug_support)
1515		debugfs_create_file("enable_dbr_debug", 0200, ar->debug.debugfs_pdev,
1516				    ar, &fops_dbr_debug);
1517
1518	debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_pdev, ar,
1519			    &fops_ps_state_enable);
1520
1521	if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
1522		     ar->ab->wmi_ab.svc_map)) {
1523		debugfs_create_file("ps_timekeeper_enable", 0600,
1524				    ar->debug.debugfs_pdev, ar,
1525				    &fops_ps_timekeeper_enable);
1526
1527		debugfs_create_file("reset_ps_duration", 0200,
1528				    ar->debug.debugfs_pdev, ar,
1529				    &fops_reset_ps_duration);
1530	}
1531
1532	return 0;
1533}
1534
1535void ath11k_debugfs_unregister(struct ath11k *ar)
1536{
1537	struct ath11k_debug_dbr *dbr_debug;
1538	struct ath11k_dbg_dbr_data *dbr_dbg_data;
1539	int i;
1540
1541	for (i = 0; i < WMI_DIRECT_BUF_MAX; i++) {
1542		dbr_debug = ar->debug.dbr_debug[i];
1543		if (!dbr_debug)
1544			continue;
1545
1546		dbr_dbg_data = &dbr_debug->dbr_dbg_data;
1547		kfree(dbr_dbg_data->entries);
1548		debugfs_remove_recursive(dbr_debug->dbr_debugfs);
1549		kfree(dbr_debug);
1550		ar->debug.dbr_debug[i] = NULL;
1551	}
1552}
1553
1554static ssize_t ath11k_write_twt_add_dialog(struct file *file,
1555					   const char __user *ubuf,
1556					   size_t count, loff_t *ppos)
1557{
1558	struct ath11k_vif *arvif = file->private_data;
1559	struct wmi_twt_add_dialog_params params = {};
1560	struct wmi_twt_enable_params twt_params = {};
1561	struct ath11k *ar = arvif->ar;
1562	u8 buf[128] = {};
1563	int ret;
1564
1565	if (ar->twt_enabled == 0) {
1566		ath11k_err(ar->ab, "twt support is not enabled\n");
1567		return -EOPNOTSUPP;
1568	}
1569
1570	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1571	if (ret < 0)
1572		return ret;
1573
1574	buf[ret] = '\0';
1575	ret = sscanf(buf,
1576		     "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u %u %u %hhu %hhu %hhu %hhu %hhu",
1577		     &params.peer_macaddr[0],
1578		     &params.peer_macaddr[1],
1579		     &params.peer_macaddr[2],
1580		     &params.peer_macaddr[3],
1581		     &params.peer_macaddr[4],
1582		     &params.peer_macaddr[5],
1583		     &params.dialog_id,
1584		     &params.wake_intvl_us,
1585		     &params.wake_intvl_mantis,
1586		     &params.wake_dura_us,
1587		     &params.sp_offset_us,
1588		     &params.twt_cmd,
1589		     &params.flag_bcast,
1590		     &params.flag_trigger,
1591		     &params.flag_flow_type,
1592		     &params.flag_protection);
1593	if (ret != 16)
1594		return -EINVAL;
1595
1596	/* In the case of station vif, TWT is entirely handled by
1597	 * the firmware based on the input parameters in the TWT enable
1598	 * WMI command that is sent to the target during assoc.
1599	 * For manually testing the TWT feature, we need to first disable
1600	 * TWT and send enable command again with TWT input parameter
1601	 * sta_cong_timer_ms set to 0.
1602	 */
1603	if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1604		ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1605
1606		ath11k_wmi_fill_default_twt_params(&twt_params);
1607		twt_params.sta_cong_timer_ms = 0;
1608
1609		ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1610	}
1611
1612	params.vdev_id = arvif->vdev_id;
1613
1614	ret = ath11k_wmi_send_twt_add_dialog_cmd(arvif->ar, &params);
1615	if (ret)
1616		goto err_twt_add_dialog;
1617
1618	return count;
1619
1620err_twt_add_dialog:
1621	if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1622		ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1623		ath11k_wmi_fill_default_twt_params(&twt_params);
1624		ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1625	}
1626
1627	return ret;
1628}
1629
1630static ssize_t ath11k_write_twt_del_dialog(struct file *file,
1631					   const char __user *ubuf,
1632					   size_t count, loff_t *ppos)
1633{
1634	struct ath11k_vif *arvif = file->private_data;
1635	struct wmi_twt_del_dialog_params params = {};
1636	struct wmi_twt_enable_params twt_params = {};
1637	struct ath11k *ar = arvif->ar;
1638	u8 buf[64] = {};
1639	int ret;
1640
1641	if (ar->twt_enabled == 0) {
1642		ath11k_err(ar->ab, "twt support is not enabled\n");
1643		return -EOPNOTSUPP;
1644	}
1645
1646	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1647	if (ret < 0)
1648		return ret;
1649
1650	buf[ret] = '\0';
1651	ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1652		     &params.peer_macaddr[0],
1653		     &params.peer_macaddr[1],
1654		     &params.peer_macaddr[2],
1655		     &params.peer_macaddr[3],
1656		     &params.peer_macaddr[4],
1657		     &params.peer_macaddr[5],
1658		     &params.dialog_id);
1659	if (ret != 7)
1660		return -EINVAL;
1661
1662	params.vdev_id = arvif->vdev_id;
1663
1664	ret = ath11k_wmi_send_twt_del_dialog_cmd(arvif->ar, &params);
1665	if (ret)
1666		return ret;
1667
1668	if (arvif->vif->type == NL80211_IFTYPE_STATION) {
1669		ath11k_wmi_send_twt_disable_cmd(ar, ar->pdev->pdev_id);
1670		ath11k_wmi_fill_default_twt_params(&twt_params);
1671		ath11k_wmi_send_twt_enable_cmd(ar, ar->pdev->pdev_id, &twt_params);
1672	}
1673
1674	return count;
1675}
1676
1677static ssize_t ath11k_write_twt_pause_dialog(struct file *file,
1678					     const char __user *ubuf,
1679					     size_t count, loff_t *ppos)
1680{
1681	struct ath11k_vif *arvif = file->private_data;
1682	struct wmi_twt_pause_dialog_params params = {};
1683	u8 buf[64] = {};
1684	int ret;
1685
1686	if (arvif->ar->twt_enabled == 0) {
1687		ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1688		return -EOPNOTSUPP;
1689	}
1690
1691	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1692	if (ret < 0)
1693		return ret;
1694
1695	buf[ret] = '\0';
1696	ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u",
1697		     &params.peer_macaddr[0],
1698		     &params.peer_macaddr[1],
1699		     &params.peer_macaddr[2],
1700		     &params.peer_macaddr[3],
1701		     &params.peer_macaddr[4],
1702		     &params.peer_macaddr[5],
1703		     &params.dialog_id);
1704	if (ret != 7)
1705		return -EINVAL;
1706
1707	params.vdev_id = arvif->vdev_id;
1708
1709	ret = ath11k_wmi_send_twt_pause_dialog_cmd(arvif->ar, &params);
1710	if (ret)
1711		return ret;
1712
1713	return count;
1714}
1715
1716static ssize_t ath11k_write_twt_resume_dialog(struct file *file,
1717					      const char __user *ubuf,
1718					      size_t count, loff_t *ppos)
1719{
1720	struct ath11k_vif *arvif = file->private_data;
1721	struct wmi_twt_resume_dialog_params params = {};
1722	u8 buf[64] = {};
1723	int ret;
1724
1725	if (arvif->ar->twt_enabled == 0) {
1726		ath11k_err(arvif->ar->ab, "twt support is not enabled\n");
1727		return -EOPNOTSUPP;
1728	}
1729
1730	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
1731	if (ret < 0)
1732		return ret;
1733
1734	buf[ret] = '\0';
1735	ret = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx %u %u %u",
1736		     &params.peer_macaddr[0],
1737		     &params.peer_macaddr[1],
1738		     &params.peer_macaddr[2],
1739		     &params.peer_macaddr[3],
1740		     &params.peer_macaddr[4],
1741		     &params.peer_macaddr[5],
1742		     &params.dialog_id,
1743		     &params.sp_offset_us,
1744		     &params.next_twt_size);
1745	if (ret != 9)
1746		return -EINVAL;
1747
1748	params.vdev_id = arvif->vdev_id;
1749
1750	ret = ath11k_wmi_send_twt_resume_dialog_cmd(arvif->ar, &params);
1751	if (ret)
1752		return ret;
1753
1754	return count;
1755}
1756
1757static const struct file_operations ath11k_fops_twt_add_dialog = {
1758	.write = ath11k_write_twt_add_dialog,
1759	.open = simple_open
1760};
1761
1762static const struct file_operations ath11k_fops_twt_del_dialog = {
1763	.write = ath11k_write_twt_del_dialog,
1764	.open = simple_open
1765};
1766
1767static const struct file_operations ath11k_fops_twt_pause_dialog = {
1768	.write = ath11k_write_twt_pause_dialog,
1769	.open = simple_open
1770};
1771
1772static const struct file_operations ath11k_fops_twt_resume_dialog = {
1773	.write = ath11k_write_twt_resume_dialog,
1774	.open = simple_open
1775};
1776
1777void ath11k_debugfs_op_vif_add(struct ieee80211_hw *hw,
1778			       struct ieee80211_vif *vif)
1779{
1780	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
1781	struct ath11k_base *ab = arvif->ar->ab;
1782	struct dentry *debugfs_twt;
1783
1784	if (arvif->vif->type != NL80211_IFTYPE_AP &&
1785	    !(arvif->vif->type == NL80211_IFTYPE_STATION &&
1786	      test_bit(WMI_TLV_SERVICE_STA_TWT, ab->wmi_ab.svc_map)))
1787		return;
1788
1789	debugfs_twt = debugfs_create_dir("twt",
1790					 arvif->vif->debugfs_dir);
1791	debugfs_create_file("add_dialog", 0200, debugfs_twt,
1792			    arvif, &ath11k_fops_twt_add_dialog);
1793
1794	debugfs_create_file("del_dialog", 0200, debugfs_twt,
1795			    arvif, &ath11k_fops_twt_del_dialog);
1796
1797	debugfs_create_file("pause_dialog", 0200, debugfs_twt,
1798			    arvif, &ath11k_fops_twt_pause_dialog);
1799
1800	debugfs_create_file("resume_dialog", 0200, debugfs_twt,
1801			    arvif, &ath11k_fops_twt_resume_dialog);
1802}
1803
~/ Read-only file preview.