diff options
Diffstat (limited to 'net/8021q/vlan.c')
-rw-r--r-- | net/8021q/vlan.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index ab2225da0ee2..b529110c9355 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -165,8 +165,12 @@ void unregister_vlan_dev(struct net_device *dev) | |||
165 | 165 | ||
166 | synchronize_net(); | 166 | synchronize_net(); |
167 | 167 | ||
168 | unregister_netdevice(dev); | ||
169 | |||
168 | /* If the group is now empty, kill off the group. */ | 170 | /* If the group is now empty, kill off the group. */ |
169 | if (grp->nr_vlans == 0) { | 171 | if (grp->nr_vlans == 0) { |
172 | vlan_gvrp_uninit_applicant(real_dev); | ||
173 | |||
170 | if (real_dev->features & NETIF_F_HW_VLAN_RX) | 174 | if (real_dev->features & NETIF_F_HW_VLAN_RX) |
171 | real_dev->vlan_rx_register(real_dev, NULL); | 175 | real_dev->vlan_rx_register(real_dev, NULL); |
172 | 176 | ||
@@ -178,8 +182,6 @@ void unregister_vlan_dev(struct net_device *dev) | |||
178 | 182 | ||
179 | /* Get rid of the vlan's reference to real_dev */ | 183 | /* Get rid of the vlan's reference to real_dev */ |
180 | dev_put(real_dev); | 184 | dev_put(real_dev); |
181 | |||
182 | unregister_netdevice(dev); | ||
183 | } | 185 | } |
184 | 186 | ||
185 | static void vlan_transfer_operstate(const struct net_device *dev, | 187 | static void vlan_transfer_operstate(const struct net_device *dev, |
@@ -249,15 +251,18 @@ int register_vlan_dev(struct net_device *dev) | |||
249 | ngrp = grp = vlan_group_alloc(real_dev); | 251 | ngrp = grp = vlan_group_alloc(real_dev); |
250 | if (!grp) | 252 | if (!grp) |
251 | return -ENOBUFS; | 253 | return -ENOBUFS; |
254 | err = vlan_gvrp_init_applicant(real_dev); | ||
255 | if (err < 0) | ||
256 | goto out_free_group; | ||
252 | } | 257 | } |
253 | 258 | ||
254 | err = vlan_group_prealloc_vid(grp, vlan_id); | 259 | err = vlan_group_prealloc_vid(grp, vlan_id); |
255 | if (err < 0) | 260 | if (err < 0) |
256 | goto out_free_group; | 261 | goto out_uninit_applicant; |
257 | 262 | ||
258 | err = register_netdevice(dev); | 263 | err = register_netdevice(dev); |
259 | if (err < 0) | 264 | if (err < 0) |
260 | goto out_free_group; | 265 | goto out_uninit_applicant; |
261 | 266 | ||
262 | /* Account for reference in struct vlan_dev_info */ | 267 | /* Account for reference in struct vlan_dev_info */ |
263 | dev_hold(real_dev); | 268 | dev_hold(real_dev); |
@@ -278,6 +283,9 @@ int register_vlan_dev(struct net_device *dev) | |||
278 | 283 | ||
279 | return 0; | 284 | return 0; |
280 | 285 | ||
286 | out_uninit_applicant: | ||
287 | if (ngrp) | ||
288 | vlan_gvrp_uninit_applicant(real_dev); | ||
281 | out_free_group: | 289 | out_free_group: |
282 | if (ngrp) | 290 | if (ngrp) |
283 | vlan_group_free(ngrp); | 291 | vlan_group_free(ngrp); |
@@ -591,9 +599,9 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg) | |||
591 | err = -EPERM; | 599 | err = -EPERM; |
592 | if (!capable(CAP_NET_ADMIN)) | 600 | if (!capable(CAP_NET_ADMIN)) |
593 | break; | 601 | break; |
594 | err = vlan_dev_set_vlan_flag(dev, | 602 | err = vlan_dev_change_flags(dev, |
595 | args.u.flag, | 603 | args.vlan_qos ? args.u.flag : 0, |
596 | args.vlan_qos); | 604 | args.u.flag); |
597 | break; | 605 | break; |
598 | 606 | ||
599 | case SET_VLAN_NAME_TYPE_CMD: | 607 | case SET_VLAN_NAME_TYPE_CMD: |
@@ -713,14 +721,20 @@ static int __init vlan_proto_init(void) | |||
713 | if (err < 0) | 721 | if (err < 0) |
714 | goto err2; | 722 | goto err2; |
715 | 723 | ||
716 | err = vlan_netlink_init(); | 724 | err = vlan_gvrp_init(); |
717 | if (err < 0) | 725 | if (err < 0) |
718 | goto err3; | 726 | goto err3; |
719 | 727 | ||
728 | err = vlan_netlink_init(); | ||
729 | if (err < 0) | ||
730 | goto err4; | ||
731 | |||
720 | dev_add_pack(&vlan_packet_type); | 732 | dev_add_pack(&vlan_packet_type); |
721 | vlan_ioctl_set(vlan_ioctl_handler); | 733 | vlan_ioctl_set(vlan_ioctl_handler); |
722 | return 0; | 734 | return 0; |
723 | 735 | ||
736 | err4: | ||
737 | vlan_gvrp_uninit(); | ||
724 | err3: | 738 | err3: |
725 | unregister_netdevice_notifier(&vlan_notifier_block); | 739 | unregister_netdevice_notifier(&vlan_notifier_block); |
726 | err2: | 740 | err2: |
@@ -745,8 +759,9 @@ static void __exit vlan_cleanup_module(void) | |||
745 | BUG_ON(!hlist_empty(&vlan_group_hash[i])); | 759 | BUG_ON(!hlist_empty(&vlan_group_hash[i])); |
746 | 760 | ||
747 | unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops); | 761 | unregister_pernet_gen_device(vlan_net_id, &vlan_net_ops); |
748 | |||
749 | synchronize_net(); | 762 | synchronize_net(); |
763 | |||
764 | vlan_gvrp_uninit(); | ||
750 | } | 765 | } |
751 | 766 | ||
752 | module_init(vlan_proto_init); | 767 | module_init(vlan_proto_init); |