debugfs.c 14.4 KB
Newer Older
1

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

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

19 20
#define DEBUGFS_FORMAT_BUFFER_SIZE 100

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 131
#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 已提交
132
		RCU_INIT_POINTER(local->tx_latency, NULL);
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 186
		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,
};

187 188 189 190 191 192 193 194 195 196 197 198 199 200
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 已提交
201
#define DEBUGFS_READONLY_FILE_FN(name, fmt, value...)			\
J
Jiri Benc 已提交
202 203 204 205 206
static ssize_t name## _read(struct file *file, char __user *userbuf,	\
			    size_t count, loff_t *ppos)			\
{									\
	struct ieee80211_local *local = file->private_data;		\
									\
207 208
	return mac80211_format_buffer(userbuf, count, ppos, 		\
				      fmt "\n", ##value);		\
B
Ben Greear 已提交
209 210 211
}

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

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

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

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


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

240
#ifdef CONFIG_PM
241 242 243 244 245 246
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();
247
	__ieee80211_suspend(&local->hw, NULL);
248 249 250 251 252 253 254 255
	__ieee80211_resume(&local->hw);
	rtnl_unlock();

	return count;
}

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

B
Ben Greear 已提交
261 262 263 264 265 266 267 268 269
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 */

270 271 272
	if (!buf)
		return 0;

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

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

J
Johannes Berg 已提交
325 326 327 328 329 330 331 332 333 334 335 336
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 已提交
337
				skb_queue_len(&local->pending[q]));
J
Johannes Berg 已提交
338 339 340 341 342
	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);

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

B
Ben Greear 已提交
343 344
DEBUGFS_READONLY_FILE_OPS(hwflags);
DEBUGFS_READONLY_FILE_OPS(queues);
J
Johannes Berg 已提交
345

J
Jiri Benc 已提交
346 347 348 349 350 351 352 353 354 355 356 357
/* 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;

358
	rtnl_lock();
359
	res = drv_get_stats(local, &stats);
J
Jiri Benc 已提交
360
	rtnl_unlock();
361 362 363
	if (res)
		return res;
	res = printvalue(&stats, buf, sizeof(buf));
J
Jiri Benc 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
	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,					\
386
	.open = simple_open,						\
387
	.llseek = generic_file_llseek,					\
J
Jiri Benc 已提交
388 389
};

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

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 已提交
412
	DEBUGFS_ADD(queues);
413
#ifdef CONFIG_PM
414
	DEBUGFS_ADD_MODE(reset, 0200);
415
#endif
B
Ben Greear 已提交
416
	DEBUGFS_ADD(hwflags);
B
Ben Greear 已提交
417 418
	DEBUGFS_ADD(user_power);
	DEBUGFS_ADD(power);
J
Jiri Benc 已提交
419 420 421 422 423 424 425

	statsd = debugfs_create_dir("statistics", phyd);

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

426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	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 已提交
442
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
443 444 445 446 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
	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 已提交
475
#endif
476 477 478 479
	DEBUGFS_DEVSTATS_ADD(dot11ACKFailureCount);
	DEBUGFS_DEVSTATS_ADD(dot11RTSFailureCount);
	DEBUGFS_DEVSTATS_ADD(dot11FCSErrorCount);
	DEBUGFS_DEVSTATS_ADD(dot11RTSSuccessCount);
480 481

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