Commit 97da4b3b authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (07/12) Probe2 -- 3c505

from viro NE18-3c505
	* switched 3c505 to dynamic allocation
	* 3c505: embedded ->priv
	* 3c505: fixed use of uninitialized variable
	* 3c505: fixed resource leaks on failure exits
Additional:
	* add free_netdev
parent e3fcad0f
...@@ -1293,42 +1293,6 @@ static void elp_set_mc_list(struct net_device *dev) ...@@ -1293,42 +1293,6 @@ static void elp_set_mc_list(struct net_device *dev)
} }
} }
/******************************************************
*
* initialise Etherlink Plus board
*
******************************************************/
static inline void elp_init(struct net_device *dev)
{
elp_device *adapter = dev->priv;
/*
* set ptrs to various functions
*/
dev->open = elp_open; /* local */
dev->stop = elp_close; /* local */
dev->get_stats = elp_get_stats; /* local */
dev->hard_start_xmit = elp_start_xmit; /* local */
dev->tx_timeout = elp_timeout; /* local */
dev->watchdog_timeo = 10*HZ;
dev->set_multicast_list = elp_set_mc_list; /* local */
dev->ethtool_ops = &netdev_ethtool_ops; /* local */
/* Setup the generic properties */
ether_setup(dev);
/*
* setup ptr to adapter specific information
*/
memset(&(adapter->stats), 0, sizeof(struct net_device_stats));
/*
* memory information
*/
dev->mem_start = dev->mem_end = 0;
}
/************************************************************ /************************************************************
* *
* A couple of tests to see if there's 3C505 or not * A couple of tests to see if there's 3C505 or not
...@@ -1442,12 +1406,13 @@ static int __init elp_autodetect(struct net_device *dev) ...@@ -1442,12 +1406,13 @@ static int __init elp_autodetect(struct net_device *dev)
* work at all if it was in a weird state). * work at all if it was in a weird state).
*/ */
int __init elplus_probe(struct net_device *dev) static int __init elplus_setup(struct net_device *dev)
{ {
elp_device *adapter; elp_device *adapter = dev->priv;
int i, tries, tries1, okay; int i, tries, tries1, okay;
unsigned long timeout; unsigned long timeout;
unsigned long cookie = 0; unsigned long cookie = 0;
int err = -ENODEV;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
...@@ -1456,18 +1421,9 @@ int __init elplus_probe(struct net_device *dev) ...@@ -1456,18 +1421,9 @@ int __init elplus_probe(struct net_device *dev)
*/ */
dev->base_addr = elp_autodetect(dev); dev->base_addr = elp_autodetect(dev);
if (!(dev->base_addr)) if (!dev->base_addr)
return -ENODEV; return -ENODEV;
/*
* setup ptr to adapter specific information
*/
adapter = (elp_device *) (dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL));
if (adapter == NULL) {
printk(KERN_ERR "%s: out of memory\n", dev->name);
return -ENODEV;
}
adapter->send_pcb_semaphore = 0; adapter->send_pcb_semaphore = 0;
for (tries1 = 0; tries1 < 3; tries1++) { for (tries1 = 0; tries1 < 3; tries1++) {
...@@ -1544,8 +1500,7 @@ int __init elplus_probe(struct net_device *dev) ...@@ -1544,8 +1500,7 @@ int __init elplus_probe(struct net_device *dev)
outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev); outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);
} }
printk(KERN_ERR "%s: failed to initialise 3c505\n", dev->name); printk(KERN_ERR "%s: failed to initialise 3c505\n", dev->name);
release_region(dev->base_addr, ELP_IO_EXTENT); goto out;
return -ENODEV;
okay: okay:
if (dev->irq) { /* Is there a preset IRQ? */ if (dev->irq) { /* Is there a preset IRQ? */
...@@ -1560,14 +1515,14 @@ int __init elplus_probe(struct net_device *dev) ...@@ -1560,14 +1515,14 @@ int __init elplus_probe(struct net_device *dev)
case 0: case 0:
printk(KERN_ERR "%s: IRQ probe failed: check 3c505 jumpers.\n", printk(KERN_ERR "%s: IRQ probe failed: check 3c505 jumpers.\n",
dev->name); dev->name);
return -ENODEV; goto out;
case 1: case 1:
case 6: case 6:
case 8: case 8:
case 13: case 13:
printk(KERN_ERR "%s: Impossible IRQ %d reported by probe_irq_off().\n", printk(KERN_ERR "%s: Impossible IRQ %d reported by probe_irq_off().\n",
dev->name, dev->irq); dev->name, dev->irq);
return -ENODEV; goto out;
} }
/* /*
* Now we have the IRQ number so we can disable the interrupts from * Now we have the IRQ number so we can disable the interrupts from
...@@ -1636,16 +1591,48 @@ int __init elplus_probe(struct net_device *dev) ...@@ -1636,16 +1591,48 @@ int __init elplus_probe(struct net_device *dev)
printk(KERN_ERR "%s: adapter configuration failed\n", dev->name); printk(KERN_ERR "%s: adapter configuration failed\n", dev->name);
} }
/* dev->open = elp_open; /* local */
* initialise the device dev->stop = elp_close; /* local */
*/ dev->get_stats = elp_get_stats; /* local */
elp_init(dev); dev->hard_start_xmit = elp_start_xmit; /* local */
dev->tx_timeout = elp_timeout; /* local */
dev->watchdog_timeo = 10*HZ;
dev->set_multicast_list = elp_set_mc_list; /* local */
dev->ethtool_ops = &netdev_ethtool_ops; /* local */
memset(&(adapter->stats), 0, sizeof(struct net_device_stats));
dev->mem_start = dev->mem_end = 0;
err = register_netdev(dev);
if (err)
goto out;
return 0; return 0;
out:
release_region(dev->base_addr, ELP_IO_EXTENT);
return err;
}
struct net_device * __init elplus_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(elp_device));
int err;
if (!dev)
return ERR_PTR(-ENOMEM);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
err = elplus_setup(dev);
if (err) {
free_netdev(dev);
return ERR_PTR(err);
}
return dev;
} }
#ifdef MODULE #ifdef MODULE
static struct net_device dev_3c505[ELP_MAX_CARDS]; static struct net_device *dev_3c505[ELP_MAX_CARDS];
static int io[ELP_MAX_CARDS]; static int io[ELP_MAX_CARDS];
static int irq[ELP_MAX_CARDS]; static int irq[ELP_MAX_CARDS];
static int dma[ELP_MAX_CARDS]; static int dma[ELP_MAX_CARDS];
...@@ -1661,10 +1648,12 @@ int init_module(void) ...@@ -1661,10 +1648,12 @@ int init_module(void)
int this_dev, found = 0; int this_dev, found = 0;
for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) { for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_3c505[this_dev]; struct net_device *dev = alloc_etherdev(sizeof(elp_device));
if (!dev)
break;
dev->irq = irq[this_dev]; dev->irq = irq[this_dev];
dev->base_addr = io[this_dev]; dev->base_addr = io[this_dev];
dev->init = elplus_probe;
if (dma[this_dev]) { if (dma[this_dev]) {
dev->dma = dma[this_dev]; dev->dma = dma[this_dev];
} else { } else {
...@@ -1672,16 +1661,22 @@ int init_module(void) ...@@ -1672,16 +1661,22 @@ int init_module(void)
printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n"); printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n");
} }
if (io[this_dev] == 0) { if (io[this_dev] == 0) {
if (this_dev) break; if (this_dev) {
free_netdev(dev);
break;
}
printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n"); printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n");
} }
if (register_netdev(dev) != 0) { if (elplus_setup(dev) != 0) {
printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]); printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]);
if (found != 0) return 0; free_netdev(dev);
return -ENXIO; break;
} }
dev_3c505[this_dev] = dev;
found++; found++;
} }
if (!found)
return -ENODEV;
return 0; return 0;
} }
...@@ -1690,12 +1685,11 @@ void cleanup_module(void) ...@@ -1690,12 +1685,11 @@ void cleanup_module(void)
int this_dev; int this_dev;
for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) { for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_3c505[this_dev]; struct net_device *dev = dev_3c505[this_dev];
if (dev->priv != NULL) { if (dev) {
unregister_netdev(dev); unregister_netdev(dev);
kfree(dev->priv);
dev->priv = NULL;
release_region(dev->base_addr, ELP_IO_EXTENT); release_region(dev->base_addr, ELP_IO_EXTENT);
free_netdev(dev);
} }
} }
} }
......
...@@ -63,7 +63,7 @@ extern int arlan_probe(struct net_device *); ...@@ -63,7 +63,7 @@ extern int arlan_probe(struct net_device *);
extern int el16_probe(struct net_device *); extern int el16_probe(struct net_device *);
extern int elmc_probe(struct net_device *); extern int elmc_probe(struct net_device *);
extern int skmca_probe(struct net_device *); extern int skmca_probe(struct net_device *);
extern int elplus_probe(struct net_device *); extern struct net_device *elplus_probe(int unit);
extern int ac3200_probe(struct net_device *); extern int ac3200_probe(struct net_device *);
extern int es_probe(struct net_device *); extern int es_probe(struct net_device *);
extern int lne390_probe(struct net_device *); extern int lne390_probe(struct net_device *);
...@@ -273,14 +273,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -273,14 +273,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_EL16 /* 3c507 */ #ifdef CONFIG_EL16 /* 3c507 */
{el16_probe, 0}, {el16_probe, 0},
#endif
#ifdef CONFIG_ELPLUS /* 3c505 */
{elplus_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_ELPLUS /* 3c505 */
{elplus_probe, 0},
#endif
#ifdef CONFIG_SK_G16 #ifdef CONFIG_SK_G16
{SK_init, 0}, {SK_init, 0},
#endif #endif
......
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