Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2003-10-16 11:09:43 -0700
committerStephen Hemminger <shemminger@osdl.org>2003-10-16 11:09:43 -0700
commit754f80fb5810dc2c3878df22aa88404c113e7dce (patch)
treef10530f06440c25cc9e6bd76f9afbe760ba07588
parentc700a9de6dd6f700db8c8fb4ea13d7c6b1ad9f1a (diff)
[NET]: Catch buggy net drivers changing getstats op after registry.
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/dev.c29
-rw-r--r--net/core/net-sysfs.c1
3 files changed, 31 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2a53de551b53..cf00126c50ed 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -469,6 +469,7 @@ struct net_device
/* class/net/name entry */
struct class_device class_dev;
+ struct net_device_stats* (*last_stats)(struct net_device *);
};
#define SET_MODULE_OWNER(dev) do { } while (0)
diff --git a/net/core/dev.c b/net/core/dev.c
index 7cf411e5eb5c..7ba82b6a6429 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -713,6 +713,19 @@ static int default_rebuild_header(struct sk_buff *skb)
return 1;
}
+
+/*
+ * Some old buggy device drivers change get_stats after registering
+ * the device. Try and trap them here.
+ * This can be elimnated when all devices are known fixed.
+ */
+static inline int get_stats_changed(struct net_device *dev)
+{
+ int changed = dev->last_stats != dev->get_stats;
+ dev->last_stats = dev->get_stats;
+ return changed;
+}
+
/**
* dev_open - prepare an interface for use.
* @dev: device to open
@@ -737,6 +750,14 @@ int dev_open(struct net_device *dev)
return 0;
/*
+ * Check for broken device drivers.
+ */
+ if (get_stats_changed(dev) && net_ratelimit()) {
+ printk(KERN_ERR "%s: driver changed get_stats after register\n",
+ dev->name);
+ }
+
+ /*
* Is it even present?
*/
if (!netif_device_present(dev))
@@ -753,6 +774,14 @@ int dev_open(struct net_device *dev)
}
/*
+ * Check for more broken device drivers.
+ */
+ if (get_stats_changed(dev) && net_ratelimit()) {
+ printk(KERN_ERR "%s: driver changed get_stats in open\n",
+ dev->name);
+ }
+
+ /*
* If it went open OK then:
*/
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index b1fa8f6ccc2a..ae9b5c8e8098 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -419,6 +419,7 @@ int netdev_register_sysfs(struct net_device *net)
}
+ net->last_stats = net->get_stats;
if (net->get_stats &&
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
goto out_unreg;