xref: /openbmc/linux/drivers/net/wireless/ti/wl1251/debugfs.c (revision f277683477c7bdff8236e731cf882b3ef89dde0d)
190921014SLuciano Coelho /*
290921014SLuciano Coelho  * This file is part of wl1251
390921014SLuciano Coelho  *
490921014SLuciano Coelho  * Copyright (C) 2009 Nokia Corporation
590921014SLuciano Coelho  *
690921014SLuciano Coelho  * This program is free software; you can redistribute it and/or
790921014SLuciano Coelho  * modify it under the terms of the GNU General Public License
890921014SLuciano Coelho  * version 2 as published by the Free Software Foundation.
990921014SLuciano Coelho  *
1090921014SLuciano Coelho  * This program is distributed in the hope that it will be useful, but
1190921014SLuciano Coelho  * WITHOUT ANY WARRANTY; without even the implied warranty of
1290921014SLuciano Coelho  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1390921014SLuciano Coelho  * General Public License for more details.
1490921014SLuciano Coelho  *
1590921014SLuciano Coelho  * You should have received a copy of the GNU General Public License
1690921014SLuciano Coelho  * along with this program; if not, write to the Free Software
1790921014SLuciano Coelho  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
1890921014SLuciano Coelho  * 02110-1301 USA
1990921014SLuciano Coelho  *
2090921014SLuciano Coelho  */
2190921014SLuciano Coelho 
2290921014SLuciano Coelho #include "debugfs.h"
2390921014SLuciano Coelho 
2490921014SLuciano Coelho #include <linux/skbuff.h>
2590921014SLuciano Coelho #include <linux/slab.h>
2690921014SLuciano Coelho 
2790921014SLuciano Coelho #include "wl1251.h"
2890921014SLuciano Coelho #include "acx.h"
2990921014SLuciano Coelho #include "ps.h"
3090921014SLuciano Coelho 
3190921014SLuciano Coelho /* ms */
3290921014SLuciano Coelho #define WL1251_DEBUGFS_STATS_LIFETIME 1000
3390921014SLuciano Coelho 
3490921014SLuciano Coelho /* debugfs macros idea from mac80211 */
3590921014SLuciano Coelho 
3690921014SLuciano Coelho #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
3790921014SLuciano Coelho static ssize_t name## _read(struct file *file, char __user *userbuf,	\
3890921014SLuciano Coelho 			    size_t count, loff_t *ppos)			\
3990921014SLuciano Coelho {									\
4090921014SLuciano Coelho 	struct wl1251 *wl = file->private_data;				\
4190921014SLuciano Coelho 	char buf[buflen];						\
4290921014SLuciano Coelho 	int res;							\
4390921014SLuciano Coelho 									\
4490921014SLuciano Coelho 	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
4590921014SLuciano Coelho 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
4690921014SLuciano Coelho }									\
4790921014SLuciano Coelho 									\
4890921014SLuciano Coelho static const struct file_operations name## _ops = {			\
4990921014SLuciano Coelho 	.read = name## _read,						\
50*f2776834SJohn W. Linville 	.open = simple_open,						\
5190921014SLuciano Coelho 	.llseek	= generic_file_llseek,					\
5290921014SLuciano Coelho };
5390921014SLuciano Coelho 
5490921014SLuciano Coelho #define DEBUGFS_ADD(name, parent)					\
5590921014SLuciano Coelho 	wl->debugfs.name = debugfs_create_file(#name, 0400, parent,	\
5690921014SLuciano Coelho 					       wl, &name## _ops);	\
5790921014SLuciano Coelho 	if (IS_ERR(wl->debugfs.name)) {					\
5890921014SLuciano Coelho 		ret = PTR_ERR(wl->debugfs.name);			\
5990921014SLuciano Coelho 		wl->debugfs.name = NULL;				\
6090921014SLuciano Coelho 		goto out;						\
6190921014SLuciano Coelho 	}
6290921014SLuciano Coelho 
6390921014SLuciano Coelho #define DEBUGFS_DEL(name)						\
6490921014SLuciano Coelho 	do {								\
6590921014SLuciano Coelho 		debugfs_remove(wl->debugfs.name);			\
6690921014SLuciano Coelho 		wl->debugfs.name = NULL;				\
6790921014SLuciano Coelho 	} while (0)
6890921014SLuciano Coelho 
6990921014SLuciano Coelho #define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt)			\
7090921014SLuciano Coelho static ssize_t sub## _ ##name## _read(struct file *file,		\
7190921014SLuciano Coelho 				      char __user *userbuf,		\
7290921014SLuciano Coelho 				      size_t count, loff_t *ppos)	\
7390921014SLuciano Coelho {									\
7490921014SLuciano Coelho 	struct wl1251 *wl = file->private_data;				\
7590921014SLuciano Coelho 	char buf[buflen];						\
7690921014SLuciano Coelho 	int res;							\
7790921014SLuciano Coelho 									\
7890921014SLuciano Coelho 	wl1251_debugfs_update_stats(wl);				\
7990921014SLuciano Coelho 									\
8090921014SLuciano Coelho 	res = scnprintf(buf, buflen, fmt "\n",				\
8190921014SLuciano Coelho 			wl->stats.fw_stats->sub.name);			\
8290921014SLuciano Coelho 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
8390921014SLuciano Coelho }									\
8490921014SLuciano Coelho 									\
8590921014SLuciano Coelho static const struct file_operations sub## _ ##name## _ops = {		\
8690921014SLuciano Coelho 	.read = sub## _ ##name## _read,					\
87*f2776834SJohn W. Linville 	.open = simple_open,						\
8890921014SLuciano Coelho 	.llseek	= generic_file_llseek,					\
8990921014SLuciano Coelho };
9090921014SLuciano Coelho 
9190921014SLuciano Coelho #define DEBUGFS_FWSTATS_ADD(sub, name)				\
9290921014SLuciano Coelho 	DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
9390921014SLuciano Coelho 
9490921014SLuciano Coelho #define DEBUGFS_FWSTATS_DEL(sub, name)				\
9590921014SLuciano Coelho 	DEBUGFS_DEL(sub## _ ##name)
9690921014SLuciano Coelho 
9790921014SLuciano Coelho static void wl1251_debugfs_update_stats(struct wl1251 *wl)
9890921014SLuciano Coelho {
9990921014SLuciano Coelho 	int ret;
10090921014SLuciano Coelho 
10190921014SLuciano Coelho 	mutex_lock(&wl->mutex);
10290921014SLuciano Coelho 
10390921014SLuciano Coelho 	ret = wl1251_ps_elp_wakeup(wl);
10490921014SLuciano Coelho 	if (ret < 0)
10590921014SLuciano Coelho 		goto out;
10690921014SLuciano Coelho 
10790921014SLuciano Coelho 	if (wl->state == WL1251_STATE_ON &&
10890921014SLuciano Coelho 	    time_after(jiffies, wl->stats.fw_stats_update +
10990921014SLuciano Coelho 		       msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) {
11090921014SLuciano Coelho 		wl1251_acx_statistics(wl, wl->stats.fw_stats);
11190921014SLuciano Coelho 		wl->stats.fw_stats_update = jiffies;
11290921014SLuciano Coelho 	}
11390921014SLuciano Coelho 
11490921014SLuciano Coelho 	wl1251_ps_elp_sleep(wl);
11590921014SLuciano Coelho 
11690921014SLuciano Coelho out:
11790921014SLuciano Coelho 	mutex_unlock(&wl->mutex);
11890921014SLuciano Coelho }
11990921014SLuciano Coelho 
12090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
12190921014SLuciano Coelho 
12290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
12390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
12490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
12590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
12690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
12790921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
12890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
12990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
13090921014SLuciano Coelho 
13190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
13290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
13390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
13490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
13590921014SLuciano Coelho 
13690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
13790921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
13890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
13990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
14090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
14190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
14290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
14390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
14490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
14590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
14690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
14790921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
14890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
14990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
15090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
15190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
15290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
15390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
15490921014SLuciano Coelho 
15590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
15690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
15790921014SLuciano Coelho /* skipping wep.reserved */
15890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
15990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
16090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
16190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
16290921014SLuciano Coelho 
16390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
16490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
16590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
16690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
16790921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
16890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
16990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
17090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
17190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
17290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
17390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
17490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
17590921014SLuciano Coelho /* skipping cont_miss_bcns_spread for now */
17690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
17790921014SLuciano Coelho 
17890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
17990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
18090921014SLuciano Coelho 
18190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
18290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
18390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
18490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
18590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
18690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
18790921014SLuciano Coelho 
18890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
18990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
19090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
19190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
19290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
19390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
19490921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
19590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
19690921014SLuciano Coelho 
19790921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
19890921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
19990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
20090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
20190921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
20290921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
20390921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
20490921014SLuciano Coelho 
20590921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
20690921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
20790921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
20890921014SLuciano Coelho 		     20, "%u");
20990921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
21090921014SLuciano Coelho DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
21190921014SLuciano Coelho 
21290921014SLuciano Coelho DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
21390921014SLuciano Coelho DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
21490921014SLuciano Coelho 		      wl->stats.excessive_retries);
21590921014SLuciano Coelho 
21690921014SLuciano Coelho static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
21790921014SLuciano Coelho 				 size_t count, loff_t *ppos)
21890921014SLuciano Coelho {
21990921014SLuciano Coelho 	struct wl1251 *wl = file->private_data;
22090921014SLuciano Coelho 	u32 queue_len;
22190921014SLuciano Coelho 	char buf[20];
22290921014SLuciano Coelho 	int res;
22390921014SLuciano Coelho 
22490921014SLuciano Coelho 	queue_len = skb_queue_len(&wl->tx_queue);
22590921014SLuciano Coelho 
22690921014SLuciano Coelho 	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
22790921014SLuciano Coelho 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
22890921014SLuciano Coelho }
22990921014SLuciano Coelho 
23090921014SLuciano Coelho static const struct file_operations tx_queue_len_ops = {
23190921014SLuciano Coelho 	.read = tx_queue_len_read,
232*f2776834SJohn W. Linville 	.open = simple_open,
23390921014SLuciano Coelho 	.llseek = generic_file_llseek,
23490921014SLuciano Coelho };
23590921014SLuciano Coelho 
23690921014SLuciano Coelho static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf,
23790921014SLuciano Coelho 				    size_t count, loff_t *ppos)
23890921014SLuciano Coelho {
23990921014SLuciano Coelho 	struct wl1251 *wl = file->private_data;
24090921014SLuciano Coelho 	char buf[3], status;
24190921014SLuciano Coelho 	int len;
24290921014SLuciano Coelho 
24390921014SLuciano Coelho 	if (wl->tx_queue_stopped)
24490921014SLuciano Coelho 		status = 's';
24590921014SLuciano Coelho 	else
24690921014SLuciano Coelho 		status = 'r';
24790921014SLuciano Coelho 
24890921014SLuciano Coelho 	len = scnprintf(buf, sizeof(buf), "%c\n", status);
24990921014SLuciano Coelho 	return simple_read_from_buffer(userbuf, count, ppos, buf, len);
25090921014SLuciano Coelho }
25190921014SLuciano Coelho 
25290921014SLuciano Coelho static const struct file_operations tx_queue_status_ops = {
25390921014SLuciano Coelho 	.read = tx_queue_status_read,
254*f2776834SJohn W. Linville 	.open = simple_open,
25590921014SLuciano Coelho 	.llseek = generic_file_llseek,
25690921014SLuciano Coelho };
25790921014SLuciano Coelho 
25890921014SLuciano Coelho static void wl1251_debugfs_delete_files(struct wl1251 *wl)
25990921014SLuciano Coelho {
26090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
26190921014SLuciano Coelho 
26290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
26390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
26490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
26590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, dropped);
26690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, fcs_err);
26790921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
26890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, path_reset);
26990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rx, reset_counter);
27090921014SLuciano Coelho 
27190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(dma, rx_requested);
27290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(dma, rx_errors);
27390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(dma, tx_requested);
27490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(dma, tx_errors);
27590921014SLuciano Coelho 
27690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
27790921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, fiqs);
27890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, rx_headers);
27990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
28090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
28190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, irqs);
28290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, tx_procs);
28390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
28490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, dma0_done);
28590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, dma1_done);
28690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
28790921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, commands);
28890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, rx_procs);
28990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
29090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
29190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, pci_pm);
29290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, wakeups);
29390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(isr, low_rssi);
29490921014SLuciano Coelho 
29590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
29690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(wep, default_key_count);
29790921014SLuciano Coelho 	/* skipping wep.reserved */
29890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(wep, key_not_found);
29990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
30090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(wep, packets);
30190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(wep, interrupt);
30290921014SLuciano Coelho 
30390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
30490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
30590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
30690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
30790921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
30890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
30990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
31090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
31190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
31290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
31390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
31490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
31590921014SLuciano Coelho 	/* skipping cont_miss_bcns_spread for now */
31690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
31790921014SLuciano Coelho 
31890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
31990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(mic, calc_failure);
32090921014SLuciano Coelho 
32190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
32290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
32390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
32490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
32590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
32690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
32790921014SLuciano Coelho 
32890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, heart_beat);
32990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, calibration);
33090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
33190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
33290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, rx_pool);
33390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, oom_late);
33490921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
33590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(event, tx_stuck);
33690921014SLuciano Coelho 
33790921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
33890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
33990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
34090921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
34190921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
34290921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
34390921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
34490921014SLuciano Coelho 
34590921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
34690921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
34790921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
34890921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
34990921014SLuciano Coelho 	DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
35090921014SLuciano Coelho 
35190921014SLuciano Coelho 	DEBUGFS_DEL(tx_queue_len);
35290921014SLuciano Coelho 	DEBUGFS_DEL(tx_queue_status);
35390921014SLuciano Coelho 	DEBUGFS_DEL(retry_count);
35490921014SLuciano Coelho 	DEBUGFS_DEL(excessive_retries);
35590921014SLuciano Coelho }
35690921014SLuciano Coelho 
35790921014SLuciano Coelho static int wl1251_debugfs_add_files(struct wl1251 *wl)
35890921014SLuciano Coelho {
35990921014SLuciano Coelho 	int ret = 0;
36090921014SLuciano Coelho 
36190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
36290921014SLuciano Coelho 
36390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
36490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
36590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
36690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, dropped);
36790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, fcs_err);
36890921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
36990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, path_reset);
37090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rx, reset_counter);
37190921014SLuciano Coelho 
37290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(dma, rx_requested);
37390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(dma, rx_errors);
37490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(dma, tx_requested);
37590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(dma, tx_errors);
37690921014SLuciano Coelho 
37790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
37890921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, fiqs);
37990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, rx_headers);
38090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
38190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
38290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, irqs);
38390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, tx_procs);
38490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
38590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, dma0_done);
38690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, dma1_done);
38790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
38890921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, commands);
38990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, rx_procs);
39090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
39190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
39290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, pci_pm);
39390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, wakeups);
39490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(isr, low_rssi);
39590921014SLuciano Coelho 
39690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
39790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(wep, default_key_count);
39890921014SLuciano Coelho 	/* skipping wep.reserved */
39990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(wep, key_not_found);
40090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
40190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(wep, packets);
40290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(wep, interrupt);
40390921014SLuciano Coelho 
40490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
40590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
40690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
40790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
40890921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
40990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
41090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
41190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
41290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
41390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
41490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
41590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
41690921014SLuciano Coelho 	/* skipping cont_miss_bcns_spread for now */
41790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
41890921014SLuciano Coelho 
41990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
42090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(mic, calc_failure);
42190921014SLuciano Coelho 
42290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
42390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
42490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
42590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
42690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
42790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
42890921014SLuciano Coelho 
42990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, heart_beat);
43090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, calibration);
43190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
43290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
43390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, rx_pool);
43490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, oom_late);
43590921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
43690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(event, tx_stuck);
43790921014SLuciano Coelho 
43890921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
43990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
44090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
44190921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
44290921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
44390921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
44490921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
44590921014SLuciano Coelho 
44690921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
44790921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
44890921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
44990921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
45090921014SLuciano Coelho 	DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
45190921014SLuciano Coelho 
45290921014SLuciano Coelho 	DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir);
45390921014SLuciano Coelho 	DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir);
45490921014SLuciano Coelho 	DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
45590921014SLuciano Coelho 	DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
45690921014SLuciano Coelho 
45790921014SLuciano Coelho out:
45890921014SLuciano Coelho 	if (ret < 0)
45990921014SLuciano Coelho 		wl1251_debugfs_delete_files(wl);
46090921014SLuciano Coelho 
46190921014SLuciano Coelho 	return ret;
46290921014SLuciano Coelho }
46390921014SLuciano Coelho 
46490921014SLuciano Coelho void wl1251_debugfs_reset(struct wl1251 *wl)
46590921014SLuciano Coelho {
46690921014SLuciano Coelho 	if (wl->stats.fw_stats != NULL)
46790921014SLuciano Coelho 		memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
46890921014SLuciano Coelho 	wl->stats.retry_count = 0;
46990921014SLuciano Coelho 	wl->stats.excessive_retries = 0;
47090921014SLuciano Coelho }
47190921014SLuciano Coelho 
47290921014SLuciano Coelho int wl1251_debugfs_init(struct wl1251 *wl)
47390921014SLuciano Coelho {
47490921014SLuciano Coelho 	int ret;
47590921014SLuciano Coelho 
47690921014SLuciano Coelho 	wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
47790921014SLuciano Coelho 
47890921014SLuciano Coelho 	if (IS_ERR(wl->debugfs.rootdir)) {
47990921014SLuciano Coelho 		ret = PTR_ERR(wl->debugfs.rootdir);
48090921014SLuciano Coelho 		wl->debugfs.rootdir = NULL;
48190921014SLuciano Coelho 		goto err;
48290921014SLuciano Coelho 	}
48390921014SLuciano Coelho 
48490921014SLuciano Coelho 	wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
48590921014SLuciano Coelho 						       wl->debugfs.rootdir);
48690921014SLuciano Coelho 
48790921014SLuciano Coelho 	if (IS_ERR(wl->debugfs.fw_statistics)) {
48890921014SLuciano Coelho 		ret = PTR_ERR(wl->debugfs.fw_statistics);
48990921014SLuciano Coelho 		wl->debugfs.fw_statistics = NULL;
49090921014SLuciano Coelho 		goto err_root;
49190921014SLuciano Coelho 	}
49290921014SLuciano Coelho 
49390921014SLuciano Coelho 	wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
49490921014SLuciano Coelho 				      GFP_KERNEL);
49590921014SLuciano Coelho 
49690921014SLuciano Coelho 	if (!wl->stats.fw_stats) {
49790921014SLuciano Coelho 		ret = -ENOMEM;
49890921014SLuciano Coelho 		goto err_fw;
49990921014SLuciano Coelho 	}
50090921014SLuciano Coelho 
50190921014SLuciano Coelho 	wl->stats.fw_stats_update = jiffies;
50290921014SLuciano Coelho 
50390921014SLuciano Coelho 	ret = wl1251_debugfs_add_files(wl);
50490921014SLuciano Coelho 
50590921014SLuciano Coelho 	if (ret < 0)
50690921014SLuciano Coelho 		goto err_file;
50790921014SLuciano Coelho 
50890921014SLuciano Coelho 	return 0;
50990921014SLuciano Coelho 
51090921014SLuciano Coelho err_file:
51190921014SLuciano Coelho 	kfree(wl->stats.fw_stats);
51290921014SLuciano Coelho 	wl->stats.fw_stats = NULL;
51390921014SLuciano Coelho 
51490921014SLuciano Coelho err_fw:
51590921014SLuciano Coelho 	debugfs_remove(wl->debugfs.fw_statistics);
51690921014SLuciano Coelho 	wl->debugfs.fw_statistics = NULL;
51790921014SLuciano Coelho 
51890921014SLuciano Coelho err_root:
51990921014SLuciano Coelho 	debugfs_remove(wl->debugfs.rootdir);
52090921014SLuciano Coelho 	wl->debugfs.rootdir = NULL;
52190921014SLuciano Coelho 
52290921014SLuciano Coelho err:
52390921014SLuciano Coelho 	return ret;
52490921014SLuciano Coelho }
52590921014SLuciano Coelho 
52690921014SLuciano Coelho void wl1251_debugfs_exit(struct wl1251 *wl)
52790921014SLuciano Coelho {
52890921014SLuciano Coelho 	wl1251_debugfs_delete_files(wl);
52990921014SLuciano Coelho 
53090921014SLuciano Coelho 	kfree(wl->stats.fw_stats);
53190921014SLuciano Coelho 	wl->stats.fw_stats = NULL;
53290921014SLuciano Coelho 
53390921014SLuciano Coelho 	debugfs_remove(wl->debugfs.fw_statistics);
53490921014SLuciano Coelho 	wl->debugfs.fw_statistics = NULL;
53590921014SLuciano Coelho 
53690921014SLuciano Coelho 	debugfs_remove(wl->debugfs.rootdir);
53790921014SLuciano Coelho 	wl->debugfs.rootdir = NULL;
53890921014SLuciano Coelho 
53990921014SLuciano Coelho }
540