diff options
Diffstat (limited to 'net/core/net-sysfs.c')
-rw-r--r-- | net/core/net-sysfs.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 427ded841224..59cfc7d8fc45 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/slab.h> | ||
16 | #include <net/sock.h> | 17 | #include <net/sock.h> |
17 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
18 | #include <linux/wireless.h> | 19 | #include <linux/wireless.h> |
@@ -130,6 +131,48 @@ static ssize_t show_carrier(struct device *dev, | |||
130 | return -EINVAL; | 131 | return -EINVAL; |
131 | } | 132 | } |
132 | 133 | ||
134 | static ssize_t show_speed(struct device *dev, | ||
135 | struct device_attribute *attr, char *buf) | ||
136 | { | ||
137 | struct net_device *netdev = to_net_dev(dev); | ||
138 | int ret = -EINVAL; | ||
139 | |||
140 | if (!rtnl_trylock()) | ||
141 | return restart_syscall(); | ||
142 | |||
143 | if (netif_running(netdev) && | ||
144 | netdev->ethtool_ops && | ||
145 | netdev->ethtool_ops->get_settings) { | ||
146 | struct ethtool_cmd cmd = { ETHTOOL_GSET }; | ||
147 | |||
148 | if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) | ||
149 | ret = sprintf(buf, fmt_dec, ethtool_cmd_speed(&cmd)); | ||
150 | } | ||
151 | rtnl_unlock(); | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static ssize_t show_duplex(struct device *dev, | ||
156 | struct device_attribute *attr, char *buf) | ||
157 | { | ||
158 | struct net_device *netdev = to_net_dev(dev); | ||
159 | int ret = -EINVAL; | ||
160 | |||
161 | if (!rtnl_trylock()) | ||
162 | return restart_syscall(); | ||
163 | |||
164 | if (netif_running(netdev) && | ||
165 | netdev->ethtool_ops && | ||
166 | netdev->ethtool_ops->get_settings) { | ||
167 | struct ethtool_cmd cmd = { ETHTOOL_GSET }; | ||
168 | |||
169 | if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) | ||
170 | ret = sprintf(buf, "%s\n", cmd.duplex ? "full" : "half"); | ||
171 | } | ||
172 | rtnl_unlock(); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
133 | static ssize_t show_dormant(struct device *dev, | 176 | static ssize_t show_dormant(struct device *dev, |
134 | struct device_attribute *attr, char *buf) | 177 | struct device_attribute *attr, char *buf) |
135 | { | 178 | { |
@@ -259,6 +302,8 @@ static struct device_attribute net_class_attributes[] = { | |||
259 | __ATTR(address, S_IRUGO, show_address, NULL), | 302 | __ATTR(address, S_IRUGO, show_address, NULL), |
260 | __ATTR(broadcast, S_IRUGO, show_broadcast, NULL), | 303 | __ATTR(broadcast, S_IRUGO, show_broadcast, NULL), |
261 | __ATTR(carrier, S_IRUGO, show_carrier, NULL), | 304 | __ATTR(carrier, S_IRUGO, show_carrier, NULL), |
305 | __ATTR(speed, S_IRUGO, show_speed, NULL), | ||
306 | __ATTR(duplex, S_IRUGO, show_duplex, NULL), | ||
262 | __ATTR(dormant, S_IRUGO, show_dormant, NULL), | 307 | __ATTR(dormant, S_IRUGO, show_dormant, NULL), |
263 | __ATTR(operstate, S_IRUGO, show_operstate, NULL), | 308 | __ATTR(operstate, S_IRUGO, show_operstate, NULL), |
264 | __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), | 309 | __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), |
@@ -366,7 +411,8 @@ static ssize_t wireless_show(struct device *d, char *buf, | |||
366 | const struct iw_statistics *iw; | 411 | const struct iw_statistics *iw; |
367 | ssize_t ret = -EINVAL; | 412 | ssize_t ret = -EINVAL; |
368 | 413 | ||
369 | rtnl_lock(); | 414 | if (!rtnl_trylock()) |
415 | return restart_syscall(); | ||
370 | if (dev_isalive(dev)) { | 416 | if (dev_isalive(dev)) { |
371 | iw = get_wireless_stats(dev); | 417 | iw = get_wireless_stats(dev); |
372 | if (iw) | 418 | if (iw) |
@@ -481,7 +527,7 @@ void netdev_unregister_kobject(struct net_device * net) | |||
481 | 527 | ||
482 | kobject_get(&dev->kobj); | 528 | kobject_get(&dev->kobj); |
483 | 529 | ||
484 | if (dev_net(net) != &init_net) | 530 | if (!net_eq(dev_net(net), &init_net)) |
485 | return; | 531 | return; |
486 | 532 | ||
487 | device_del(dev); | 533 | device_del(dev); |
@@ -500,15 +546,22 @@ int netdev_register_kobject(struct net_device *net) | |||
500 | dev_set_name(dev, "%s", net->name); | 546 | dev_set_name(dev, "%s", net->name); |
501 | 547 | ||
502 | #ifdef CONFIG_SYSFS | 548 | #ifdef CONFIG_SYSFS |
503 | *groups++ = &netstat_group; | 549 | /* Allow for a device specific group */ |
550 | if (*groups) | ||
551 | groups++; | ||
504 | 552 | ||
553 | *groups++ = &netstat_group; | ||
505 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | 554 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
506 | if (net->wireless_handlers || net->ieee80211_ptr) | 555 | if (net->ieee80211_ptr) |
507 | *groups++ = &wireless_group; | 556 | *groups++ = &wireless_group; |
557 | #ifdef CONFIG_WIRELESS_EXT | ||
558 | else if (net->wireless_handlers) | ||
559 | *groups++ = &wireless_group; | ||
560 | #endif | ||
508 | #endif | 561 | #endif |
509 | #endif /* CONFIG_SYSFS */ | 562 | #endif /* CONFIG_SYSFS */ |
510 | 563 | ||
511 | if (dev_net(net) != &init_net) | 564 | if (!net_eq(dev_net(net), &init_net)) |
512 | return 0; | 565 | return 0; |
513 | 566 | ||
514 | return device_add(dev); | 567 | return device_add(dev); |