vserver 1.9.3
[linux-2.6.git] / net / decnet / dn_dev.c
index 11b0f0c..a21a326 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/sysctl.h>
 #include <linux/notifier.h>
 #include <asm/uaccess.h>
+#include <asm/system.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
 #include <net/flow.h>
@@ -247,21 +248,6 @@ static struct dn_dev_sysctl_table {
        }, {0}}
 };
 
-static inline __u16 mtu2blksize(struct net_device *dev)
-{
-       u32 blksize = dev->mtu;
-       if (blksize > 0xffff)
-               blksize = 0xffff;
-
-       if (dev->type == ARPHRD_ETHER ||
-           dev->type == ARPHRD_PPP ||
-           dev->type == ARPHRD_IPGRE ||
-           dev->type == ARPHRD_LOOPBACK)
-               blksize -= 2;
-
-       return (__u16)blksize;
-}
-
 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
 {
        struct dn_dev_sysctl_table *t;
@@ -314,52 +300,6 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
        }
 }
 
-struct net_device *dn_dev_get_default(void)
-{
-       struct net_device *dev;
-       read_lock(&dndev_lock);
-       dev = decnet_default_device;
-       if (dev) {
-               if (dev->dn_ptr)
-                       dev_hold(dev);
-               else
-                       dev = NULL;
-       }
-       read_unlock(&dndev_lock);
-       return dev;
-}
-
-int dn_dev_set_default(struct net_device *dev, int force)
-{
-       struct net_device *old = NULL;
-       int rv = -EBUSY;
-       if (!dev->dn_ptr)
-               return -ENODEV;
-       write_lock(&dndev_lock);
-       if (force || decnet_default_device == NULL) {
-               old = decnet_default_device;
-               decnet_default_device = dev;
-               rv = 0;
-       }
-       write_unlock(&dndev_lock);
-       if (old)
-               dev_put(dev);
-       return rv;
-}
-
-static void dn_dev_check_default(struct net_device *dev)
-{
-       write_lock(&dndev_lock);
-       if (dev == decnet_default_device) {
-               decnet_default_device = NULL;
-       } else {
-               dev = NULL;
-       }
-       write_unlock(&dndev_lock);
-       if (dev)
-               dev_put(dev);
-}
-
 static int dn_forwarding_proc(ctl_table *table, int write, 
                                struct file *filep,
                                void __user *buffer,
@@ -454,6 +394,21 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
 
 #endif /* CONFIG_SYSCTL */
 
+static inline __u16 mtu2blksize(struct net_device *dev)
+{
+       u32 blksize = dev->mtu;
+       if (blksize > 0xffff)
+               blksize = 0xffff;
+
+       if (dev->type == ARPHRD_ETHER ||
+           dev->type == ARPHRD_PPP ||
+           dev->type == ARPHRD_IPGRE ||
+           dev->type == ARPHRD_LOOPBACK)
+               blksize -= 2;
+
+       return (__u16)blksize;
+}
+
 static struct dn_ifaddr *dn_dev_alloc_ifa(void)
 {
        struct dn_ifaddr *ifa;
@@ -635,6 +590,52 @@ rarok:
        goto done;
 }
 
+struct net_device *dn_dev_get_default(void)
+{
+       struct net_device *dev;
+       read_lock(&dndev_lock);
+       dev = decnet_default_device;
+       if (dev) {
+               if (dev->dn_ptr)
+                       dev_hold(dev);
+               else
+                       dev = NULL;
+       }
+       read_unlock(&dndev_lock);
+       return dev;
+}
+
+int dn_dev_set_default(struct net_device *dev, int force)
+{
+       struct net_device *old = NULL;
+       int rv = -EBUSY;
+       if (!dev->dn_ptr)
+               return -ENODEV;
+       write_lock(&dndev_lock);
+       if (force || decnet_default_device == NULL) {
+               old = decnet_default_device;
+               decnet_default_device = dev;
+               rv = 0;
+       }
+       write_unlock(&dndev_lock);
+       if (old)
+               dev_put(dev);
+       return rv;
+}
+
+static void dn_dev_check_default(struct net_device *dev)
+{
+       write_lock(&dndev_lock);
+       if (dev == decnet_default_device) {
+               decnet_default_device = NULL;
+       } else {
+               dev = NULL;
+       }
+       write_unlock(&dndev_lock);
+       if (dev)
+               dev_put(dev);
+}
+
 static struct dn_dev *dn_dev_by_index(int ifindex)
 {
        struct net_device *dev;
@@ -1108,6 +1109,7 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 
        memset(dn_db, 0, sizeof(struct dn_dev));
        memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
+       smp_wmb();
        dev->dn_ptr = dn_db;
        dn_db->dev = dev;
        init_timer(&dn_db->timer);
@@ -1215,6 +1217,7 @@ static void dn_dev_delete(struct net_device *dev)
        dev->dn_ptr = NULL;
 
        neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
+       neigh_ifdown(&dn_neigh_table, dev);
 
        if (dn_db->router)
                neigh_release(dn_db->router);