Commit d38569ab authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller

vlan: Fix lockdep warning with stacked vlan devices.

This reverts commit dc8eaaa0.
	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: default avatarVlad Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 25175ba5
...@@ -73,7 +73,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) ...@@ -73,7 +73,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
/* found in socket.c */ /* found in socket.c */
extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
static inline int is_vlan_dev(struct net_device *dev) static inline bool is_vlan_dev(struct net_device *dev)
{ {
return dev->priv_flags & IFF_802_1Q_VLAN; return dev->priv_flags & IFF_802_1Q_VLAN;
} }
...@@ -159,6 +159,7 @@ struct vlan_dev_priv { ...@@ -159,6 +159,7 @@ struct vlan_dev_priv {
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *netpoll; struct netpoll *netpoll;
#endif #endif
unsigned int nest_level;
}; };
static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
......
...@@ -169,6 +169,7 @@ int register_vlan_dev(struct net_device *dev) ...@@ -169,6 +169,7 @@ int register_vlan_dev(struct net_device *dev)
if (err < 0) if (err < 0)
goto out_uninit_mvrp; goto out_uninit_mvrp;
vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1;
err = register_netdevice(dev); err = register_netdevice(dev);
if (err < 0) if (err < 0)
goto out_uninit_mvrp; goto out_uninit_mvrp;
......
...@@ -493,48 +493,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) ...@@ -493,48 +493,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
} }
} }
static int vlan_calculate_locking_subclass(struct net_device *real_dev)
{
int subclass = 0;
while (is_vlan_dev(real_dev)) {
subclass++;
real_dev = vlan_dev_priv(real_dev)->real_dev;
}
return subclass;
}
static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from)
{
int err = 0, subclass;
subclass = vlan_calculate_locking_subclass(to);
spin_lock_nested(&to->addr_list_lock, subclass);
err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
spin_unlock(&to->addr_list_lock);
}
static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from)
{
int err = 0, subclass;
subclass = vlan_calculate_locking_subclass(to);
spin_lock_nested(&to->addr_list_lock, subclass);
err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
spin_unlock(&to->addr_list_lock);
}
static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
{ {
vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev);
} }
/* /*
...@@ -562,6 +524,11 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass) ...@@ -562,6 +524,11 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
} }
static int vlan_dev_get_lock_subclass(struct net_device *dev)
{
return vlan_dev_priv(dev)->nest_level;
}
static const struct header_ops vlan_header_ops = { static const struct header_ops vlan_header_ops = {
.create = vlan_dev_hard_header, .create = vlan_dev_hard_header,
.rebuild = vlan_dev_rebuild_header, .rebuild = vlan_dev_rebuild_header,
...@@ -597,7 +564,6 @@ static const struct net_device_ops vlan_netdev_ops; ...@@ -597,7 +564,6 @@ static const struct net_device_ops vlan_netdev_ops;
static int vlan_dev_init(struct net_device *dev) static int vlan_dev_init(struct net_device *dev)
{ {
struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
int subclass = 0;
netif_carrier_off(dev); netif_carrier_off(dev);
...@@ -646,8 +612,7 @@ static int vlan_dev_init(struct net_device *dev) ...@@ -646,8 +612,7 @@ static int vlan_dev_init(struct net_device *dev)
SET_NETDEV_DEVTYPE(dev, &vlan_type); SET_NETDEV_DEVTYPE(dev, &vlan_type);
subclass = vlan_calculate_locking_subclass(dev); vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));
vlan_dev_set_lockdep_class(dev, subclass);
vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
if (!vlan_dev_priv(dev)->vlan_pcpu_stats) if (!vlan_dev_priv(dev)->vlan_pcpu_stats)
...@@ -819,6 +784,7 @@ static const struct net_device_ops vlan_netdev_ops = { ...@@ -819,6 +784,7 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup,
#endif #endif
.ndo_fix_features = vlan_dev_fix_features, .ndo_fix_features = vlan_dev_fix_features,
.ndo_get_lock_subclass = vlan_dev_get_lock_subclass,
}; };
void vlan_setup(struct net_device *dev) void vlan_setup(struct net_device *dev)
......
...@@ -5287,7 +5287,6 @@ void __dev_set_rx_mode(struct net_device *dev) ...@@ -5287,7 +5287,6 @@ void __dev_set_rx_mode(struct net_device *dev)
if (ops->ndo_set_rx_mode) if (ops->ndo_set_rx_mode)
ops->ndo_set_rx_mode(dev); ops->ndo_set_rx_mode(dev);
} }
EXPORT_SYMBOL(__dev_set_rx_mode);
void dev_set_rx_mode(struct net_device *dev) void dev_set_rx_mode(struct net_device *dev)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment