diff options
Diffstat (limited to 'drivers/net/macsec.c')
-rw-r--r-- | drivers/net/macsec.c | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index d13e6e15d7b5..351e701eb043 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 = { |
@@ -3047,22 +3058,31 @@ static void macsec_del_dev(struct macsec_dev *macsec) | |||
3047 | } | 3058 | } |
3048 | } | 3059 | } |
3049 | 3060 | ||
3061 | static void macsec_common_dellink(struct net_device *dev, struct list_head *head) | ||
3062 | { | ||
3063 | struct macsec_dev *macsec = macsec_priv(dev); | ||
3064 | struct net_device *real_dev = macsec->real_dev; | ||
3065 | |||
3066 | unregister_netdevice_queue(dev, head); | ||
3067 | list_del_rcu(&macsec->secys); | ||
3068 | macsec_del_dev(macsec); | ||
3069 | netdev_upper_dev_unlink(real_dev, dev); | ||
3070 | |||
3071 | macsec_generation++; | ||
3072 | } | ||
3073 | |||
3050 | static void macsec_dellink(struct net_device *dev, struct list_head *head) | 3074 | static void macsec_dellink(struct net_device *dev, struct list_head *head) |
3051 | { | 3075 | { |
3052 | struct macsec_dev *macsec = macsec_priv(dev); | 3076 | struct macsec_dev *macsec = macsec_priv(dev); |
3053 | struct net_device *real_dev = macsec->real_dev; | 3077 | struct net_device *real_dev = macsec->real_dev; |
3054 | struct macsec_rxh_data *rxd = macsec_data_rtnl(real_dev); | 3078 | struct macsec_rxh_data *rxd = macsec_data_rtnl(real_dev); |
3055 | 3079 | ||
3056 | macsec_generation++; | 3080 | macsec_common_dellink(dev, head); |
3057 | 3081 | ||
3058 | unregister_netdevice_queue(dev, head); | ||
3059 | list_del_rcu(&macsec->secys); | ||
3060 | if (list_empty(&rxd->secys)) { | 3082 | if (list_empty(&rxd->secys)) { |
3061 | netdev_rx_handler_unregister(real_dev); | 3083 | netdev_rx_handler_unregister(real_dev); |
3062 | kfree(rxd); | 3084 | kfree(rxd); |
3063 | } | 3085 | } |
3064 | |||
3065 | macsec_del_dev(macsec); | ||
3066 | } | 3086 | } |
3067 | 3087 | ||
3068 | static int register_macsec_dev(struct net_device *real_dev, | 3088 | static int register_macsec_dev(struct net_device *real_dev, |
@@ -3181,6 +3201,16 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3181 | 3201 | ||
3182 | dev_hold(real_dev); | 3202 | dev_hold(real_dev); |
3183 | 3203 | ||
3204 | macsec->nest_level = dev_get_nest_level(real_dev) + 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 | |||
3184 | /* need to be already registered so that ->init has run and | 3214 | /* need to be already registered so that ->init has run and |
3185 | * the MAC addr is set | 3215 | * the MAC addr is set |
3186 | */ | 3216 | */ |
@@ -3193,12 +3223,12 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3193 | 3223 | ||
3194 | if (rx_handler && sci_exists(real_dev, sci)) { | 3224 | if (rx_handler && sci_exists(real_dev, sci)) { |
3195 | err = -EBUSY; | 3225 | err = -EBUSY; |
3196 | goto unregister; | 3226 | goto unlink; |
3197 | } | 3227 | } |
3198 | 3228 | ||
3199 | err = macsec_add_dev(dev, sci, icv_len); | 3229 | err = macsec_add_dev(dev, sci, icv_len); |
3200 | if (err) | 3230 | if (err) |
3201 | goto unregister; | 3231 | goto unlink; |
3202 | 3232 | ||
3203 | if (data) | 3233 | if (data) |
3204 | macsec_changelink_common(dev, data); | 3234 | macsec_changelink_common(dev, data); |
@@ -3213,6 +3243,8 @@ static int macsec_newlink(struct net *net, struct net_device *dev, | |||
3213 | 3243 | ||
3214 | del_dev: | 3244 | del_dev: |
3215 | macsec_del_dev(macsec); | 3245 | macsec_del_dev(macsec); |
3246 | unlink: | ||
3247 | netdev_upper_dev_unlink(real_dev, dev); | ||
3216 | unregister: | 3248 | unregister: |
3217 | unregister_netdevice(dev); | 3249 | unregister_netdevice(dev); |
3218 | return err; | 3250 | return err; |
@@ -3382,8 +3414,12 @@ static int macsec_notify(struct notifier_block *this, unsigned long event, | |||
3382 | 3414 | ||
3383 | rxd = macsec_data_rtnl(real_dev); | 3415 | rxd = macsec_data_rtnl(real_dev); |
3384 | list_for_each_entry_safe(m, n, &rxd->secys, secys) { | 3416 | list_for_each_entry_safe(m, n, &rxd->secys, secys) { |
3385 | macsec_dellink(m->secy.netdev, &head); | 3417 | macsec_common_dellink(m->secy.netdev, &head); |
3386 | } | 3418 | } |
3419 | |||
3420 | netdev_rx_handler_unregister(real_dev); | ||
3421 | kfree(rxd); | ||
3422 | |||
3387 | unregister_netdevice_many(&head); | 3423 | unregister_netdevice_many(&head); |
3388 | break; | 3424 | break; |
3389 | } | 3425 | } |