* [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).