summaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c19
-rw-r--r--net/core/dst.c9
-rw-r--r--net/core/fib_rules.c14
-rw-r--r--net/core/flow.c26
-rw-r--r--net/core/neighbour.c40
-rw-r--r--net/core/net-sysfs.c175
-rw-r--r--net/core/netpoll.c53
-rw-r--r--net/core/pktgen.c156
-rw-r--r--net/core/rtnetlink.c23
-rw-r--r--net/core/skbuff.c2
10 files changed, 252 insertions, 265 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index e660cb57e42..1e94a1b9a0f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -751,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname)
else
strlcpy(dev->name, newname, IFNAMSIZ);
- err = class_device_rename(&dev->class_dev, dev->name);
+ err = device_rename(&dev->dev, dev->name);
if (!err) {
hlist_del(&dev->name_hlist);
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
@@ -3221,8 +3221,8 @@ void free_netdev(struct net_device *dev)
BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
dev->reg_state = NETREG_RELEASED;
- /* will free via class release */
- class_device_put(&dev->class_dev);
+ /* will free via device release */
+ put_device(&dev->dev);
#else
kfree((char *)dev - dev->padded);
#endif
@@ -3247,7 +3247,7 @@ void synchronize_net(void)
* unregister_netdev() instead of this.
*/
-int unregister_netdevice(struct net_device *dev)
+void unregister_netdevice(struct net_device *dev)
{
struct net_device *d, **dp;
@@ -3258,7 +3258,9 @@ int unregister_netdevice(struct net_device *dev)
if (dev->reg_state == NETREG_UNINITIALIZED) {
printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
"was registered\n", dev->name, dev);
- return -ENODEV;
+
+ WARN_ON(1);
+ return;
}
BUG_ON(dev->reg_state != NETREG_REGISTERED);
@@ -3280,11 +3282,7 @@ int unregister_netdevice(struct net_device *dev)
break;
}
}
- if (!d) {
- printk(KERN_ERR "unregister net_device: '%s' not found\n",
- dev->name);
- return -ENODEV;
- }
+ BUG_ON(!d);
dev->reg_state = NETREG_UNREGISTERING;
@@ -3316,7 +3314,6 @@ int unregister_netdevice(struct net_device *dev)
synchronize_net();
dev_put(dev);
- return 0;
}
/**
diff --git a/net/core/dst.c b/net/core/dst.c
index 836ec660692..1a53fb39b7e 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -99,7 +99,14 @@ static void dst_run_gc(unsigned long dummy)
printk("dst_total: %d/%d %ld\n",
atomic_read(&dst_total), delayed, dst_gc_timer_expires);
#endif
- mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
+ /* if the next desired timer is more than 4 seconds in the future
+ * then round the timer to whole seconds
+ */
+ if (dst_gc_timer_expires > 4*HZ)
+ mod_timer(&dst_gc_timer,
+ round_jiffies(jiffies + dst_gc_timer_expires));
+ else
+ mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
out:
spin_unlock(&dst_lock);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 1df6cd4568d..215f1bff048 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -331,7 +331,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
if (nlh == NULL)
- return -1;
+ return -EMSGSIZE;
frh = nlmsg_data(nlh);
frh->table = rule->table;
@@ -359,7 +359,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
return nlmsg_end(skb, nlh);
nla_put_failure:
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
}
int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
@@ -405,9 +406,12 @@ static void notify_rule_change(int event, struct fib_rule *rule,
goto errout;
err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
- /* failure implies BUG in fib_rule_nlmsg_size() */
- BUG_ON(err < 0);
-
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
errout:
if (err < 0)
diff --git a/net/core/flow.c b/net/core/flow.c
index d137f971f97..5d25697920b 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -231,22 +231,16 @@ nocache:
err = resolver(key, family, dir, &obj, &obj_ref);
- if (fle) {
- if (err) {
- /* Force security policy check on next lookup */
- *head = fle->next;
- flow_entry_kill(cpu, fle);
- } else {
- fle->genid = atomic_read(&flow_cache_genid);
-
- if (fle->object)
- atomic_dec(fle->object_ref);
-
- fle->object = obj;
- fle->object_ref = obj_ref;
- if (obj)
- atomic_inc(fle->object_ref);
- }
+ if (fle && !err) {
+ fle->genid = atomic_read(&flow_cache_genid);
+
+ if (fle->object)
+ atomic_dec(fle->object_ref);
+
+ fle->object = obj;
+ fle->object_ref = obj_ref;
+ if (obj)
+ atomic_inc(fle->object_ref);
}
local_bh_enable();
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0ab1987b934..054d46493d2 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -577,9 +577,10 @@ void neigh_destroy(struct neighbour *neigh)
while ((hh = neigh->hh) != NULL) {
neigh->hh = hh->hh_next;
hh->hh_next = NULL;
- write_lock_bh(&hh->hh_lock);
+
+ write_seqlock_bh(&hh->hh_lock);
hh->hh_output = neigh_blackhole;
- write_unlock_bh(&hh->hh_lock);
+ write_sequnlock_bh(&hh->hh_lock);
if (atomic_dec_and_test(&hh->hh_refcnt))
kfree(hh);
}
@@ -695,7 +696,10 @@ next_elt:
if (!expire)
expire = 1;
- mod_timer(&tbl->gc_timer, now + expire);
+ if (expire>HZ)
+ mod_timer(&tbl->gc_timer, round_jiffies(now + expire));
+ else
+ mod_timer(&tbl->gc_timer, now + expire);
write_unlock(&tbl->lock);
}
@@ -897,9 +901,9 @@ static void neigh_update_hhs(struct neighbour *neigh)
if (update) {
for (hh = neigh->hh; hh; hh = hh->hh_next) {
- write_lock_bh(&hh->hh_lock);
+ write_seqlock_bh(&hh->hh_lock);
update(hh, neigh->dev, neigh->ha);
- write_unlock_bh(&hh->hh_lock);
+ write_sequnlock_bh(&hh->hh_lock);
}
}
}
@@ -1089,7 +1093,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
break;
if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
- rwlock_init(&hh->hh_lock);
+ seqlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 0);
hh->hh_next = NULL;
@@ -1636,7 +1640,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
if (nlh == NULL)
- return -ENOBUFS;
+ return -EMSGSIZE;
ndtmsg = nlmsg_data(nlh);
@@ -1705,7 +1709,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
nla_put_failure:
read_unlock_bh(&tbl->lock);
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
}
static int neightbl_fill_param_info(struct sk_buff *skb,
@@ -1719,7 +1724,7 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
if (nlh == NULL)
- return -ENOBUFS;
+ return -EMSGSIZE;
ndtmsg = nlmsg_data(nlh);
@@ -1736,7 +1741,8 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
return nlmsg_end(skb, nlh);
errout:
read_unlock_bh(&tbl->lock);
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
}
static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
@@ -1954,7 +1960,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
if (nlh == NULL)
- return -ENOBUFS;
+ return -EMSGSIZE;
ndm = nlmsg_data(nlh);
ndm->ndm_family = neigh->ops->family;
@@ -1986,7 +1992,8 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
return nlmsg_end(skb, nlh);
nla_put_failure:
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
}
@@ -2428,9 +2435,12 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
goto errout;
err = neigh_fill_info(skb, n, 0, 0, type, flags);
- /* failure implies BUG in neigh_nlmsg_size() */
- BUG_ON(err < 0);
-
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
errout:
if (err < 0)
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index f47f319bb7d..44db095a8f7 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -18,9 +18,6 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
-#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
-#define to_net_dev(class) container_of(class, struct net_device, class_dev)
-
static const char fmt_hex[] = "%#x\n";
static const char fmt_long_hex[] = "%#lx\n";
static const char fmt_dec[] = "%d\n";
@@ -32,10 +29,11 @@ static inline int dev_isalive(const struct net_device *dev)
}
/* use same locking rules as GIF* ioctl's */
-static ssize_t netdev_show(const struct class_device *cd, char *buf,
+static ssize_t netdev_show(const struct device *dev,
+ struct device_attribute *attr, char *buf,
ssize_t (*format)(const struct net_device *, char *))
{
- struct net_device *net = to_net_dev(cd);
+ struct net_device *net = to_net_dev(dev);
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
@@ -52,14 +50,15 @@ static ssize_t format_##field(const struct net_device *net, char *buf) \
{ \
return sprintf(buf, format_string, net->field); \
} \
-static ssize_t show_##field(struct class_device *cd, char *buf) \
+static ssize_t show_##field(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
{ \
- return netdev_show(cd, buf, format_##field); \
+ return netdev_show(dev, attr, buf, format_##field); \
}
/* use same locking and permission rules as SIF* ioctl's */
-static ssize_t netdev_store(struct class_device *dev,
+static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len,
int (*set)(struct net_device *, unsigned long))
{
@@ -104,7 +103,8 @@ static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
return cp - buf;
}
-static ssize_t show_address(struct class_device *dev, char *buf)
+static ssize_t show_address(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct net_device *net = to_net_dev(dev);
ssize_t ret = -EINVAL;
@@ -116,7 +116,8 @@ static ssize_t show_address(struct class_device *dev, char *buf)
return ret;
}
-static ssize_t show_broadcast(struct class_device *dev, char *buf)
+static ssize_t show_broadcast(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct net_device *net = to_net_dev(dev);
if (dev_isalive(net))
@@ -124,7 +125,8 @@ static ssize_t show_broadcast(struct class_device *dev, char *buf)
return -EINVAL;
}
-static ssize_t show_carrier(struct class_device *dev, char *buf)
+static ssize_t show_carrier(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct net_device *netdev = to_net_dev(dev);
if (netif_running(netdev)) {
@@ -133,7 +135,8 @@ static ssize_t show_carrier(struct class_device *dev, char *buf)
return -EINVAL;
}
-static ssize_t show_dormant(struct class_device *dev, char *buf)
+static ssize_t show_dormant(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct net_device *netdev = to_net_dev(dev);
@@ -153,7 +156,8 @@ static const char *operstates[] = {
"up"
};
-static ssize_t show_operstate(struct class_device *dev, char *buf)
+static ssize_t show_operstate(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
const struct net_device *netdev = to_net_dev(dev);
unsigned char operstate;
@@ -178,9 +182,10 @@ static int change_mtu(struct net_device *net, unsigned long new_mtu)
return dev_set_mtu(net, (int) new_mtu);
}
-static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_mtu(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
{
- return netdev_store(dev, buf, len, change_mtu);
+ return netdev_store(dev, attr, buf, len, change_mtu);
}
NETDEVICE_SHOW(flags, fmt_hex);
@@ -190,9 +195,10 @@ static int change_flags(struct net_device *net, unsigned long new_flags)
return dev_change_flags(net, (unsigned) new_flags);
}
-static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_flags(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
{
- return netdev_store(dev, buf, len, change_flags);
+ return netdev_store(dev, attr, buf, len, change_flags);
}
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
@@ -203,9 +209,11 @@ static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
return 0;
}
-static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_tx_queue_len(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
{
- return netdev_store(dev, buf, len, change_tx_queue_len);
+ return netdev_store(dev, attr, buf, len, change_tx_queue_len);
}
NETDEVICE_SHOW(weight, fmt_dec);
@@ -216,12 +224,13 @@ static int change_weight(struct net_device *net, unsigned long new_weight)
return 0;
}
-static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len)
+static ssize_t store_weight(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
{
- return netdev_store(dev, buf, len, change_weight);
+ return netdev_store(dev, attr, buf, len, change_weight);
}
-static struct class_device_attribute net_class_attributes[] = {
+static struct device_attribute net_class_attributes[] = {
__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
__ATTR(iflink, S_IRUGO, show_iflink, NULL),
__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
@@ -242,10 +251,11 @@ static struct class_device_attribute net_class_attributes[] = {
};
/* Show a given an attribute in the statistics group */
-static ssize_t netstat_show(const struct class_device *cd, char *buf,
+static ssize_t netstat_show(const struct device *d,
+ struct device_attribute *attr, char *buf,
unsigned long offset)
{
- struct net_device *dev = to_net_dev(cd);
+ struct net_device *dev = to_net_dev(d);
struct net_device_stats *stats;
ssize_t ret = -EINVAL;
@@ -265,12 +275,13 @@ static ssize_t netstat_show(const struct class_device *cd, char *buf,
/* generate a read-only statistics attribute */
#define NETSTAT_ENTRY(name) \
-static ssize_t show_##name(struct class_device *cd, char *buf) \
+static ssize_t show_##name(struct device *d, \
+ struct device_attribute *attr, char *buf) \
{ \
- return netstat_show(cd, buf, \
+ return netstat_show(d, attr, buf, \
offsetof(struct net_device_stats, name)); \
} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
NETSTAT_ENTRY(rx_packets);
NETSTAT_ENTRY(tx_packets);
@@ -297,29 +308,29 @@ NETSTAT_ENTRY(rx_compressed);
NETSTAT_ENTRY(tx_compressed);
static struct attribute *netstat_attrs[] = {
- &class_device_attr_rx_packets.attr,
- &class_device_attr_tx_packets.attr,
- &class_device_attr_rx_bytes.attr,
- &class_device_attr_tx_bytes.attr,
- &class_device_attr_rx_errors.attr,
- &class_device_attr_tx_errors.attr,
- &class_device_attr_rx_dropped.attr,
- &class_device_attr_tx_dropped.attr,
- &class_device_attr_multicast.attr,
- &class_device_attr_collisions.attr,
- &class_device_attr_rx_length_errors.attr,
- &class_device_attr_rx_over_errors.attr,
- &class_device_attr_rx_crc_errors.attr,
- &class_device_attr_rx_frame_errors.attr,
- &class_device_attr_rx_fifo_errors.attr,
- &class_device_attr_rx_missed_errors.attr,
- &class_device_attr_tx_aborted_errors.attr,
- &class_device_attr_tx_carrier_errors.attr,
- &class_device_attr_tx_fifo_errors.attr,
- &class_device_attr_tx_heartbeat_errors.attr,
- &class_device_attr_tx_window_errors.attr,
- &class_device_attr_rx_compressed.attr,
- &class_device_attr_tx_compressed.attr,
+ &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,
NULL
};
@@ -331,11 +342,11 @@ static struct attribute_group netstat_group = {
#ifdef WIRELESS_EXT
/* helper function that does all the locking etc for wireless stats */
-static ssize_t wireless_show(struct class_device *cd, char *buf,
+static ssize_t wireless_show(struct device *d, char *buf,
ssize_t (*format)(const struct iw_statistics *,
char *))
{
- struct net_device *dev = to_net_dev(cd);
+ struct net_device *dev = to_net_dev(d);
const struct iw_statistics *iw = NULL;
ssize_t ret = -EINVAL;
@@ -358,11 +369,12 @@ static ssize_t format_iw_##name(const struct iw_statistics *iw, char *buf) \
{ \
return sprintf(buf, format_string, iw->field); \
} \
-static ssize_t show_iw_##name(struct class_device *cd, char *buf) \
+static ssize_t show_iw_##name(struct device *d, \
+ struct device_attribute *attr, char *buf) \
{ \
- return wireless_show(cd, buf, format_iw_##name); \
+ return wireless_show(d, buf, format_iw_##name); \
} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL)
+static DEVICE_ATTR(name, S_IRUGO, show_iw_##name, NULL)
WIRELESS_SHOW(status, status, fmt_hex);
WIRELESS_SHOW(link, qual.qual, fmt_dec);
@@ -376,16 +388,16 @@ WIRELESS_SHOW(retries, discard.retries, fmt_dec);
WIRELESS_SHOW(beacon, miss.beacon, fmt_dec);
static struct attribute *wireless_attrs[] = {
- &class_device_attr_status.attr,
- &class_device_attr_link.attr,
- &class_device_attr_level.attr,
- &class_device_attr_noise.attr,
- &class_device_attr_nwid.attr,
- &class_device_attr_crypt.attr,
- &class_device_attr_fragment.attr,
- &class_device_attr_retries.attr,
- &class_device_attr_misc.attr,
- &class_device_attr_beacon.attr,
+ &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,
NULL
};
@@ -396,10 +408,10 @@ static struct attribute_group wireless_group = {
#endif
#ifdef CONFIG_HOTPLUG
-static int netdev_uevent(struct class_device *cd, char **envp,
+static int netdev_uevent(struct device *d, char **envp,
int num_envp, char *buf, int size)
{
- struct net_device *dev = to_net_dev(cd);
+ struct net_device *dev = to_net_dev(d);
int i = 0;
int n;
@@ -419,12 +431,11 @@ static int netdev_uevent(struct class_device *cd, char **envp,
/*
* netdev_release -- destroy and free a dead device.
- * Called when last reference to class_device kobject is gone.
+ * Called when last reference to device kobject is gone.
*/
-static void netdev_release(struct class_device *cd)
+static void netdev_release(struct device *d)
{
- struct net_device *dev
- = container_of(cd, struct net_device, class_dev);
+ struct net_device *dev = to_net_dev(d);
BUG_ON(dev->reg_state != NETREG_RELEASED);
@@ -433,31 +444,31 @@ static void netdev_release(struct class_device *cd)
static struct class net_class = {
.name = "net",
- .release = netdev_release,
- .class_dev_attrs = net_class_attributes,
+ .dev_release = netdev_release,
+ .dev_attrs = net_class_attributes,
#ifdef CONFIG_HOTPLUG
- .uevent = netdev_uevent,
+ .dev_uevent = netdev_uevent,
#endif
};
void netdev_unregister_sysfs(struct net_device * net)
{
- class_device_del(&(net->class_dev));
+ device_del(&(net->dev));
}
/* Create sysfs entries for network device. */
int netdev_register_sysfs(struct net_device *net)
{
- struct class_device *class_dev = &(net->class_dev);
+ struct device *dev = &(net->dev);
struct attribute_group **groups = net->sysfs_groups;
- class_device_initialize(class_dev);
- class_dev->class = &net_class;
- class_dev->class_data = net;
- class_dev->groups = groups;
+ device_initialize(dev);
+ dev->class = &net_class;
+ dev->platform_data = net;
+ dev->groups = groups;
BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ);
- strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
+ strlcpy(dev->bus_id, net->name, BUS_ID_SIZE);
if (net->get_stats)
*groups++ = &netstat_group;
@@ -467,7 +478,7 @@ int netdev_register_sysfs(struct net_device *net)
*groups++ = &wireless_group;
#endif
- return class_device_add(class_dev);
+ return device_add(dev);
}
int netdev_sysfs_init(void)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index b3c559b9ac3..823215d8e90 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -55,6 +55,7 @@ static void queue_process(struct work_struct *work)
struct netpoll_info *npinfo =
container_of(work, struct netpoll_info, tx_work.work);
struct sk_buff *skb;
+ unsigned long flags;
while ((skb = skb_dequeue(&npinfo->txq))) {
struct net_device *dev = skb->dev;
@@ -64,15 +65,19 @@ static void queue_process(struct work_struct *work)
continue;
}
- netif_tx_lock_bh(dev);
+ local_irq_save(flags);
+ netif_tx_lock(dev);
if (netif_queue_stopped(dev) ||
dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
skb_queue_head(&npinfo->txq, skb);
- netif_tx_unlock_bh(dev);
+ netif_tx_unlock(dev);
+ local_irq_restore(flags);
schedule_delayed_work(&npinfo->tx_work, HZ/10);
return;
}
+ netif_tx_unlock(dev);
+ local_irq_restore(flags);
}
}
@@ -242,22 +247,28 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
/* don't get messages out of order, and no recursion */
if (skb_queue_len(&npinfo->txq) == 0 &&
- npinfo->poll_owner != smp_processor_id() &&
- netif_tx_trylock(dev)) {
- /* try until next clock tick */
- for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; tries > 0; --tries) {
- if (!netif_queue_stopped(dev))
- status = dev->hard_start_xmit(skb, dev);
+ npinfo->poll_owner != smp_processor_id()) {
+ unsigned long flags;
- if (status == NETDEV_TX_OK)
- break;
+ local_irq_save(flags);
+ if (netif_tx_trylock(dev)) {
+ /* try until next clock tick */
+ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+ tries > 0; --tries) {
+ if (!netif_queue_stopped(dev))
+ status = dev->hard_start_xmit(skb, dev);
- /* tickle device maybe there is some cleanup */
- netpoll_poll(np);
+ if (status == NETDEV_TX_OK)
+ break;
+
+ /* tickle device maybe there is some cleanup */
+ netpoll_poll(np);
- udelay(USEC_PER_POLL);
+ udelay(USEC_PER_POLL);
+ }
+ netif_tx_unlock(dev);
}
- netif_tx_unlock(dev);
+ local_irq_restore(flags);
}
if (status != NETDEV_TX_OK) {
@@ -330,6 +341,7 @@ static void arp_reply(struct sk_buff *skb)
unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
__be32 sip, tip;
+ unsigned char *sha;
struct sk_buff *send_skb;
struct netpoll *np = NULL;
@@ -356,9 +368,14 @@ static void arp_reply(struct sk_buff *skb)
arp->ar_op != htons(ARPOP_REQUEST))
return;
- arp_ptr = (unsigned char *)(arp+1) + skb->dev->addr_len;
+ arp_ptr = (unsigned char *)(arp+1);
+ /* save the location of the src hw addr */
+ sha = arp_ptr;
+ arp_ptr += skb->dev->addr_len;
memcpy(&sip, arp_ptr, 4);
- arp_ptr += 4 + skb->dev->addr_len;
+ arp_ptr += 4;
+ /* if we actually cared about dst hw addr, it would get copied here */
+ arp_ptr += skb->dev->addr_len;
memcpy(&tip, arp_ptr, 4);
/* Should we ignore arp? */
@@ -381,7 +398,7 @@ static void arp_reply(struct sk_buff *skb)
if (np->dev->hard_header &&
np->dev->hard_header(send_skb, skb->dev, ptype,
- np->remote_mac, np->local_mac,
+ sha, np->local_mac,
send_skb->len) < 0) {
kfree_skb(send_skb);
return;
@@ -405,7 +422,7 @@ static void arp_reply(struct sk_buff *skb)
arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &tip, 4);
arp_ptr += 4;
- memcpy(arp_ptr, np->remote_mac, np->dev->addr_len);
+ memcpy(arp_ptr, sha, np->dev->addr_len);
arp_ptr += np->dev->addr_len;
memcpy(arp_ptr, &sip, 4);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 1897a3a385d..04d4b93c68e 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -148,6 +148,7 @@
#include <linux/seq_file.h>
#include <linux/wait.h>
#include <linux/etherdevice.h>
+#include <linux/kthread.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
@@ -360,8 +361,7 @@ struct pktgen_thread {
spinlock_t if_lock;
struct list_head if_list; /* All device here */
struct list_head th_list;
- int removed;
- char name[32];
+ struct task_struct *tsk;
char result[512];
u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */
@@ -1689,7 +1689,7 @@ static int pktgen_thread_show(struct seq_file *seq, void *v)
BUG_ON(!t);
seq_printf(seq, "Name: %s max_before_softirq: %d\n",
- t->name, t->max_before_softirq);
+ t->tsk->comm, t->max_before_softirq);
seq_printf(seq, "Running: ");
@@ -3112,7 +3112,7 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
{
/* Remove from the thread list */
- remove_proc_entry(t->name, pg_proc_dir);
+ remove_proc_entry(t->tsk->comm, pg_proc_dir);
mutex_lock(&pktgen_thread_lock);
@@ -3260,58 +3260,40 @@ out:;
* Main loop of the thread goes here
*/
-static void pktgen_thread_worker(struct pktgen_thread *t)
+static int pktgen_thread_worker(void *arg)
{
DEFINE_WAIT(wait);
+ struct pktgen_thread *t = arg;
struct pktgen_dev *pkt_dev = NULL;
int cpu = t->cpu;
- sigset_t tmpsig;
u32 max_before_softirq;
u32 tx_since_softirq = 0;
- daemonize("pktgen/%d", cpu);
-
- /* Block all signals except SIGKILL, SIGSTOP and SIGTERM */
-
- spin_lock_irq(&current->sighand->siglock);
- tmpsig = current->blocked;
- siginitsetinv(&current->blocked,
- sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGTERM));
-
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- /* Migrate to the right CPU */
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- if (smp_processor_id() != cpu)
- BUG();
+ BUG_ON(smp_processor_id() != cpu);
init_waitqueue_head(&t->queue);
- t->control &= ~(T_TERMINATE);
- t->control &= ~(T_RUN);
- t->control &= ~(T_STOP);
- t->control &= ~(T_REMDEVALL);
- t->control &= ~(T_REMDEV);
-
t->pid = current->pid;
PG_DEBUG(printk("pktgen: starting pktgen/%d: pid=%d\n", cpu, current->pid));
max_before_softirq = t->max_before_softirq;
- __set_current_state(TASK_INTERRUPTIBLE);
- mb();
+ set_current_state(TASK_INTERRUPTIBLE);
- while (1) {
-
- __set_current_state(TASK_RUNNING);
+ while (!kthread_should_stop()) {
+ pkt_dev = next_to_run(t);
- /*
- * Get next dev to xmit -- if any.
- */
+ if (!pkt_dev &&
+ (t->control & (T_STOP | T_RUN | T_REMDEVALL | T_REMDEV))
+ == 0) {
+ prepare_to_wait(&(t->queue), &wait,
+ TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ / 10);
+ finish_wait(&(t->queue), &wait);
+ }
- pkt_dev = next_to_run(t);
+ __set_current_state(TASK_RUNNING);
if (pkt_dev) {
@@ -3329,21 +3311,8 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
do_softirq();
tx_since_softirq = 0;
}
- } else {
- prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
- finish_wait(&(t->queue), &wait);
}
- /*
- * Back from sleep, either due to the timeout or signal.
- * We check if we have any "posted" work for us.
- */
-
- if (t->control & T_TERMINATE || signal_pending(current))
- /* we received a request to terminate ourself */
- break;
-
if (t->control & T_STOP) {
pktgen_stop(t);
t->control &= ~(T_STOP);
@@ -3364,20 +3333,19 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
t->control &= ~(T_REMDEV);
}
- if (need_resched())
- schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
}
- PG_DEBUG(printk("pktgen: %s stopping all device\n", t->name));
+ PG_DEBUG(printk("pktgen: %s stopping all device\n", t->tsk->comm));
pktgen_stop(t);
- PG_DEBUG(printk("pktgen: %s removing all device\n", t->name));
+ PG_DEBUG(printk("pktgen: %s removing all device\n", t->tsk->comm));
pktgen_rem_all_ifs(t);
- PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
+ PG_DEBUG(printk("pktgen: %s removing thread.\n", t->tsk->comm));
pktgen_rem_thread(t);
- t->removed = 1;
+ return 0;
}
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
@@ -3495,37 +3463,11 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
return add_dev_to_thread(t, pkt_dev);
}
-static struct pktgen_thread *__init pktgen_find_thread(const char *name)
+static int __init pktgen_create_thread(int cpu)
{
struct pktgen_thread *t;
-
- mutex_lock(&pktgen_thread_lock);
-
- list_for_each_entry(t, &pktgen_threads, th_list)
- if (strcmp(t->name, name) == 0) {
- mutex_unlock(&pktgen_thread_lock);
- return t;
- }
-
- mutex_unlock(&pktgen_thread_lock);
- return NULL;
-}
-
-static int __init pktgen_create_thread(const char *name, int cpu)
-{
- int err;
- struct pktgen_thread *t = NULL;
struct proc_dir_entry *pe;
-
- if (strlen(name) > 31) {
- printk("pktgen: ERROR: Thread name cannot be more than 31 characters.\n");
- return -EINVAL;
- }
-
- if (pktgen_find_thread(name)) {
- printk("pktgen: ERROR: thread: %s already exists\n", name);
- return -EINVAL;
- }
+ struct task_struct *p;
t = kzalloc(sizeof(struct pktgen_thread), GFP_KERNEL);
if (!t) {
@@ -3533,14 +3475,29 @@ static int __init pktgen_create_thread(const char *name, int cpu)
return -ENOMEM;
}
- strcpy(t->name, name);
spin_lock_init(&t->if_lock);
t->cpu = cpu;
- pe = create_proc_entry(t->name, 0600, pg_proc_dir);
+ INIT_LIST_HEAD(&t->if_list);
+
+ list_add_tail(&t->th_list, &pktgen_threads);
+
+ p = kthread_create(pktgen_thread_worker, t, "kpktgend_%d", cpu);
+ if (IS_ERR(p)) {
+ printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
+ list_del(&t->th_list);
+ kfree(t);
+ return PTR_ERR(p);
+ }
+ kthread_bind(p, cpu);
+ t->tsk = p;
+
+ pe = create_proc_entry(t->tsk->comm, 0600, pg_proc_dir);
if (!pe) {
printk("pktgen: cannot create %s/%s procfs entry.\n",
- PG_PROC_DIR, t->name);
+ PG_PROC_DIR, t->tsk->comm);
+ kthread_stop(p);
+ list_del(&t->th_list);
kfree(t);
return -EINVAL;
}
@@ -3548,21 +3505,7 @@ static int __init pktgen_create_thread(const char *name, int cpu)
pe->proc_fops = &pktgen_thread_fops;
pe->data = t;
- INIT_LIST_HEAD(&t->if_list);
-
- list_add_tail(&t->th_list, &pktgen_threads);
-
- t->removed = 0;
-
- err = kernel_thread((void *)pktgen_thread_worker, (void *)t,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (err < 0) {
- printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu);
- remove_proc_entry(t->name, pg_proc_dir);
- list_del(&t->th_list);
- kfree(t);
- return err;
- }
+ wake_up_process(p);
return 0;
}
@@ -3643,10 +3586,8 @@ static int __init pg_init(void)
for_each_online_cpu(cpu) {
int err;
- char buf[30];
- sprintf(buf, "kpktgend_%i", cpu);
- err = pktgen_create_thread(buf, cpu);
+ err = pktgen_create_thread(cpu);
if (err)
printk("pktgen: WARNING: Cannot create thread for cpu %d (%d)\n",
cpu, err);
@@ -3674,9 +3615,8 @@ static void __exit pg_cleanup(void)
list_for_each_safe(q, n, &pktgen_threads) {
t = list_entry(q, struct pktgen_thread, th_list);
- t->control |= (T_TERMINATE);
-
- wait_event_interruptible_timeout(queue, (t->removed == 1), HZ);
+ kthread_stop(t->tsk);
+ kfree(t);
}
/* Un-register us from receiving netdevice events */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index e76539a5eb5..9bf9ae05f15 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -320,7 +320,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
if (nlh == NULL)
- return -ENOBUFS;
+ return -EMSGSIZE;
ifm = nlmsg_data(nlh);
ifm->ifi_family = AF_UNSPEC;
@@ -384,7 +384,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
return nlmsg_end(skb, nlh);
nla_put_failure:
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
}
static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
@@ -633,9 +634,12 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
- /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
- BUG_ON(err < 0);
-
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in if_nlmsg_size */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(nskb);
+ goto errout;
+ }
err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
errout:
kfree(iw_buf);
@@ -678,9 +682,12 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
goto errout;
err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
- /* failure implies BUG in if_nlmsg_size() */
- BUG_ON(err < 0);
-
+ if (err < 0) {
+ /* -EMSGSIZE implies BUG in if_nlmsg_size() */
+ WARN_ON(err == -EMSGSIZE);
+ kfree_skb(skb);
+ goto errout;
+ }
err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
errout:
if (err < 0)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index de7801d589e..f3404ae9f19 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -268,7 +268,7 @@ nodata:
struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
unsigned int length, gfp_t gfp_mask)
{
- int node = dev->class_dev.dev ? dev_to_node(dev->class_dev.dev) : -1;
+ int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
struct sk_buff *skb;
skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);