Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / net / bridge / br_notify.c
index 594bb5b..a43a9c1 100644 (file)
 
 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
 
-struct notifier_block br_device_notifier =
-{
+struct notifier_block br_device_notifier = {
        .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)
 {
-       struct net_device *dev;
-       struct net_bridge_port *p;
+       struct net_device *dev = ptr;
+       struct net_bridge_port *p = dev->br_port;
        struct net_bridge *br;
 
-       dev = ptr;
-       p = dev->br_port;
-
+       /* not a port of a bridge */
        if (p == NULL)
                return NOTIFY_DONE;
 
        br = p->br;
 
        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:
                br_fdb_changeaddr(p, dev->dev_addr);
+               br_stp_recalculate_bridge_id(br);
+               break;
+
+       case NETDEV_CHANGE:
                if (br->dev->flags & IFF_UP)
-                       br_stp_recalculate_bridge_id(br);
+                       schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
+               break;
+
+       case NETDEV_FEAT_CHANGE:
+               if (br->dev->flags & IFF_UP) 
+                       br_features_recompute(br);
+
+               /* could do recursive feature change notification
+                * but who would care?? 
+                */
                break;
 
        case NETDEV_DOWN:
@@ -53,15 +72,17 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
                break;
 
        case NETDEV_UP:
-               if (br->dev->flags & IFF_UP)
+               if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) 
                        br_stp_enable_port(p);
                break;
 
        case NETDEV_UNREGISTER:
+               spin_unlock_bh(&br->lock);
                br_del_if(br, dev);
-               break;
-       }
+               goto done;
+       } 
        spin_unlock_bh(&br->lock);
 
+ done:
        return NOTIFY_DONE;
 }