Blame view

net/core/net-sysfs.c 35.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
   * net-sysfs.c - network device class and attributes
   *
   * Copyright (c) 2003 Stephen Hemminger <shemminger@osdl.org>
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
5
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License
   *	as published by the Free Software Foundation; either version
   *	2 of the License, or (at your option) any later version.
   */
4fc268d24   Randy Dunlap   [PATCH] capable/c...
11
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
  #include <linux/kernel.h>
  #include <linux/netdevice.h>
  #include <linux/if_arp.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
15
  #include <linux/slab.h>
608b4b954   Eric W. Biederman   netns: Teach netw...
16
  #include <linux/nsproxy.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <net/sock.h>
608b4b954   Eric W. Biederman   netns: Teach netw...
18
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <linux/rtnetlink.h>
  #include <linux/wireless.h>
fec5e652e   Tom Herbert   rfs: Receive Flow...
21
  #include <linux/vmalloc.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
22
  #include <linux/export.h>
114cf5802   Tom Herbert   bql: Byte queue l...
23
  #include <linux/jiffies.h>
8f1546cad   Johannes Berg   wext: add back wi...
24
  #include <net/wext.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

342709efc   Pavel Emelyanov   [NET]: Remove in-...
26
  #include "net-sysfs.h"
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
27
  #ifdef CONFIG_SYSFS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
  static const char fmt_hex[] = "%#x
  ";
d1102b59c   David S. Miller   [NET]: Use %lx fo...
30
31
  static const char fmt_long_hex[] = "%#lx
  ";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  static const char fmt_dec[] = "%d
  ";
8ae6daca8   David Decotigny   ethtool: Call eth...
34
35
  static const char fmt_udec[] = "%u
  ";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  static const char fmt_ulong[] = "%lu
  ";
be1f3c2c0   Ben Hutchings   net: Enable 64-bi...
38
39
  static const char fmt_u64[] = "%llu
  ";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
41
  static inline int dev_isalive(const struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  {
fe9925b55   Stephen Hemminger   [NET]: Create net...
43
  	return dev->reg_state <= NETREG_REGISTERED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
  }
  
  /* use same locking rules as GIF* ioctl's */
43cb76d91   Greg Kroah-Hartman   Network: convert ...
47
48
  static ssize_t netdev_show(const struct device *dev,
  			   struct device_attribute *attr, char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
  			   ssize_t (*format)(const struct net_device *, char *))
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
51
  	struct net_device *net = to_net_dev(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  	ssize_t ret = -EINVAL;
  
  	read_lock(&dev_base_lock);
  	if (dev_isalive(net))
  		ret = (*format)(net, buf);
  	read_unlock(&dev_base_lock);
  
  	return ret;
  }
  
  /* generate a show function for simple field */
  #define NETDEVICE_SHOW(field, format_string)				\
  static ssize_t format_##field(const struct net_device *net, char *buf)	\
  {									\
  	return sprintf(buf, format_string, net->field);			\
  }									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
68
69
  static ssize_t show_##field(struct device *dev,				\
  			    struct device_attribute *attr, char *buf)	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  {									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
71
  	return netdev_show(dev, attr, buf, format_##field);		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
  }
  
  
  /* use same locking and permission rules as SIF* ioctl's */
43cb76d91   Greg Kroah-Hartman   Network: convert ...
76
  static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  			    const char *buf, size_t len,
  			    int (*set)(struct net_device *, unsigned long))
  {
  	struct net_device *net = to_net_dev(dev);
  	char *endp;
  	unsigned long new;
  	int ret = -EINVAL;
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
  
  	new = simple_strtoul(buf, &endp, 0);
  	if (endp == buf)
  		goto err;
5a5990d30   Stephen Hemminger   net: Avoid race b...
91
  	if (!rtnl_trylock())
336ca57c3   Eric W. Biederman   net-sysfs: Use rt...
92
  		return restart_syscall();
5a5990d30   Stephen Hemminger   net: Avoid race b...
93

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
  	if (dev_isalive(net)) {
  		if ((ret = (*set)(net, new)) == 0)
  			ret = len;
  	}
  	rtnl_unlock();
   err:
  	return ret;
  }
9d29672c6   David Woodhouse   [NET]: Expose net...
102
  NETDEVICE_SHOW(dev_id, fmt_hex);
c1f79426e   Stefan Assmann   sysfs: add attrib...
103
  NETDEVICE_SHOW(addr_assign_type, fmt_dec);
fd586bacf   Kay Sievers   [PATCH] net: swic...
104
105
106
  NETDEVICE_SHOW(addr_len, fmt_dec);
  NETDEVICE_SHOW(iflink, fmt_dec);
  NETDEVICE_SHOW(ifindex, fmt_dec);
fd586bacf   Kay Sievers   [PATCH] net: swic...
107
  NETDEVICE_SHOW(type, fmt_dec);
b00055aac   Stefan Rompf   [NET] core: add R...
108
  NETDEVICE_SHOW(link_mode, fmt_dec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
  
  /* use same locking rules as GIFHWADDR ioctl's */
43cb76d91   Greg Kroah-Hartman   Network: convert ...
111
112
  static ssize_t show_address(struct device *dev, struct device_attribute *attr,
  			    char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
  {
  	struct net_device *net = to_net_dev(dev);
  	ssize_t ret = -EINVAL;
  
  	read_lock(&dev_base_lock);
  	if (dev_isalive(net))
7ffc49a6e   Michael Chan   [ETH]: Combine fo...
119
  		ret = sysfs_format_mac(buf, net->dev_addr, net->addr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
  	read_unlock(&dev_base_lock);
  	return ret;
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
123
124
  static ssize_t show_broadcast(struct device *dev,
  			    struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  {
  	struct net_device *net = to_net_dev(dev);
  	if (dev_isalive(net))
7ffc49a6e   Michael Chan   [ETH]: Combine fo...
128
  		return sysfs_format_mac(buf, net->broadcast, net->addr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
  	return -EINVAL;
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
131
132
  static ssize_t show_carrier(struct device *dev,
  			    struct device_attribute *attr, char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
136
137
138
139
  {
  	struct net_device *netdev = to_net_dev(dev);
  	if (netif_running(netdev)) {
  		return sprintf(buf, fmt_dec, !!netif_carrier_ok(netdev));
  	}
  	return -EINVAL;
  }
d519e17e2   Andy Gospodarek   net: export devic...
140
141
142
143
144
145
146
147
  static ssize_t show_speed(struct device *dev,
  			  struct device_attribute *attr, char *buf)
  {
  	struct net_device *netdev = to_net_dev(dev);
  	int ret = -EINVAL;
  
  	if (!rtnl_trylock())
  		return restart_syscall();
8ae6daca8   David Decotigny   ethtool: Call eth...
148
149
  	if (netif_running(netdev)) {
  		struct ethtool_cmd cmd;
4bc71cb98   Jiri Pirko   net: consolidate ...
150
  		if (!__ethtool_get_settings(netdev, &cmd))
8ae6daca8   David Decotigny   ethtool: Call eth...
151
  			ret = sprintf(buf, fmt_udec, ethtool_cmd_speed(&cmd));
d519e17e2   Andy Gospodarek   net: export devic...
152
153
154
155
156
157
158
159
160
161
162
163
164
  	}
  	rtnl_unlock();
  	return ret;
  }
  
  static ssize_t show_duplex(struct device *dev,
  			   struct device_attribute *attr, char *buf)
  {
  	struct net_device *netdev = to_net_dev(dev);
  	int ret = -EINVAL;
  
  	if (!rtnl_trylock())
  		return restart_syscall();
8ae6daca8   David Decotigny   ethtool: Call eth...
165
166
  	if (netif_running(netdev)) {
  		struct ethtool_cmd cmd;
4bc71cb98   Jiri Pirko   net: consolidate ...
167
  		if (!__ethtool_get_settings(netdev, &cmd))
8ae6daca8   David Decotigny   ethtool: Call eth...
168
169
170
  			ret = sprintf(buf, "%s
  ",
  				      cmd.duplex ? "full" : "half");
d519e17e2   Andy Gospodarek   net: export devic...
171
172
173
174
  	}
  	rtnl_unlock();
  	return ret;
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
175
176
  static ssize_t show_dormant(struct device *dev,
  			    struct device_attribute *attr, char *buf)
b00055aac   Stefan Rompf   [NET] core: add R...
177
178
179
180
181
182
183
184
  {
  	struct net_device *netdev = to_net_dev(dev);
  
  	if (netif_running(netdev))
  		return sprintf(buf, fmt_dec, !!netif_dormant(netdev));
  
  	return -EINVAL;
  }
36cbd3dcc   Jan Engelhardt   net: mark read-on...
185
  static const char *const operstates[] = {
b00055aac   Stefan Rompf   [NET] core: add R...
186
187
188
189
190
191
192
193
  	"unknown",
  	"notpresent", /* currently unused */
  	"down",
  	"lowerlayerdown",
  	"testing", /* currently unused */
  	"dormant",
  	"up"
  };
43cb76d91   Greg Kroah-Hartman   Network: convert ...
194
195
  static ssize_t show_operstate(struct device *dev,
  			      struct device_attribute *attr, char *buf)
b00055aac   Stefan Rompf   [NET] core: add R...
196
197
198
199
200
201
202
203
204
  {
  	const struct net_device *netdev = to_net_dev(dev);
  	unsigned char operstate;
  
  	read_lock(&dev_base_lock);
  	operstate = netdev->operstate;
  	if (!netif_running(netdev))
  		operstate = IF_OPER_DOWN;
  	read_unlock(&dev_base_lock);
e3a5cd9ed   Adrian Bunk   [NET]: Fix an off...
205
  	if (operstate >= ARRAY_SIZE(operstates))
b00055aac   Stefan Rompf   [NET] core: add R...
206
207
208
209
210
  		return -EINVAL; /* should not happen */
  
  	return sprintf(buf, "%s
  ", operstates[operstate]);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
217
  /* read-write attributes */
  NETDEVICE_SHOW(mtu, fmt_dec);
  
  static int change_mtu(struct net_device *net, unsigned long new_mtu)
  {
  	return dev_set_mtu(net, (int) new_mtu);
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
218
219
  static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
  			 const char *buf, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
221
  	return netdev_store(dev, attr, buf, len, change_mtu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
228
  NETDEVICE_SHOW(flags, fmt_hex);
  
  static int change_flags(struct net_device *net, unsigned long new_flags)
  {
  	return dev_change_flags(net, (unsigned) new_flags);
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
229
230
  static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
  			   const char *buf, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
232
  	return netdev_store(dev, attr, buf, len, change_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
238
239
240
  NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
  
  static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
  {
  	net->tx_queue_len = new_len;
  	return 0;
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
241
242
243
  static ssize_t store_tx_queue_len(struct device *dev,
  				  struct device_attribute *attr,
  				  const char *buf, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
245
  	return netdev_store(dev, attr, buf, len, change_tx_queue_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  }
0b815a1a6   Stephen Hemminger   net: network devi...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
  			     const char *buf, size_t len)
  {
  	struct net_device *netdev = to_net_dev(dev);
  	size_t count = len;
  	ssize_t ret;
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
  
  	/* ignore trailing newline */
  	if (len >  0 && buf[len - 1] == '
  ')
  		--count;
336ca57c3   Eric W. Biederman   net-sysfs: Use rt...
261
262
  	if (!rtnl_trylock())
  		return restart_syscall();
0b815a1a6   Stephen Hemminger   net: network devi...
263
264
265
266
267
268
269
270
271
272
273
  	ret = dev_set_alias(netdev, buf, count);
  	rtnl_unlock();
  
  	return ret < 0 ? ret : len;
  }
  
  static ssize_t show_ifalias(struct device *dev,
  			    struct device_attribute *attr, char *buf)
  {
  	const struct net_device *netdev = to_net_dev(dev);
  	ssize_t ret = 0;
336ca57c3   Eric W. Biederman   net-sysfs: Use rt...
274
275
  	if (!rtnl_trylock())
  		return restart_syscall();
0b815a1a6   Stephen Hemminger   net: network devi...
276
277
278
279
280
281
  	if (netdev->ifalias)
  		ret = sprintf(buf, "%s
  ", netdev->ifalias);
  	rtnl_unlock();
  	return ret;
  }
a512b92b3   Vlad Dogaru   net: add sysfs en...
282
283
284
285
286
287
288
289
290
291
292
293
294
  NETDEVICE_SHOW(group, fmt_dec);
  
  static int change_group(struct net_device *net, unsigned long new_group)
  {
  	dev_set_group(net, (int) new_group);
  	return 0;
  }
  
  static ssize_t store_group(struct device *dev, struct device_attribute *attr,
  			 const char *buf, size_t len)
  {
  	return netdev_store(dev, attr, buf, len, change_group);
  }
43cb76d91   Greg Kroah-Hartman   Network: convert ...
295
  static struct device_attribute net_class_attributes[] = {
c1f79426e   Stefan Assmann   sysfs: add attrib...
296
  	__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL),
fd586bacf   Kay Sievers   [PATCH] net: swic...
297
  	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
9d29672c6   David Woodhouse   [NET]: Expose net...
298
  	__ATTR(dev_id, S_IRUGO, show_dev_id, NULL),
0b815a1a6   Stephen Hemminger   net: network devi...
299
  	__ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias),
fd586bacf   Kay Sievers   [PATCH] net: swic...
300
301
  	__ATTR(iflink, S_IRUGO, show_iflink, NULL),
  	__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
fd586bacf   Kay Sievers   [PATCH] net: swic...
302
  	__ATTR(type, S_IRUGO, show_type, NULL),
b00055aac   Stefan Rompf   [NET] core: add R...
303
  	__ATTR(link_mode, S_IRUGO, show_link_mode, NULL),
fd586bacf   Kay Sievers   [PATCH] net: swic...
304
305
306
  	__ATTR(address, S_IRUGO, show_address, NULL),
  	__ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
  	__ATTR(carrier, S_IRUGO, show_carrier, NULL),
d519e17e2   Andy Gospodarek   net: export devic...
307
308
  	__ATTR(speed, S_IRUGO, show_speed, NULL),
  	__ATTR(duplex, S_IRUGO, show_duplex, NULL),
b00055aac   Stefan Rompf   [NET] core: add R...
309
310
  	__ATTR(dormant, S_IRUGO, show_dormant, NULL),
  	__ATTR(operstate, S_IRUGO, show_operstate, NULL),
fd586bacf   Kay Sievers   [PATCH] net: swic...
311
312
313
314
  	__ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
  	__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
  	__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
  	       store_tx_queue_len),
b6644cb70   Xiaotian Feng   net: rename group...
315
  	__ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group),
fd586bacf   Kay Sievers   [PATCH] net: swic...
316
  	{}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
  };
  
  /* Show a given an attribute in the statistics group */
43cb76d91   Greg Kroah-Hartman   Network: convert ...
320
321
  static ssize_t netstat_show(const struct device *d,
  			    struct device_attribute *attr, char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
  			    unsigned long offset)
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
324
  	struct net_device *dev = to_net_dev(d);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	ssize_t ret = -EINVAL;
be1f3c2c0   Ben Hutchings   net: Enable 64-bi...
326
327
  	WARN_ON(offset > sizeof(struct rtnl_link_stats64) ||
  			offset % sizeof(u64) != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  
  	read_lock(&dev_base_lock);
96e74088f   Pavel Emelyanov   net: The dev->get...
330
  	if (dev_isalive(dev)) {
28172739f   Eric Dumazet   net: fix 64 bit c...
331
332
  		struct rtnl_link_stats64 temp;
  		const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);
be1f3c2c0   Ben Hutchings   net: Enable 64-bi...
333
  		ret = sprintf(buf, fmt_u64, *(u64 *)(((u8 *) stats) + offset));
96e74088f   Pavel Emelyanov   net: The dev->get...
334
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
338
339
340
  	read_unlock(&dev_base_lock);
  	return ret;
  }
  
  /* generate a read-only statistics attribute */
  #define NETSTAT_ENTRY(name)						\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
341
342
  static ssize_t show_##name(struct device *d,				\
  			   struct device_attribute *attr, char *buf) 	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  {									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
344
  	return netstat_show(d, attr, buf,				\
be1f3c2c0   Ben Hutchings   net: Enable 64-bi...
345
  			    offsetof(struct rtnl_link_stats64, name));	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  }									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
347
  static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  
  NETSTAT_ENTRY(rx_packets);
  NETSTAT_ENTRY(tx_packets);
  NETSTAT_ENTRY(rx_bytes);
  NETSTAT_ENTRY(tx_bytes);
  NETSTAT_ENTRY(rx_errors);
  NETSTAT_ENTRY(tx_errors);
  NETSTAT_ENTRY(rx_dropped);
  NETSTAT_ENTRY(tx_dropped);
  NETSTAT_ENTRY(multicast);
  NETSTAT_ENTRY(collisions);
  NETSTAT_ENTRY(rx_length_errors);
  NETSTAT_ENTRY(rx_over_errors);
  NETSTAT_ENTRY(rx_crc_errors);
  NETSTAT_ENTRY(rx_frame_errors);
  NETSTAT_ENTRY(rx_fifo_errors);
  NETSTAT_ENTRY(rx_missed_errors);
  NETSTAT_ENTRY(tx_aborted_errors);
  NETSTAT_ENTRY(tx_carrier_errors);
  NETSTAT_ENTRY(tx_fifo_errors);
  NETSTAT_ENTRY(tx_heartbeat_errors);
  NETSTAT_ENTRY(tx_window_errors);
  NETSTAT_ENTRY(rx_compressed);
  NETSTAT_ENTRY(tx_compressed);
  
  static struct attribute *netstat_attrs[] = {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  	&dev_attr_rx_packets.attr,
  	&dev_attr_tx_packets.attr,
  	&dev_attr_rx_bytes.attr,
  	&dev_attr_tx_bytes.attr,
  	&dev_attr_rx_errors.attr,
  	&dev_attr_tx_errors.attr,
  	&dev_attr_rx_dropped.attr,
  	&dev_attr_tx_dropped.attr,
  	&dev_attr_multicast.attr,
  	&dev_attr_collisions.attr,
  	&dev_attr_rx_length_errors.attr,
  	&dev_attr_rx_over_errors.attr,
  	&dev_attr_rx_crc_errors.attr,
  	&dev_attr_rx_frame_errors.attr,
  	&dev_attr_rx_fifo_errors.attr,
  	&dev_attr_rx_missed_errors.attr,
  	&dev_attr_tx_aborted_errors.attr,
  	&dev_attr_tx_carrier_errors.attr,
  	&dev_attr_tx_fifo_errors.attr,
  	&dev_attr_tx_heartbeat_errors.attr,
  	&dev_attr_tx_window_errors.attr,
  	&dev_attr_rx_compressed.attr,
  	&dev_attr_tx_compressed.attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
403
404
  	NULL
  };
  
  
  static struct attribute_group netstat_group = {
  	.name  = "statistics",
  	.attrs  = netstat_attrs,
  };
22bb1be4d   Johannes Berg   wext: make sysfs ...
405
  #ifdef CONFIG_WIRELESS_EXT_SYSFS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  /* helper function that does all the locking etc for wireless stats */
43cb76d91   Greg Kroah-Hartman   Network: convert ...
407
  static ssize_t wireless_show(struct device *d, char *buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
  			     ssize_t (*format)(const struct iw_statistics *,
  					       char *))
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
411
  	struct net_device *dev = to_net_dev(d);
8f1546cad   Johannes Berg   wext: add back wi...
412
  	const struct iw_statistics *iw;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  	ssize_t ret = -EINVAL;
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
414

b8afe6416   Eric W. Biederman   net-sysfs: Use rt...
415
416
  	if (!rtnl_trylock())
  		return restart_syscall();
6dd214b55   Andrey Borzenkov   [PATCH] fix /sys/...
417
  	if (dev_isalive(dev)) {
8f1546cad   Johannes Berg   wext: add back wi...
418
419
  		iw = get_wireless_stats(dev);
  		if (iw)
6dd214b55   Andrey Borzenkov   [PATCH] fix /sys/...
420
421
  			ret = (*format)(iw, buf);
  	}
a160ee69c   Johannes Berg   wext: let get_wir...
422
  	rtnl_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
426
427
428
429
430
431
432
  
  	return ret;
  }
  
  /* show function template for wireless fields */
  #define WIRELESS_SHOW(name, field, format_string)			\
  static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \
  {									\
  	return sprintf(buf, format_string, iw->field);			\
  }									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
433
434
  static ssize_t show_iw_##name(struct device *d,				\
  			      struct device_attribute *attr, char *buf)	\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  {									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
436
  	return wireless_show(d, buf, format_iw_##name);			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  }									\
43cb76d91   Greg Kroah-Hartman   Network: convert ...
438
  static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
443
444
445
446
447
448
449
450
451
  
  WIRELESS_SHOW(status, status, fmt_hex);
  WIRELESS_SHOW(link, qual.qual, fmt_dec);
  WIRELESS_SHOW(level, qual.level, fmt_dec);
  WIRELESS_SHOW(noise, qual.noise, fmt_dec);
  WIRELESS_SHOW(nwid, discard.nwid, fmt_dec);
  WIRELESS_SHOW(crypt, discard.code, fmt_dec);
  WIRELESS_SHOW(fragment, discard.fragment, fmt_dec);
  WIRELESS_SHOW(misc, discard.misc, fmt_dec);
  WIRELESS_SHOW(retries, discard.retries, fmt_dec);
  WIRELESS_SHOW(beacon, miss.beacon, fmt_dec);
  
  static struct attribute *wireless_attrs[] = {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
452
453
454
455
456
457
458
459
460
461
  	&dev_attr_status.attr,
  	&dev_attr_link.attr,
  	&dev_attr_level.attr,
  	&dev_attr_noise.attr,
  	&dev_attr_nwid.attr,
  	&dev_attr_crypt.attr,
  	&dev_attr_fragment.attr,
  	&dev_attr_retries.attr,
  	&dev_attr_misc.attr,
  	&dev_attr_beacon.attr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
464
465
466
467
468
469
  	NULL
  };
  
  static struct attribute_group wireless_group = {
  	.name = "wireless",
  	.attrs = wireless_attrs,
  };
  #endif
d6523ddf2   Eric W. Biederman   net/sysfs: Fix th...
470
  #endif /* CONFIG_SYSFS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
471

30bde1f50   Stephen Rothwell   rps: fix net-sysf...
472
  #ifdef CONFIG_RPS
0a9627f26   Tom Herbert   rps: Receive Pack...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  /*
   * RX queue sysfs structures and functions.
   */
  struct rx_queue_attribute {
  	struct attribute attr;
  	ssize_t (*show)(struct netdev_rx_queue *queue,
  	    struct rx_queue_attribute *attr, char *buf);
  	ssize_t (*store)(struct netdev_rx_queue *queue,
  	    struct rx_queue_attribute *attr, const char *buf, size_t len);
  };
  #define to_rx_queue_attr(_attr) container_of(_attr,		\
      struct rx_queue_attribute, attr)
  
  #define to_rx_queue(obj) container_of(obj, struct netdev_rx_queue, kobj)
  
  static ssize_t rx_queue_attr_show(struct kobject *kobj, struct attribute *attr,
  				  char *buf)
  {
  	struct rx_queue_attribute *attribute = to_rx_queue_attr(attr);
  	struct netdev_rx_queue *queue = to_rx_queue(kobj);
  
  	if (!attribute->show)
  		return -EIO;
  
  	return attribute->show(queue, attribute, buf);
  }
  
  static ssize_t rx_queue_attr_store(struct kobject *kobj, struct attribute *attr,
  				   const char *buf, size_t count)
  {
  	struct rx_queue_attribute *attribute = to_rx_queue_attr(attr);
  	struct netdev_rx_queue *queue = to_rx_queue(kobj);
  
  	if (!attribute->store)
  		return -EIO;
  
  	return attribute->store(queue, attribute, buf, count);
  }
fa50d6457   stephen hemminger   net: make rx_queu...
511
  static const struct sysfs_ops rx_queue_sysfs_ops = {
0a9627f26   Tom Herbert   rps: Receive Pack...
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  	.show = rx_queue_attr_show,
  	.store = rx_queue_attr_store,
  };
  
  static ssize_t show_rps_map(struct netdev_rx_queue *queue,
  			    struct rx_queue_attribute *attribute, char *buf)
  {
  	struct rps_map *map;
  	cpumask_var_t mask;
  	size_t len = 0;
  	int i;
  
  	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
  		return -ENOMEM;
  
  	rcu_read_lock();
  	map = rcu_dereference(queue->rps_map);
  	if (map)
  		for (i = 0; i < map->len; i++)
  			cpumask_set_cpu(map->cpus[i], mask);
  
  	len += cpumask_scnprintf(buf + len, PAGE_SIZE, mask);
  	if (PAGE_SIZE - len < 3) {
  		rcu_read_unlock();
  		free_cpumask_var(mask);
  		return -EINVAL;
  	}
  	rcu_read_unlock();
  
  	free_cpumask_var(mask);
  	len += sprintf(buf + len, "
  ");
  	return len;
  }
f5acb907d   Eric Dumazet   rps: static funct...
546
  static ssize_t store_rps_map(struct netdev_rx_queue *queue,
0a9627f26   Tom Herbert   rps: Receive Pack...
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
  		      struct rx_queue_attribute *attribute,
  		      const char *buf, size_t len)
  {
  	struct rps_map *old_map, *map;
  	cpumask_var_t mask;
  	int err, cpu, i;
  	static DEFINE_SPINLOCK(rps_map_lock);
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
  
  	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
  		return -ENOMEM;
  
  	err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
  	if (err) {
  		free_cpumask_var(mask);
  		return err;
  	}
  
  	map = kzalloc(max_t(unsigned,
  	    RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES),
  	    GFP_KERNEL);
  	if (!map) {
  		free_cpumask_var(mask);
  		return -ENOMEM;
  	}
  
  	i = 0;
  	for_each_cpu_and(cpu, mask, cpu_online_mask)
  		map->cpus[i++] = cpu;
  
  	if (i)
  		map->len = i;
  	else {
  		kfree(map);
  		map = NULL;
  	}
  
  	spin_lock(&rps_map_lock);
6e3f7faf3   Eric Dumazet   rps: add __rcu an...
587
588
  	old_map = rcu_dereference_protected(queue->rps_map,
  					    lockdep_is_held(&rps_map_lock));
0a9627f26   Tom Herbert   rps: Receive Pack...
589
590
  	rcu_assign_pointer(queue->rps_map, map);
  	spin_unlock(&rps_map_lock);
adc9300e7   Eric Dumazet   net: use jump_lab...
591
592
593
  	if (map)
  		jump_label_inc(&rps_needed);
  	if (old_map) {
f6f80238f   Lai Jiangshan   net,rcu: convert ...
594
  		kfree_rcu(old_map, rcu);
adc9300e7   Eric Dumazet   net: use jump_lab...
595
596
  		jump_label_dec(&rps_needed);
  	}
0a9627f26   Tom Herbert   rps: Receive Pack...
597
598
599
  	free_cpumask_var(mask);
  	return len;
  }
fec5e652e   Tom Herbert   rfs: Receive Flow...
600
601
602
603
604
  static ssize_t show_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
  					   struct rx_queue_attribute *attr,
  					   char *buf)
  {
  	struct rps_dev_flow_table *flow_table;
60b778ce5   Eric Dumazet   rfs: better sizin...
605
  	unsigned long val = 0;
fec5e652e   Tom Herbert   rfs: Receive Flow...
606
607
608
609
  
  	rcu_read_lock();
  	flow_table = rcu_dereference(queue->rps_flow_table);
  	if (flow_table)
60b778ce5   Eric Dumazet   rfs: better sizin...
610
  		val = (unsigned long)flow_table->mask + 1;
fec5e652e   Tom Herbert   rfs: Receive Flow...
611
  	rcu_read_unlock();
60b778ce5   Eric Dumazet   rfs: better sizin...
612
613
  	return sprintf(buf, "%lu
  ", val);
fec5e652e   Tom Herbert   rfs: Receive Flow...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  }
  
  static void rps_dev_flow_table_release_work(struct work_struct *work)
  {
  	struct rps_dev_flow_table *table = container_of(work,
  	    struct rps_dev_flow_table, free_work);
  
  	vfree(table);
  }
  
  static void rps_dev_flow_table_release(struct rcu_head *rcu)
  {
  	struct rps_dev_flow_table *table = container_of(rcu,
  	    struct rps_dev_flow_table, rcu);
  
  	INIT_WORK(&table->free_work, rps_dev_flow_table_release_work);
  	schedule_work(&table->free_work);
  }
f5acb907d   Eric Dumazet   rps: static funct...
632
  static ssize_t store_rps_dev_flow_table_cnt(struct netdev_rx_queue *queue,
fec5e652e   Tom Herbert   rfs: Receive Flow...
633
634
635
  				     struct rx_queue_attribute *attr,
  				     const char *buf, size_t len)
  {
60b778ce5   Eric Dumazet   rfs: better sizin...
636
  	unsigned long mask, count;
fec5e652e   Tom Herbert   rfs: Receive Flow...
637
638
  	struct rps_dev_flow_table *table, *old_table;
  	static DEFINE_SPINLOCK(rps_dev_flow_lock);
60b778ce5   Eric Dumazet   rfs: better sizin...
639
  	int rc;
fec5e652e   Tom Herbert   rfs: Receive Flow...
640
641
642
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
60b778ce5   Eric Dumazet   rfs: better sizin...
643
644
645
  	rc = kstrtoul(buf, 0, &count);
  	if (rc < 0)
  		return rc;
fec5e652e   Tom Herbert   rfs: Receive Flow...
646
647
  
  	if (count) {
60b778ce5   Eric Dumazet   rfs: better sizin...
648
649
650
651
652
653
654
655
656
657
658
659
  		mask = count - 1;
  		/* mask = roundup_pow_of_two(count) - 1;
  		 * without overflows...
  		 */
  		while ((mask | (mask >> 1)) != mask)
  			mask |= (mask >> 1);
  		/* On 64 bit arches, must check mask fits in table->mask (u32),
  		 * and on 32bit arches, must check RPS_DEV_FLOW_TABLE_SIZE(mask + 1)
  		 * doesnt overflow.
  		 */
  #if BITS_PER_LONG > 32
  		if (mask > (unsigned long)(u32)mask)
a0a129f8b   Xi Wang   rps: fix insuffic...
660
  			return -EINVAL;
60b778ce5   Eric Dumazet   rfs: better sizin...
661
662
  #else
  		if (mask > (ULONG_MAX - RPS_DEV_FLOW_TABLE_SIZE(1))
a0a129f8b   Xi Wang   rps: fix insuffic...
663
  				/ sizeof(struct rps_dev_flow)) {
fec5e652e   Tom Herbert   rfs: Receive Flow...
664
665
666
  			/* Enforce a limit to prevent overflow */
  			return -EINVAL;
  		}
60b778ce5   Eric Dumazet   rfs: better sizin...
667
668
  #endif
  		table = vmalloc(RPS_DEV_FLOW_TABLE_SIZE(mask + 1));
fec5e652e   Tom Herbert   rfs: Receive Flow...
669
670
  		if (!table)
  			return -ENOMEM;
60b778ce5   Eric Dumazet   rfs: better sizin...
671
672
673
  		table->mask = mask;
  		for (count = 0; count <= mask; count++)
  			table->flows[count].cpu = RPS_NO_CPU;
fec5e652e   Tom Herbert   rfs: Receive Flow...
674
675
676
677
  	} else
  		table = NULL;
  
  	spin_lock(&rps_dev_flow_lock);
6e3f7faf3   Eric Dumazet   rps: add __rcu an...
678
679
  	old_table = rcu_dereference_protected(queue->rps_flow_table,
  					      lockdep_is_held(&rps_dev_flow_lock));
fec5e652e   Tom Herbert   rfs: Receive Flow...
680
681
682
683
684
685
686
687
  	rcu_assign_pointer(queue->rps_flow_table, table);
  	spin_unlock(&rps_dev_flow_lock);
  
  	if (old_table)
  		call_rcu(&old_table->rcu, rps_dev_flow_table_release);
  
  	return len;
  }
0a9627f26   Tom Herbert   rps: Receive Pack...
688
689
  static struct rx_queue_attribute rps_cpus_attribute =
  	__ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map);
fec5e652e   Tom Herbert   rfs: Receive Flow...
690
691
692
693
  
  static struct rx_queue_attribute rps_dev_flow_table_cnt_attribute =
  	__ATTR(rps_flow_cnt, S_IRUGO | S_IWUSR,
  	    show_rps_dev_flow_table_cnt, store_rps_dev_flow_table_cnt);
0a9627f26   Tom Herbert   rps: Receive Pack...
694
695
  static struct attribute *rx_queue_default_attrs[] = {
  	&rps_cpus_attribute.attr,
fec5e652e   Tom Herbert   rfs: Receive Flow...
696
  	&rps_dev_flow_table_cnt_attribute.attr,
0a9627f26   Tom Herbert   rps: Receive Pack...
697
698
699
700
701
702
  	NULL
  };
  
  static void rx_queue_release(struct kobject *kobj)
  {
  	struct netdev_rx_queue *queue = to_rx_queue(kobj);
6e3f7faf3   Eric Dumazet   rps: add __rcu an...
703
704
  	struct rps_map *map;
  	struct rps_dev_flow_table *flow_table;
0a9627f26   Tom Herbert   rps: Receive Pack...
705

fec5e652e   Tom Herbert   rfs: Receive Flow...
706

33d480ce6   Eric Dumazet   net: cleanup some...
707
  	map = rcu_dereference_protected(queue->rps_map, 1);
9ea19481d   John Fastabend   net: zero kobject...
708
709
  	if (map) {
  		RCU_INIT_POINTER(queue->rps_map, NULL);
f6f80238f   Lai Jiangshan   net,rcu: convert ...
710
  		kfree_rcu(map, rcu);
9ea19481d   John Fastabend   net: zero kobject...
711
  	}
6e3f7faf3   Eric Dumazet   rps: add __rcu an...
712

33d480ce6   Eric Dumazet   net: cleanup some...
713
  	flow_table = rcu_dereference_protected(queue->rps_flow_table, 1);
9ea19481d   John Fastabend   net: zero kobject...
714
715
  	if (flow_table) {
  		RCU_INIT_POINTER(queue->rps_flow_table, NULL);
6e3f7faf3   Eric Dumazet   rps: add __rcu an...
716
  		call_rcu(&flow_table->rcu, rps_dev_flow_table_release);
9ea19481d   John Fastabend   net: zero kobject...
717
  	}
0a9627f26   Tom Herbert   rps: Receive Pack...
718

9ea19481d   John Fastabend   net: zero kobject...
719
  	memset(kobj, 0, sizeof(*kobj));
fe8222406   Tom Herbert   net: Simplify RX ...
720
  	dev_put(queue->dev);
0a9627f26   Tom Herbert   rps: Receive Pack...
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  }
  
  static struct kobj_type rx_queue_ktype = {
  	.sysfs_ops = &rx_queue_sysfs_ops,
  	.release = rx_queue_release,
  	.default_attrs = rx_queue_default_attrs,
  };
  
  static int rx_queue_add_kobject(struct net_device *net, int index)
  {
  	struct netdev_rx_queue *queue = net->_rx + index;
  	struct kobject *kobj = &queue->kobj;
  	int error = 0;
  
  	kobj->kset = net->queues_kset;
  	error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
  	    "rx-%u", index);
  	if (error) {
  		kobject_put(kobj);
  		return error;
  	}
  
  	kobject_uevent(kobj, KOBJ_ADD);
fe8222406   Tom Herbert   net: Simplify RX ...
744
  	dev_hold(queue->dev);
0a9627f26   Tom Herbert   rps: Receive Pack...
745
746
747
  
  	return error;
  }
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
748
  #endif /* CONFIG_RPS */
0a9627f26   Tom Herbert   rps: Receive Pack...
749

62fe0b40a   Ben Hutchings   net: Allow changi...
750
751
  int
  net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
0a9627f26   Tom Herbert   rps: Receive Pack...
752
  {
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
753
  #ifdef CONFIG_RPS
0a9627f26   Tom Herbert   rps: Receive Pack...
754
755
  	int i;
  	int error = 0;
62fe0b40a   Ben Hutchings   net: Allow changi...
756
  	for (i = old_num; i < new_num; i++) {
0a9627f26   Tom Herbert   rps: Receive Pack...
757
  		error = rx_queue_add_kobject(net, i);
62fe0b40a   Ben Hutchings   net: Allow changi...
758
759
  		if (error) {
  			new_num = old_num;
0a9627f26   Tom Herbert   rps: Receive Pack...
760
  			break;
62fe0b40a   Ben Hutchings   net: Allow changi...
761
  		}
0a9627f26   Tom Herbert   rps: Receive Pack...
762
  	}
62fe0b40a   Ben Hutchings   net: Allow changi...
763
764
  	while (--i >= new_num)
  		kobject_put(&net->_rx[i].kobj);
0a9627f26   Tom Herbert   rps: Receive Pack...
765
766
  
  	return error;
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
767
768
769
  #else
  	return 0;
  #endif
0a9627f26   Tom Herbert   rps: Receive Pack...
770
  }
ccf5ff69f   david decotigny   net: new counter ...
771
  #ifdef CONFIG_SYSFS
1d24eb481   Tom Herbert   xps: Transmit Pac...
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  /*
   * netdev_queue sysfs structures and functions.
   */
  struct netdev_queue_attribute {
  	struct attribute attr;
  	ssize_t (*show)(struct netdev_queue *queue,
  	    struct netdev_queue_attribute *attr, char *buf);
  	ssize_t (*store)(struct netdev_queue *queue,
  	    struct netdev_queue_attribute *attr, const char *buf, size_t len);
  };
  #define to_netdev_queue_attr(_attr) container_of(_attr,		\
      struct netdev_queue_attribute, attr)
  
  #define to_netdev_queue(obj) container_of(obj, struct netdev_queue, kobj)
  
  static ssize_t netdev_queue_attr_show(struct kobject *kobj,
  				      struct attribute *attr, char *buf)
  {
  	struct netdev_queue_attribute *attribute = to_netdev_queue_attr(attr);
  	struct netdev_queue *queue = to_netdev_queue(kobj);
  
  	if (!attribute->show)
  		return -EIO;
  
  	return attribute->show(queue, attribute, buf);
  }
  
  static ssize_t netdev_queue_attr_store(struct kobject *kobj,
  				       struct attribute *attr,
  				       const char *buf, size_t count)
  {
  	struct netdev_queue_attribute *attribute = to_netdev_queue_attr(attr);
  	struct netdev_queue *queue = to_netdev_queue(kobj);
  
  	if (!attribute->store)
  		return -EIO;
  
  	return attribute->store(queue, attribute, buf, count);
  }
  
  static const struct sysfs_ops netdev_queue_sysfs_ops = {
  	.show = netdev_queue_attr_show,
  	.store = netdev_queue_attr_store,
  };
ccf5ff69f   david decotigny   net: new counter ...
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
  static ssize_t show_trans_timeout(struct netdev_queue *queue,
  				  struct netdev_queue_attribute *attribute,
  				  char *buf)
  {
  	unsigned long trans_timeout;
  
  	spin_lock_irq(&queue->_xmit_lock);
  	trans_timeout = queue->trans_timeout;
  	spin_unlock_irq(&queue->_xmit_lock);
  
  	return sprintf(buf, "%lu", trans_timeout);
  }
  
  static struct netdev_queue_attribute queue_trans_timeout =
  	__ATTR(tx_timeout, S_IRUGO, show_trans_timeout, NULL);
114cf5802   Tom Herbert   bql: Byte queue l...
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
  #ifdef CONFIG_BQL
  /*
   * Byte queue limits sysfs structures and functions.
   */
  static ssize_t bql_show(char *buf, unsigned int value)
  {
  	return sprintf(buf, "%u
  ", value);
  }
  
  static ssize_t bql_set(const char *buf, const size_t count,
  		       unsigned int *pvalue)
  {
  	unsigned int value;
  	int err;
  
  	if (!strcmp(buf, "max") || !strcmp(buf, "max
  "))
  		value = DQL_MAX_LIMIT;
  	else {
  		err = kstrtouint(buf, 10, &value);
  		if (err < 0)
  			return err;
  		if (value > DQL_MAX_LIMIT)
  			return -EINVAL;
  	}
  
  	*pvalue = value;
  
  	return count;
  }
  
  static ssize_t bql_show_hold_time(struct netdev_queue *queue,
  				  struct netdev_queue_attribute *attr,
  				  char *buf)
  {
  	struct dql *dql = &queue->dql;
  
  	return sprintf(buf, "%u
  ", jiffies_to_msecs(dql->slack_hold_time));
  }
  
  static ssize_t bql_set_hold_time(struct netdev_queue *queue,
  				 struct netdev_queue_attribute *attribute,
  				 const char *buf, size_t len)
  {
  	struct dql *dql = &queue->dql;
  	unsigned value;
  	int err;
  
  	err = kstrtouint(buf, 10, &value);
  	if (err < 0)
  		return err;
  
  	dql->slack_hold_time = msecs_to_jiffies(value);
  
  	return len;
  }
  
  static struct netdev_queue_attribute bql_hold_time_attribute =
  	__ATTR(hold_time, S_IRUGO | S_IWUSR, bql_show_hold_time,
  	    bql_set_hold_time);
  
  static ssize_t bql_show_inflight(struct netdev_queue *queue,
  				 struct netdev_queue_attribute *attr,
  				 char *buf)
  {
  	struct dql *dql = &queue->dql;
  
  	return sprintf(buf, "%u
  ", dql->num_queued - dql->num_completed);
  }
  
  static struct netdev_queue_attribute bql_inflight_attribute =
  	__ATTR(inflight, S_IRUGO | S_IWUSR, bql_show_inflight, NULL);
  
  #define BQL_ATTR(NAME, FIELD)						\
  static ssize_t bql_show_ ## NAME(struct netdev_queue *queue,		\
  				 struct netdev_queue_attribute *attr,	\
  				 char *buf)				\
  {									\
  	return bql_show(buf, queue->dql.FIELD);				\
  }									\
  									\
  static ssize_t bql_set_ ## NAME(struct netdev_queue *queue,		\
  				struct netdev_queue_attribute *attr,	\
  				const char *buf, size_t len)		\
  {									\
  	return bql_set(buf, len, &queue->dql.FIELD);			\
  }									\
  									\
  static struct netdev_queue_attribute bql_ ## NAME ## _attribute =	\
  	__ATTR(NAME, S_IRUGO | S_IWUSR, bql_show_ ## NAME,		\
  	    bql_set_ ## NAME);
  
  BQL_ATTR(limit, limit)
  BQL_ATTR(limit_max, max_limit)
  BQL_ATTR(limit_min, min_limit)
  
  static struct attribute *dql_attrs[] = {
  	&bql_limit_attribute.attr,
  	&bql_limit_max_attribute.attr,
  	&bql_limit_min_attribute.attr,
  	&bql_hold_time_attribute.attr,
  	&bql_inflight_attribute.attr,
  	NULL
  };
  
  static struct attribute_group dql_group = {
  	.name  = "byte_queue_limits",
  	.attrs  = dql_attrs,
  };
  #endif /* CONFIG_BQL */
ccf5ff69f   david decotigny   net: new counter ...
944
  #ifdef CONFIG_XPS
1d24eb481   Tom Herbert   xps: Transmit Pac...
945
  static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue)
0a9627f26   Tom Herbert   rps: Receive Pack...
946
  {
1d24eb481   Tom Herbert   xps: Transmit Pac...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
  	struct net_device *dev = queue->dev;
  	int i;
  
  	for (i = 0; i < dev->num_tx_queues; i++)
  		if (queue == &dev->_tx[i])
  			break;
  
  	BUG_ON(i >= dev->num_tx_queues);
  
  	return i;
  }
  
  
  static ssize_t show_xps_map(struct netdev_queue *queue,
  			    struct netdev_queue_attribute *attribute, char *buf)
  {
  	struct net_device *dev = queue->dev;
  	struct xps_dev_maps *dev_maps;
  	cpumask_var_t mask;
  	unsigned long index;
  	size_t len = 0;
  	int i;
  
  	if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
  		return -ENOMEM;
  
  	index = get_netdev_queue_index(queue);
  
  	rcu_read_lock();
  	dev_maps = rcu_dereference(dev->xps_maps);
  	if (dev_maps) {
  		for_each_possible_cpu(i) {
  			struct xps_map *map =
  			    rcu_dereference(dev_maps->cpu_map[i]);
  			if (map) {
  				int j;
  				for (j = 0; j < map->len; j++) {
  					if (map->queues[j] == index) {
  						cpumask_set_cpu(i, mask);
  						break;
  					}
  				}
  			}
  		}
  	}
  	rcu_read_unlock();
  
  	len += cpumask_scnprintf(buf + len, PAGE_SIZE, mask);
  	if (PAGE_SIZE - len < 3) {
  		free_cpumask_var(mask);
  		return -EINVAL;
  	}
  
  	free_cpumask_var(mask);
  	len += sprintf(buf + len, "
  ");
  	return len;
  }
1d24eb481   Tom Herbert   xps: Transmit Pac...
1005
  static DEFINE_MUTEX(xps_map_mutex);
a41778694   Eric Dumazet   xps: add __rcu an...
1006
1007
  #define xmap_dereference(P)		\
  	rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
1d24eb481   Tom Herbert   xps: Transmit Pac...
1008

927fbec13   Tom Herbert   xps: Add xps_queu...
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
  static void xps_queue_release(struct netdev_queue *queue)
  {
  	struct net_device *dev = queue->dev;
  	struct xps_dev_maps *dev_maps;
  	struct xps_map *map;
  	unsigned long index;
  	int i, pos, nonempty = 0;
  
  	index = get_netdev_queue_index(queue);
  
  	mutex_lock(&xps_map_mutex);
  	dev_maps = xmap_dereference(dev->xps_maps);
  
  	if (dev_maps) {
  		for_each_possible_cpu(i) {
  			map = xmap_dereference(dev_maps->cpu_map[i]);
  			if (!map)
  				continue;
  
  			for (pos = 0; pos < map->len; pos++)
  				if (map->queues[pos] == index)
  					break;
  
  			if (pos < map->len) {
  				if (map->len > 1)
  					map->queues[pos] =
  					    map->queues[--map->len];
  				else {
  					RCU_INIT_POINTER(dev_maps->cpu_map[i],
  					    NULL);
  					kfree_rcu(map, rcu);
  					map = NULL;
  				}
  			}
  			if (map)
  				nonempty = 1;
  		}
  
  		if (!nonempty) {
  			RCU_INIT_POINTER(dev->xps_maps, NULL);
  			kfree_rcu(dev_maps, rcu);
  		}
  	}
  	mutex_unlock(&xps_map_mutex);
  }
1d24eb481   Tom Herbert   xps: Transmit Pac...
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
  static ssize_t store_xps_map(struct netdev_queue *queue,
  		      struct netdev_queue_attribute *attribute,
  		      const char *buf, size_t len)
  {
  	struct net_device *dev = queue->dev;
  	cpumask_var_t mask;
  	int err, i, cpu, pos, map_len, alloc_len, need_set;
  	unsigned long index;
  	struct xps_map *map, *new_map;
  	struct xps_dev_maps *dev_maps, *new_dev_maps;
  	int nonempty = 0;
19b05f811   david decotigny   net-sysfs: fixed ...
1065
  	int numa_node_id = -2;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
  
  	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
  		return -ENOMEM;
  
  	index = get_netdev_queue_index(queue);
  
  	err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
  	if (err) {
  		free_cpumask_var(mask);
  		return err;
  	}
  
  	new_dev_maps = kzalloc(max_t(unsigned,
  	    XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES), GFP_KERNEL);
  	if (!new_dev_maps) {
  		free_cpumask_var(mask);
  		return -ENOMEM;
  	}
  
  	mutex_lock(&xps_map_mutex);
a41778694   Eric Dumazet   xps: add __rcu an...
1089
  	dev_maps = xmap_dereference(dev->xps_maps);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1090
1091
  
  	for_each_possible_cpu(cpu) {
a41778694   Eric Dumazet   xps: add __rcu an...
1092
1093
1094
  		map = dev_maps ?
  			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
  		new_map = map;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1095
1096
1097
1098
1099
1100
1101
1102
  		if (map) {
  			for (pos = 0; pos < map->len; pos++)
  				if (map->queues[pos] == index)
  					break;
  			map_len = map->len;
  			alloc_len = map->alloc_len;
  		} else
  			pos = map_len = alloc_len = 0;
2142c131a   KOSAKI Motohiro   net: convert to n...
1103
  		need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu);
f2cd2d3e9   Eric Dumazet   net sched: use xp...
1104
1105
  #ifdef CONFIG_NUMA
  		if (need_set) {
19b05f811   david decotigny   net-sysfs: fixed ...
1106
1107
1108
1109
  			if (numa_node_id == -2)
  				numa_node_id = cpu_to_node(cpu);
  			else if (numa_node_id != cpu_to_node(cpu))
  				numa_node_id = -1;
f2cd2d3e9   Eric Dumazet   net sched: use xp...
1110
1111
  		}
  #endif
1d24eb481   Tom Herbert   xps: Transmit Pac...
1112
1113
1114
1115
1116
  		if (need_set && pos >= map_len) {
  			/* Need to add queue to this CPU's map */
  			if (map_len >= alloc_len) {
  				alloc_len = alloc_len ?
  				    2 * alloc_len : XPS_MIN_MAP_ALLOC;
b02038a17   Eric Dumazet   xps: NUMA allocat...
1117
1118
1119
  				new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len),
  						       GFP_KERNEL,
  						       cpu_to_node(cpu));
1d24eb481   Tom Herbert   xps: Transmit Pac...
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
  				if (!new_map)
  					goto error;
  				new_map->alloc_len = alloc_len;
  				for (i = 0; i < map_len; i++)
  					new_map->queues[i] = map->queues[i];
  				new_map->len = map_len;
  			}
  			new_map->queues[new_map->len++] = index;
  		} else if (!need_set && pos < map_len) {
  			/* Need to remove queue from this CPU's map */
  			if (map_len > 1)
  				new_map->queues[pos] =
  				    new_map->queues[--new_map->len];
  			else
  				new_map = NULL;
  		}
a41778694   Eric Dumazet   xps: add __rcu an...
1136
  		RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], new_map);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1137
1138
1139
1140
  	}
  
  	/* Cleanup old maps */
  	for_each_possible_cpu(cpu) {
a41778694   Eric Dumazet   xps: add __rcu an...
1141
1142
1143
  		map = dev_maps ?
  			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
  		if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map)
edc86d8a1   Lai Jiangshan   net,rcu: convert ...
1144
  			kfree_rcu(map, rcu);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1145
1146
1147
  		if (new_dev_maps->cpu_map[cpu])
  			nonempty = 1;
  	}
cf778b00e   Eric Dumazet   net: reintroduce ...
1148
1149
1150
  	if (nonempty) {
  		rcu_assign_pointer(dev->xps_maps, new_dev_maps);
  	} else {
1d24eb481   Tom Herbert   xps: Transmit Pac...
1151
  		kfree(new_dev_maps);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
1152
  		RCU_INIT_POINTER(dev->xps_maps, NULL);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1153
1154
1155
  	}
  
  	if (dev_maps)
b55071eb6   Lai Jiangshan   net,rcu: convert ...
1156
  		kfree_rcu(dev_maps, rcu);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1157

19b05f811   david decotigny   net-sysfs: fixed ...
1158
  	netdev_queue_numa_node_write(queue, (numa_node_id >= 0) ? numa_node_id :
b236da693   Changli Gao   net: use NUMA_NO_...
1159
  					    NUMA_NO_NODE);
f2cd2d3e9   Eric Dumazet   net sched: use xp...
1160

1d24eb481   Tom Herbert   xps: Transmit Pac...
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
  	mutex_unlock(&xps_map_mutex);
  
  	free_cpumask_var(mask);
  	return len;
  
  error:
  	mutex_unlock(&xps_map_mutex);
  
  	if (new_dev_maps)
  		for_each_possible_cpu(i)
a41778694   Eric Dumazet   xps: add __rcu an...
1171
1172
1173
  			kfree(rcu_dereference_protected(
  				new_dev_maps->cpu_map[i],
  				1));
1d24eb481   Tom Herbert   xps: Transmit Pac...
1174
1175
1176
1177
1178
1179
1180
  	kfree(new_dev_maps);
  	free_cpumask_var(mask);
  	return -ENOMEM;
  }
  
  static struct netdev_queue_attribute xps_cpus_attribute =
      __ATTR(xps_cpus, S_IRUGO | S_IWUSR, show_xps_map, store_xps_map);
ccf5ff69f   david decotigny   net: new counter ...
1181
  #endif /* CONFIG_XPS */
1d24eb481   Tom Herbert   xps: Transmit Pac...
1182
1183
  
  static struct attribute *netdev_queue_default_attrs[] = {
ccf5ff69f   david decotigny   net: new counter ...
1184
1185
  	&queue_trans_timeout.attr,
  #ifdef CONFIG_XPS
1d24eb481   Tom Herbert   xps: Transmit Pac...
1186
  	&xps_cpus_attribute.attr,
ccf5ff69f   david decotigny   net: new counter ...
1187
  #endif
1d24eb481   Tom Herbert   xps: Transmit Pac...
1188
1189
1190
1191
1192
1193
  	NULL
  };
  
  static void netdev_queue_release(struct kobject *kobj)
  {
  	struct netdev_queue *queue = to_netdev_queue(kobj);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1194

114cf5802   Tom Herbert   bql: Byte queue l...
1195
  #ifdef CONFIG_XPS
927fbec13   Tom Herbert   xps: Add xps_queu...
1196
  	xps_queue_release(queue);
114cf5802   Tom Herbert   bql: Byte queue l...
1197
  #endif
1d24eb481   Tom Herbert   xps: Transmit Pac...
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
  
  	memset(kobj, 0, sizeof(*kobj));
  	dev_put(queue->dev);
  }
  
  static struct kobj_type netdev_queue_ktype = {
  	.sysfs_ops = &netdev_queue_sysfs_ops,
  	.release = netdev_queue_release,
  	.default_attrs = netdev_queue_default_attrs,
  };
  
  static int netdev_queue_add_kobject(struct net_device *net, int index)
  {
  	struct netdev_queue *queue = net->_tx + index;
  	struct kobject *kobj = &queue->kobj;
  	int error = 0;
  
  	kobj->kset = net->queues_kset;
  	error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
  	    "tx-%u", index);
114cf5802   Tom Herbert   bql: Byte queue l...
1218
1219
1220
1221
1222
1223
1224
1225
  	if (error)
  		goto exit;
  
  #ifdef CONFIG_BQL
  	error = sysfs_create_group(kobj, &dql_group);
  	if (error)
  		goto exit;
  #endif
1d24eb481   Tom Herbert   xps: Transmit Pac...
1226
1227
1228
  
  	kobject_uevent(kobj, KOBJ_ADD);
  	dev_hold(queue->dev);
114cf5802   Tom Herbert   bql: Byte queue l...
1229
1230
1231
  	return 0;
  exit:
  	kobject_put(kobj);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1232
1233
  	return error;
  }
ccf5ff69f   david decotigny   net: new counter ...
1234
  #endif /* CONFIG_SYSFS */
1d24eb481   Tom Herbert   xps: Transmit Pac...
1235
1236
1237
1238
  
  int
  netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num)
  {
ccf5ff69f   david decotigny   net: new counter ...
1239
  #ifdef CONFIG_SYSFS
1d24eb481   Tom Herbert   xps: Transmit Pac...
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
  	int i;
  	int error = 0;
  
  	for (i = old_num; i < new_num; i++) {
  		error = netdev_queue_add_kobject(net, i);
  		if (error) {
  			new_num = old_num;
  			break;
  		}
  	}
114cf5802   Tom Herbert   bql: Byte queue l...
1250
1251
1252
1253
1254
1255
1256
1257
  	while (--i >= new_num) {
  		struct netdev_queue *queue = net->_tx + i;
  
  #ifdef CONFIG_BQL
  		sysfs_remove_group(&queue->kobj, &dql_group);
  #endif
  		kobject_put(&queue->kobj);
  	}
1d24eb481   Tom Herbert   xps: Transmit Pac...
1258
1259
  
  	return error;
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1260
1261
  #else
  	return 0;
ccf5ff69f   david decotigny   net: new counter ...
1262
  #endif /* CONFIG_SYSFS */
1d24eb481   Tom Herbert   xps: Transmit Pac...
1263
1264
1265
1266
  }
  
  static int register_queue_kobjects(struct net_device *net)
  {
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1267
  	int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1268

ccf5ff69f   david decotigny   net: new counter ...
1269
  #ifdef CONFIG_SYSFS
62fe0b40a   Ben Hutchings   net: Allow changi...
1270
1271
1272
1273
  	net->queues_kset = kset_create_and_add("queues",
  	    NULL, &net->dev.kobj);
  	if (!net->queues_kset)
  		return -ENOMEM;
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1274
1275
1276
1277
1278
1279
  #endif
  
  #ifdef CONFIG_RPS
  	real_rx = net->real_num_rx_queues;
  #endif
  	real_tx = net->real_num_tx_queues;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1280

bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1281
  	error = net_rx_queue_update_kobjects(net, 0, real_rx);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1282
1283
  	if (error)
  		goto error;
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1284
  	rxq = real_rx;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1285

bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1286
  	error = netdev_queue_update_kobjects(net, 0, real_tx);
1d24eb481   Tom Herbert   xps: Transmit Pac...
1287
1288
  	if (error)
  		goto error;
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1289
  	txq = real_tx;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1290
1291
1292
1293
1294
1295
1296
  
  	return 0;
  
  error:
  	netdev_queue_update_kobjects(net, txq, 0);
  	net_rx_queue_update_kobjects(net, rxq, 0);
  	return error;
62fe0b40a   Ben Hutchings   net: Allow changi...
1297
  }
0a9627f26   Tom Herbert   rps: Receive Pack...
1298

1d24eb481   Tom Herbert   xps: Transmit Pac...
1299
  static void remove_queue_kobjects(struct net_device *net)
62fe0b40a   Ben Hutchings   net: Allow changi...
1300
  {
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1301
1302
1303
1304
1305
1306
1307
1308
1309
  	int real_rx = 0, real_tx = 0;
  
  #ifdef CONFIG_RPS
  	real_rx = net->real_num_rx_queues;
  #endif
  	real_tx = net->real_num_tx_queues;
  
  	net_rx_queue_update_kobjects(net, real_rx, 0);
  	netdev_queue_update_kobjects(net, real_tx, 0);
ccf5ff69f   david decotigny   net: new counter ...
1310
  #ifdef CONFIG_SYSFS
0a9627f26   Tom Herbert   rps: Receive Pack...
1311
  	kset_unregister(net->queues_kset);
bf2641451   Tom Herbert   xps: Add CONFIG_XPS
1312
  #endif
0a9627f26   Tom Herbert   rps: Receive Pack...
1313
  }
608b4b954   Eric W. Biederman   netns: Teach netw...
1314

a685e0898   Al Viro   Delay struct net ...
1315
  static void *net_grab_current_ns(void)
608b4b954   Eric W. Biederman   netns: Teach netw...
1316
  {
a685e0898   Al Viro   Delay struct net ...
1317
1318
1319
1320
1321
1322
  	struct net *ns = current->nsproxy->net_ns;
  #ifdef CONFIG_NET_NS
  	if (ns)
  		atomic_inc(&ns->passive);
  #endif
  	return ns;
608b4b954   Eric W. Biederman   netns: Teach netw...
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
  }
  
  static const void *net_initial_ns(void)
  {
  	return &init_net;
  }
  
  static const void *net_netlink_ns(struct sock *sk)
  {
  	return sock_net(sk);
  }
046007949   Johannes Berg   cfg80211: support...
1334
  struct kobj_ns_type_operations net_ns_type_operations = {
608b4b954   Eric W. Biederman   netns: Teach netw...
1335
  	.type = KOBJ_NS_TYPE_NET,
a685e0898   Al Viro   Delay struct net ...
1336
  	.grab_current_ns = net_grab_current_ns,
608b4b954   Eric W. Biederman   netns: Teach netw...
1337
1338
  	.netlink_ns = net_netlink_ns,
  	.initial_ns = net_initial_ns,
a685e0898   Al Viro   Delay struct net ...
1339
  	.drop_ns = net_drop_ns,
608b4b954   Eric W. Biederman   netns: Teach netw...
1340
  };
046007949   Johannes Berg   cfg80211: support...
1341
  EXPORT_SYMBOL_GPL(net_ns_type_operations);
608b4b954   Eric W. Biederman   netns: Teach netw...
1342

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
  #ifdef CONFIG_HOTPLUG
7eff2e7a8   Kay Sievers   Driver core: chan...
1344
  static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1346
  	struct net_device *dev = to_net_dev(d);
7eff2e7a8   Kay Sievers   Driver core: chan...
1347
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348

312c004d3   Kay Sievers   [PATCH] driver co...
1349
  	/* pass interface to uevent. */
7eff2e7a8   Kay Sievers   Driver core: chan...
1350
  	retval = add_uevent_var(env, "INTERFACE=%s", dev->name);
bf62456eb   Eric Rannaud   uevent: use add_u...
1351
1352
  	if (retval)
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353

ca2f37dbc   Jean Tourrilhes   Driver core: noti...
1354
1355
1356
  	/* pass ifindex to uevent.
  	 * ifindex is useful as it won't change (interface name may change)
  	 * and is what RtNetlink uses natively. */
7eff2e7a8   Kay Sievers   Driver core: chan...
1357
  	retval = add_uevent_var(env, "IFINDEX=%d", dev->ifindex);
ca2f37dbc   Jean Tourrilhes   Driver core: noti...
1358

bf62456eb   Eric Rannaud   uevent: use add_u...
1359
  exit:
bf62456eb   Eric Rannaud   uevent: use add_u...
1360
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
1362
1363
1364
  }
  #endif
  
  /*
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
1365
   *	netdev_release -- destroy and free a dead device.
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1366
   *	Called when last reference to device kobject is gone.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
   */
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1368
  static void netdev_release(struct device *d)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1369
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1370
  	struct net_device *dev = to_net_dev(d);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
1372
  
  	BUG_ON(dev->reg_state != NETREG_RELEASED);
0b815a1a6   Stephen Hemminger   net: network devi...
1373
  	kfree(dev->ifalias);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
1375
  	kfree((char *)dev - dev->padded);
  }
608b4b954   Eric W. Biederman   netns: Teach netw...
1376
1377
1378
1379
1380
1381
  static const void *net_namespace(struct device *d)
  {
  	struct net_device *dev;
  	dev = container_of(d, struct net_device, dev);
  	return dev_net(dev);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
  static struct class net_class = {
  	.name = "net",
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1384
  	.dev_release = netdev_release,
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1385
  #ifdef CONFIG_SYSFS
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1386
  	.dev_attrs = net_class_attributes,
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1387
  #endif /* CONFIG_SYSFS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  #ifdef CONFIG_HOTPLUG
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1389
  	.dev_uevent = netdev_uevent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
  #endif
608b4b954   Eric W. Biederman   netns: Teach netw...
1391
1392
  	.ns_type = &net_ns_type_operations,
  	.namespace = net_namespace,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393
  };
9093bbb2d   Stephen Hemminger   [NET]: Fix race c...
1394
1395
1396
  /* Delete sysfs entries but hold kobject reference until after all
   * netdev references are gone.
   */
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1397
  void netdev_unregister_kobject(struct net_device * net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  {
9093bbb2d   Stephen Hemminger   [NET]: Fix race c...
1399
1400
1401
  	struct device *dev = &(net->dev);
  
  	kobject_get(&dev->kobj);
3891845e1   Eric W. Biederman   netns: Coexist wi...
1402

1d24eb481   Tom Herbert   xps: Transmit Pac...
1403
  	remove_queue_kobjects(net);
0a9627f26   Tom Herbert   rps: Receive Pack...
1404

9093bbb2d   Stephen Hemminger   [NET]: Fix race c...
1405
  	device_del(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
1408
  }
  
  /* Create sysfs entries for network device. */
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1409
  int netdev_register_kobject(struct net_device *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1410
  {
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1411
  	struct device *dev = &(net->dev);
a4dbd6740   David Brownell   driver model: con...
1412
  	const struct attribute_group **groups = net->sysfs_groups;
0a9627f26   Tom Herbert   rps: Receive Pack...
1413
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414

a1b3f594d   Eric W. Biederman   net: Expose all n...
1415
  	device_initialize(dev);
43cb76d91   Greg Kroah-Hartman   Network: convert ...
1416
1417
1418
  	dev->class = &net_class;
  	dev->platform_data = net;
  	dev->groups = groups;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419

a2205472c   Stephen Hemminger   net: fix warning ...
1420
  	dev_set_name(dev, "%s", net->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421

8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1422
  #ifdef CONFIG_SYSFS
0c509a6c9   Eric W. Biederman   net: Allow device...
1423
1424
1425
  	/* Allow for a device specific group */
  	if (*groups)
  		groups++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1426

0c509a6c9   Eric W. Biederman   net: Allow device...
1427
  	*groups++ = &netstat_group;
22bb1be4d   Johannes Berg   wext: make sysfs ...
1428
  #ifdef CONFIG_WIRELESS_EXT_SYSFS
3d23e349d   Johannes Berg   wext: refactor
1429
  	if (net->ieee80211_ptr)
fe9925b55   Stephen Hemminger   [NET]: Create net...
1430
  		*groups++ = &wireless_group;
3d23e349d   Johannes Berg   wext: refactor
1431
1432
1433
1434
  #ifdef CONFIG_WIRELESS_EXT
  	else if (net->wireless_handlers)
  		*groups++ = &wireless_group;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
  #endif
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1436
  #endif /* CONFIG_SYSFS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437

0a9627f26   Tom Herbert   rps: Receive Pack...
1438
1439
1440
  	error = device_add(dev);
  	if (error)
  		return error;
1d24eb481   Tom Herbert   xps: Transmit Pac...
1441
  	error = register_queue_kobjects(net);
0a9627f26   Tom Herbert   rps: Receive Pack...
1442
1443
1444
1445
1446
1447
  	if (error) {
  		device_del(dev);
  		return error;
  	}
  
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1448
  }
b8a9787ed   Jay Vosburgh   bonding: Allow se...
1449
1450
1451
1452
  int netdev_class_create_file(struct class_attribute *class_attr)
  {
  	return class_create_file(&net_class, class_attr);
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
1453
  EXPORT_SYMBOL(netdev_class_create_file);
b8a9787ed   Jay Vosburgh   bonding: Allow se...
1454
1455
1456
1457
1458
  
  void netdev_class_remove_file(struct class_attribute *class_attr)
  {
  	class_remove_file(&net_class, class_attr);
  }
b8a9787ed   Jay Vosburgh   bonding: Allow se...
1459
  EXPORT_SYMBOL(netdev_class_remove_file);
8b41d1887   Eric W. Biederman   [NET]: Fix runnin...
1460
  int netdev_kobject_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1461
  {
608b4b954   Eric W. Biederman   netns: Teach netw...
1462
  	kobj_ns_type_register(&net_ns_type_operations);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1463
1464
  	return class_register(&net_class);
  }