Commit 4e8a1fcb authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (12/42) ne

Based on NE36-ne
	* switched ne/ne2k_cbus to dynamic allocation
	* ne/ne2k_cbus: fixed order of freeing bugs
	* ne/ne2k_cbus: fixed resource leaks on failure exits
	* ne/ne2k_cbus: fixed clobbering on autoprobe
parent b513c765
......@@ -46,7 +46,7 @@ extern int ultra_probe(struct net_device *dev);
extern int ultra32_probe(struct net_device *dev);
extern int wd_probe(struct net_device *dev);
extern int el2_probe(struct net_device *dev);
extern int ne_probe(struct net_device *dev);
extern struct net_device *ne_probe(int unit);
extern int hp_probe(struct net_device *dev);
extern int hp_plus_probe(struct net_device *dev);
extern struct net_device *express_probe(int unit);
......@@ -221,14 +221,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif
#ifdef CONFIG_E2100 /* Cabletron E21xx series. */
{e2100_probe, 0},
#endif
#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
{ne_probe, 0},
#endif
{NULL, 0},
};
static struct devprobe2 isa_probes2[] __initdata = {
#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */
{ne_probe, 0},
#endif
#ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */
{lance_probe, 0},
#endif
......
......@@ -126,7 +126,6 @@ bad_clone_list[] __initdata = {
#define NESM_START_PG 0x40 /* First page of TX buffer */
#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
int ne_probe(struct net_device *dev);
static int ne_probe1(struct net_device *dev, int ioaddr);
static int ne_probe_isapnp(struct net_device *dev);
......@@ -163,9 +162,10 @@ static void ne_block_output(struct net_device *dev, const int count,
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */
int __init ne_probe(struct net_device *dev)
static int __init do_ne_probe(struct net_device *dev)
{
unsigned int base_addr = dev->base_addr;
int irq = dev->irq;
SET_MODULE_OWNER(dev);
......@@ -183,6 +183,7 @@ int __init ne_probe(struct net_device *dev)
/* Last resort. The semi-risky ISA auto-probe. */
for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
int ioaddr = netcard_portlist[base_addr];
dev->irq = irq;
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
......@@ -191,6 +192,44 @@ int __init ne_probe(struct net_device *dev)
return -ENODEV;
}
static void cleanup_card(struct net_device *dev)
{
void *priv = dev->priv;
struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
if (idev)
pnp_device_detach(idev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, NE_IO_EXTENT);
kfree(priv);
}
struct net_device * __init ne_probe(int unit)
{
struct net_device *dev = alloc_etherdev(0);
int err;
if (!dev)
return ERR_PTR(-ENOMEM);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
dev->priv = NULL; /* until all 8390-based use alloc_etherdev() */
err = do_ne_probe(dev);
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);
}
static int __init ne_probe_isapnp(struct net_device *dev)
{
int i;
......@@ -734,7 +773,7 @@ static void ne_block_output(struct net_device *dev, int count,
#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
static struct net_device dev_ne[MAX_NE_CARDS];
static struct net_device *dev_ne[MAX_NE_CARDS];
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
......@@ -758,25 +797,32 @@ int init_module(void)
int this_dev, found = 0;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
struct net_device *dev = alloc_etherdev(0);
if (!dev)
break;
dev->priv = NULL;
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
dev->init = ne_probe;
if (do_ne_probe(dev) == 0) {
if (register_netdev(dev) == 0) {
found++;
dev_ne[found++] = dev;
continue;
}
if (found != 0) { /* Got at least one. */
return 0;
cleanup_card(dev);
}
free_netdev(dev);
if (found)
break;
if (io[this_dev] != 0)
printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
else
printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
return -ENXIO;
}
if (found)
return 0;
return -ENODEV;
}
void cleanup_module(void)
......@@ -784,16 +830,11 @@ void cleanup_module(void)
int this_dev;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
if (dev->priv != NULL) {
void *priv = dev->priv;
struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
if (idev)
pnp_device_detach(idev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, NE_IO_EXTENT);
struct net_device *dev = dev_ne[this_dev];
if (dev) {
unregister_netdev(dev);
kfree(priv);
cleanup_card(dev);
free_netdev(dev);
}
}
}
......
......@@ -78,7 +78,6 @@ bad_clone_list[] __initdata = {
#include "ne2k_cbus.h"
int ne_probe(struct net_device *dev);
static int ne_probe1(struct net_device *dev, int ioaddr);
static int ne_open(struct net_device *dev);
static int ne_close(struct net_device *dev);
......@@ -113,9 +112,10 @@ static void ne_block_output(struct net_device *dev, const int count,
E2010 starts at 0x100 and ends at 0x4000.
E2010-x starts at 0x100 and ends at 0xffff. */
int __init ne_probe(struct net_device *dev)
static int __init do_ne_probe(struct net_device *dev)
{
unsigned int base_addr = dev->base_addr;
int irq = dev->irq;
SET_MODULE_OWNER(dev);
......@@ -135,7 +135,7 @@ int __init ne_probe(struct net_device *dev)
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr);
result = ne_probe_cbus(dev, hw, base_addr);
result = ne_probe_cbus(dev, hw, base_addr, irq);
if (result != 0)
ne2k_cbus_destroy(dev);
......@@ -156,13 +156,13 @@ int __init ne_probe(struct net_device *dev)
if (hw && hw->hwtype) {
const unsigned short *plist;
for (plist = hw->portlist; *plist; plist++)
if (ne_probe_cbus(dev, hw, *plist) == 0)
if (ne_probe_cbus(dev, hw, *plist, irq) == 0)
return 0;
} else {
for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
const unsigned short *plist;
for (plist = hw->portlist; *plist; plist++)
if (ne_probe_cbus(dev, hw, *plist) == 0)
if (ne_probe_cbus(dev, hw, *plist, irq) == 0)
return 0;
}
}
......@@ -174,7 +174,47 @@ int __init ne_probe(struct net_device *dev)
return -ENODEV;
}
static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr)
static void cleanup_card(struct net_device *dev)
{
const struct ne2k_cbus_region *rlist;
const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
free_irq(dev->irq, dev);
for (rlist = hw->regionlist; rlist->range; rlist++) {
release_region(dev->base_addr + rlist->start,
rlist->range);
}
ne2k_cbus_destroy(dev);
}
struct net_device * __init ne_probe(int unit)
{
struct net_device *dev = alloc_etherdev(0);
int err;
if (!dev)
return ERR_PTR(-ENOMEM);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
dev->priv = NULL; /* until all 8390-based use alloc_etherdev() */
err = do_ne_probe(dev);
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);
}
static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq)
{
if (ei_debug > 2)
printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n",
......@@ -182,6 +222,7 @@ static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_h
if (hw && hw->hwtype) {
ne2k_cbus_set_hwtype(dev, hw, ioaddr);
dev->irq = irq;
return ne_probe1(dev, ioaddr);
} else {
/* auto detect */
......@@ -189,6 +230,7 @@ static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_h
printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n");
for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) {
ne2k_cbus_set_hwtype(dev, hw, ioaddr);
dev->irq = irq;
if (ne_probe1(dev, ioaddr) == 0)
return 0;
}
......@@ -301,11 +343,12 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
if (ei_debug > 2)
printk(" [CNET98EL-specific initialize...");
outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); /* 0x20|0x1 */
ret = -ENODEV;
i = inb(ioaddr);
if ((i & ~0x2) != (0x20 | 0x01))
return -ENODEV;
goto err_out;
if ((inb(ioaddr + 0x7) & 0x80) != 0x80)
return -ENODEV;
goto err_out;
outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* out(ioaddr+0xc, 0x20) */
/* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */
outb_p(ENDCFG_WTS | 0x48, ioaddr + EN0_DCFG); /* 0x49 */
......@@ -330,7 +373,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
if (ei_debug > 2)
printk("] ");
printk("memory failure at %x\n", i);
return -ENODEV;
goto err_out;
}
if (ei_debug > 2)
printk(" good...");
......@@ -338,7 +381,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
if (ei_debug > 2)
printk("] ");
printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n");
return -ENODEV;
goto err_out;
}
outb((dev->irq > 5) ? (dev->irq & 4):(dev->irq >> 1), ioaddr + (0x2 | 0x400));
outb(0x7e, ioaddr + (0x4 | 0x400));
......@@ -779,7 +822,7 @@ static void ne_block_output(struct net_device *dev, int count,
#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
static struct net_device dev_ne[MAX_NE_CARDS];
static struct net_device *dev_ne[MAX_NE_CARDS];
static int io[MAX_NE_CARDS];
static int irq[MAX_NE_CARDS];
static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */
......@@ -806,26 +849,33 @@ int init_module(void)
int this_dev, found = 0;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
struct net_device *dev = alloc_etherdev(0);
if (!dev)
break;
dev->priv = NULL;
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = hwtype[this_dev];
dev->init = ne_probe;
if (do_ne_probe(dev) == 0) {
if (register_netdev(dev) == 0) {
found++;
dev_ne[found++] = dev;
continue;
}
if (found != 0) { /* Got at least one. */
return 0;
cleanup_card(dev);
}
free_netdev(dev);
if (found)
break;
if (io[this_dev] != 0)
printk(KERN_WARNING "ne2k_cbus: No NE*000 card found at i/o = %#x\n", io[this_dev]);
else
printk(KERN_NOTICE "ne2k_cbus: You must supply \"io=0xNNN\" value(s) for C-Bus cards.\n");
printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
return -ENXIO;
}
if (found)
return 0;
return -ENODEV;
}
void cleanup_module(void)
......@@ -833,18 +883,11 @@ void cleanup_module(void)
int this_dev;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
if (dev->priv != NULL) {
const struct ne2k_cbus_region *rlist;
const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK));
free_irq(dev->irq, dev);
for (rlist = hw->regionlist; rlist->range; rlist++) {
release_region(dev->base_addr + rlist->start,
rlist->range);
}
struct net_device *dev = dev_ne[this_dev];
if (dev) {
unregister_netdev(dev);
ne2k_cbus_destroy(dev);
cleanup_card(dev);
free_netdev(dev);
}
}
}
......
......@@ -477,5 +477,5 @@ static void __init ne2k_cbus_writemem(struct net_device *dev, int ioaddr, unsign
}
#endif
static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr);
static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr, int irq);
/* End of ne2k_cbus.h */
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