diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-03-04 04:14:51 +0300 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-05 08:06:19 +0300 |
commit | 6e86b89084a60355f0e1fb876ca0cfbca62ee85c (patch) | |
tree | 076b621fad864de984661a9a15bd526bc068776b | |
parent | 501f74f29498543c27f4f9697f5c1e980dd2de0d (diff) | |
download | linux-6e86b89084a60355f0e1fb876ca0cfbca62ee85c.tar.xz |
[BRIDGE]: fix crash in STP
Bridge would crash because of uninitailized timer if STP is used and
device was inserted into a bridge before bridge was up. This got
introduced when the delayed port checking was added. Fix is to not
enable STP on port unless bridge is up.
Bugzilla: http://bugzilla.kernel.org/show_bug.cgi?id=6140
Dup: http://bugzilla.kernel.org/show_bug.cgi?id=6156
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/bridge/br_if.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 7fa3a5a9971f..8b38c839d539 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -81,26 +81,27 @@ static void port_carrier_check(void *arg) { struct net_device *dev = arg; struct net_bridge_port *p; + struct net_bridge *br; rtnl_lock(); p = dev->br_port; if (!p) goto done; - - if (netif_carrier_ok(p->dev)) { - u32 cost = port_cost(p->dev); - - spin_lock_bh(&p->br->lock); - if (p->state == BR_STATE_DISABLED) { - p->path_cost = cost; - br_stp_enable_port(p); + br = p->br; + + if (netif_carrier_ok(dev)) + p->path_cost = port_cost(dev); + + if (br->dev->flags & IFF_UP) { + spin_lock_bh(&br->lock); + if (netif_carrier_ok(dev)) { + if (p->state == BR_STATE_DISABLED) + br_stp_enable_port(p); + } else { + if (p->state != BR_STATE_DISABLED) + br_stp_disable_port(p); } - spin_unlock_bh(&p->br->lock); - } else { - spin_lock_bh(&p->br->lock); - if (p->state != BR_STATE_DISABLED) - br_stp_disable_port(p); - spin_unlock_bh(&p->br->lock); + spin_unlock_bh(&br->lock); } done: rtnl_unlock(); |