[PATCH] (10/42) smc

DORMANTno replies

From: Stephen Hemminger <hidden>
Date: 2003-11-13 00:41:58

Based on viro NE34-smc
	* switched smc to dynamic allocation
	* smc: embedded ->priv
	* smc: fixed resource leaks on failure exits
	* smc: fixed clobbering on autoprobe

diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Tue Nov 11 11:03:51 2003
+++ b/drivers/net/Space.c	Tue Nov 11 11:03:51 2003
@@ -73,7 +73,7 @@
 extern int sonic_probe(struct net_device *);
 extern struct net_device *SK_init(int unit);
 extern struct net_device *seeq8005_probe(int unit);
-extern int smc_init( struct net_device * );
+extern struct net_device *smc_init(int unit);
 extern int atarilance_probe(struct net_device *);
 extern int sun3lance_probe(struct net_device *);
 extern int sun3_82586_probe(struct net_device *);
@@ -228,13 +228,13 @@
 #ifdef CONFIG_LANCE		/* ISA/VLB (use pcnet32 for PCI cards) */
 	{lance_probe, 0},
 #endif
-#ifdef CONFIG_SMC9194
-	{smc_init, 0},
-#endif
 	{NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_SMC9194
+	{smc_init, 0},
+#endif
 #ifdef CONFIG_SEEQ8005 
 	{seeq8005_probe, 0},
 #endif
diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c
--- a/drivers/net/smc9194.c	Tue Nov 11 11:03:51 2003
+++ b/drivers/net/smc9194.c	Tue Nov 11 11:03:51 2003
@@ -191,7 +191,7 @@
  .
  . NB:This shouldn't be static since it is referred to externally.
 */
-int smc_init(struct net_device *dev);
+struct net_device *smc_init(int unit);
 
 /*
  . The kernel calls this function when someone wants to use the device,
@@ -672,7 +672,7 @@
 
 /*-------------------------------------------------------------------------
  |
- | smc_init( struct net_device * dev )
+ | smc_init(int unit)
  |   Input parameters:
  |	dev->base_addr == 0, try to find all possible locations
  |	dev->base_addr == 1, return failure code
@@ -680,31 +680,56 @@
  |	dev->base_addr == <anything else>   this is the address to check
  |
  |   Output:
- |	0 --> there is a device
- |	anything else, error
+ |	pointer to net_device or ERR_PTR(error)
  |
  ---------------------------------------------------------------------------
 */
-int __init smc_init(struct net_device *dev)
+static int io;
+static int irq;
+static int ifport;
+
+struct net_device * __init smc_init(int unit)
 {
-	int i;
-	int base_addr = dev->base_addr;
+	struct net_device *dev = alloc_etherdev(sizeof(struct smc_local));
+	unsigned *port;
+	int err = 0;
+
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	if (unit >= 0) {
+		sprintf(dev->name, "eth%d", unit);
+		netdev_boot_setup_check(dev);
+		io = dev->base_addr;
+		irq = dev->irq;
+	}
 
 	SET_MODULE_OWNER(dev);
 
-	/*  try a specific location */
-	if (base_addr > 0x1ff)
-		return smc_probe(dev, base_addr);
-	else if (base_addr != 0)
-		return -ENXIO;
-
-	/* check every ethernet address */
-	for (i = 0; smc_portlist[i]; i++)
-		if (smc_probe(dev, smc_portlist[i]) == 0)
-			return 0;
-
-	/* couldn't find anything */
-	return -ENODEV;
+	if (io > 0x1ff) {	/* Check a single specified location. */
+		err = smc_probe(dev, io);
+	} else if (io != 0) {	/* Don't probe at all. */
+		err = -ENXIO;
+	} else {
+		for (port = smc_portlist; *port; port++) {
+			if (smc_probe(dev, *port) == 0)
+				break;
+		}
+		if (!*port)
+			err = -ENODEV;
+	}
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	free_irq(dev->irq, dev);
+	release_region(dev->base_addr, SMC_IO_EXTENT);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
 }
 
 /*----------------------------------------------------------------------
@@ -821,6 +846,9 @@
 	if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
 		return -EBUSY;
 
+	dev->irq = irq;
+	dev->if_port = ifport;
+
 	/* First, see if the high byte is 0x33 */
 	bank = inw( ioaddr + BANK_SELECT );
 	if ( (bank & 0xFF00) != 0x3300 ) {
@@ -969,28 +997,14 @@
 		printk("%2.2x:", dev->dev_addr[i] );
 	printk("%2.2x \n", dev->dev_addr[5] );
 
-
-	/* Initialize the private structure. */
-	if (dev->priv == NULL) {
-		dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL);
-		if (dev->priv == NULL) {
-			retval = -ENOMEM;
-			goto err_out;
-		}
-	}
 	/* set the private data to zero by default */
 	memset(dev->priv, 0, sizeof(struct smc_local));
 
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-
 	/* Grab the IRQ */
       	retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
       	if (retval) {
 		printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name,
 			dev->irq, retval);
-		kfree(dev->priv);
-		dev->priv = NULL;
   	  	goto err_out;
       	}
 
@@ -1524,10 +1538,7 @@
 
 #ifdef MODULE
 
-static struct net_device devSMC9194;
-static int io;
-static int irq;
-static int ifport;
+static struct net_device *devSMC9194;
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(io, "i");
@@ -1539,32 +1550,23 @@
 
 int init_module(void)
 {
-	int result;
-
 	if (io == 0)
 		printk(KERN_WARNING
 		CARDNAME": You shouldn't use auto-probing with insmod!\n" );
 
 	/* copy the parameters from insmod into the device structure */
-	devSMC9194.base_addr = io;
-	devSMC9194.irq       = irq;
-	devSMC9194.if_port	= ifport;
-	devSMC9194.init   	= smc_init;
-	if ((result = register_netdev(&devSMC9194)) != 0)
-		return result;
-
+	devSMC9194 = smc_init(-1);
+	if (IS_ERR(devSMC9194))
+		return PTR_ERR(devSMC9194);
 	return 0;
 }
 
 void cleanup_module(void)
 {
-	unregister_netdev(&devSMC9194);
-
-	free_irq(devSMC9194.irq, &devSMC9194);
-	release_region(devSMC9194.base_addr, SMC_IO_EXTENT);
-
-	if (devSMC9194.priv)
-		kfree(devSMC9194.priv);
+	unregister_netdev(devSMC9194);
+	free_irq(devSMC9194->irq, devSMC9194);
+	release_region(devSMC9194->base_addr, SMC_IO_EXTENT);
+	free_netdev(devSMC9194);
 }
 
 #endif /* MODULE */
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help