X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=net%2Fbridge%2Fbr_if.c;h=f3a2e29be40c30b173f447bc5ee412cf28c2dcc4;hb=2189850f42beff23af32d847bd043cd1d1811a80;hp=55bb2634c088cfccdb9a737449a008f406167302;hpb=cfee47f99bc14a6d7c6b0be2284db2cef310a815;p=powerpc.git diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 55bb2634c0..f3a2e29be4 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -47,7 +47,7 @@ static int port_cost(struct net_device *dev) set_fs(KERNEL_DS); err = dev_ethtool(&ifr); set_fs(old_fs); - + if (!err) { switch(ecmd.speed) { case SPEED_100: @@ -77,26 +77,15 @@ static int port_cost(struct net_device *dev) * Called from work queue to allow for calling functions that * might sleep (such as speed check), and to debounce. */ -static void port_carrier_check(struct work_struct *work) +void br_port_carrier_check(struct net_bridge_port *p) { - struct net_bridge_port *p; - struct net_device *dev; - struct net_bridge *br; - - dev = container_of(work, struct net_bridge_port, - carrier_check.work)->dev; - work_release(work); - - rtnl_lock(); - p = dev->br_port; - if (!p) - goto done; - br = p->br; + struct net_device *dev = p->dev; + struct net_bridge *br = p->br; if (netif_carrier_ok(dev)) p->path_cost = port_cost(dev); - if (br->dev->flags & IFF_UP) { + if (netif_running(br->dev)) { spin_lock_bh(&br->lock); if (netif_carrier_ok(dev)) { if (p->state == BR_STATE_DISABLED) @@ -107,8 +96,6 @@ static void port_carrier_check(struct work_struct *work) } spin_unlock_bh(&br->lock); } -done: - rtnl_unlock(); } static void release_nbp(struct kobject *kobj) @@ -161,8 +148,6 @@ static void del_nbp(struct net_bridge_port *p) dev_set_promiscuity(dev, -1); - cancel_delayed_work(&p->carrier_check); - spin_lock_bh(&br->lock); br_stp_disable_port(p); spin_unlock_bh(&br->lock); @@ -191,7 +176,7 @@ static void del_br(struct net_bridge *br) del_timer_sync(&br->gc_timer); br_sysfs_delbr(br->dev); - unregister_netdevice(br->dev); + unregister_netdevice(br->dev); } static struct net_device *new_bridge_dev(const char *name) @@ -201,7 +186,7 @@ static struct net_device *new_bridge_dev(const char *name) dev = alloc_netdev(sizeof(struct net_bridge), name, br_dev_setup); - + if (!dev) return NULL; @@ -258,12 +243,12 @@ static int find_portno(struct net_bridge *br) } /* called with RTNL but without bridge lock */ -static struct net_bridge_port *new_nbp(struct net_bridge *br, +static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev) { int index; struct net_bridge_port *p; - + index = find_portno(br); if (index < 0) return ERR_PTR(index); @@ -276,17 +261,16 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, dev_hold(dev); p->dev = dev; p->path_cost = port_cost(dev); - p->priority = 0x8000 >> BR_PORT_BITS; + p->priority = 0x8000 >> BR_PORT_BITS; p->port_no = index; br_init_port(p); p->state = BR_STATE_DISABLED; - INIT_DELAYED_WORK_NAR(&p->carrier_check, port_carrier_check); br_stp_port_timer_init(p); kobject_init(&p->kobj); kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); p->kobj.ktype = &brport_ktype; - p->kobj.parent = &(dev->class_dev.kobj); + p->kobj.parent = &(dev->dev.kobj); p->kobj.kset = NULL; return p; @@ -298,7 +282,7 @@ int br_add_bridge(const char *name) int ret; dev = new_bridge_dev(name); - if (!dev) + if (!dev) return -ENOMEM; rtnl_lock(); @@ -329,7 +313,7 @@ int br_del_bridge(const char *name) rtnl_lock(); dev = __dev_get_by_name(name); - if (dev == NULL) + if (dev == NULL) ret = -ENXIO; /* Could not find device */ else if (!(dev->priv_flags & IFF_EBRIDGE)) { @@ -340,9 +324,9 @@ int br_del_bridge(const char *name) else if (dev->flags & IFF_UP) { /* Not shutdown yet. */ ret = -EBUSY; - } + } - else + else del_br(netdev_priv(dev)); rtnl_unlock(); @@ -428,7 +412,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) if (err) goto err0; - err = br_fdb_insert(br, p, dev->dev_addr); + err = br_fdb_insert(br, p, dev->dev_addr); if (err) goto err1; @@ -444,10 +428,14 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) spin_lock_bh(&br->lock); br_stp_recalculate_bridge_id(br); br_features_recompute(br); - schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE); + + if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && + (br->dev->flags & IFF_UP)) + br_stp_enable_port(p); spin_unlock_bh(&br->lock); dev_set_mtu(br->dev, br_min_mtu(br)); + kobject_uevent(&p->kobj, KOBJ_ADD); return 0; @@ -464,8 +452,8 @@ err0: int br_del_if(struct net_bridge *br, struct net_device *dev) { struct net_bridge_port *p = dev->br_port; - - if (!p || p->br != br) + + if (!p || p->br != br) return -EINVAL; del_nbp(p);