debugfs.c 14.6 KB
Newer Older
1

J
Jiri Benc 已提交
2 3 4 5 6 7 8 9 10 11 12 13
/*
 * mac80211 debugfs for wireless PHYs
 *
 * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
 *
 * GPLv2
 *
 */

#include <linux/debugfs.h>
#include <linux/rtnetlink.h>
#include "ieee80211_i.h"
14
#include "driver-ops.h"
J
Johannes Berg 已提交
15
#include "rate.h"
J
Jiri Benc 已提交
16 17
#include "debugfs.h"

18 19
#define DEBUGFS_FORMAT_BUFFER_SIZE 100

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
#define TX_LATENCY_BIN_DELIMTER_C ','
#define TX_LATENCY_BIN_DELIMTER_S ","
#define TX_LATENCY_BINS_DISABLED "enable(bins disabled)\n"
#define TX_LATENCY_DISABLED "disable\n"


/*
 * Display if Tx latency statistics & bins are enabled/disabled
 */
static ssize_t sta_tx_latency_stat_read(struct file *file,
					char __user *userbuf,
					size_t count, loff_t *ppos)
{
	struct ieee80211_local *local = file->private_data;
	struct ieee80211_tx_latency_bin_ranges  *tx_latency;
	char *buf;
	int bufsz, i, ret;
	int pos = 0;

	rcu_read_lock();

	tx_latency = rcu_dereference(local->tx_latency);

	if (tx_latency && tx_latency->n_ranges) {
		bufsz = tx_latency->n_ranges * 15;
		buf = kzalloc(bufsz, GFP_ATOMIC);
		if (!buf)
			goto err;

		for (i = 0; i < tx_latency->n_ranges; i++)
			pos += scnprintf(buf + pos, bufsz - pos, "%d,",
					 tx_latency->ranges[i]);
		pos += scnprintf(buf + pos, bufsz - pos, "\n");
	} else if (tx_latency) {
		bufsz = sizeof(TX_LATENCY_BINS_DISABLED) + 1;
		buf = kzalloc(bufsz, GFP_ATOMIC);
		if (!buf)
			goto err;

		pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
				 TX_LATENCY_BINS_DISABLED);
	} else {
		bufsz = sizeof(TX_LATENCY_DISABLED) + 1;
		buf = kzalloc(bufsz, GFP_ATOMIC);
		if (!buf)
			goto err;

		pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
				 TX_LATENCY_DISABLED);
	}

	rcu_read_unlock();

	ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
	kfree(buf);

	return ret;
err:
	rcu_read_unlock();
	return -ENOMEM;
}

/*
 * Receive input from user regarding Tx latency statistics
 * The input should indicate if Tx latency statistics and bins are
 * enabled/disabled.
 * If bins are enabled input should indicate the amount of different bins and
 * their ranges. Each bin will count how many Tx frames transmitted within the
 * appropriate latency.
 * Legal input is:
 * a) "enable(bins disabled)" - to enable only general statistics
 * b) "a,b,c,d,...z" - to enable general statistics and bins, where all are
 * numbers and a < b < c < d.. < z
 * c) "disable" - disable all statistics
 * NOTE: must configure Tx latency statistics bins before stations connected.
 */

static ssize_t sta_tx_latency_stat_write(struct file *file,
					 const char __user *userbuf,
					 size_t count, loff_t *ppos)
{
	struct ieee80211_local *local = file->private_data;
	char buf[128] = {};
	char *bins = buf;
	char *token;
	int buf_size, i, alloc_size;
	int prev_bin = 0;
	int n_ranges = 0;
	int ret = count;
	struct ieee80211_tx_latency_bin_ranges  *tx_latency;

	if (sizeof(buf) <= count)
		return -EINVAL;
	buf_size = count;
	if (copy_from_user(buf, userbuf, buf_size))
		return -EFAULT;

	mutex_lock(&local->sta_mtx);

	/* cannot change config once we have stations */
	if (local->num_sta)
		goto unlock;

	tx_latency =
		rcu_dereference_protected(local->tx_latency,
					  lockdep_is_held(&local->sta_mtx));

	/* disable Tx statistics */
	if (!strcmp(buf, TX_LATENCY_DISABLED)) {
		if (!tx_latency)
			goto unlock;
M
Monam Agarwal 已提交
131
		RCU_INIT_POINTER(local->tx_latency, NULL);
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
		synchronize_rcu();
		kfree(tx_latency);
		goto unlock;
	}

	/* Tx latency already enabled */
	if (tx_latency)
		goto unlock;

	if (strcmp(TX_LATENCY_BINS_DISABLED, buf)) {
		/* check how many bins and between what ranges user requested */
		token = buf;
		while (*token != '\0') {
			if (*token == TX_LATENCY_BIN_DELIMTER_C)
				n_ranges++;
			token++;
		}
		n_ranges++;
	}

	alloc_size = sizeof(struct ieee80211_tx_latency_bin_ranges) +
		     n_ranges * sizeof(u32);
	tx_latency = kzalloc(alloc_size, GFP_ATOMIC);
	if (!tx_latency) {
		ret = -ENOMEM;
		goto unlock;
	}
	tx_latency->n_ranges = n_ranges;
	for (i = 0; i < n_ranges; i++) { /* setting bin ranges */
		token = strsep(&bins, TX_LATENCY_BIN_DELIMTER_S);
		sscanf(token, "%d", &tx_latency->ranges[i]);
		/* bins values should be in ascending order */
		if (prev_bin >= tx_latency->ranges[i]) {
			ret = -EINVAL;
			kfree(tx_latency);
			goto unlock;
		}
		prev_bin = tx_latency->ranges[i];
	}
	rcu_assign_pointer(local->tx_latency, tx_latency);

unlock:
	mutex_unlock(&local->sta_mtx);

	return ret;
}

static const struct file_operations stats_tx_latency_ops = {
	.write = sta_tx_latency_stat_write,
	.read = sta_tx_latency_stat_read,
	.open = simple_open,
	.llseek = generic_file_llseek,
};

186 187 188 189 190 191 192 193 194 195 196 197 198 199
int mac80211_format_buffer(char __user *userbuf, size_t count,
				  loff_t *ppos, char *fmt, ...)
{
	va_list args;
	char buf[DEBUGFS_FORMAT_BUFFER_SIZE];
	int res;

	va_start(args, fmt);
	res = vscnprintf(buf, sizeof(buf), fmt, args);
	va_end(args);

	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}

B
Ben Greear 已提交
200
#define DEBUGFS_READONLY_FILE_FN(name, fmt, value...)			\
J
Jiri Benc 已提交
201 202 203 204 205
static ssize_t name## _read(struct file *file, char __user *userbuf,	\
			    size_t count, loff_t *ppos)			\
{									\
	struct ieee80211_local *local = file->private_data;		\
									\
206 207
	return mac80211_format_buffer(userbuf, count, ppos, 		\
				      fmt "\n", ##value);		\
B
Ben Greear 已提交
208 209 210
}

#define DEBUGFS_READONLY_FILE_OPS(name)			\
J
Jiri Benc 已提交
211 212
static const struct file_operations name## _ops = {			\
	.read = name## _read,						\
213
	.open = simple_open,						\
214
	.llseek = generic_file_llseek,					\
J
Jiri Benc 已提交
215 216
};

B
Ben Greear 已提交
217 218 219 220
#define DEBUGFS_READONLY_FILE(name, fmt, value...)		\
	DEBUGFS_READONLY_FILE_FN(name, fmt, value)		\
	DEBUGFS_READONLY_FILE_OPS(name)

J
Jiri Benc 已提交
221
#define DEBUGFS_ADD(name)						\
222
	debugfs_create_file(#name, 0400, phyd, local, &name## _ops);
J
Jiri Benc 已提交
223

224
#define DEBUGFS_ADD_MODE(name, mode)					\
225
	debugfs_create_file(#name, mode, phyd, local, &name## _ops);
J
Jiri Benc 已提交
226 227


B
Ben Greear 已提交
228 229 230 231
DEBUGFS_READONLY_FILE(user_power, "%d",
		      local->user_power_level);
DEBUGFS_READONLY_FILE(power, "%d",
		      local->hw.conf.power_level);
232
DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
J
Jiri Benc 已提交
233
		      local->total_ps_buffered);
234
DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
J
Jiri Benc 已提交
235
		      local->wep_iv & 0xffffff);
236
DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
237
	local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
238

239
#ifdef CONFIG_PM
240 241 242 243 244 245
static ssize_t reset_write(struct file *file, const char __user *user_buf,
			   size_t count, loff_t *ppos)
{
	struct ieee80211_local *local = file->private_data;

	rtnl_lock();
246
	__ieee80211_suspend(&local->hw, NULL);
247 248 249 250 251 252 253 254
	__ieee80211_resume(&local->hw);
	rtnl_unlock();

	return count;
}

static const struct file_operations reset_ops = {
	.write = reset_write,
255
	.open = simple_open,
256
	.llseek = noop_llseek,
257
};
258
#endif
259

B
Ben Greear 已提交
260 261 262 263 264 265 266 267 268
static ssize_t hwflags_read(struct file *file, char __user *user_buf,
			    size_t count, loff_t *ppos)
{
	struct ieee80211_local *local = file->private_data;
	int mxln = 500;
	ssize_t rv;
	char *buf = kzalloc(mxln, GFP_KERNEL);
	int sf = 0; /* how many written so far */

269 270 271
	if (!buf)
		return 0;

E
Eliad Peller 已提交
272
	sf += scnprintf(buf, mxln - sf, "0x%x\n", local->hw.flags);
B
Ben Greear 已提交
273
	if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
E
Eliad Peller 已提交
274
		sf += scnprintf(buf + sf, mxln - sf, "HAS_RATE_CONTROL\n");
B
Ben Greear 已提交
275
	if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
E
Eliad Peller 已提交
276
		sf += scnprintf(buf + sf, mxln - sf, "RX_INCLUDES_FCS\n");
B
Ben Greear 已提交
277
	if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)
E
Eliad Peller 已提交
278 279
		sf += scnprintf(buf + sf, mxln - sf,
				"HOST_BCAST_PS_BUFFERING\n");
B
Ben Greear 已提交
280
	if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)
E
Eliad Peller 已提交
281 282
		sf += scnprintf(buf + sf, mxln - sf,
				"2GHZ_SHORT_SLOT_INCAPABLE\n");
B
Ben Greear 已提交
283
	if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)
E
Eliad Peller 已提交
284 285
		sf += scnprintf(buf + sf, mxln - sf,
				"2GHZ_SHORT_PREAMBLE_INCAPABLE\n");
B
Ben Greear 已提交
286
	if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
E
Eliad Peller 已提交
287
		sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n");
B
Ben Greear 已提交
288
	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
E
Eliad Peller 已提交
289
		sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n");
290
	if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC)
E
Eliad Peller 已提交
291 292
		sf += scnprintf(buf + sf, mxln - sf,
				"NEED_DTIM_BEFORE_ASSOC\n");
B
Ben Greear 已提交
293
	if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)
E
Eliad Peller 已提交
294
		sf += scnprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n");
B
Ben Greear 已提交
295
	if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
E
Eliad Peller 已提交
296
		sf += scnprintf(buf + sf, mxln - sf, "AMPDU_AGGREGATION\n");
B
Ben Greear 已提交
297
	if (local->hw.flags & IEEE80211_HW_SUPPORTS_PS)
E
Eliad Peller 已提交
298
		sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_PS\n");
B
Ben Greear 已提交
299
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
E
Eliad Peller 已提交
300
		sf += scnprintf(buf + sf, mxln - sf, "PS_NULLFUNC_STACK\n");
B
Ben Greear 已提交
301
	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
E
Eliad Peller 已提交
302
		sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_DYNAMIC_PS\n");
B
Ben Greear 已提交
303
	if (local->hw.flags & IEEE80211_HW_MFP_CAPABLE)
E
Eliad Peller 已提交
304
		sf += scnprintf(buf + sf, mxln - sf, "MFP_CAPABLE\n");
B
Ben Greear 已提交
305
	if (local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS)
E
Eliad Peller 已提交
306
		sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_STATIC_SMPS\n");
B
Ben Greear 已提交
307
	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
E
Eliad Peller 已提交
308 309
		sf += scnprintf(buf + sf, mxln - sf,
				"SUPPORTS_DYNAMIC_SMPS\n");
B
Ben Greear 已提交
310
	if (local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
E
Eliad Peller 已提交
311
		sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_UAPSD\n");
B
Ben Greear 已提交
312
	if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
E
Eliad Peller 已提交
313 314
		sf += scnprintf(buf + sf, mxln - sf,
				"REPORTS_TX_ACK_STATUS\n");
B
Ben Greear 已提交
315
	if (local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
E
Eliad Peller 已提交
316
		sf += scnprintf(buf + sf, mxln - sf, "CONNECTION_MONITOR\n");
B
Ben Greear 已提交
317
	if (local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK)
E
Eliad Peller 已提交
318
		sf += scnprintf(buf + sf, mxln - sf, "SUPPORTS_PER_STA_GTK\n");
B
Ben Greear 已提交
319
	if (local->hw.flags & IEEE80211_HW_AP_LINK_PS)
E
Eliad Peller 已提交
320
		sf += scnprintf(buf + sf, mxln - sf, "AP_LINK_PS\n");
321
	if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)
E
Eliad Peller 已提交
322
		sf += scnprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n");
B
Ben Greear 已提交
323 324 325 326 327

	rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
	kfree(buf);
	return rv;
}
328

J
Johannes Berg 已提交
329 330 331 332 333 334 335 336 337 338 339 340
static ssize_t queues_read(struct file *file, char __user *user_buf,
			   size_t count, loff_t *ppos)
{
	struct ieee80211_local *local = file->private_data;
	unsigned long flags;
	char buf[IEEE80211_MAX_QUEUES * 20];
	int q, res = 0;

	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
	for (q = 0; q < local->hw.queues; q++)
		res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
				local->queue_stop_reasons[q],
J
Johannes Berg 已提交
341
				skb_queue_len(&local->pending[q]));
J
Johannes Berg 已提交
342 343 344 345 346
	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);

	return simple_read_from_buffer(user_buf, count, ppos, buf, res);
}

B
Ben Greear 已提交
347 348
DEBUGFS_READONLY_FILE_OPS(hwflags);
DEBUGFS_READONLY_FILE_OPS(queues);
J
Johannes Berg 已提交
349

J
Jiri Benc 已提交
350 351 352 353 354 355 356 357 358 359 360 361
/* statistics stuff */

static ssize_t format_devstat_counter(struct ieee80211_local *local,
	char __user *userbuf,
	size_t count, loff_t *ppos,
	int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
			  int buflen))
{
	struct ieee80211_low_level_stats stats;
	char buf[20];
	int res;

362
	rtnl_lock();
363
	res = drv_get_stats(local, &stats);
J
Jiri Benc 已提交
364
	rtnl_unlock();
365 366 367
	if (res)
		return res;
	res = printvalue(&stats, buf, sizeof(buf));
J
Jiri Benc 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
	return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}

#define DEBUGFS_DEVSTATS_FILE(name)					\
static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
				 char *buf, int buflen)			\
{									\
	return scnprintf(buf, buflen, "%u\n", stats->name);		\
}									\
static ssize_t stats_ ##name## _read(struct file *file,			\
				     char __user *userbuf,		\
				     size_t count, loff_t *ppos)	\
{									\
	return format_devstat_counter(file->private_data,		\
				      userbuf,				\
				      count,				\
				      ppos,				\
				      print_devstats_##name);		\
}									\
									\
static const struct file_operations stats_ ##name## _ops = {		\
	.read = stats_ ##name## _read,					\
390
	.open = simple_open,						\
391
	.llseek = generic_file_llseek,					\
J
Jiri Benc 已提交
392 393
};

394 395 396
#define DEBUGFS_STATS_ADD(name, field)					\
	debugfs_create_u32(#name, 0400, statsd, (u32 *) &field);
#define DEBUGFS_DEVSTATS_ADD(name)					\
397
	debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
J
Jiri Benc 已提交
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415

DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);

void debugfs_hw_add(struct ieee80211_local *local)
{
	struct dentry *phyd = local->hw.wiphy->debugfsdir;
	struct dentry *statsd;

	if (!phyd)
		return;

	local->debugfs.keys = debugfs_create_dir("keys", phyd);

	DEBUGFS_ADD(total_ps_buffered);
	DEBUGFS_ADD(wep_iv);
J
Johannes Berg 已提交
416
	DEBUGFS_ADD(queues);
417
#ifdef CONFIG_PM
418
	DEBUGFS_ADD_MODE(reset, 0200);
419
#endif
B
Ben Greear 已提交
420
	DEBUGFS_ADD(hwflags);
B
Ben Greear 已提交
421 422
	DEBUGFS_ADD(user_power);
	DEBUGFS_ADD(power);
J
Jiri Benc 已提交
423 424 425 426 427 428 429

	statsd = debugfs_create_dir("statistics", phyd);

	/* if the dir failed, don't put all the other things into the root! */
	if (!statsd)
		return;

430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
	DEBUGFS_STATS_ADD(transmitted_fragment_count,
		local->dot11TransmittedFragmentCount);
	DEBUGFS_STATS_ADD(multicast_transmitted_frame_count,
		local->dot11MulticastTransmittedFrameCount);
	DEBUGFS_STATS_ADD(failed_count, local->dot11FailedCount);
	DEBUGFS_STATS_ADD(retry_count, local->dot11RetryCount);
	DEBUGFS_STATS_ADD(multiple_retry_count,
		local->dot11MultipleRetryCount);
	DEBUGFS_STATS_ADD(frame_duplicate_count,
		local->dot11FrameDuplicateCount);
	DEBUGFS_STATS_ADD(received_fragment_count,
		local->dot11ReceivedFragmentCount);
	DEBUGFS_STATS_ADD(multicast_received_frame_count,
		local->dot11MulticastReceivedFrameCount);
	DEBUGFS_STATS_ADD(transmitted_frame_count,
		local->dot11TransmittedFrameCount);
J
Jiri Benc 已提交
446
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop);
	DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued);
	DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted,
		local->tx_handlers_drop_unencrypted);
	DEBUGFS_STATS_ADD(tx_handlers_drop_fragment,
		local->tx_handlers_drop_fragment);
	DEBUGFS_STATS_ADD(tx_handlers_drop_wep,
		local->tx_handlers_drop_wep);
	DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc,
		local->tx_handlers_drop_not_assoc);
	DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port,
		local->tx_handlers_drop_unauth_port);
	DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop);
	DEBUGFS_STATS_ADD(rx_handlers_queued, local->rx_handlers_queued);
	DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc,
		local->rx_handlers_drop_nullfunc);
	DEBUGFS_STATS_ADD(rx_handlers_drop_defrag,
		local->rx_handlers_drop_defrag);
	DEBUGFS_STATS_ADD(rx_handlers_drop_short,
		local->rx_handlers_drop_short);
	DEBUGFS_STATS_ADD(tx_expand_skb_head,
		local->tx_expand_skb_head);
	DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned,
		local->tx_expand_skb_head_cloned);
	DEBUGFS_STATS_ADD(rx_expand_skb_head,
		local->rx_expand_skb_head);
	DEBUGFS_STATS_ADD(rx_expand_skb_head2,
		local->rx_expand_skb_head2);
	DEBUGFS_STATS_ADD(rx_handlers_fragments,
		local->rx_handlers_fragments);
	DEBUGFS_STATS_ADD(tx_status_drop,
		local->tx_status_drop);
J
Jiri Benc 已提交
479
#endif
480 481 482 483
	DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
	DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
	DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
	DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
484 485

	DEBUGFS_DEVSTATS_ADD(tx_latency);
J
Jiri Benc 已提交
486
}