Commit 06add1e9 authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (6/42) at1700

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
parent 39def843
...@@ -52,7 +52,7 @@ extern int hp_plus_probe(struct net_device *dev); ...@@ -52,7 +52,7 @@ extern int hp_plus_probe(struct net_device *dev);
extern struct net_device *express_probe(int unit); extern struct net_device *express_probe(int unit);
extern struct net_device *eepro_probe(int unit); extern struct net_device *eepro_probe(int unit);
extern int at1500_probe(struct net_device *); 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 *fmv18x_probe(int unit);
extern struct net_device *eth16i_probe(int unit); extern struct net_device *eth16i_probe(int unit);
extern struct net_device *i82596_probe(int unit); extern struct net_device *i82596_probe(int unit);
...@@ -240,14 +240,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -240,14 +240,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_CS89x0 #ifdef CONFIG_CS89x0
{cs89x0_probe, 0}, {cs89x0_probe, 0},
#endif
#ifdef CONFIG_AT1700
{at1700_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_AT1700
{at1700_probe, 0},
#endif
#ifdef CONFIG_FMV18X /* Fujitsu FMV-181/182 */ #ifdef CONFIG_FMV18X /* Fujitsu FMV-181/182 */
{fmv18x_probe, 0}, {fmv18x_probe, 0},
#endif #endif
......
...@@ -81,12 +81,12 @@ static int fmv18x_probe_list[] __initdata = { ...@@ -81,12 +81,12 @@ static int fmv18x_probe_list[] __initdata = {
*/ */
#ifndef CONFIG_X86_PC9800 #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 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
}; };
#else /* CONFIG_X86_PC9800 */ #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 0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0
}; };
...@@ -196,8 +196,6 @@ struct net_local { ...@@ -196,8 +196,6 @@ struct net_local {
/* Index to functions, as function prototypes. */ /* 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 at1700_probe1(struct net_device *dev, int ioaddr);
static int read_eeprom(long ioaddr, int location); static int read_eeprom(long ioaddr, int location);
static int net_open(struct net_device *dev); static int net_open(struct net_device *dev);
...@@ -232,24 +230,78 @@ static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = { ...@@ -232,24 +230,78 @@ static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = {
(detachable devices only). (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)
{ {
#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; int i;
int base_addr = dev->base_addr; for (i = 0; i < 0x2000; i += 0x200)
release_region(dev->base_addr + i, 2);
}
#endif
}
SET_MODULE_OWNER(dev); struct net_device * __init at1700_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
unsigned *port;
int err = 0;
if (base_addr > 0x1ff) /* Check a single specified location. */ if (!dev)
return at1700_probe1(dev, base_addr); return ERR_PTR(-ENODEV);
else if (base_addr != 0) /* Don't probe at all. */
return -ENXIO;
for (i = 0; at1700_probe_list[i]; i++) { if (unit >= 0) {
int ioaddr = at1700_probe_list[i]; sprintf(dev->name, "eth%d", unit);
if (at1700_probe1(dev, ioaddr) == 0) netdev_boot_setup_check(dev);
return 0; io = dev->base_addr;
irq = dev->irq;
} else {
dev->base_addr = io;
dev->irq = irq;
} }
return -ENODEV;
SET_MODULE_OWNER(dev);
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;
}
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 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
...@@ -267,7 +319,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -267,7 +319,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0; unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
int slot, ret = -ENODEV; int slot, ret = -ENODEV;
struct net_local *lp; struct net_local *lp = dev->priv;
#ifndef CONFIG_X86_PC9800 #ifndef CONFIG_X86_PC9800
if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name))
...@@ -285,7 +337,8 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -285,7 +337,8 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
#endif #endif
/* Resetting the chip doesn't reset the ISA interface, so don't bother. /* 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. That means we have to be careful with the register values we probe
for.
*/ */
#ifdef notdef #ifdef notdef
printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n", printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
...@@ -331,14 +384,12 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -331,14 +384,12 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
break; break;
/* probing for a card at a particular IO/IRQ */ /* probing for a card at a particular IO/IRQ */
if (dev && if ((dev->irq && dev->irq != irq) ||
((dev->irq && dev->irq != irq) || (dev->base_addr && dev->base_addr != ioaddr)) {
(dev->base_addr && dev->base_addr != ioaddr))) {
slot++; /* probing next slot */ slot++; /* probing next slot */
continue; continue;
} }
if (dev)
dev->irq = irq; dev->irq = irq;
/* claim the slot */ /* claim the slot */
...@@ -476,13 +527,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -476,13 +527,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
if (net_debug) if (net_debug)
printk(version); printk(version);
/* Initialize the device structure. */ memset(lp, 0, sizeof(struct net_local));
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));
dev->open = net_open; dev->open = net_open;
dev->stop = net_close; dev->stop = net_close;
...@@ -492,11 +537,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -492,11 +537,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
dev->tx_timeout = net_tx_timeout; dev->tx_timeout = net_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
lp = (struct net_local *)dev->priv; spin_lock_init(&lp->lock);
lp->lock = SPIN_LOCK_UNLOCKED;
/* Fill in the fields of 'dev' with ethernet-generic values. */
ether_setup(dev);
lp->jumpered = is_fmv18x; lp->jumpered = is_fmv18x;
lp->mca_slot = slot; lp->mca_slot = slot;
...@@ -505,14 +546,11 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) ...@@ -505,14 +546,11 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
if (ret) { if (ret) {
printk (" AT1700 at %#3x is unusable due to a conflict on" printk (" AT1700 at %#3x is unusable due to a conflict on"
"IRQ %d.\n", ioaddr, irq); "IRQ %d.\n", ioaddr, irq);
goto err_out_priv; goto err_out;
} }
return 0; return 0;
err_out_priv:
kfree(dev->priv);
dev->priv = NULL;
err_out: err_out:
#ifndef CONFIG_X86_PC9800 #ifndef CONFIG_X86_PC9800
release_region(ioaddr, AT1700_IO_EXTENT); release_region(ioaddr, AT1700_IO_EXTENT);
...@@ -940,14 +978,7 @@ set_rx_mode(struct net_device *dev) ...@@ -940,14 +978,7 @@ set_rx_mode(struct net_device *dev)
} }
#ifdef MODULE #ifdef MODULE
static struct net_device dev_at1700; static struct net_device *dev_at1700;
#ifndef CONFIG_X86_PC9800
static int io = 0x260;
#else
static int io = 0xd0;
#endif
static int irq;
MODULE_PARM(io, "i"); MODULE_PARM(io, "i");
MODULE_PARM(irq, "i"); MODULE_PARM(irq, "i");
...@@ -960,41 +991,18 @@ int init_module(void) ...@@ -960,41 +991,18 @@ int init_module(void)
{ {
if (io == 0) if (io == 0)
printk("at1700: You should not use auto-probing with insmod!\n"); printk("at1700: You should not use auto-probing with insmod!\n");
dev_at1700.base_addr = io; dev_at1700 = at1700_probe(-1);
dev_at1700.irq = irq; if (IS_ERR(dev_at1700))
dev_at1700.init = at1700_probe; return PTR_ERR(dev_at1700);
if (register_netdev(&dev_at1700) != 0) {
printk("at1700: register_netdev() returned non-zero.\n");
return -EIO;
}
return 0; return 0;
} }
void void
cleanup_module(void) cleanup_module(void)
{ {
#ifdef CONFIG_MCA unregister_netdev(dev_at1700);
struct net_local *lp = dev_at1700.priv; cleanup_card(dev_at1700);
if(lp->mca_slot) free_netdev(dev_at1700);
{
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
} }
#endif /* MODULE */ #endif /* MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment