Linux Audio

Check our new training course

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