[VLAN]: Split up device creation

Split up device creation in allocation/registration functions taking
struct net_device * and a small wrapper for the ioctl handling. This is
needed by the netlink interface to properly set up the device before
registration.

Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]>

---
commit c59e99d32d8085f8ed1aa794106c28e546220581
tree dca7eeb9815666e863e5739a8c0a4698333026bc
parent 1057887432918a89e5b374c29ac36224716cb0e4
author Patrick McHardy <[EMAIL PROTECTED]> Tue, 29 May 2007 17:52:41 +0200
committer Patrick McHardy <[EMAIL PROTECTED]> Tue, 29 May 2007 17:52:41 +0200

 net/8021q/vlan.c |  196 ++++++++++++++++++++++++++----------------------------
 net/8021q/vlan.h |    4 +
 2 files changed, 100 insertions(+), 100 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index d470913..e5405cf 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -380,64 +380,110 @@ static void vlan_transfer_operstate(const struct 
net_device *dev, struct net_dev
        }
 }
 
-/*  Attach a VLAN device to a mac address (ie Ethernet Card).
- *  Returns the device that was created, or NULL if there was
- *  an error of some kind.
- */
-static struct net_device *register_vlan_device(struct net_device *real_dev,
-                                              unsigned short VLAN_ID)
+int vlan_check_device(struct net_device *dev, unsigned short vlan_id)
 {
-       struct vlan_group *grp, *reg = NULL;
-       struct net_device *new_dev;
-       char name[IFNAMSIZ];
-
-#ifdef VLAN_DEBUG
-       printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
-               __FUNCTION__, eth_IF_name, VLAN_ID);
-#endif
-
-       if (VLAN_ID >= VLAN_VID_MASK)
-               goto out_ret_null;
-
-       if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
+       if (dev->features & NETIF_F_VLAN_CHALLENGED) {
                printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
-                       __FUNCTION__, real_dev->name);
-               goto out_ret_null;
+                       __FUNCTION__, dev->name);
+               return -EOPNOTSUPP;
        }
 
-       if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
-           (real_dev->vlan_rx_register == NULL ||
-            real_dev->vlan_rx_kill_vid == NULL)) {
+       if ((dev->features & NETIF_F_HW_VLAN_RX) &&
+           (dev->vlan_rx_register == NULL || dev->vlan_rx_kill_vid == NULL)) {
                printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-                       __FUNCTION__, real_dev->name);
-               goto out_ret_null;
+                       __FUNCTION__, dev->name);
+               return -EOPNOTSUPP;
        }
 
-       if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
-           (real_dev->vlan_rx_add_vid == NULL ||
-            real_dev->vlan_rx_kill_vid == NULL)) {
+       if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
+           (dev->vlan_rx_add_vid == NULL || dev->vlan_rx_kill_vid == NULL)) {
                printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
-                       __FUNCTION__, real_dev->name);
-               goto out_ret_null;
+                       __FUNCTION__, dev->name);
+               return -EOPNOTSUPP;
        }
 
        /* The real device must be up and operating in order to
-        * assosciate a VLAN device with it.
+        * associate a VLAN device with it.
         */
-       if (!(real_dev->flags & IFF_UP))
-               goto out_ret_null;
+       if (!(dev->flags & IFF_UP))
+               return -ENETDOWN;
 
-       if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
-               /* was already registered. */
-               printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", 
__FUNCTION__);
-               goto out_ret_null;
+       if (__find_vlan_dev(dev, vlan_id) != NULL)
+               return -EEXIST;
+
+       return 0;
+}
+
+int vlan_register_dev(struct net_device *dev)
+{
+       struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+       struct net_device *real_dev = vlan->real_dev;
+       struct vlan_group *group, *reg = NULL;
+       int err;
+
+       group = __vlan_find_group(real_dev->ifindex);
+       if (!group) {
+               err = -ENOMEM;
+               group = reg = vlan_group_alloc(real_dev->ifindex);
+               if (!group)
+                       goto err1;
        }
 
-       /* Gotta set up the fields for the device. */
+       err = register_netdevice(dev);
+       if (err < 0)
+               goto err2;
+
+       /* Account for reference in struct vlan_dev_info */
+       dev_hold(real_dev);
+
+       vlan_transfer_operstate(real_dev, dev);
+       linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
+
+       /* So, got the sucker initialized, now lets place
+        * it into our local structure.
+        */
+       vlan_group_set_device(group, vlan->vlan_id, dev);
+
+       if (reg && real_dev->features & NETIF_F_HW_VLAN_RX)
+               real_dev->vlan_rx_register(real_dev, reg);
+       if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+               real_dev->vlan_rx_add_vid(real_dev, vlan->vlan_id);
+
+       if (vlan_proc_add_dev(dev) < 0)
+               printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
+                      dev->name);
+       return 0;
+
+err2:
+       if (reg)
+               vlan_group_free(reg);
+err1:
+       return err;
+}
+
+/*  Attach a VLAN device to a mac address (ie Ethernet Card).
+ *  Returns 0 if the device was created or a negative error code otherwise.
+ */
+static int register_vlan_device(struct net_device *real_dev,
+                               unsigned short VLAN_ID)
+{
+       struct net_device *new_dev;
+       char name[IFNAMSIZ];
+       int err;
+
 #ifdef VLAN_DEBUG
-       printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",
-              vlan_name_type);
+       printk(VLAN_DBG "%s: if_name -:%s:-     vid: %i\n",
+               __FUNCTION__, eth_IF_name, VLAN_ID);
 #endif
+
+       if (VLAN_ID >= VLAN_VID_MASK)
+               return -ERANGE;
+
+       err = vlan_check_device(real_dev, VLAN_ID);
+       if (err < 0)
+               return err;
+
+       /* Gotta set up the fields for the device. */
        switch (vlan_name_type) {
        case VLAN_NAME_TYPE_RAW_PLUS_VID:
                /* name will look like:  eth1.0005 */
@@ -465,71 +511,25 @@ static struct net_device *register_vlan_device(struct 
net_device *real_dev,
 
        new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
                               vlan_setup);
-
        if (new_dev == NULL)
-               goto out_ret_null;
+               return -ENOMEM;
 
 #ifdef VLAN_DEBUG
        printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-#endif
-
-       VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
-       VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
-       VLAN_DEV_INFO(new_dev)->dent = NULL;
-       VLAN_DEV_INFO(new_dev)->flags = 1;
-
        VLAN_MEM_DBG("new_dev->priv malloc, addr: %p  size: %i\n",
                     new_dev->priv,
                     sizeof(struct vlan_dev_info));
-
-#ifdef VLAN_DEBUG
-       printk(VLAN_DBG "About to go find the group for idx: %i\n",
-              real_dev->ifindex);
-#endif
-       grp = __vlan_find_group(real_dev->ifindex);
-       if (!grp) {
-               reg = grp = vlan_group_alloc(real_dev->ifindex);
-               if (!grp)
-                       goto out_free_newdev;
-       }
-
-       if (register_netdevice(new_dev))
-               goto out_free_group;
-
-       vlan_transfer_operstate(real_dev, new_dev);
-       linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
-
-       /* So, got the sucker initialized, now lets place
-        * it into our local structure.
-        */
-       if (reg && real_dev->features & NETIF_F_HW_VLAN_RX)
-               real_dev->vlan_rx_register(real_dev, reg);
-
-       vlan_group_set_device(grp, VLAN_ID, new_dev);
-
-       if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
-               printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
-                                                        new_dev->name);
-
-       if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
-               real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
-
-       /* Account for reference in struct vlan_dev_info */
-       dev_hold(real_dev);
-#ifdef VLAN_DEBUG
-       printk(VLAN_DBG "Allocated new device successfully, returning.\n");
 #endif
-       return new_dev;
 
-out_free_group:
-       if (reg)
-               vlan_group_free(reg);
+       VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
+       VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
+       VLAN_DEV_INFO(new_dev)->flags = 1;
 
-out_free_newdev:
-       free_netdev(new_dev);
+       err = vlan_register_dev(new_dev);
+       if (err < 0)
+               free_netdev(new_dev);
 
-out_ret_null:
-       return NULL;
+       return 0;
 }
 
 static int vlan_device_event(struct notifier_block *unused, unsigned long 
event, void *ptr)
@@ -699,11 +699,7 @@ static int vlan_ioctl_handler(void __user *arg)
                 * talk to:  args.dev1   We also have the
                 * VLAN ID:  args.u.VID
                 */
-               if (register_vlan_device(dev, args.u.VID)) {
-                       err = 0;
-               } else {
-                       err = -EINVAL;
-               }
+               err = register_vlan_device(dev, args.u.VID);
                break;
 
        case DEL_VLAN_CMD:
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index b837390..47f0c53 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -72,4 +72,8 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, 
char *result);
 void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
 
+int vlan_check_device(struct net_device *dev, unsigned short vlan_id);
+int vlan_register_dev(struct net_device *dev);
+int vlan_unregister_dev(struct net_device *dev);
+
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to