Commit 650d56cd authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

[BRIDGE]: rmmod device while bridge is down fails

The changes to bridge notifier to handle link state changes introduced
a bug. The case of device unregistering while bridge is down was no
longer being handled. Add comment so maintainer doesn't forget.
Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 881fff34
...@@ -23,32 +23,39 @@ struct notifier_block br_device_notifier = { ...@@ -23,32 +23,39 @@ struct notifier_block br_device_notifier = {
.notifier_call = br_device_event .notifier_call = br_device_event
}; };
/*
* Handle changes in state of network devices enslaved to a bridge.
*
* Note: don't care about up/down if bridge itself is down, because
* port state is checked when bridge is brought up.
*/
static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{ {
struct net_device *dev = ptr; struct net_device *dev = ptr;
struct net_bridge_port *p = dev->br_port; struct net_bridge_port *p = dev->br_port;
struct net_bridge *br; struct net_bridge *br;
/* not a port of a bridge */
if (p == NULL) if (p == NULL)
return NOTIFY_DONE; return NOTIFY_DONE;
br = p->br; br = p->br;
if ( !(br->dev->flags & IFF_UP))
return NOTIFY_DONE;
if (event == NETDEV_CHANGEMTU) {
dev_set_mtu(br->dev, br_min_mtu(br));
return NOTIFY_DONE;
}
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
switch (event) { switch (event) {
case NETDEV_CHANGEMTU:
dev_set_mtu(br->dev, br_min_mtu(br));
break;
case NETDEV_CHANGEADDR: case NETDEV_CHANGEADDR:
br_fdb_changeaddr(p, dev->dev_addr); br_fdb_changeaddr(p, dev->dev_addr);
br_stp_recalculate_bridge_id(br); br_stp_recalculate_bridge_id(br);
break; break;
case NETDEV_CHANGE: /* device is up but carrier changed */ case NETDEV_CHANGE: /* device is up but carrier changed */
if (!(br->dev->flags & IFF_UP))
break;
if (netif_carrier_ok(dev)) { if (netif_carrier_ok(dev)) {
if (p->state == BR_STATE_DISABLED) if (p->state == BR_STATE_DISABLED)
br_stp_enable_port(p); br_stp_enable_port(p);
...@@ -59,11 +66,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v ...@@ -59,11 +66,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
break; break;
case NETDEV_DOWN: case NETDEV_DOWN:
if (br->dev->flags & IFF_UP)
br_stp_disable_port(p); br_stp_disable_port(p);
break; break;
case NETDEV_UP: case NETDEV_UP:
if (netif_carrier_ok(dev)) if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
br_stp_enable_port(p); br_stp_enable_port(p);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment