xref: /linux/net/mac80211/debugfs.c (revision 199d69f27326858b16449eb1cc1623299db64415)
17bcfaf2fSJohannes Berg 
2e9f207f0SJiri Benc /*
3e9f207f0SJiri Benc  * mac80211 debugfs for wireless PHYs
4e9f207f0SJiri Benc  *
5e9f207f0SJiri Benc  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
6e9f207f0SJiri Benc  *
7e9f207f0SJiri Benc  * GPLv2
8e9f207f0SJiri Benc  *
9e9f207f0SJiri Benc  */
10e9f207f0SJiri Benc 
11e9f207f0SJiri Benc #include <linux/debugfs.h>
12e9f207f0SJiri Benc #include <linux/rtnetlink.h>
13e9f207f0SJiri Benc #include "ieee80211_i.h"
1424487981SJohannes Berg #include "driver-ops.h"
152c8dccc7SJohannes Berg #include "rate.h"
16e9f207f0SJiri Benc #include "debugfs.h"
17e9f207f0SJiri Benc 
18e9f207f0SJiri Benc int mac80211_open_file_generic(struct inode *inode, struct file *file)
19e9f207f0SJiri Benc {
20e9f207f0SJiri Benc 	file->private_data = inode->i_private;
21e9f207f0SJiri Benc 	return 0;
22e9f207f0SJiri Benc }
23e9f207f0SJiri Benc 
24e9f207f0SJiri Benc #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
25e9f207f0SJiri Benc static ssize_t name## _read(struct file *file, char __user *userbuf,	\
26e9f207f0SJiri Benc 			    size_t count, loff_t *ppos)			\
27e9f207f0SJiri Benc {									\
28e9f207f0SJiri Benc 	struct ieee80211_local *local = file->private_data;		\
29e9f207f0SJiri Benc 	char buf[buflen];						\
30e9f207f0SJiri Benc 	int res;							\
31e9f207f0SJiri Benc 									\
32e9f207f0SJiri Benc 	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
33e9f207f0SJiri Benc 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
34e9f207f0SJiri Benc }									\
35e9f207f0SJiri Benc 									\
36e9f207f0SJiri Benc static const struct file_operations name## _ops = {			\
37e9f207f0SJiri Benc 	.read = name## _read,						\
38e9f207f0SJiri Benc 	.open = mac80211_open_file_generic,				\
39e9f207f0SJiri Benc };
40e9f207f0SJiri Benc 
41e9f207f0SJiri Benc #define DEBUGFS_ADD(name)						\
427bcfaf2fSJohannes Berg 	debugfs_create_file(#name, 0400, phyd, local, &name## _ops);
43e9f207f0SJiri Benc 
44827b1fb4SJohannes Berg #define DEBUGFS_ADD_MODE(name, mode)					\
457bcfaf2fSJohannes Berg 	debugfs_create_file(#name, mode, phyd, local, &name## _ops);
46e9f207f0SJiri Benc 
47e9f207f0SJiri Benc 
48e9f207f0SJiri Benc DEBUGFS_READONLY_FILE(frequency, 20, "%d",
498318d78aSJohannes Berg 		      local->hw.conf.channel->center_freq);
50e9f207f0SJiri Benc DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
51e9f207f0SJiri Benc 		      local->total_ps_buffered);
523b5d665bSAlina Friedrichsen DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
53e9f207f0SJiri Benc 		      local->wep_iv & 0xffffff);
54e9f207f0SJiri Benc DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
55af65cd96SJohannes Berg 	local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
563b5d665bSAlina Friedrichsen 
573b5d665bSAlina Friedrichsen static ssize_t tsf_read(struct file *file, char __user *user_buf,
583b5d665bSAlina Friedrichsen 			     size_t count, loff_t *ppos)
593b5d665bSAlina Friedrichsen {
603b5d665bSAlina Friedrichsen 	struct ieee80211_local *local = file->private_data;
6124487981SJohannes Berg 	u64 tsf;
623b5d665bSAlina Friedrichsen 	char buf[100];
633b5d665bSAlina Friedrichsen 
6424487981SJohannes Berg 	tsf = drv_get_tsf(local);
653b5d665bSAlina Friedrichsen 
663b5d665bSAlina Friedrichsen 	snprintf(buf, sizeof(buf), "0x%016llx\n", (unsigned long long) tsf);
673b5d665bSAlina Friedrichsen 
683b5d665bSAlina Friedrichsen 	return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
693b5d665bSAlina Friedrichsen }
703b5d665bSAlina Friedrichsen 
713b5d665bSAlina Friedrichsen static ssize_t tsf_write(struct file *file,
723b5d665bSAlina Friedrichsen                          const char __user *user_buf,
733b5d665bSAlina Friedrichsen                          size_t count, loff_t *ppos)
743b5d665bSAlina Friedrichsen {
753b5d665bSAlina Friedrichsen 	struct ieee80211_local *local = file->private_data;
763b5d665bSAlina Friedrichsen 	unsigned long long tsf;
773b5d665bSAlina Friedrichsen 	char buf[100];
783b5d665bSAlina Friedrichsen 	size_t len;
793b5d665bSAlina Friedrichsen 
803b5d665bSAlina Friedrichsen 	len = min(count, sizeof(buf) - 1);
813b5d665bSAlina Friedrichsen 	if (copy_from_user(buf, user_buf, len))
823b5d665bSAlina Friedrichsen 		return -EFAULT;
833b5d665bSAlina Friedrichsen 	buf[len] = '\0';
843b5d665bSAlina Friedrichsen 
853b5d665bSAlina Friedrichsen 	if (strncmp(buf, "reset", 5) == 0) {
863b5d665bSAlina Friedrichsen 		if (local->ops->reset_tsf) {
8724487981SJohannes Berg 			drv_reset_tsf(local);
883b5d665bSAlina Friedrichsen 			printk(KERN_INFO "%s: debugfs reset TSF\n", wiphy_name(local->hw.wiphy));
893b5d665bSAlina Friedrichsen 		}
903b5d665bSAlina Friedrichsen 	} else {
913b5d665bSAlina Friedrichsen 		tsf = simple_strtoul(buf, NULL, 0);
923b5d665bSAlina Friedrichsen 		if (local->ops->set_tsf) {
9324487981SJohannes Berg 			drv_set_tsf(local, tsf);
943b5d665bSAlina Friedrichsen 			printk(KERN_INFO "%s: debugfs set TSF to %#018llx\n", wiphy_name(local->hw.wiphy), tsf);
953b5d665bSAlina Friedrichsen 		}
963b5d665bSAlina Friedrichsen 	}
973b5d665bSAlina Friedrichsen 
983b5d665bSAlina Friedrichsen 	return count;
993b5d665bSAlina Friedrichsen }
1003b5d665bSAlina Friedrichsen 
1013b5d665bSAlina Friedrichsen static const struct file_operations tsf_ops = {
1023b5d665bSAlina Friedrichsen 	.read = tsf_read,
1033b5d665bSAlina Friedrichsen 	.write = tsf_write,
1043b5d665bSAlina Friedrichsen 	.open = mac80211_open_file_generic
1053b5d665bSAlina Friedrichsen };
106e9f207f0SJiri Benc 
107827b1fb4SJohannes Berg static ssize_t reset_write(struct file *file, const char __user *user_buf,
108827b1fb4SJohannes Berg 			   size_t count, loff_t *ppos)
109827b1fb4SJohannes Berg {
110827b1fb4SJohannes Berg 	struct ieee80211_local *local = file->private_data;
111827b1fb4SJohannes Berg 
112827b1fb4SJohannes Berg 	rtnl_lock();
113827b1fb4SJohannes Berg 	__ieee80211_suspend(&local->hw);
114827b1fb4SJohannes Berg 	__ieee80211_resume(&local->hw);
115827b1fb4SJohannes Berg 	rtnl_unlock();
116827b1fb4SJohannes Berg 
117827b1fb4SJohannes Berg 	return count;
118827b1fb4SJohannes Berg }
119827b1fb4SJohannes Berg 
120827b1fb4SJohannes Berg static const struct file_operations reset_ops = {
121827b1fb4SJohannes Berg 	.write = reset_write,
122827b1fb4SJohannes Berg 	.open = mac80211_open_file_generic,
123827b1fb4SJohannes Berg };
124827b1fb4SJohannes Berg 
125d3707d99SJohannes Berg static ssize_t noack_read(struct file *file, char __user *user_buf,
126d3707d99SJohannes Berg 			  size_t count, loff_t *ppos)
127d3707d99SJohannes Berg {
128d3707d99SJohannes Berg 	struct ieee80211_local *local = file->private_data;
129d3707d99SJohannes Berg 	int res;
130d3707d99SJohannes Berg 	char buf[10];
131d3707d99SJohannes Berg 
132d3707d99SJohannes Berg 	res = scnprintf(buf, sizeof(buf), "%d\n", local->wifi_wme_noack_test);
133d3707d99SJohannes Berg 
134d3707d99SJohannes Berg 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
135d3707d99SJohannes Berg }
136d3707d99SJohannes Berg 
137d3707d99SJohannes Berg static ssize_t noack_write(struct file *file,
138d3707d99SJohannes Berg 			   const char __user *user_buf,
139d3707d99SJohannes Berg 			   size_t count, loff_t *ppos)
140d3707d99SJohannes Berg {
141d3707d99SJohannes Berg 	struct ieee80211_local *local = file->private_data;
142d3707d99SJohannes Berg 	char buf[10];
143d3707d99SJohannes Berg 	size_t len;
144d3707d99SJohannes Berg 
145d3707d99SJohannes Berg 	len = min(count, sizeof(buf) - 1);
146d3707d99SJohannes Berg 	if (copy_from_user(buf, user_buf, len))
147d3707d99SJohannes Berg 		return -EFAULT;
148d3707d99SJohannes Berg 	buf[len] = '\0';
149d3707d99SJohannes Berg 
150d3707d99SJohannes Berg 	local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0);
151d3707d99SJohannes Berg 
152d3707d99SJohannes Berg 	return count;
153d3707d99SJohannes Berg }
154d3707d99SJohannes Berg 
155d3707d99SJohannes Berg static const struct file_operations noack_ops = {
156d3707d99SJohannes Berg 	.read = noack_read,
157d3707d99SJohannes Berg 	.write = noack_write,
158d3707d99SJohannes Berg 	.open = mac80211_open_file_generic
159d3707d99SJohannes Berg };
160d3707d99SJohannes Berg 
16150ae0cf1SKalle Valo static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
16250ae0cf1SKalle Valo 				 size_t count, loff_t *ppos)
16350ae0cf1SKalle Valo {
16450ae0cf1SKalle Valo 	struct ieee80211_local *local = file->private_data;
16550ae0cf1SKalle Valo 	int res;
16650ae0cf1SKalle Valo 	char buf[10];
16750ae0cf1SKalle Valo 
16850ae0cf1SKalle Valo 	res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_queues);
16950ae0cf1SKalle Valo 
17050ae0cf1SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
17150ae0cf1SKalle Valo }
17250ae0cf1SKalle Valo 
17350ae0cf1SKalle Valo static ssize_t uapsd_queues_write(struct file *file,
17450ae0cf1SKalle Valo 				  const char __user *user_buf,
17550ae0cf1SKalle Valo 				  size_t count, loff_t *ppos)
17650ae0cf1SKalle Valo {
17750ae0cf1SKalle Valo 	struct ieee80211_local *local = file->private_data;
17850ae0cf1SKalle Valo 	unsigned long val;
17950ae0cf1SKalle Valo 	char buf[10];
18050ae0cf1SKalle Valo 	size_t len;
18150ae0cf1SKalle Valo 	int ret;
18250ae0cf1SKalle Valo 
18350ae0cf1SKalle Valo 	len = min(count, sizeof(buf) - 1);
18450ae0cf1SKalle Valo 	if (copy_from_user(buf, user_buf, len))
18550ae0cf1SKalle Valo 		return -EFAULT;
18650ae0cf1SKalle Valo 	buf[len] = '\0';
18750ae0cf1SKalle Valo 
18850ae0cf1SKalle Valo 	ret = strict_strtoul(buf, 0, &val);
18950ae0cf1SKalle Valo 
19050ae0cf1SKalle Valo 	if (ret)
19150ae0cf1SKalle Valo 		return -EINVAL;
19250ae0cf1SKalle Valo 
19350ae0cf1SKalle Valo 	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
19450ae0cf1SKalle Valo 		return -ERANGE;
19550ae0cf1SKalle Valo 
19650ae0cf1SKalle Valo 	local->uapsd_queues = val;
19750ae0cf1SKalle Valo 
19850ae0cf1SKalle Valo 	return count;
19950ae0cf1SKalle Valo }
20050ae0cf1SKalle Valo 
20150ae0cf1SKalle Valo static const struct file_operations uapsd_queues_ops = {
20250ae0cf1SKalle Valo 	.read = uapsd_queues_read,
20350ae0cf1SKalle Valo 	.write = uapsd_queues_write,
20450ae0cf1SKalle Valo 	.open = mac80211_open_file_generic
20550ae0cf1SKalle Valo };
20650ae0cf1SKalle Valo 
20750ae0cf1SKalle Valo static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
20850ae0cf1SKalle Valo 				     size_t count, loff_t *ppos)
20950ae0cf1SKalle Valo {
21050ae0cf1SKalle Valo 	struct ieee80211_local *local = file->private_data;
21150ae0cf1SKalle Valo 	int res;
21250ae0cf1SKalle Valo 	char buf[10];
21350ae0cf1SKalle Valo 
21450ae0cf1SKalle Valo 	res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_max_sp_len);
21550ae0cf1SKalle Valo 
21650ae0cf1SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
21750ae0cf1SKalle Valo }
21850ae0cf1SKalle Valo 
21950ae0cf1SKalle Valo static ssize_t uapsd_max_sp_len_write(struct file *file,
22050ae0cf1SKalle Valo 				      const char __user *user_buf,
22150ae0cf1SKalle Valo 				      size_t count, loff_t *ppos)
22250ae0cf1SKalle Valo {
22350ae0cf1SKalle Valo 	struct ieee80211_local *local = file->private_data;
22450ae0cf1SKalle Valo 	unsigned long val;
22550ae0cf1SKalle Valo 	char buf[10];
22650ae0cf1SKalle Valo 	size_t len;
22750ae0cf1SKalle Valo 	int ret;
22850ae0cf1SKalle Valo 
22950ae0cf1SKalle Valo 	len = min(count, sizeof(buf) - 1);
23050ae0cf1SKalle Valo 	if (copy_from_user(buf, user_buf, len))
23150ae0cf1SKalle Valo 		return -EFAULT;
23250ae0cf1SKalle Valo 	buf[len] = '\0';
23350ae0cf1SKalle Valo 
23450ae0cf1SKalle Valo 	ret = strict_strtoul(buf, 0, &val);
23550ae0cf1SKalle Valo 
23650ae0cf1SKalle Valo 	if (ret)
23750ae0cf1SKalle Valo 		return -EINVAL;
23850ae0cf1SKalle Valo 
23950ae0cf1SKalle Valo 	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
24050ae0cf1SKalle Valo 		return -ERANGE;
24150ae0cf1SKalle Valo 
24250ae0cf1SKalle Valo 	local->uapsd_max_sp_len = val;
24350ae0cf1SKalle Valo 
24450ae0cf1SKalle Valo 	return count;
24550ae0cf1SKalle Valo }
24650ae0cf1SKalle Valo 
24750ae0cf1SKalle Valo static const struct file_operations uapsd_max_sp_len_ops = {
24850ae0cf1SKalle Valo 	.read = uapsd_max_sp_len_read,
24950ae0cf1SKalle Valo 	.write = uapsd_max_sp_len_write,
25050ae0cf1SKalle Valo 	.open = mac80211_open_file_generic
25150ae0cf1SKalle Valo };
25250ae0cf1SKalle Valo 
253*199d69f2SBenoit Papillault static ssize_t channel_type_read(struct file *file, char __user *user_buf,
254*199d69f2SBenoit Papillault 		       size_t count, loff_t *ppos)
255*199d69f2SBenoit Papillault {
256*199d69f2SBenoit Papillault 	struct ieee80211_local *local = file->private_data;
257*199d69f2SBenoit Papillault 	const char *buf;
258*199d69f2SBenoit Papillault 
259*199d69f2SBenoit Papillault 	switch (local->hw.conf.channel_type) {
260*199d69f2SBenoit Papillault 	case NL80211_CHAN_NO_HT:
261*199d69f2SBenoit Papillault 		buf = "no ht\n";
262*199d69f2SBenoit Papillault 		break;
263*199d69f2SBenoit Papillault 	case NL80211_CHAN_HT20:
264*199d69f2SBenoit Papillault 		buf = "ht20\n";
265*199d69f2SBenoit Papillault 		break;
266*199d69f2SBenoit Papillault 	case NL80211_CHAN_HT40MINUS:
267*199d69f2SBenoit Papillault 		buf = "ht40-\n";
268*199d69f2SBenoit Papillault 		break;
269*199d69f2SBenoit Papillault 	case NL80211_CHAN_HT40PLUS:
270*199d69f2SBenoit Papillault 		buf = "ht40+\n";
271*199d69f2SBenoit Papillault 		break;
272*199d69f2SBenoit Papillault 	default:
273*199d69f2SBenoit Papillault 		buf = "???";
274*199d69f2SBenoit Papillault 		break;
275*199d69f2SBenoit Papillault 	}
276*199d69f2SBenoit Papillault 
277*199d69f2SBenoit Papillault 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
278*199d69f2SBenoit Papillault }
279*199d69f2SBenoit Papillault 
280*199d69f2SBenoit Papillault static const struct file_operations channel_type_ops = {
281*199d69f2SBenoit Papillault 	.read = channel_type_read,
282*199d69f2SBenoit Papillault 	.open = mac80211_open_file_generic
283*199d69f2SBenoit Papillault };
284*199d69f2SBenoit Papillault 
285db2e6bd4SJohannes Berg static ssize_t queues_read(struct file *file, char __user *user_buf,
286db2e6bd4SJohannes Berg 			   size_t count, loff_t *ppos)
287db2e6bd4SJohannes Berg {
288db2e6bd4SJohannes Berg 	struct ieee80211_local *local = file->private_data;
289db2e6bd4SJohannes Berg 	unsigned long flags;
290db2e6bd4SJohannes Berg 	char buf[IEEE80211_MAX_QUEUES * 20];
291db2e6bd4SJohannes Berg 	int q, res = 0;
292db2e6bd4SJohannes Berg 
293db2e6bd4SJohannes Berg 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
294db2e6bd4SJohannes Berg 	for (q = 0; q < local->hw.queues; q++)
295db2e6bd4SJohannes Berg 		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
296db2e6bd4SJohannes Berg 				local->queue_stop_reasons[q],
2973b8d81e0SJohannes Berg 				skb_queue_len(&local->pending[q]));
298db2e6bd4SJohannes Berg 	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
299db2e6bd4SJohannes Berg 
300db2e6bd4SJohannes Berg 	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
301db2e6bd4SJohannes Berg }
302db2e6bd4SJohannes Berg 
303db2e6bd4SJohannes Berg static const struct file_operations queues_ops = {
304db2e6bd4SJohannes Berg 	.read = queues_read,
305db2e6bd4SJohannes Berg 	.open = mac80211_open_file_generic
306db2e6bd4SJohannes Berg };
307db2e6bd4SJohannes Berg 
308e9f207f0SJiri Benc /* statistics stuff */
309e9f207f0SJiri Benc 
310e9f207f0SJiri Benc #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)			\
311e9f207f0SJiri Benc 	DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
312e9f207f0SJiri Benc 
313e9f207f0SJiri Benc static ssize_t format_devstat_counter(struct ieee80211_local *local,
314e9f207f0SJiri Benc 	char __user *userbuf,
315e9f207f0SJiri Benc 	size_t count, loff_t *ppos,
316e9f207f0SJiri Benc 	int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
317e9f207f0SJiri Benc 			  int buflen))
318e9f207f0SJiri Benc {
319e9f207f0SJiri Benc 	struct ieee80211_low_level_stats stats;
320e9f207f0SJiri Benc 	char buf[20];
321e9f207f0SJiri Benc 	int res;
322e9f207f0SJiri Benc 
32375636525SJohannes Berg 	rtnl_lock();
32424487981SJohannes Berg 	res = drv_get_stats(local, &stats);
325e9f207f0SJiri Benc 	rtnl_unlock();
32624487981SJohannes Berg 	if (res)
32724487981SJohannes Berg 		return res;
328e9f207f0SJiri Benc 	res = printvalue(&stats, buf, sizeof(buf));
329e9f207f0SJiri Benc 	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
330e9f207f0SJiri Benc }
331e9f207f0SJiri Benc 
332e9f207f0SJiri Benc #define DEBUGFS_DEVSTATS_FILE(name)					\
333e9f207f0SJiri Benc static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
334e9f207f0SJiri Benc 				 char *buf, int buflen)			\
335e9f207f0SJiri Benc {									\
336e9f207f0SJiri Benc 	return scnprintf(buf, buflen, "%u\n", stats->name);		\
337e9f207f0SJiri Benc }									\
338e9f207f0SJiri Benc static ssize_t stats_ ##name## _read(struct file *file,			\
339e9f207f0SJiri Benc 				     char __user *userbuf,		\
340e9f207f0SJiri Benc 				     size_t count, loff_t *ppos)	\
341e9f207f0SJiri Benc {									\
342e9f207f0SJiri Benc 	return format_devstat_counter(file->private_data,		\
343e9f207f0SJiri Benc 				      userbuf,				\
344e9f207f0SJiri Benc 				      count,				\
345e9f207f0SJiri Benc 				      ppos,				\
346e9f207f0SJiri Benc 				      print_devstats_##name);		\
347e9f207f0SJiri Benc }									\
348e9f207f0SJiri Benc 									\
349e9f207f0SJiri Benc static const struct file_operations stats_ ##name## _ops = {		\
350e9f207f0SJiri Benc 	.read = stats_ ##name## _read,					\
351e9f207f0SJiri Benc 	.open = mac80211_open_file_generic,				\
352e9f207f0SJiri Benc };
353e9f207f0SJiri Benc 
354e9f207f0SJiri Benc #define DEBUGFS_STATS_ADD(name)						\
3557bcfaf2fSJohannes Berg 	debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
356e9f207f0SJiri Benc 
357e9f207f0SJiri Benc DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
358e9f207f0SJiri Benc 		   local->dot11TransmittedFragmentCount);
359e9f207f0SJiri Benc DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
360e9f207f0SJiri Benc 		   local->dot11MulticastTransmittedFrameCount);
361e9f207f0SJiri Benc DEBUGFS_STATS_FILE(failed_count, 20, "%u",
362e9f207f0SJiri Benc 		   local->dot11FailedCount);
363e9f207f0SJiri Benc DEBUGFS_STATS_FILE(retry_count, 20, "%u",
364e9f207f0SJiri Benc 		   local->dot11RetryCount);
365e9f207f0SJiri Benc DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
366e9f207f0SJiri Benc 		   local->dot11MultipleRetryCount);
367e9f207f0SJiri Benc DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
368e9f207f0SJiri Benc 		   local->dot11FrameDuplicateCount);
369e9f207f0SJiri Benc DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
370e9f207f0SJiri Benc 		   local->dot11ReceivedFragmentCount);
371e9f207f0SJiri Benc DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
372e9f207f0SJiri Benc 		   local->dot11MulticastReceivedFrameCount);
373e9f207f0SJiri Benc DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
374e9f207f0SJiri Benc 		   local->dot11TransmittedFrameCount);
375e9f207f0SJiri Benc #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
376e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
377e9f207f0SJiri Benc 		   local->tx_handlers_drop);
378e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
379e9f207f0SJiri Benc 		   local->tx_handlers_queued);
380e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
381e9f207f0SJiri Benc 		   local->tx_handlers_drop_unencrypted);
382e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
383e9f207f0SJiri Benc 		   local->tx_handlers_drop_fragment);
384e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
385e9f207f0SJiri Benc 		   local->tx_handlers_drop_wep);
386e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
387e9f207f0SJiri Benc 		   local->tx_handlers_drop_not_assoc);
388e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
389e9f207f0SJiri Benc 		   local->tx_handlers_drop_unauth_port);
390e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
391e9f207f0SJiri Benc 		   local->rx_handlers_drop);
392e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
393e9f207f0SJiri Benc 		   local->rx_handlers_queued);
394e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
395e9f207f0SJiri Benc 		   local->rx_handlers_drop_nullfunc);
396e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
397e9f207f0SJiri Benc 		   local->rx_handlers_drop_defrag);
398e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
399e9f207f0SJiri Benc 		   local->rx_handlers_drop_short);
400e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
401e9f207f0SJiri Benc 		   local->rx_handlers_drop_passive_scan);
402e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
403e9f207f0SJiri Benc 		   local->tx_expand_skb_head);
404e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
405e9f207f0SJiri Benc 		   local->tx_expand_skb_head_cloned);
406e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
407e9f207f0SJiri Benc 		   local->rx_expand_skb_head);
408e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
409e9f207f0SJiri Benc 		   local->rx_expand_skb_head2);
410e9f207f0SJiri Benc DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
411e9f207f0SJiri Benc 		   local->rx_handlers_fragments);
412e9f207f0SJiri Benc DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
413e9f207f0SJiri Benc 		   local->tx_status_drop);
414e9f207f0SJiri Benc 
415e9f207f0SJiri Benc #endif
416e9f207f0SJiri Benc 
417e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
418e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
419e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
420e9f207f0SJiri Benc DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
421e9f207f0SJiri Benc 
422e9f207f0SJiri Benc 
423e9f207f0SJiri Benc void debugfs_hw_add(struct ieee80211_local *local)
424e9f207f0SJiri Benc {
425e9f207f0SJiri Benc 	struct dentry *phyd = local->hw.wiphy->debugfsdir;
426e9f207f0SJiri Benc 	struct dentry *statsd;
427e9f207f0SJiri Benc 
428e9f207f0SJiri Benc 	if (!phyd)
429e9f207f0SJiri Benc 		return;
430e9f207f0SJiri Benc 
431e9f207f0SJiri Benc 	local->debugfs.stations = debugfs_create_dir("stations", phyd);
432e9f207f0SJiri Benc 	local->debugfs.keys = debugfs_create_dir("keys", phyd);
433e9f207f0SJiri Benc 
434e9f207f0SJiri Benc 	DEBUGFS_ADD(frequency);
435e9f207f0SJiri Benc 	DEBUGFS_ADD(total_ps_buffered);
436e9f207f0SJiri Benc 	DEBUGFS_ADD(wep_iv);
437ae54c985SAlina Friedrichsen 	DEBUGFS_ADD(tsf);
438db2e6bd4SJohannes Berg 	DEBUGFS_ADD(queues);
439827b1fb4SJohannes Berg 	DEBUGFS_ADD_MODE(reset, 0200);
440d3707d99SJohannes Berg 	DEBUGFS_ADD(noack);
44150ae0cf1SKalle Valo 	DEBUGFS_ADD(uapsd_queues);
44250ae0cf1SKalle Valo 	DEBUGFS_ADD(uapsd_max_sp_len);
443*199d69f2SBenoit Papillault 	DEBUGFS_ADD(channel_type);
444e9f207f0SJiri Benc 
445e9f207f0SJiri Benc 	statsd = debugfs_create_dir("statistics", phyd);
446e9f207f0SJiri Benc 
447e9f207f0SJiri Benc 	/* if the dir failed, don't put all the other things into the root! */
448e9f207f0SJiri Benc 	if (!statsd)
449e9f207f0SJiri Benc 		return;
450e9f207f0SJiri Benc 
451e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(transmitted_fragment_count);
452e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(multicast_transmitted_frame_count);
453e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(failed_count);
454e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(retry_count);
455e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(multiple_retry_count);
456e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(frame_duplicate_count);
457e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(received_fragment_count);
458e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(multicast_received_frame_count);
459e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(transmitted_frame_count);
460e9f207f0SJiri Benc #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
461e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_drop);
462e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_queued);
463e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted);
464e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_drop_fragment);
465e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
466e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
467e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
468e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_drop);
469e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_queued);
470e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
471e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
472e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_drop_short);
473e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan);
474e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_expand_skb_head);
475e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
476e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_expand_skb_head);
477e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_expand_skb_head2);
478e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(rx_handlers_fragments);
479e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(tx_status_drop);
480e9f207f0SJiri Benc #endif
481e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(dot11ACKFailureCount);
482e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(dot11RTSFailureCount);
483e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(dot11FCSErrorCount);
484e9f207f0SJiri Benc 	DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
485e9f207f0SJiri Benc }
486