[PATCH] (6/42) at1700

DORMANTno replies

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

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

diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Tue Nov 11 09:35:37 2003
+++ b/drivers/net/Space.c	Tue Nov 11 09:35:37 2003
@@ -52,7 +52,7 @@
 extern struct net_device *express_probe(int unit);
 extern struct net_device *eepro_probe(int unit);
 extern int at1500_probe(struct net_device *);
-extern int at1700_probe(struct net_device *);
+extern struct net_device *at1700_probe(int unit);
 extern struct net_device *fmv18x_probe(int unit);
 extern struct net_device *eth16i_probe(int unit);
 extern struct net_device *i82596_probe(int unit);
@@ -241,13 +241,13 @@
 #ifdef CONFIG_CS89x0
  	{cs89x0_probe, 0},
 #endif
-#ifdef CONFIG_AT1700
-	{at1700_probe, 0},
-#endif
 	{NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_AT1700
+	{at1700_probe, 0},
+#endif
 #ifdef CONFIG_FMV18X		/* Fujitsu FMV-181/182 */
 	{fmv18x_probe, 0},
 #endif
diff -Nru a/drivers/net/at1700.c b/drivers/net/at1700.c
--- a/drivers/net/at1700.c	Tue Nov 11 09:35:37 2003
+++ b/drivers/net/at1700.c	Tue Nov 11 09:35:37 2003
@@ -81,12 +81,12 @@
  */
 
 #ifndef CONFIG_X86_PC9800
-static int at1700_probe_list[] __initdata = {
+static unsigned at1700_probe_list[] __initdata = {
 	0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
 };
 
 #else /* CONFIG_X86_PC9800 */
-static int at1700_probe_list[] __initdata = {
+static unsigned at1700_probe_list[] __initdata = {
 	0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0
 };
 
@@ -196,8 +196,6 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int at1700_probe(struct net_device *dev);
-
 static int at1700_probe1(struct net_device *dev, int ioaddr);
 static int read_eeprom(long ioaddr, int location);
 static int net_open(struct net_device *dev);
@@ -232,24 +230,78 @@
    (detachable devices only).
    */
 
-int __init at1700_probe(struct net_device *dev)
+#ifndef CONFIG_X86_PC9800
+static int io = 0x260;
+#else
+static int io = 0xd0;
+#endif
+
+static int irq;
+
+static void cleanup_card(struct net_device *dev)
 {
-	int i;
-	int base_addr = dev->base_addr;
+#ifdef CONFIG_MCA	
+	struct net_local *lp = dev->priv;
+	if (lp->mca_slot)
+		mca_mark_as_unused(lp->mca_slot);
+#endif	
+	free_irq(dev->irq, NULL);
+#ifndef CONFIG_X86_PC9800
+	release_region(dev->base_addr, AT1700_IO_EXTENT);
+#else
+	{
+		int i;
+		for (i = 0; i < 0x2000; i += 0x200)
+			release_region(dev->base_addr + i, 2);
+	}
+#endif
+}
+
+struct net_device * __init at1700_probe(int unit)
+{
+	struct net_device *dev = alloc_etherdev(sizeof(struct net_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;
+	} else {
+		dev->base_addr = io;
+		dev->irq = irq;
+	}
 
 	SET_MODULE_OWNER(dev);
 
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return at1700_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	for (i = 0; at1700_probe_list[i]; i++) {
-		int ioaddr = at1700_probe_list[i];
-		if (at1700_probe1(dev, ioaddr) == 0)
-			return 0;
+	if (io > 0x1ff) {	/* Check a single specified location. */
+		err = at1700_probe1(dev, io);
+	} else if (io != 0) {	/* Don't probe at all. */
+		err = -ENXIO;
+	} else {
+		for (port = at1700_probe_list; *port; port++) {
+			if (at1700_probe1(dev, *port) == 0)
+				break;
+			dev->irq = irq;
+		}
+		if (!*port)
+			err = -ENODEV;
 	}
-	return -ENODEV;
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	cleanup_card(dev);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
 }
 
 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
@@ -267,7 +319,7 @@
 	char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
 	unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
 	int slot, ret = -ENODEV;
-	struct net_local *lp;
+	struct net_local *lp = dev->priv;
 	
 #ifndef CONFIG_X86_PC9800
 	if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name))
@@ -284,9 +336,10 @@
 	}
 #endif
 
-		/* Resetting the chip doesn't reset the ISA interface, so don't bother.
-	   That means we have to be careful with the register values we probe for.
-	   */
+	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
+	   That means we have to be careful with the register values we probe
+	   for.
+	 */
 #ifdef notdef
 	printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
 		   ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
@@ -331,15 +384,13 @@
 						break;
 
 					/* probing for a card at a particular IO/IRQ */
-				if (dev &&
-					((dev->irq && dev->irq != irq) ||
-					 (dev->base_addr && dev->base_addr != ioaddr))) {
+				if ((dev->irq && dev->irq != irq) ||
+				    (dev->base_addr && dev->base_addr != ioaddr)) {
 				  	slot++;		/* probing next slot */
 				  	continue;
 				}
 
-				if (dev)
-					dev->irq = irq;
+				dev->irq = irq;
 				
 				/* claim the slot */
 				mca_set_adapter_name( slot, at1720_mca_adapters[j].name );
@@ -476,13 +527,7 @@
 	if (net_debug)
 		printk(version);
 
-	/* Initialize the device structure. */
-	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-	if (dev->priv == NULL) {
-		ret = -ENOMEM;
-		goto err_out;
-	}
-	memset(dev->priv, 0, sizeof(struct net_local));
+	memset(lp, 0, sizeof(struct net_local));
 
 	dev->open		= net_open;
 	dev->stop		= net_close;
@@ -492,11 +537,7 @@
 	dev->tx_timeout = net_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
-	lp = (struct net_local *)dev->priv;
-	lp->lock = SPIN_LOCK_UNLOCKED;
-
-	/* Fill in the fields of 'dev' with ethernet-generic values. */
-	ether_setup(dev);
+	spin_lock_init(&lp->lock);
 
 	lp->jumpered = is_fmv18x;
 	lp->mca_slot = slot;
@@ -505,14 +546,11 @@
 	if (ret) {
 		printk ("  AT1700 at %#3x is unusable due to a conflict on"
 				"IRQ %d.\n", ioaddr, irq);
-		goto err_out_priv;
+		goto err_out;
 	}
 
 	return 0;
 
-err_out_priv:
-	kfree(dev->priv);
-	dev->priv = NULL;
 err_out:
 #ifndef CONFIG_X86_PC9800
 	release_region(ioaddr, AT1700_IO_EXTENT);
@@ -940,14 +978,7 @@
 }
 
 #ifdef MODULE
-static struct net_device dev_at1700;
-#ifndef CONFIG_X86_PC9800
-static int io = 0x260;
-#else
-static int io = 0xd0;
-#endif
-
-static int irq;
+static struct net_device *dev_at1700;
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -960,41 +991,18 @@
 {
 	if (io == 0)
 		printk("at1700: You should not use auto-probing with insmod!\n");
-	dev_at1700.base_addr = io;
-	dev_at1700.irq       = irq;
-	dev_at1700.init      = at1700_probe;
-	if (register_netdev(&dev_at1700) != 0) {
-		printk("at1700: register_netdev() returned non-zero.\n");
-		return -EIO;
-	}
+	dev_at1700 = at1700_probe(-1);
+	if (IS_ERR(dev_at1700))
+		return PTR_ERR(dev_at1700);
 	return 0;
 }
 
 void
 cleanup_module(void)
 {
-#ifdef CONFIG_MCA	
-	struct net_local *lp = dev_at1700.priv;
-	if(lp->mca_slot)
-	{
-		mca_mark_as_unused(lp->mca_slot);
-	}
-#endif	
-	unregister_netdev(&dev_at1700);
-	kfree(dev_at1700.priv);
-	dev_at1700.priv = NULL;
-
-	/* If we don't do this, we can't re-insmod it later. */
-	free_irq(dev_at1700.irq, NULL);
-#ifndef CONFIG_X86_PC9800
-	release_region(dev_at1700.base_addr, AT1700_IO_EXTENT);
-#else
-	{
-		int i;
-		for (i = 0; i < 0x2000; i += 0x200)
-			release_region(dev_at1700.base_addr + i, 2);
-	}
-#endif
+	unregister_netdev(dev_at1700);
+	cleanup_card(dev_at1700);
+	free_netdev(dev_at1700);
 }
 #endif /* MODULE */
 MODULE_LICENSE("GPL");
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help