From 09e497f176bf3622f80e3be5c5108be761c0c93f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 10 Jan 2004 05:06:43 -0500 Subject: [PATCH] [PATCH] (22/42) 3c527 NE46-3c527 * switched 3c527 to dynamic allocation * 3c527: switched to embedded ->priv * 3c527: fixed resource leaks on failure exits --- drivers/net/3c527.c | 98 ++++++++++++++++++++------------------------- drivers/net/Space.c | 8 ++-- 2 files changed, 48 insertions(+), 58 deletions(-) diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index b12030a33d52f..cc8951c839210 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -208,8 +208,6 @@ static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); }; /* Index to functions, as function prototypes. */ -extern int mc32_probe(struct net_device *dev); - static int mc32_probe1(struct net_device *dev, int ioaddr); static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len); static int mc32_open(struct net_device *dev); @@ -222,9 +220,19 @@ static void mc32_set_multicast_list(struct net_device *dev); static void mc32_reset_multicast_list(struct net_device *dev); static struct ethtool_ops netdev_ethtool_ops; +static void cleanup_card(struct net_device *dev) +{ + struct mc32_local *lp=dev->priv; + unsigned slot = lp->slot; + mca_mark_as_unused(slot); + mca_set_adapter_name(slot, NULL); + free_irq(dev->irq, dev); + release_region(dev->base_addr, MC32_IO_EXTENT); +} + /** * mc32_probe - Search for supported boards - * @dev: device to probe + * @unit: interface number to use * * Because MCA bus is a real bus and we can scan for cards we could do a * single scan for all boards here. Right now we use the passed in device @@ -232,11 +240,19 @@ static struct ethtool_ops netdev_ethtool_ops; * in particular. */ -int __init mc32_probe(struct net_device *dev) +struct net_device *__init mc32_probe(int unit) { + struct net_device *dev = alloc_etherdev(sizeof(struct mc32_local)); static int current_mca_slot = -1; int i; int adapter_found = 0; + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) + sprintf(dev->name, "eth%d", unit); SET_MODULE_OWNER(dev); @@ -257,12 +273,18 @@ int __init mc32_probe(struct net_device *dev) mca_set_adapter_name(current_mca_slot, mc32_adapters[i].name); mca_mark_as_used(current_mca_slot); - return 0; + err = register_netdev(dev); + if (err) { + cleanup_card(dev); + free_netdev(dev); + dev = ERR_PTR(err); + } + return dev; } } } - return -ENODEV; + return ERR_PTR(-ENODEV); } /** @@ -282,7 +304,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) int i, err; u8 POS; u32 base; - struct mc32_local *lp; + struct mc32_local *lp = dev->priv; static u16 mca_io_bases[]={ 0x7280,0x7290, 0x7680,0x7690, @@ -409,24 +431,14 @@ static int __init mc32_probe1(struct net_device *dev, int slot) * Grab the IRQ */ - i = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ, dev->name, dev); - if (i) { + err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ, dev->name, dev); + if (err) { release_region(dev->base_addr, MC32_IO_EXTENT); printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return i; + goto err_exit_ports; } - - /* Initialize the device structure. */ - dev->priv = kmalloc(sizeof(struct mc32_local), GFP_KERNEL); - if (dev->priv == NULL) - { - err = -ENOMEM; - goto err_exit_irq; - } - - memset(dev->priv, 0, sizeof(struct mc32_local)); - lp = dev->priv; + memset(lp, 0, sizeof(struct mc32_local)); lp->slot = slot; i=0; @@ -440,7 +452,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) { printk(KERN_ERR "%s: failed to boot adapter.\n", dev->name); err = -ENODEV; - goto err_exit_free; + goto err_exit_irq; } udelay(1000); if(inb(dev->base_addr+2)&(1<<5)) @@ -455,7 +467,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) else printk(KERN_ERR "%s: unknown failure %d.\n", dev->name, base); err = -ENODEV; - goto err_exit_free; + goto err_exit_irq; } base=0; @@ -471,7 +483,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) { printk(KERN_ERR "%s: mailbox read fail (%d).\n", dev->name, i); err = -ENODEV; - goto err_exit_free; + goto err_exit_irq; } } @@ -516,15 +528,11 @@ static int __init mc32_probe1(struct net_device *dev, int slot) lp->tx_ring_tail=lp->tx_ring_head=0; - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - return 0; -err_exit_free: - kfree(dev->priv); err_exit_irq: free_irq(dev->irq, dev); +err_exit_ports: release_region(dev->base_addr, MC32_IO_EXTENT); return err; } @@ -1684,7 +1692,7 @@ static struct ethtool_ops netdev_ethtool_ops = { #ifdef MODULE -static struct net_device this_device; +static struct net_device *this_device; /** * init_module - entry point @@ -1696,12 +1704,9 @@ static struct net_device this_device; int init_module(void) { - int result; - - this_device.init = mc32_probe; - if ((result = register_netdev(&this_device)) != 0) - return result; - + this_device = mc32_probe(-1); + if (IS_ERR(this_device)) + return PTR_ERR(this_device); return 0; } @@ -1718,24 +1723,9 @@ int init_module(void) void cleanup_module(void) { - int slot; - - unregister_netdev(&this_device); - - /* - * If we don't do this, we can't re-insmod it later. - */ - - if (this_device.priv) - { - struct mc32_local *lp=this_device.priv; - slot = lp->slot; - mca_mark_as_unused(slot); - mca_set_adapter_name(slot, NULL); - kfree(this_device.priv); - } - free_irq(this_device.irq, &this_device); - release_region(this_device.base_addr, MC32_IO_EXTENT); + unregister_netdev(this_device); + cleanup_card(this_device); + free_netdev(this_device); } #endif /* MODULE */ diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 23920c0b28e80..a03d02a5b6c23 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -90,7 +90,7 @@ extern int mace_probe(struct net_device *dev); extern int macsonic_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); -extern int mc32_probe(struct net_device *dev); +extern struct net_device *mc32_probe(int unit); extern struct net_device *cops_probe(int unit); extern struct net_device *ltpc_probe(void); @@ -183,14 +183,14 @@ static struct devprobe mca_probes[] __initdata = { #endif #ifdef CONFIG_ELMC /* 3c523 */ {elmc_probe, 0}, -#endif -#ifdef CONFIG_ELMC_II /* 3c527 */ - {mc32_probe, 0}, #endif {NULL, 0}, }; static struct devprobe2 mca_probes2[] __initdata = { +#ifdef CONFIG_ELMC_II /* 3c527 */ + {mc32_probe, 0}, +#endif #ifdef CONFIG_SKMC /* SKnet Microchannel */ {skmca_probe, 0}, #endif -- 2.53.0