OSDN Git Service

Merge git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/linux-2.6-nsfd
[android-x86/kernel.git] / net / bridge / br_if.c
index 718b603..1bacca4 100644 (file)
@@ -36,8 +36,8 @@ static int port_cost(struct net_device *dev)
        if (dev->ethtool_ops && dev->ethtool_ops->get_settings) {
                struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, };
 
-               if (!dev->ethtool_ops->get_settings(dev, &ecmd)) {
-                       switch(ecmd.speed) {
+               if (!dev_ethtool_get_settings(dev, &ecmd)) {
+                       switch (ethtool_cmd_speed(&ecmd)) {
                        case SPEED_10000:
                                return 2;
                        case SPEED_1000:
@@ -147,6 +147,7 @@ static void del_nbp(struct net_bridge_port *p)
        dev->priv_flags &= ~IFF_BRIDGE_PORT;
 
        netdev_rx_handler_unregister(dev);
+       synchronize_net();
 
        netdev_set_master(dev, NULL);
 
@@ -175,56 +176,6 @@ static void del_br(struct net_bridge *br, struct list_head *head)
        unregister_netdevice_queue(br->dev, head);
 }
 
-static struct net_device *new_bridge_dev(struct net *net, const char *name)
-{
-       struct net_bridge *br;
-       struct net_device *dev;
-
-       dev = alloc_netdev(sizeof(struct net_bridge), name,
-                          br_dev_setup);
-
-       if (!dev)
-               return NULL;
-       dev_net_set(dev, net);
-
-       br = netdev_priv(dev);
-       br->dev = dev;
-
-       br->stats = alloc_percpu(struct br_cpu_netstats);
-       if (!br->stats) {
-               free_netdev(dev);
-               return NULL;
-       }
-
-       spin_lock_init(&br->lock);
-       INIT_LIST_HEAD(&br->port_list);
-       spin_lock_init(&br->hash_lock);
-
-       br->bridge_id.prio[0] = 0x80;
-       br->bridge_id.prio[1] = 0x00;
-
-       memcpy(br->group_addr, br_group_address, ETH_ALEN);
-
-       br->feature_mask = dev->features;
-       br->stp_enabled = BR_NO_STP;
-       br->designated_root = br->bridge_id;
-       br->root_path_cost = 0;
-       br->root_port = 0;
-       br->bridge_max_age = br->max_age = 20 * HZ;
-       br->bridge_hello_time = br->hello_time = 2 * HZ;
-       br->bridge_forward_delay = br->forward_delay = 15 * HZ;
-       br->topology_change = 0;
-       br->topology_change_detected = 0;
-       br->ageing_time = 300 * HZ;
-
-       br_netfilter_rtable_init(br);
-
-       br_stp_timer_init(br);
-       br_multicast_init(br);
-
-       return dev;
-}
-
 /* find an available port number */
 static int find_portno(struct net_bridge *br)
 {
@@ -277,42 +228,19 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
        return p;
 }
 
-static struct device_type br_type = {
-       .name   = "bridge",
-};
-
 int br_add_bridge(struct net *net, const char *name)
 {
        struct net_device *dev;
-       int ret;
 
-       dev = new_bridge_dev(net, name);
+       dev = alloc_netdev(sizeof(struct net_bridge), name,
+                          br_dev_setup);
+
        if (!dev)
                return -ENOMEM;
 
-       rtnl_lock();
-       if (strchr(dev->name, '%')) {
-               ret = dev_alloc_name(dev, dev->name);
-               if (ret < 0)
-                       goto out_free;
-       }
-
-       SET_NETDEV_DEVTYPE(dev, &br_type);
-
-       ret = register_netdevice(dev);
-       if (ret)
-               goto out_free;
-
-       ret = br_sysfs_addbr(dev);
-       if (ret)
-               unregister_netdevice(dev);
- out:
-       rtnl_unlock();
-       return ret;
+       dev_net_set(dev, net);
 
-out_free:
-       free_netdev(dev);
-       goto out;
+       return register_netdev(dev);
 }
 
 int br_del_bridge(struct net *net, const char *name)
@@ -364,15 +292,15 @@ int br_min_mtu(const struct net_bridge *br)
 /*
  * Recomputes features using slave's features
  */
-void br_features_recompute(struct net_bridge *br)
+u32 br_features_recompute(struct net_bridge *br, u32 features)
 {
        struct net_bridge_port *p;
-       u32 features, mask;
+       u32 mask;
 
-       features = mask = br->feature_mask;
        if (list_empty(&br->port_list))
-               goto done;
+               return features;
 
+       mask = features;
        features &= ~NETIF_F_ONE_FOR_ALL;
 
        list_for_each_entry(p, &br->port_list, list) {
@@ -380,8 +308,7 @@ void br_features_recompute(struct net_bridge *br)
                                                     p->dev->features, mask);
        }
 
-done:
-       br->dev->features = netdev_fix_features(br->dev, features);
+       return features;
 }
 
 /* called with RTNL */
@@ -412,6 +339,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
        if (IS_ERR(p))
                return PTR_ERR(p);
 
+       call_netdevice_notifiers(NETDEV_JOIN, dev);
+
        err = dev_set_promiscuity(dev, 1);
        if (err)
                goto put_back;
@@ -446,9 +375,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        list_add_rcu(&p->list, &br->port_list);
 
+       netdev_update_features(br->dev);
+
        spin_lock_bh(&br->lock);
        changed_addr = br_stp_recalculate_bridge_id(br);
-       br_features_recompute(br);
 
        if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
            (br->dev->flags & IFF_UP))
@@ -496,9 +426,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
 
        spin_lock_bh(&br->lock);
        br_stp_recalculate_bridge_id(br);
-       br_features_recompute(br);
        spin_unlock_bh(&br->lock);
 
+       netdev_update_features(br->dev);
+
        return 0;
 }