[PATCH] (23/42) 3c523
DORMANTno replies
From: Stephen Hemminger <hidden>
Date: 2003-11-13 00:44:08
NE47-3c523 from viro * switched 3c523 to dynamic allocation * 3c523: switched to embedded ->priv * 3c523: fixed order of freeing bugs * 3c523: fixed resource leaks on failure exits diff -Nru a/drivers/net/3c523.c b/drivers/net/3c523.c
--- a/drivers/net/3c523.c Tue Nov 11 13:50:42 2003
+++ b/drivers/net/3c523.c Tue Nov 11 13:50:42 2003@@ -410,7 +410,7 @@ /*****************************************************************/ -int __init elmc_probe(struct net_device *dev) +static int __init do_elmc_probe(struct net_device *dev) { static int slot; int base_addr = dev->base_addr;
@@ -420,7 +420,7 @@ int i = 0; unsigned int size = 0; int retval; - struct priv *pr; + struct priv *pr = dev->priv; SET_MODULE_OWNER(dev); if (MCA_bus == 0) {
@@ -455,10 +455,9 @@ } /* we didn't find any 3c523 in the slots we checked for */ - if (slot == MCA_NOTFOUND) { - retval = ((base_addr || irq) ? -ENXIO : -ENODEV); - goto err_out; - } + if (slot == MCA_NOTFOUND) + return ((base_addr || irq) ? -ENXIO : -ENODEV); + mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC"); mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
@@ -497,13 +496,7 @@ break; } - pr = dev->priv = kmalloc(sizeof(struct priv), GFP_KERNEL); - if (dev->priv == NULL) { - retval = -ENOMEM; - goto err_out; - } memset(pr, 0, sizeof(struct priv)); - pr->slot = slot; printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
@@ -530,8 +523,6 @@ if (!check586(dev, dev->mem_start, size)) { printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, dev->mem_start); - kfree(dev->priv); - dev->priv = NULL; retval = -ENODEV; goto err_out; }
@@ -573,8 +564,6 @@ #endif dev->ethtool_ops = &netdev_ethtool_ops; - ether_setup(dev); - /* note that we haven't actually requested the IRQ from the kernel. That gets done in elmc_open(). I'm not sure that's such a good idea, but it works, so I'll go with it. */
@@ -585,9 +574,41 @@ return 0; err_out: + mca_set_adapter_procfn(slot, NULL, NULL); release_region(dev->base_addr, ELMC_IO_EXTENT); return retval; } + +static void cleanup_card(struct net_device *dev) +{ + mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, NULL, NULL); + release_region(dev->base_addr, ELMC_IO_EXTENT); +} + +struct net_device * __init elmc_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(sizeof(struct priv)); + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + err = do_elmc_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); +} /********************************************** * init the chip (elmc-interrupt should be disabled?!)
@@ -1245,7 +1266,7 @@ /* Increase if needed ;) */ #define MAX_3C523_CARDS 4 -static struct net_device dev_elmc[MAX_3C523_CARDS]; +static struct net_device *dev_elmc[MAX_3C523_CARDS]; static int irq[MAX_3C523_CARDS]; static int io[MAX_3C523_CARDS]; MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i");
@@ -1258,16 +1279,24 @@ int this_dev,found = 0; /* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */ - for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) - { - struct net_device *dev = &dev_elmc[this_dev]; + for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) { + struct net_device *dev = alloc_etherdev(sizeof(struct priv)); + if (!dev) + break; dev->irq=irq[this_dev]; dev->base_addr=io[this_dev]; - dev->init=elmc_probe; - if(register_netdev(dev)!=0) { - if(io[this_dev]==0) break; - printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); - } else found++; + if (do_elmc_probe(dev) == 0) { + if (register_netdev(dev) == 0) { + dev_elmc[this_dev] = dev; + found++; + continue; + } + cleanup_card(dev); + } + free_netdev(dev); + if (io[this_dev]==0) + break; + printk(KERN_WARNING "3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); } if(found==0) {
@@ -1279,31 +1308,12 @@ void cleanup_module(void) { int this_dev; - for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) { - - struct net_device *dev = &dev_elmc[this_dev]; - if(dev->priv) { - /* shutdown interrupts on the card */ - elmc_id_reset586(); - if (dev->irq != 0) { - /* this should be done by close, but if we failed to - initialize properly something may have gotten hosed. */ - free_irq(dev->irq, dev); - dev->irq = 0; - } - if (dev->base_addr != 0) { - release_region(dev->base_addr, ELMC_IO_EXTENT); - dev->base_addr = 0; - } - irq[this_dev] = 0; - io[this_dev] = 0; + for (this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) { + struct net_device *dev = dev_elmc[this_dev]; + if (dev) { unregister_netdev(dev); - - mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, - NULL, NULL); - - kfree(dev->priv); - dev->priv = NULL; + cleanup_card(dev); + free_netdev(dev); } } }
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c Tue Nov 11 13:50:42 2003
+++ b/drivers/net/Space.c Tue Nov 11 13:50:42 2003@@ -60,7 +60,7 @@ extern struct net_device *wavelan_probe(int unit); extern struct net_device *arlan_probe(int unit); extern struct net_device *el16_probe(int unit); -extern int elmc_probe(struct net_device *); +extern struct net_device *elmc_probe(int unit); extern struct net_device *skmca_probe(int unit); extern struct net_device *elplus_probe(int unit); extern int ac3200_probe(struct net_device *);
@@ -181,13 +181,13 @@ #ifdef CONFIG_NE2_MCA {ne2_probe, 0}, #endif -#ifdef CONFIG_ELMC /* 3c523 */ - {elmc_probe, 0}, -#endif {NULL, 0}, }; static struct devprobe2 mca_probes2[] __initdata = { +#ifdef CONFIG_ELMC /* 3c523 */ + {elmc_probe, 0}, +#endif #ifdef CONFIG_ELMC_II /* 3c527 */ {mc32_probe, 0}, #endif