]> git.neil.brown.name Git - history.git/commitdiff
[NET]: Catch buggy net drivers changing getstats op after registry.
authorStephen Hemminger <shemminger@osdl.org>
Thu, 16 Oct 2003 18:09:43 +0000 (11:09 -0700)
committerStephen Hemminger <shemminger@osdl.org>
Thu, 16 Oct 2003 18:09:43 +0000 (11:09 -0700)
include/linux/netdevice.h
net/core/dev.c
net/core/net-sysfs.c

index 2a53de551b536dc247737066b86e30c92b970905..cf00126c50edc90fb6a035fbc396fe6c34fbc496 100644 (file)
@@ -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)
index 7cf411e5eb5c53e596dc17408a94b7d9d253b66d..7ba82b6a6429432a74d4372f0e32bcae34ec92cf 100644 (file)
@@ -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
@@ -736,6 +749,14 @@ int dev_open(struct net_device *dev)
        if (dev->flags & IFF_UP)
                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?
         */
@@ -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:
         */
 
index b1fa8f6ccc2a5f01745046edcffd84391eeab397..ae9b5c8e8098328c5fc517ddbc75a1bcd730b039 100644 (file)
@@ -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;