netdev
[Top] [All Lists]

[PATCH] (10/12) Probe2 -- wavelan

To: jgarzik@xxxxxxxxx
Subject: [PATCH] (10/12) Probe2 -- wavelan
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Tue, 14 Oct 2003 15:34:10 -0700
Cc: netdev@xxxxxxxxxxx
Sender: netdev-bounce@xxxxxxxxxxx
Original by Al Viro (NE21-wavelan)
        * switched wavelan to dynamic allocation
        * wavelan: embedded ->priv
        * wavelan: fixed clobbering on autoprobe
        * wavelan: fixed IO before request_region()
        * wavelan: fixed resource leaks on failure exits
        * wavelan: fixed order of freeing bugs
Updated to apply agains jgarzik/net-drivers-2.5-exp


diff -urN 08-arlan/drivers/net/Space.c 09-wavelan/drivers/net/Space.c
--- 08-arlan/drivers/net/Space.c        2003-09-29 16:23:44.000000000 -0700
+++ 09-wavelan/drivers/net/Space.c      2003-09-29 16:30:02.000000000 -0700
@@ -58,7 +58,7 @@
 extern int i82596_probe(struct net_device *);
 extern int ewrk3_probe(struct net_device *);
 extern int el1_probe(struct net_device *);
-extern int wavelan_probe(struct net_device *);
+extern struct net_device *wavelan_probe(int unit);
 extern struct net_device *arlan_probe(int unit);
 extern struct net_device *el16_probe(int unit);
 extern int elmc_probe(struct net_device *);
@@ -269,13 +269,13 @@
 #ifdef CONFIG_EL1              /* 3c501 */
        {el1_probe, 0},
 #endif
-#ifdef CONFIG_WAVELAN          /* WaveLAN */
-       {wavelan_probe, 0},
-#endif
        {NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_WAVELAN          /* WaveLAN */
+       {wavelan_probe, 0},
+#endif
 #ifdef CONFIG_ARLAN            /* Aironet */
        {arlan_probe, 0},
 #endif
diff -urN 08-arlan/drivers/net/wireless/wavelan.c 
09-wavelan/drivers/net/wireless/wavelan.c
--- 08-arlan/drivers/net/wireless/wavelan.c     2003-09-27 17:50:59.000000000 
-0700
+++ 09-wavelan/drivers/net/wireless/wavelan.c   2003-09-29 16:30:09.000000000 
-0700
@@ -4091,12 +4091,24 @@
  * device structure
  * (called by wavelan_probe() and via init_module()).
  */
-static int __init wavelan_config(device * dev)
+static int __init wavelan_config(device *dev, unsigned short ioaddr)
 {
-       unsigned long ioaddr = dev->base_addr;
        u8 irq_mask;
        int irq;
        net_local *lp;
+       mac_addr mac;
+       int err;
+
+       if (!request_region(ioaddr, sizeof(ha_t), "wavelan"))
+               return -EADDRINUSE;
+
+       err = wv_check_ioaddr(ioaddr, mac);
+       if (err)
+               goto out;
+
+       memcpy(dev->dev_addr, mac, 6);
+
+       dev->base_addr = ioaddr;
 
 #ifdef DEBUG_CALLBACK_TRACE
        printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%lx)\n",
@@ -4136,25 +4148,18 @@
                       "%s: wavelan_config(): could not wavelan_map_irq(%d).\n",
                       dev->name, irq_mask);
 #endif
-               return -EAGAIN;
+               err = -EAGAIN;
+               goto out;
        }
 
        dev->irq = irq;
 
-       if (!request_region(ioaddr, sizeof(ha_t), "wavelan"))
-               return -EBUSY;
-
        dev->mem_start = 0x0000;
        dev->mem_end = 0x0000;
        dev->if_port = 0;
 
        /* Initialize device structures */
-       dev->priv = kmalloc(sizeof(net_local), GFP_KERNEL);
-       if (dev->priv == NULL) {
-               release_region(ioaddr, sizeof(ha_t));
-               return -ENOMEM;
-       }
-       memset(dev->priv, 0x00, sizeof(net_local));
+       memset(dev->priv, 0, sizeof(net_local));
        lp = (net_local *) dev->priv;
 
        /* Back link to the device structure. */
@@ -4172,12 +4177,6 @@
        /* Init spinlock */
        spin_lock_init(&lp->spinlock);
 
-       /*
-        * Fill in the fields of the device structure
-        * with generic Ethernet values.
-        */
-       ether_setup(dev);
-
        SET_MODULE_OWNER(dev);
        dev->open = wavelan_open;
        dev->stop = wavelan_close;
@@ -4204,6 +4203,9 @@
        printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name);
 #endif
        return 0;
+out:
+       release_region(ioaddr, sizeof(ha_t));
+       return err;
 }
 
 /*------------------------------------------------------------------*/
@@ -4214,19 +4216,13 @@
  * We follow the example in drivers/net/ne.c.
  * (called in "Space.c")
  */
-int __init wavelan_probe(device * dev)
+struct net_device * __init wavelan_probe(int unit)
 {
+       struct net_device *dev;
        short base_addr;
-       mac_addr mac;           /* MAC address (check existence of WaveLAN) */
+       int def_irq;
        int i;
-       int r;
-
-#ifdef DEBUG_CALLBACK_TRACE
-       printk(KERN_DEBUG
-              "%s: ->wavelan_probe(dev=0x%x (base_addr=0x%x))\n",
-              dev->name, (unsigned int) dev,
-              (unsigned int) dev->base_addr);
-#endif
+       int r = 0;
 
 #ifdef STRUCT_CHECK
        if (wv_struct_check() != (char *) NULL) {
@@ -4237,8 +4233,20 @@
        }
 #endif                         /* STRUCT_CHECK */
 
-       /* Check the value of the command line parameter for base address. */
+       dev = alloc_etherdev(sizeof(net_local));
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
        base_addr = dev->base_addr;
+       def_irq = dev->irq;
+
+#ifdef DEBUG_CALLBACK_TRACE
+       printk(KERN_DEBUG
+              "%s: ->wavelan_probe(dev=%p (base_addr=0x%x))\n",
+              dev->name, dev, (unsigned int) dev->base_addr);
+#endif
 
        /* Don't probe at all. */
        if (base_addr < 0) {
@@ -4247,16 +4255,9 @@
                       "%s: wavelan_probe(): invalid base address\n",
                       dev->name);
 #endif
-               return -ENXIO;
-       }
-
-       /* Check a single specified location. */
-       if (base_addr > 0x100) {
-               /* Check if there is something at this base address */
-               if ((r = wv_check_ioaddr(base_addr, mac)) == 0) {
-                       memcpy(dev->dev_addr, mac, 6);  /* Copy MAC address. */
-                       r = wavelan_config(dev);
-               }
+               r = -ENXIO;
+       } else if (base_addr > 0x100) { /* Check a single specified location. */
+               r = wavelan_config(dev, base_addr);
 #ifdef DEBUG_CONFIG_INFO
                if (r != 0)
                        printk(KERN_DEBUG
@@ -4267,35 +4268,33 @@
 #ifdef DEBUG_CALLBACK_TRACE
                printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name);
 #endif
-               return r;
-       }
-
-       /* Scan all possible addresses of the WaveLAN hardware. */
-       for (i = 0; i < NELS(iobase); i++) {
-               /* Check whether there is something at this base address. */
-               if (wv_check_ioaddr(iobase[i], mac) == 0) {
-                       dev->base_addr = iobase[i];     /* Copy base address. */
-                       memcpy(dev->dev_addr, mac, 6);  /* Copy MAC address. */
-                       if (wavelan_config(dev) == 0) {
+       } else { /* Scan all possible addresses of the WaveLAN hardware. */
+               for (i = 0; i < NELS(iobase); i++) {
+                       dev->irq = def_irq;
+                       if (wavelan_config(dev, iobase[i]) == 0) {
 #ifdef DEBUG_CALLBACK_TRACE
                                printk(KERN_DEBUG
                                       "%s: <-wavelan_probe()\n",
                                       dev->name);
 #endif
-                               return 0;
+                               break;
                        }
                }
+               if (i == NELS(iobase))
+                       r = -ENODEV;
        }
-
-       /* We may have touched base_addr.  Another driver may not like it. */
-       dev->base_addr = base_addr;
-
-#ifdef DEBUG_CONFIG_INFO
-       printk(KERN_DEBUG "%s: wavelan_probe(): no device found\n",
-              dev->name);
-#endif
-
-       return -ENODEV;
+       if (r) 
+               goto out;
+       r = register_netdev(dev);
+       if (r)
+               goto out1;
+       return dev;
+out1:
+       release_region(dev->base_addr, sizeof(ha_t));
+       wavelan_list = wavelan_list->next;
+out:
+       kfree(dev);
+       return ERR_PTR(r);
 }
 
 /****************************** MODULE ******************************/
@@ -4311,7 +4310,6 @@
  */
 int init_module(void)
 {
-       mac_addr mac;           /* MAC address (check WaveLAN existence) */
        int ret = -EIO;         /* Return error if no cards found */
        int i;
 
@@ -4337,38 +4335,28 @@
        /* Loop on all possible base addresses. */
        i = -1;
        while ((io[++i] != 0) && (i < NELS(io))) {
-               /* Check if there is something at this base address. */
-               if (wv_check_ioaddr(io[i], mac) == 0) {
-                       device *dev;
+               struct net_device *dev = alloc_etherdev(sizeof(net_local));
+               if (!dev)
+                       break;
+               memcpy(dev->name, name[i], IFNAMSIZ);   /* Copy name */
+               dev->base_addr = io[i];
+               dev->irq = irq[i];
 
-                       /* Create device and set basic arguments. */
-                       dev =
-                           kmalloc(sizeof(struct net_device), GFP_KERNEL);
-                       if (dev == NULL) {
-                               ret = -ENOMEM;
-                               break;
-                       }
-                       memset(dev, 0x00, sizeof(struct net_device));
-                       memcpy(dev->name, name[i], IFNAMSIZ);   /* Copy name */
-                       dev->base_addr = io[i];
-                       dev->irq = irq[i];
-                       dev->init = &wavelan_config;
-                       memcpy(dev->dev_addr, mac, 6);  /* Copy MAC address. */
-
-                       /* Try to create the device. */
+               /* Check if there is something at this base address. */
+               if (wavelan_config(dev, io[i]) == 0) {
                        if (register_netdev(dev) != 0) {
-                               /* Deallocate everything. */
-                               /* Note: if dev->priv is mallocated, there is 
no way to fail. */
-                               kfree(dev);
+                               release_region(dev->base_addr, sizeof(ha_t));
+                               wavelan_list = wavelan_list->next;
                        } else {
-                               /* If at least one device OK, we do not fail */
                                ret = 0;
+                               continue;
                        }
-               }               /* if there is something at the address */
-       }                       /* Loop on all addresses. */
+               }
+               kfree(dev);
+       }
 
 #ifdef DEBUG_CONFIG_ERROR
-       if (wavelan_list == (net_local *) NULL)
+       if (!wavelan_list)
                printk(KERN_WARNING
                       "WaveLAN init_module(): no device found\n");
 #endif
@@ -4390,7 +4378,7 @@
 #endif
 
        /* Loop on all devices and release them. */
-       while (wavelan_list != (net_local *) NULL) {
+       while (wavelan_list) {
                device *dev = wavelan_list->dev;
 
 #ifdef DEBUG_CONFIG_INFO
@@ -4398,18 +4386,11 @@
                       "%s: cleanup_module(): removing device at 0x%x\n",
                       dev->name, (unsigned int) dev);
 #endif
-
-               /* Release the ioport region. */
-               release_region(dev->base_addr, sizeof(ha_t));
-
-               /* Definitely remove the device. */
                unregister_netdev(dev);
 
-               /* Unlink the device. */
+               release_region(dev->base_addr, sizeof(ha_t));
                wavelan_list = wavelan_list->next;
 
-               /* Free pieces. */
-               kfree(dev->priv);
                free_netdev(dev);
        }
 
diff -urN 08-arlan/drivers/net/wireless/wavelan.p.h 
09-wavelan/drivers/net/wireless/wavelan.p.h
--- 08-arlan/drivers/net/wireless/wavelan.p.h   2003-09-27 17:50:38.000000000 
-0700
+++ 09-wavelan/drivers/net/wireless/wavelan.p.h 2003-09-29 16:30:09.000000000 
-0700
@@ -656,9 +656,8 @@
 static int
        wavelan_open(device *),         /* Open the device. */
        wavelan_close(device *),        /* Close the device. */
-       wavelan_config(device *);       /* Configure one device. */
-extern int
-       wavelan_probe(device *);        /* See Space.c. */
+       wavelan_config(device *, unsigned short);/* Configure one device. */
+extern struct net_device *wavelan_probe(int unit);     /* See Space.c. */
 
 /**************************** VARIABLES ****************************/
 

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH] (10/12) Probe2 -- wavelan, Stephen Hemminger <=