diff options
-rw-r--r-- | net/8021q/vlan.c | 52 |
1 files changed, 20 insertions, 32 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 511afe72af31..39f8d0120104 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -161,10 +161,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
161 | 161 | ||
162 | grp->nr_vlans--; | 162 | grp->nr_vlans--; |
163 | 163 | ||
164 | if (!grp->killall) { | 164 | vlan_group_set_device(grp, vlan_id, NULL); |
165 | vlan_group_set_device(grp, vlan_id, NULL); | 165 | if (!grp->killall) |
166 | synchronize_net(); | 166 | synchronize_net(); |
167 | } | 167 | |
168 | unregister_netdevice_queue(dev, head); | 168 | unregister_netdevice_queue(dev, head); |
169 | 169 | ||
170 | /* If the group is now empty, kill off the group. */ | 170 | /* If the group is now empty, kill off the group. */ |
@@ -184,34 +184,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
184 | dev_put(real_dev); | 184 | dev_put(real_dev); |
185 | } | 185 | } |
186 | 186 | ||
187 | void unregister_vlan_dev_alls(struct vlan_group *grp) | ||
188 | { | ||
189 | LIST_HEAD(list); | ||
190 | int i; | ||
191 | struct net_device *vlandev; | ||
192 | struct vlan_group save; | ||
193 | |||
194 | memcpy(&save, grp, sizeof(save)); | ||
195 | memset(&grp->vlan_devices_arrays, 0, sizeof(grp->vlan_devices_arrays)); | ||
196 | grp->killall = 1; | ||
197 | |||
198 | synchronize_net(); | ||
199 | |||
200 | /* Delete all VLANs for this dev. */ | ||
201 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | ||
202 | vlandev = vlan_group_get_device(&save, i); | ||
203 | if (!vlandev) | ||
204 | continue; | ||
205 | |||
206 | unregister_vlan_dev(vlandev, &list); | ||
207 | if (grp->nr_vlans == 0) | ||
208 | break; | ||
209 | } | ||
210 | unregister_netdevice_many(&list); | ||
211 | for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) | ||
212 | kfree(save.vlan_devices_arrays[i]); | ||
213 | } | ||
214 | |||
215 | static void vlan_transfer_operstate(const struct net_device *dev, | 187 | static void vlan_transfer_operstate(const struct net_device *dev, |
216 | struct net_device *vlandev) | 188 | struct net_device *vlandev) |
217 | { | 189 | { |
@@ -456,6 +428,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
456 | struct vlan_group *grp; | 428 | struct vlan_group *grp; |
457 | int i, flgs; | 429 | int i, flgs; |
458 | struct net_device *vlandev; | 430 | struct net_device *vlandev; |
431 | LIST_HEAD(list); | ||
459 | 432 | ||
460 | if (is_vlan_dev(dev)) | 433 | if (is_vlan_dev(dev)) |
461 | __vlan_device_event(dev, event); | 434 | __vlan_device_event(dev, event); |
@@ -553,7 +526,22 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
553 | break; | 526 | break; |
554 | 527 | ||
555 | case NETDEV_UNREGISTER: | 528 | case NETDEV_UNREGISTER: |
556 | unregister_vlan_dev_alls(grp); | 529 | /* Delete all VLANs for this dev. */ |
530 | grp->killall = 1; | ||
531 | |||
532 | for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { | ||
533 | vlandev = vlan_group_get_device(grp, i); | ||
534 | if (!vlandev) | ||
535 | continue; | ||
536 | |||
537 | /* unregistration of last vlan destroys group, abort | ||
538 | * afterwards */ | ||
539 | if (grp->nr_vlans == 1) | ||
540 | i = VLAN_GROUP_ARRAY_LEN; | ||
541 | |||
542 | unregister_vlan_dev(vlandev, &list); | ||
543 | } | ||
544 | unregister_netdevice_many(&list); | ||
557 | break; | 545 | break; |
558 | } | 546 | } |
559 | 547 | ||