aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r--net/8021q/vlan_dev.c46
1 files changed, 41 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
496static 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
508static 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
521static 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
496static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) 534static 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);