aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevic@redhat.com>2014-05-16 17:04:55 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-16 22:14:49 -0400
commitd38569ab2bba6e6b3233acfc3a84cdbcfbd1f79f (patch)
tree12d0b7fb2b3fb8256c226ef09ed42a539decddf9
parent25175ba5c9bff9aaf0229df34bb5d54c81633ec3 (diff)
vlan: Fix lockdep warning with stacked vlan devices.
This reverts commit dc8eaaa006350d24030502a4521542e74b5cb39f. vlan: Fix lockdep warning when vlan dev handle notification Instead we use the new new API to find the lock subclass of our vlan device. This way we can support configurations where vlans are interspersed with other devices: bond -> vlan -> macvlan -> vlan Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/if_vlan.h3
-rw-r--r--net/8021q/vlan.c1
-rw-r--r--net/8021q/vlan_dev.c52
-rw-r--r--net/core/dev.c1
4 files changed, 12 insertions, 45 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 13bbbde00e68..724bde8477b2 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -73,7 +73,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
73/* found in socket.c */ 73/* found in socket.c */
74extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); 74extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
75 75
76static inline int is_vlan_dev(struct net_device *dev) 76static inline bool is_vlan_dev(struct net_device *dev)
77{ 77{
78 return dev->priv_flags & IFF_802_1Q_VLAN; 78 return dev->priv_flags & IFF_802_1Q_VLAN;
79} 79}
@@ -159,6 +159,7 @@ struct vlan_dev_priv {
159#ifdef CONFIG_NET_POLL_CONTROLLER 159#ifdef CONFIG_NET_POLL_CONTROLLER
160 struct netpoll *netpoll; 160 struct netpoll *netpoll;
161#endif 161#endif
162 unsigned int nest_level;
162}; 163};
163 164
164static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) 165static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 175273f38cb1..44ebd5c2cd4a 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -169,6 +169,7 @@ int register_vlan_dev(struct net_device *dev)
169 if (err < 0) 169 if (err < 0)
170 goto out_uninit_mvrp; 170 goto out_uninit_mvrp;
171 171
172 vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1;
172 err = register_netdevice(dev); 173 err = register_netdevice(dev);
173 if (err < 0) 174 if (err < 0)
174 goto out_uninit_mvrp; 175 goto out_uninit_mvrp;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 733ec283ed1b..019efb79708f 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -493,48 +493,10 @@ 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
534static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) 496static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
535{ 497{
536 vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); 498 dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
537 vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); 499 dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
538} 500}
539 501
540/* 502/*
@@ -562,6 +524,11 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
562 netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); 524 netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
563} 525}
564 526
527static int vlan_dev_get_lock_subclass(struct net_device *dev)
528{
529 return vlan_dev_priv(dev)->nest_level;
530}
531
565static const struct header_ops vlan_header_ops = { 532static const struct header_ops vlan_header_ops = {
566 .create = vlan_dev_hard_header, 533 .create = vlan_dev_hard_header,
567 .rebuild = vlan_dev_rebuild_header, 534 .rebuild = vlan_dev_rebuild_header,
@@ -597,7 +564,6 @@ static const struct net_device_ops vlan_netdev_ops;
597static int vlan_dev_init(struct net_device *dev) 564static int vlan_dev_init(struct net_device *dev)
598{ 565{
599 struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; 566 struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
600 int subclass = 0;
601 567
602 netif_carrier_off(dev); 568 netif_carrier_off(dev);
603 569
@@ -646,8 +612,7 @@ static int vlan_dev_init(struct net_device *dev)
646 612
647 SET_NETDEV_DEVTYPE(dev, &vlan_type); 613 SET_NETDEV_DEVTYPE(dev, &vlan_type);
648 614
649 subclass = vlan_calculate_locking_subclass(dev); 615 vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));
650 vlan_dev_set_lockdep_class(dev, subclass);
651 616
652 vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); 617 vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
653 if (!vlan_dev_priv(dev)->vlan_pcpu_stats) 618 if (!vlan_dev_priv(dev)->vlan_pcpu_stats)
@@ -819,6 +784,7 @@ static const struct net_device_ops vlan_netdev_ops = {
819 .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, 784 .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup,
820#endif 785#endif
821 .ndo_fix_features = vlan_dev_fix_features, 786 .ndo_fix_features = vlan_dev_fix_features,
787 .ndo_get_lock_subclass = vlan_dev_get_lock_subclass,
822}; 788};
823 789
824void vlan_setup(struct net_device *dev) 790void vlan_setup(struct net_device *dev)
diff --git a/net/core/dev.c b/net/core/dev.c
index 6ee3ac25ed72..2b872bfbd172 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5287,7 +5287,6 @@ void __dev_set_rx_mode(struct net_device *dev)
5287 if (ops->ndo_set_rx_mode) 5287 if (ops->ndo_set_rx_mode)
5288 ops->ndo_set_rx_mode(dev); 5288 ops->ndo_set_rx_mode(dev);
5289} 5289}
5290EXPORT_SYMBOL(__dev_set_rx_mode);
5291 5290
5292void dev_set_rx_mode(struct net_device *dev) 5291void dev_set_rx_mode(struct net_device *dev)
5293{ 5292{