netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] (5/42) fmv18
@ 2003-11-13  0:41 Stephen Hemminger
  0 siblings, 0 replies; only message in thread
From: Stephen Hemminger @ 2003-11-13  0:41 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev

Based on viro, NE29-fmv18
	* switched fmv18x to dynamic allocation
	* fmv18x: embedded ->priv
	* fmv18x: fixed resource leaks on failure exits
	* fmv18x: fixed clobbering on autoprobe
	* fmv18x: compile fix - comment is _not_ an empty statement.  The thing
	  had been b0rken since 2.4.3-pre2, BTW...

diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Tue Nov 11 10:19:59 2003
+++ b/drivers/net/Space.c	Tue Nov 11 10:19:59 2003
@@ -53,7 +53,7 @@
 extern struct net_device *eepro_probe(int unit);
 extern int at1500_probe(struct net_device *);
 extern int at1700_probe(struct net_device *);
-extern int fmv18x_probe(struct net_device *);
+extern struct net_device *fmv18x_probe(int unit);
 extern struct net_device *eth16i_probe(int unit);
 extern struct net_device *i82596_probe(int unit);
 extern struct net_device *ewrk3_probe(int unit);
@@ -244,13 +244,13 @@
 #ifdef CONFIG_AT1700
 	{at1700_probe, 0},
 #endif
-#ifdef CONFIG_FMV18X		/* Fujitsu FMV-181/182 */
-	{fmv18x_probe, 0},
-#endif
 	{NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_FMV18X		/* Fujitsu FMV-181/182 */
+	{fmv18x_probe, 0},
+#endif
 #ifdef CONFIG_ETH16I
 	{eth16i_probe, 0},	/* ICL EtherTeam 16i/32 */
 #endif
diff -Nru a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
--- a/drivers/net/fmv18x.c	Tue Nov 11 10:19:59 2003
+++ b/drivers/net/fmv18x.c	Tue Nov 11 10:19:59 2003
@@ -57,7 +57,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
-static int fmv18x_probe_list[] __initdata = {
+static unsigned fmv18x_probe_list[] __initdata = {
 	0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
 };
 
@@ -109,8 +109,6 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int fmv18x_probe(struct net_device *dev);
-
 static int fmv18x_probe1(struct net_device *dev, short ioaddr);
 static int net_open(struct net_device *dev);
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
@@ -129,23 +127,50 @@
    (detachable devices only).
    */
 
-int __init fmv18x_probe(struct net_device *dev)
+static int io = 0x220;
+static int irq;
+
+struct net_device * __init fmv18x_probe(int unit)
 {
-	int i;
-	int base_addr = dev->base_addr;
+	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;
+	}
 
 	SET_MODULE_OWNER(dev);
 
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return fmv18x_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	for (i = 0; fmv18x_probe_list[i]; i++)
-		if (fmv18x_probe1(dev, fmv18x_probe_list[i]) == 0)
-			return 0;
-
-	return -ENODEV;
+	if (io > 0x1ff) {	/* Check a single specified location. */
+		err = fmv18x_probe1(dev, io);
+	} else if (io != 0) {	/* Don't probe at all. */
+		err = -ENXIO;
+	} else {
+		for (port = fmv18x_probe_list; *port; port++)
+			if (fmv18x_probe1(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, FMV18X_IO_EXTENT);
+out:
+	free_netdev(dev);
+	return ERR_PTR(err);
 }
 
 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
@@ -160,7 +185,7 @@
 {
 	char irqmap[4] = {3, 7, 10, 15};
 	char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
-	unsigned int i, irq, retval;
+	unsigned int i, retval;
 	struct net_local *lp;
 
 	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
@@ -170,6 +195,9 @@
 	if (!request_region(ioaddr, FMV18X_IO_EXTENT, dev->name))
 		return -EBUSY;
 
+	dev->irq = irq;
+	dev->base_addr = ioaddr;
+
 	/* Check I/O address configuration and Fujitsu vendor code */
 	if (inb(ioaddr+FJ_MACADDR  ) != 0x00
 	||  inb(ioaddr+FJ_MACADDR+1) != 0x00
@@ -181,9 +209,8 @@
 	/* Check PnP mode for FMV-183/184/183A/184A. */
 	/* This PnP routine is very poor. IO and IRQ should be known. */
 	if (inb(ioaddr + FJ_STATUS1) & 0x20) {
-		irq = dev->irq;
 		for (i = 0; i < 8; i++) {
-			if (irq == irqmap_pnp[i])
+			if (dev->irq == irqmap_pnp[i])
 				break;
 		}
 		if (i == 8) {
@@ -193,22 +220,19 @@
 	} else {
 		if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
 			return -ENODEV;
-		irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
+		dev->irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
 	}
 
 	/* Snarf the interrupt vector now. */
-	retval = request_irq(irq, &net_interrupt, 0, dev->name, dev);
+	retval = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);
 	if (retval) {
 		printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
-				"IRQ %d.\n", ioaddr, irq);
+				"IRQ %d.\n", ioaddr, dev->irq);
 		goto out;
 	}
 
 	printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
-		   ioaddr, irq);
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
+		   ioaddr, dev->irq);
 
 	for(i = 0; i < 6; i++) {
 		unsigned char val = inb(ioaddr + FJ_MACADDR + i);
@@ -279,14 +303,10 @@
 	dev->watchdog_timeo	= HZ/10;
 	dev->get_stats		= net_get_stats;
 	dev->set_multicast_list = set_multicast_list;
-
-	/* Fill in the fields of 'dev' with ethernet-generic values. */
-
-	ether_setup(dev);
 	return 0;
 
 out_irq:
-	free_irq(irq, dev);
+	free_irq(dev->irq, dev);
 out:
 	release_region(ioaddr, FMV18X_IO_EXTENT);
 	return retval;
@@ -413,9 +433,7 @@
 		lp->tx_queue_len = 0;
 		dev->trans_start = jiffies;
 		lp->tx_started = 1;
-	} else if (lp->tx_queue_len < 4096 - 1502)
-		/* Yes, there is room for one more packet. */
-	else
+	} else if (lp->tx_queue_len >= 4096 - 1502) /* No room for a packet */
 		netif_stop_queue(dev);
 
 	dev_kfree_skb(skb);
@@ -628,9 +646,7 @@
 }
 
 #ifdef MODULE
-static struct net_device dev_fmv18x;
-static int io = 0x220;
-static int irq;
+static struct net_device *dev_fmv18x;
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -644,26 +660,19 @@
 {
 	if (io == 0)
 		printk("fmv18x: You should not use auto-probing with insmod!\n");
-	dev_fmv18x.base_addr	= io;
-	dev_fmv18x.irq		= irq;
-	dev_fmv18x.init		= fmv18x_probe;
-	if (register_netdev(&dev_fmv18x) != 0) {
-		printk("fmv18x: register_netdev() returned non-zero.\n");
-		return -EIO;
-	}
+	dev_fmv18x = fmv18x_probe(-1);
+	if (IS_ERR(dev_fmv18x))
+		return PTR_ERR(dev_fmv18x);
 	return 0;
 }
 
 void
 cleanup_module(void)
 {
-	unregister_netdev(&dev_fmv18x);
-	kfree(dev_fmv18x.priv);
-	dev_fmv18x.priv = NULL;
-
-	/* If we don't do this, we can't re-insmod it later. */
-	free_irq(dev_fmv18x.irq, &dev_fmv18x);
-	release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT);
+	unregister_netdev(dev_fmv18x);
+	free_irq(dev_fmv18x->irq, dev_fmv18x);
+	release_region(dev_fmv18x->base_addr, FMV18X_IO_EXTENT);
+	free_netdev(dev_fmv18x);
 }
 #endif /* MODULE */
 \f

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-11-13  0:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-13  0:41 [PATCH] (5/42) fmv18 Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).