]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/bridge/br_if.c
net: Fix disjunct computation of netdev features
[linux-2.6-omap-h63xx.git] / net / bridge / br_if.c
index 63c18aacde8cbfc13b31d38bc040711805e97725..0a09ccf68c1c16e6362f895ba389f7287520594e 100644 (file)
@@ -168,7 +168,7 @@ static void del_br(struct net_bridge *br)
        unregister_netdevice(br->dev);
 }
 
-static struct net_device *new_bridge_dev(const char *name)
+static struct net_device *new_bridge_dev(struct net *net, const char *name)
 {
        struct net_bridge *br;
        struct net_device *dev;
@@ -178,6 +178,7 @@ static struct net_device *new_bridge_dev(const char *name)
 
        if (!dev)
                return NULL;
+       dev_net_set(dev, net);
 
        br = netdev_priv(dev);
        br->dev = dev;
@@ -262,12 +263,12 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
        return p;
 }
 
-int br_add_bridge(const char *name)
+int br_add_bridge(struct net *net, const char *name)
 {
        struct net_device *dev;
        int ret;
 
-       dev = new_bridge_dev(name);
+       dev = new_bridge_dev(net, name);
        if (!dev)
                return -ENOMEM;
 
@@ -294,13 +295,13 @@ out_free:
        goto out;
 }
 
-int br_del_bridge(const char *name)
+int br_del_bridge(struct net *net, const char *name)
 {
        struct net_device *dev;
        int ret = 0;
 
        rtnl_lock();
-       dev = __dev_get_by_name(&init_net, name);
+       dev = __dev_get_by_name(net, name);
        if (dev == NULL)
                ret =  -ENXIO;  /* Could not find device */
 
@@ -346,15 +347,21 @@ int br_min_mtu(const struct net_bridge *br)
 void br_features_recompute(struct net_bridge *br)
 {
        struct net_bridge_port *p;
-       unsigned long features;
+       unsigned long features, mask;
 
-       features = br->feature_mask;
+       features = mask = br->feature_mask;
+       if (list_empty(&br->port_list))
+               goto done;
+
+       features &= ~NETIF_F_ONE_FOR_ALL;
 
        list_for_each_entry(p, &br->port_list, list) {
-               features = netdev_compute_features(features, p->dev->features);
+               features = netdev_increment_features(features,
+                                                    p->dev->features, mask);
        }
 
-       br->dev->features = features;
+done:
+       br->dev->features = netdev_fix_features(features, NULL);
 }
 
 /* called with RTNL */
@@ -445,13 +452,13 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
        return 0;
 }
 
-void __exit br_cleanup_bridges(void)
+void br_net_exit(struct net *net)
 {
        struct net_device *dev;
 
        rtnl_lock();
 restart:
-       for_each_netdev(&init_net, dev) {
+       for_each_netdev(net, dev) {
                if (dev->priv_flags & IFF_EBRIDGE) {
                        del_br(dev->priv);
                        goto restart;