diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan_dev.c | 46 | ||||
-rw-r--r-- | net/core/dev.c | 1 |
2 files changed, 42 insertions, 5 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6f142f03716d..733ec283ed1b 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -493,10 +493,48 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) | |||
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | static int vlan_calculate_locking_subclass(struct net_device *real_dev) | ||
497 | { | ||
498 | int subclass = 0; | ||
499 | |||
500 | while (is_vlan_dev(real_dev)) { | ||
501 | subclass++; | ||
502 | real_dev = vlan_dev_priv(real_dev)->real_dev; | ||
503 | } | ||
504 | |||
505 | return subclass; | ||
506 | } | ||
507 | |||
508 | static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from) | ||
509 | { | ||
510 | int err = 0, subclass; | ||
511 | |||
512 | subclass = vlan_calculate_locking_subclass(to); | ||
513 | |||
514 | spin_lock_nested(&to->addr_list_lock, subclass); | ||
515 | err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); | ||
516 | if (!err) | ||
517 | __dev_set_rx_mode(to); | ||
518 | spin_unlock(&to->addr_list_lock); | ||
519 | } | ||
520 | |||
521 | static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from) | ||
522 | { | ||
523 | int err = 0, subclass; | ||
524 | |||
525 | subclass = vlan_calculate_locking_subclass(to); | ||
526 | |||
527 | spin_lock_nested(&to->addr_list_lock, subclass); | ||
528 | err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); | ||
529 | if (!err) | ||
530 | __dev_set_rx_mode(to); | ||
531 | spin_unlock(&to->addr_list_lock); | ||
532 | } | ||
533 | |||
496 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) | 534 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) |
497 | { | 535 | { |
498 | dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); | 536 | vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
499 | dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); | 537 | vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
500 | } | 538 | } |
501 | 539 | ||
502 | /* | 540 | /* |
@@ -608,9 +646,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
608 | 646 | ||
609 | SET_NETDEV_DEVTYPE(dev, &vlan_type); | 647 | SET_NETDEV_DEVTYPE(dev, &vlan_type); |
610 | 648 | ||
611 | if (is_vlan_dev(real_dev)) | 649 | subclass = vlan_calculate_locking_subclass(dev); |
612 | subclass = 1; | ||
613 | |||
614 | vlan_dev_set_lockdep_class(dev, subclass); | 650 | vlan_dev_set_lockdep_class(dev, subclass); |
615 | 651 | ||
616 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); | 652 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
diff --git a/net/core/dev.c b/net/core/dev.c index 5b3042e69f85..d2c8a06b3a98 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -5238,6 +5238,7 @@ void __dev_set_rx_mode(struct net_device *dev) | |||
5238 | if (ops->ndo_set_rx_mode) | 5238 | if (ops->ndo_set_rx_mode) |
5239 | ops->ndo_set_rx_mode(dev); | 5239 | ops->ndo_set_rx_mode(dev); |
5240 | } | 5240 | } |
5241 | EXPORT_SYMBOL(__dev_set_rx_mode); | ||
5241 | 5242 | ||
5242 | void dev_set_rx_mode(struct net_device *dev) | 5243 | void dev_set_rx_mode(struct net_device *dev) |
5243 | { | 5244 | { |