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");
|