18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file is part of wl1251
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Nokia Corporation
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "debugfs.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
118c2ecf20Sopenharmony_ci#include <linux/slab.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "wl1251.h"
148c2ecf20Sopenharmony_ci#include "acx.h"
158c2ecf20Sopenharmony_ci#include "ps.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/* ms */
188c2ecf20Sopenharmony_ci#define WL1251_DEBUGFS_STATS_LIFETIME 1000
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/* debugfs macros idea from mac80211 */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
238c2ecf20Sopenharmony_cistatic ssize_t name## _read(struct file *file, char __user *userbuf,	\
248c2ecf20Sopenharmony_ci			    size_t count, loff_t *ppos)			\
258c2ecf20Sopenharmony_ci{									\
268c2ecf20Sopenharmony_ci	struct wl1251 *wl = file->private_data;				\
278c2ecf20Sopenharmony_ci	char buf[buflen];						\
288c2ecf20Sopenharmony_ci	int res;							\
298c2ecf20Sopenharmony_ci									\
308c2ecf20Sopenharmony_ci	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
318c2ecf20Sopenharmony_ci	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
328c2ecf20Sopenharmony_ci}									\
338c2ecf20Sopenharmony_ci									\
348c2ecf20Sopenharmony_cistatic const struct file_operations name## _ops = {			\
358c2ecf20Sopenharmony_ci	.read = name## _read,						\
368c2ecf20Sopenharmony_ci	.open = simple_open,						\
378c2ecf20Sopenharmony_ci	.llseek	= generic_file_llseek,					\
388c2ecf20Sopenharmony_ci};
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define DEBUGFS_ADD(name, parent)					\
418c2ecf20Sopenharmony_ci	wl->debugfs.name = debugfs_create_file(#name, 0400, parent,	\
428c2ecf20Sopenharmony_ci					       wl, &name## _ops);	\
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define DEBUGFS_DEL(name)						\
458c2ecf20Sopenharmony_ci	do {								\
468c2ecf20Sopenharmony_ci		debugfs_remove(wl->debugfs.name);			\
478c2ecf20Sopenharmony_ci		wl->debugfs.name = NULL;				\
488c2ecf20Sopenharmony_ci	} while (0)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt)			\
518c2ecf20Sopenharmony_cistatic ssize_t sub## _ ##name## _read(struct file *file,		\
528c2ecf20Sopenharmony_ci				      char __user *userbuf,		\
538c2ecf20Sopenharmony_ci				      size_t count, loff_t *ppos)	\
548c2ecf20Sopenharmony_ci{									\
558c2ecf20Sopenharmony_ci	struct wl1251 *wl = file->private_data;				\
568c2ecf20Sopenharmony_ci	char buf[buflen];						\
578c2ecf20Sopenharmony_ci	int res;							\
588c2ecf20Sopenharmony_ci									\
598c2ecf20Sopenharmony_ci	wl1251_debugfs_update_stats(wl);				\
608c2ecf20Sopenharmony_ci									\
618c2ecf20Sopenharmony_ci	res = scnprintf(buf, buflen, fmt "\n",				\
628c2ecf20Sopenharmony_ci			wl->stats.fw_stats->sub.name);			\
638c2ecf20Sopenharmony_ci	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
648c2ecf20Sopenharmony_ci}									\
658c2ecf20Sopenharmony_ci									\
668c2ecf20Sopenharmony_cistatic const struct file_operations sub## _ ##name## _ops = {		\
678c2ecf20Sopenharmony_ci	.read = sub## _ ##name## _read,					\
688c2ecf20Sopenharmony_ci	.open = simple_open,						\
698c2ecf20Sopenharmony_ci	.llseek	= generic_file_llseek,					\
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define DEBUGFS_FWSTATS_ADD(sub, name)				\
738c2ecf20Sopenharmony_ci	DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define DEBUGFS_FWSTATS_DEL(sub, name)				\
768c2ecf20Sopenharmony_ci	DEBUGFS_DEL(sub## _ ##name)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic void wl1251_debugfs_update_stats(struct wl1251 *wl)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	int ret;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	mutex_lock(&wl->mutex);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	ret = wl1251_ps_elp_wakeup(wl);
858c2ecf20Sopenharmony_ci	if (ret < 0)
868c2ecf20Sopenharmony_ci		goto out;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (wl->state == WL1251_STATE_ON &&
898c2ecf20Sopenharmony_ci	    time_after(jiffies, wl->stats.fw_stats_update +
908c2ecf20Sopenharmony_ci		       msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) {
918c2ecf20Sopenharmony_ci		wl1251_acx_statistics(wl, wl->stats.fw_stats);
928c2ecf20Sopenharmony_ci		wl->stats.fw_stats_update = jiffies;
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	wl1251_ps_elp_sleep(wl);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciout:
988c2ecf20Sopenharmony_ci	mutex_unlock(&wl->mutex);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
1048c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
1058c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
1068c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
1078c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
1088c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
1098c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
1108c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
1138c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
1148c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
1158c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
1188c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
1198c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
1208c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
1218c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
1228c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
1238c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
1248c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
1258c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
1268c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
1278c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
1288c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
1298c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
1308c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
1318c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
1328c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
1338c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
1348c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
1378c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
1388c2ecf20Sopenharmony_ci/* skipping wep.reserved */
1398c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
1408c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
1418c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
1428c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
1458c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
1468c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
1478c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
1488c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
1498c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
1508c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
1518c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
1528c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
1538c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
1548c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
1558c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
1568c2ecf20Sopenharmony_ci/* skipping cont_miss_bcns_spread for now */
1578c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
1608c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
1638c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
1648c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
1658c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
1668c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
1678c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
1708c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
1718c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
1728c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
1738c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
1748c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
1758c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
1768c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
1798c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
1808c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
1818c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
1828c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
1838c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
1848c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
1878c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
1888c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
1898c2ecf20Sopenharmony_ci		     20, "%u");
1908c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
1918c2ecf20Sopenharmony_ciDEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ciDEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
1948c2ecf20Sopenharmony_ciDEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
1958c2ecf20Sopenharmony_ci		      wl->stats.excessive_retries);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
1988c2ecf20Sopenharmony_ci				 size_t count, loff_t *ppos)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	struct wl1251 *wl = file->private_data;
2018c2ecf20Sopenharmony_ci	u32 queue_len;
2028c2ecf20Sopenharmony_ci	char buf[20];
2038c2ecf20Sopenharmony_ci	int res;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	queue_len = skb_queue_len(&wl->tx_queue);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
2088c2ecf20Sopenharmony_ci	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic const struct file_operations tx_queue_len_ops = {
2128c2ecf20Sopenharmony_ci	.read = tx_queue_len_read,
2138c2ecf20Sopenharmony_ci	.open = simple_open,
2148c2ecf20Sopenharmony_ci	.llseek = generic_file_llseek,
2158c2ecf20Sopenharmony_ci};
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
2188c2ecf20Sopenharmony_ci				    size_t count, loff_t *ppos)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	struct wl1251 *wl = file->private_data;
2218c2ecf20Sopenharmony_ci	char buf[3], status;
2228c2ecf20Sopenharmony_ci	int len;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	if (wl->tx_queue_stopped)
2258c2ecf20Sopenharmony_ci		status = 's';
2268c2ecf20Sopenharmony_ci	else
2278c2ecf20Sopenharmony_ci		status = 'r';
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	len = scnprintf(buf, sizeof(buf), "%c\n", status);
2308c2ecf20Sopenharmony_ci	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistatic const struct file_operations tx_queue_status_ops = {
2348c2ecf20Sopenharmony_ci	.read = tx_queue_status_read,
2358c2ecf20Sopenharmony_ci	.open = simple_open,
2368c2ecf20Sopenharmony_ci	.llseek = generic_file_llseek,
2378c2ecf20Sopenharmony_ci};
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic void wl1251_debugfs_delete_files(struct wl1251 *wl)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
2448c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
2458c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
2468c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, dropped);
2478c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, fcs_err);
2488c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
2498c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, path_reset);
2508c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rx, reset_counter);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(dma, rx_requested);
2538c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(dma, rx_errors);
2548c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(dma, tx_requested);
2558c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(dma, tx_errors);
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
2588c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, fiqs);
2598c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, rx_headers);
2608c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
2618c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
2628c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, irqs);
2638c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, tx_procs);
2648c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
2658c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, dma0_done);
2668c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, dma1_done);
2678c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
2688c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, commands);
2698c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, rx_procs);
2708c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
2718c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
2728c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, pci_pm);
2738c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, wakeups);
2748c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(isr, low_rssi);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
2778c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(wep, default_key_count);
2788c2ecf20Sopenharmony_ci	/* skipping wep.reserved */
2798c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(wep, key_not_found);
2808c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
2818c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(wep, packets);
2828c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(wep, interrupt);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
2858c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
2868c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
2878c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
2888c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
2898c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
2908c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
2918c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
2928c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
2938c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
2948c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
2958c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
2968c2ecf20Sopenharmony_ci	/* skipping cont_miss_bcns_spread for now */
2978c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
3008c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(mic, calc_failure);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
3038c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
3048c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
3058c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
3068c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
3078c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, heart_beat);
3108c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, calibration);
3118c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
3128c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
3138c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, rx_pool);
3148c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, oom_late);
3158c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
3168c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(event, tx_stuck);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
3198c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
3208c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
3218c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
3228c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
3238c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
3248c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
3278c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
3288c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
3298c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
3308c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	DEBUGFS_DEL(tx_queue_len);
3338c2ecf20Sopenharmony_ci	DEBUGFS_DEL(tx_queue_status);
3348c2ecf20Sopenharmony_ci	DEBUGFS_DEL(retry_count);
3358c2ecf20Sopenharmony_ci	DEBUGFS_DEL(excessive_retries);
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic void wl1251_debugfs_add_files(struct wl1251 *wl)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
3438c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
3448c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
3458c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, dropped);
3468c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, fcs_err);
3478c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
3488c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, path_reset);
3498c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rx, reset_counter);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(dma, rx_requested);
3528c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(dma, rx_errors);
3538c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(dma, tx_requested);
3548c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(dma, tx_errors);
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
3578c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, fiqs);
3588c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, rx_headers);
3598c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
3608c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
3618c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, irqs);
3628c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, tx_procs);
3638c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
3648c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, dma0_done);
3658c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, dma1_done);
3668c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
3678c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, commands);
3688c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, rx_procs);
3698c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
3708c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
3718c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, pci_pm);
3728c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, wakeups);
3738c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(isr, low_rssi);
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
3768c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(wep, default_key_count);
3778c2ecf20Sopenharmony_ci	/* skipping wep.reserved */
3788c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(wep, key_not_found);
3798c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
3808c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(wep, packets);
3818c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(wep, interrupt);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
3848c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
3858c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
3868c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
3878c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
3888c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
3898c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
3908c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
3918c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
3928c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
3938c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
3948c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
3958c2ecf20Sopenharmony_ci	/* skipping cont_miss_bcns_spread for now */
3968c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
3998c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(mic, calc_failure);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
4028c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
4038c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
4048c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
4058c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
4068c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, heart_beat);
4098c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, calibration);
4108c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
4118c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
4128c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, rx_pool);
4138c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, oom_late);
4148c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
4158c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(event, tx_stuck);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
4188c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
4198c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
4208c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
4218c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
4228c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
4238c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
4268c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
4278c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
4288c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
4298c2ecf20Sopenharmony_ci	DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir);
4328c2ecf20Sopenharmony_ci	DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir);
4338c2ecf20Sopenharmony_ci	DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
4348c2ecf20Sopenharmony_ci	DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_civoid wl1251_debugfs_reset(struct wl1251 *wl)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	if (wl->stats.fw_stats != NULL)
4408c2ecf20Sopenharmony_ci		memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
4418c2ecf20Sopenharmony_ci	wl->stats.retry_count = 0;
4428c2ecf20Sopenharmony_ci	wl->stats.excessive_retries = 0;
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ciint wl1251_debugfs_init(struct wl1251 *wl)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), GFP_KERNEL);
4488c2ecf20Sopenharmony_ci	if (!wl->stats.fw_stats)
4498c2ecf20Sopenharmony_ci		return -ENOMEM;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
4548c2ecf20Sopenharmony_ci						       wl->debugfs.rootdir);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	wl->stats.fw_stats_update = jiffies;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	wl1251_debugfs_add_files(wl);
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	return 0;
4618c2ecf20Sopenharmony_ci}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_civoid wl1251_debugfs_exit(struct wl1251 *wl)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	wl1251_debugfs_delete_files(wl);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	kfree(wl->stats.fw_stats);
4688c2ecf20Sopenharmony_ci	wl->stats.fw_stats = NULL;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	debugfs_remove(wl->debugfs.fw_statistics);
4718c2ecf20Sopenharmony_ci	wl->debugfs.fw_statistics = NULL;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	debugfs_remove(wl->debugfs.rootdir);
4748c2ecf20Sopenharmony_ci	wl->debugfs.rootdir = NULL;
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_ci}
477