aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-06-13 15:05:59 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:14:40 -0400
commit42429aaee5eb44f4a48fdb056d77d0c06ef5aebc (patch)
treea23bc4a9464dd3f6323f707246b9738c87ed5482 /net/8021q
parent2f4284a406cb25d1e41454cbf9ec4545b5ed70a1 (diff)
[VLAN]: Move vlan_group allocation to seperate function
Move group allocation to a seperate function to clean up the code a bit and allocate groups before registering the device. Device registration is globally visible and causes netlink events, so we shouldn't fail afterwards. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q')
-rw-r--r--net/8021q/vlan.c78
1 files changed, 41 insertions, 37 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index dc95f7cbf291..1b9dc5ecd448 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -197,6 +197,34 @@ static void vlan_group_free(struct vlan_group *grp)
197 kfree(grp); 197 kfree(grp);
198} 198}
199 199
200static struct vlan_group *vlan_group_alloc(int ifindex)
201{
202 struct vlan_group *grp;
203 unsigned int size;
204 unsigned int i;
205
206 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
207 if (!grp)
208 return NULL;
209
210 size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
211
212 for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
213 grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
214 if (!grp->vlan_devices_arrays[i])
215 goto err;
216 }
217
218 grp->real_dev_ifindex = ifindex;
219 hlist_add_head_rcu(&grp->hlist,
220 &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
221 return grp;
222
223err:
224 vlan_group_free(grp);
225 return NULL;
226}
227
200static void vlan_rcu_free(struct rcu_head *rcu) 228static void vlan_rcu_free(struct rcu_head *rcu)
201{ 229{
202 vlan_group_free(container_of(rcu, struct vlan_group, rcu)); 230 vlan_group_free(container_of(rcu, struct vlan_group, rcu));
@@ -389,10 +417,9 @@ static void vlan_transfer_operstate(const struct net_device *dev, struct net_dev
389static struct net_device *register_vlan_device(struct net_device *real_dev, 417static struct net_device *register_vlan_device(struct net_device *real_dev,
390 unsigned short VLAN_ID) 418 unsigned short VLAN_ID)
391{ 419{
392 struct vlan_group *grp; 420 struct vlan_group *grp, *ngrp = NULL;
393 struct net_device *new_dev; 421 struct net_device *new_dev;
394 char name[IFNAMSIZ]; 422 char name[IFNAMSIZ];
395 int i;
396 423
397#ifdef VLAN_DEBUG 424#ifdef VLAN_DEBUG
398 printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", 425 printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n",
@@ -491,9 +518,15 @@ static struct net_device *register_vlan_device(struct net_device *real_dev,
491 printk(VLAN_DBG "About to go find the group for idx: %i\n", 518 printk(VLAN_DBG "About to go find the group for idx: %i\n",
492 real_dev->ifindex); 519 real_dev->ifindex);
493#endif 520#endif
521 grp = __vlan_find_group(real_dev->ifindex);
522 if (!grp) {
523 ngrp = grp = vlan_group_alloc(real_dev->ifindex);
524 if (!grp)
525 goto out_free_newdev;
526 }
494 527
495 if (register_netdevice(new_dev)) 528 if (register_netdevice(new_dev))
496 goto out_free_newdev; 529 goto out_free_group;
497 530
498 vlan_transfer_operstate(real_dev, new_dev); 531 vlan_transfer_operstate(real_dev, new_dev);
499 linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */ 532 linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
@@ -501,34 +534,8 @@ static struct net_device *register_vlan_device(struct net_device *real_dev,
501 /* So, got the sucker initialized, now lets place 534 /* So, got the sucker initialized, now lets place
502 * it into our local structure. 535 * it into our local structure.
503 */ 536 */
504 grp = __vlan_find_group(real_dev->ifindex); 537 if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
505 538 real_dev->vlan_rx_register(real_dev, ngrp);
506 /* Note, we are running under the RTNL semaphore
507 * so it cannot "appear" on us.
508 */
509 if (!grp) { /* need to add a new group */
510 grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
511 if (!grp)
512 goto out_free_unregister;
513
514 for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
515 grp->vlan_devices_arrays[i] = kzalloc(
516 sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
517 GFP_KERNEL);
518
519 if (!grp->vlan_devices_arrays[i])
520 goto out_free_arrays;
521 }
522
523 /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */
524 grp->real_dev_ifindex = real_dev->ifindex;
525
526 hlist_add_head_rcu(&grp->hlist,
527 &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
528
529 if (real_dev->features & NETIF_F_HW_VLAN_RX)
530 real_dev->vlan_rx_register(real_dev, grp);
531 }
532 539
533 vlan_group_set_device(grp, VLAN_ID, new_dev); 540 vlan_group_set_device(grp, VLAN_ID, new_dev);
534 541
@@ -546,12 +553,9 @@ static struct net_device *register_vlan_device(struct net_device *real_dev,
546#endif 553#endif
547 return new_dev; 554 return new_dev;
548 555
549out_free_arrays: 556out_free_group:
550 vlan_group_free(grp); 557 if (ngrp)
551 558 vlan_group_free(ngrp);
552out_free_unregister:
553 unregister_netdev(new_dev);
554 goto out_ret_null;
555 559
556out_free_newdev: 560out_free_newdev:
557 free_netdev(new_dev); 561 free_netdev(new_dev);