diff options
Diffstat (limited to 'net/8021q/vlan.c')
| -rw-r--r-- | net/8021q/vlan.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 2a739adaa92b..ab2225da0ee2 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
| @@ -382,6 +382,18 @@ static void vlan_sync_address(struct net_device *dev, | |||
| 382 | memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); | 382 | memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | static void vlan_transfer_features(struct net_device *dev, | ||
| 386 | struct net_device *vlandev) | ||
| 387 | { | ||
| 388 | unsigned long old_features = vlandev->features; | ||
| 389 | |||
| 390 | vlandev->features &= ~dev->vlan_features; | ||
| 391 | vlandev->features |= dev->features & dev->vlan_features; | ||
| 392 | |||
| 393 | if (old_features != vlandev->features) | ||
| 394 | netdev_features_change(vlandev); | ||
| 395 | } | ||
| 396 | |||
| 385 | static void __vlan_device_event(struct net_device *dev, unsigned long event) | 397 | static void __vlan_device_event(struct net_device *dev, unsigned long event) |
| 386 | { | 398 | { |
| 387 | switch (event) { | 399 | switch (event) { |
| @@ -410,10 +422,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
| 410 | int i, flgs; | 422 | int i, flgs; |
| 411 | struct net_device *vlandev; | 423 | struct net_device *vlandev; |
| 412 | 424 | ||
| 413 | if (is_vlan_dev(dev)) { | 425 | if (is_vlan_dev(dev)) |
| 414 | __vlan_device_event(dev, event); | 426 | __vlan_device_event(dev, event); |
| 415 | goto out; | ||
| 416 | } | ||
| 417 | 427 | ||
| 418 | grp = __vlan_find_group(dev); | 428 | grp = __vlan_find_group(dev); |
| 419 | if (!grp) | 429 | if (!grp) |
| @@ -450,6 +460,18 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
| 450 | } | 460 | } |
| 451 | break; | 461 | break; |
| 452 | 462 | ||
| 463 | case NETDEV_FEAT_CHANGE: | ||
| 464 | /* Propagate device features to underlying device */ | ||
| 465 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | ||
| 466 | vlandev = vlan_group_get_device(grp, i); | ||
| 467 | if (!vlandev) | ||
| 468 | continue; | ||
| 469 | |||
| 470 | vlan_transfer_features(dev, vlandev); | ||
| 471 | } | ||
| 472 | |||
| 473 | break; | ||
| 474 | |||
| 453 | case NETDEV_DOWN: | 475 | case NETDEV_DOWN: |
| 454 | /* Put all VLANs for this dev in the down state too. */ | 476 | /* Put all VLANs for this dev in the down state too. */ |
| 455 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | 477 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { |
