Merge branch 'generic-ipi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / net / 8021q / vlan.c
index 2a739ad..08f14f6 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/in.h>
 #include <linux/init.h>
+#include <linux/rculist.h>
 #include <net/p8022.h>
 #include <net/arp.h>
 #include <linux/rtnetlink.h>
@@ -382,6 +383,18 @@ static void vlan_sync_address(struct net_device *dev,
        memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
 }
 
+static void vlan_transfer_features(struct net_device *dev,
+                                  struct net_device *vlandev)
+{
+       unsigned long old_features = vlandev->features;
+
+       vlandev->features &= ~dev->vlan_features;
+       vlandev->features |= dev->features & dev->vlan_features;
+
+       if (old_features != vlandev->features)
+               netdev_features_change(vlandev);
+}
+
 static void __vlan_device_event(struct net_device *dev, unsigned long event)
 {
        switch (event) {
@@ -410,10 +423,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
        int i, flgs;
        struct net_device *vlandev;
 
-       if (is_vlan_dev(dev)) {
+       if (is_vlan_dev(dev))
                __vlan_device_event(dev, event);
-               goto out;
-       }
 
        grp = __vlan_find_group(dev);
        if (!grp)
@@ -450,6 +461,18 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
                }
                break;
 
+       case NETDEV_FEAT_CHANGE:
+               /* Propagate device features to underlying device */
+               for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+                       vlandev = vlan_group_get_device(grp, i);
+                       if (!vlandev)
+                               continue;
+
+                       vlan_transfer_features(dev, vlandev);
+               }
+
+               break;
+
        case NETDEV_DOWN:
                /* Put all VLANs for this dev in the down state too.  */
                for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {