diff options
author | Sabrina Dubroca <sd@queasysnail.net> | 2016-08-12 10:10:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-13 18:15:54 -0400 |
commit | e20038724552cd05e351cd7d7526d646953d26b7 (patch) | |
tree | 15cd8bf0e03c5dbf96762bedbfb3cccf4613a477 | |
parent | bc561632dddd5af0c4444d919f01cbf6d553aa0a (diff) |
macsec: fix lockdep splats when nesting devices
Currently, trying to setup a vlan over a macsec device, or other
combinations of devices, triggers a lockdep warning.
Use netdev_lockdep_set_classes and ndo_get_lock_subclass, similar to
what macvlan does.
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/macsec.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index dbd590a8177f..2043e8c97a81 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c | |||
@@ -270,6 +270,7 @@ struct macsec_dev { | |||
270 | struct pcpu_secy_stats __percpu *stats; | 270 | struct pcpu_secy_stats __percpu *stats; |
271 | struct list_head secys; | 271 | struct list_head secys; |
272 | struct gro_cells gro_cells; | 272 | struct gro_cells gro_cells; |
273 | unsigned int nest_level; | ||
273 | }; | 274 | }; |
274 | 275 | ||
275 | /** | 276 | /** |
@@ -2699,6 +2700,8 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, | |||
2699 | 2700 | ||
2700 | #define MACSEC_FEATURES \ | 2701 | #define MACSEC_FEATURES \ |
2701 | (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) | 2702 | (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST) |
2703 | static struct lock_class_key macsec_netdev_addr_lock_key; | ||
2704 | |||
2702 | static int macsec_dev_init(struct net_device *dev) | 2705 | static int macsec_dev_init(struct net_device *dev) |
2703 | { | 2706 | { |
2704 | struct macsec_dev *macsec = macsec_priv(dev); | 2707 | struct macsec_dev *macsec = macsec_priv(dev); |
@@ -2910,6 +2913,13 @@ static int macsec_get_iflink(const struct net_device *dev) | |||
2910 | return macsec_priv(dev)->real_dev->ifindex; | 2913 | return macsec_priv(dev)->real_dev->ifindex; |
2911 | } | 2914 | } |
2912 | 2915 | ||
2916 | |||
2917 | static int macsec_get_nest_level(struct net_device *dev) | ||
2918 | { | ||
2919 | return macsec_priv(dev)->nest_level; | ||
2920 | } | ||
2921 | |||
2922 | |||
2913 | static const struct net_device_ops macsec_netdev_ops = { | 2923 | static const struct net_device_ops macsec_netdev_ops = { |
2914 | .ndo_init = macsec_dev_init, | 2924 | .ndo_init = macsec_dev_init, |
2915 | .ndo_uninit = macsec_dev_uninit, | 2925 | .ndo_uninit = macsec_dev_uninit, |
@@ -2923,6 +2933,7 @@ static const struct net_device_ops macsec_netdev_ops = { | |||
2923 | .ndo_start_xmit = macsec_start_xmit, | 2933 | .ndo_start_xmit = macsec_start_xmit, |
2924 | .ndo_get_stats64 = macsec_get_stats64, | 2934 | .ndo_get_stats64 = macsec_get_stats64, |
2925 | .ndo_get_iflink = macsec_get_iflink, | 2935 | .ndo_get_iflink = macsec_get_iflink, |
2936 | .ndo_get_lock_subclass = macsec_get_nest_level, | ||
2926 | }; | 2937 | }; |
2927 | 2938 | ||
2928 | static const struct device_type macsec_type = { | 2939 | static const struct device_type macsec_type = { |
@@ -3050,10 +3061,12 @@ static void macsec_del_dev(struct macsec_dev *macsec) | |||
3050 | static void macsec_common_dellink(struct net_device *dev, struct list_head *head) | 3061 | static void macsec_common_dellink(struct net_device *dev, struct list_head *head) |
3051 | { | 3062 | { |
3052 | struct macsec_dev *macsec = macsec_priv(dev); | 3063 | struct macsec_dev *macsec = macsec_priv(dev); |
3064 | struct net_device *real_dev = macsec->real_dev; | ||
3053 | 3065 | ||
3054 | unregister_netdevice_queue(dev, head); | 3066 | unregister_netdevice_queue(dev, head); |
3055 | list_del_rcu(&macsec->secys); | 3067 | list_del_rcu(&macsec->secys); |
3056 | macsec_del_dev(macsec); | 3068 | macsec_del_dev(macsec); |
3069 | netdev_upper_dev_unlink(real_dev, dev); | ||
3057 | 3070 | ||
3058 | macsec_generation++; | 3071 | macsec_generation++; |
3059 | } | 3072 | } |
@@ -3188,6 +3201,16 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3188 | 3201 | ||
3189 | dev_hold(real_dev); | 3202 | dev_hold(real_dev); |
3190 | 3203 | ||
3204 | macsec->nest_level = dev_get_nest_level(real_dev, netif_is_macsec) + 1; | ||
3205 | netdev_lockdep_set_classes(dev); | ||
3206 | lockdep_set_class_and_subclass(&dev->addr_list_lock, | ||
3207 | &macsec_netdev_addr_lock_key, | ||
3208 | macsec_get_nest_level(dev)); | ||
3209 | |||
3210 | err = netdev_upper_dev_link(real_dev, dev); | ||
3211 | if (err < 0) | ||
3212 | goto unregister; | ||
3213 | |||
3191 | /* need to be already registered so that ->init has run and | 3214 | /* need to be already registered so that ->init has run and |
3192 | * the MAC addr is set | 3215 | * the MAC addr is set |
3193 | */ | 3216 | */ |
@@ -3200,12 +3223,12 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3200 | 3223 | ||
3201 | if (rx_handler && sci_exists(real_dev, sci)) { | 3224 | if (rx_handler && sci_exists(real_dev, sci)) { |
3202 | err = -EBUSY; | 3225 | err = -EBUSY; |
3203 | goto unregister; | 3226 | goto unlink; |
3204 | } | 3227 | } |
3205 | 3228 | ||
3206 | err = macsec_add_dev(dev, sci, icv_len); | 3229 | err = macsec_add_dev(dev, sci, icv_len); |
3207 | if (err) | 3230 | if (err) |
3208 | goto unregister; | 3231 | goto unlink; |
3209 | 3232 | ||
3210 | if (data) | 3233 | if (data) |
3211 | macsec_changelink_common(dev, data); | 3234 | macsec_changelink_common(dev, data); |
@@ -3220,6 +3243,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3220 | 3243 | ||
3221 | del_dev: | 3244 | del_dev: |
3222 | macsec_del_dev(macsec); | 3245 | macsec_del_dev(macsec); |
3246 | unlink: | ||
3247 | netdev_upper_dev_unlink(real_dev, dev); | ||
3223 | unregister: | 3248 | unregister: |
3224 | unregister_netdevice(dev); | 3249 | unregister_netdevice(dev); |
3225 | return err; | 3250 | return err; |