Commit 09e497f1 authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (22/42) 3c527

NE46-3c527
	* switched 3c527 to dynamic allocation
	* 3c527: switched to embedded ->priv
	* 3c527: fixed resource leaks on failure exits
parent d3f25fbf
...@@ -208,8 +208,6 @@ static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); }; ...@@ -208,8 +208,6 @@ static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); };
/* Index to functions, as function prototypes. */ /* 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_probe1(struct net_device *dev, int ioaddr);
static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len); static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len);
static int mc32_open(struct net_device *dev); static int mc32_open(struct net_device *dev);
...@@ -222,9 +220,19 @@ static void mc32_set_multicast_list(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 void mc32_reset_multicast_list(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops; 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 * 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 * 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 * 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; ...@@ -232,11 +240,19 @@ static struct ethtool_ops netdev_ethtool_ops;
* in particular. * 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; static int current_mca_slot = -1;
int i; int i;
int adapter_found = 0; 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); SET_MODULE_OWNER(dev);
...@@ -257,12 +273,18 @@ int __init mc32_probe(struct net_device *dev) ...@@ -257,12 +273,18 @@ int __init mc32_probe(struct net_device *dev)
mca_set_adapter_name(current_mca_slot, mca_set_adapter_name(current_mca_slot,
mc32_adapters[i].name); mc32_adapters[i].name);
mca_mark_as_used(current_mca_slot); 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) ...@@ -282,7 +304,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
int i, err; int i, err;
u8 POS; u8 POS;
u32 base; u32 base;
struct mc32_local *lp; struct mc32_local *lp = dev->priv;
static u16 mca_io_bases[]={ static u16 mca_io_bases[]={
0x7280,0x7290, 0x7280,0x7290,
0x7680,0x7690, 0x7680,0x7690,
...@@ -409,24 +431,14 @@ static int __init mc32_probe1(struct net_device *dev, int slot) ...@@ -409,24 +431,14 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
* Grab the IRQ * Grab the IRQ
*/ */
i = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ, dev->name, dev); err = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ, dev->name, dev);
if (i) { if (err) {
release_region(dev->base_addr, MC32_IO_EXTENT); release_region(dev->base_addr, MC32_IO_EXTENT);
printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
return i; goto err_exit_ports;
} }
memset(lp, 0, sizeof(struct mc32_local));
/* 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;
lp->slot = slot; lp->slot = slot;
i=0; i=0;
...@@ -440,7 +452,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) ...@@ -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); printk(KERN_ERR "%s: failed to boot adapter.\n", dev->name);
err = -ENODEV; err = -ENODEV;
goto err_exit_free; goto err_exit_irq;
} }
udelay(1000); udelay(1000);
if(inb(dev->base_addr+2)&(1<<5)) if(inb(dev->base_addr+2)&(1<<5))
...@@ -455,7 +467,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) ...@@ -455,7 +467,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
else else
printk(KERN_ERR "%s: unknown failure %d.\n", dev->name, base); printk(KERN_ERR "%s: unknown failure %d.\n", dev->name, base);
err = -ENODEV; err = -ENODEV;
goto err_exit_free; goto err_exit_irq;
} }
base=0; base=0;
...@@ -471,7 +483,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot) ...@@ -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); printk(KERN_ERR "%s: mailbox read fail (%d).\n", dev->name, i);
err = -ENODEV; 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) ...@@ -516,15 +528,11 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
lp->tx_ring_tail=lp->tx_ring_head=0; 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; return 0;
err_exit_free:
kfree(dev->priv);
err_exit_irq: err_exit_irq:
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
err_exit_ports:
release_region(dev->base_addr, MC32_IO_EXTENT); release_region(dev->base_addr, MC32_IO_EXTENT);
return err; return err;
} }
...@@ -1684,7 +1692,7 @@ static struct ethtool_ops netdev_ethtool_ops = { ...@@ -1684,7 +1692,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
#ifdef MODULE #ifdef MODULE
static struct net_device this_device; static struct net_device *this_device;
/** /**
* init_module - entry point * init_module - entry point
...@@ -1696,12 +1704,9 @@ static struct net_device this_device; ...@@ -1696,12 +1704,9 @@ static struct net_device this_device;
int init_module(void) int init_module(void)
{ {
int result; this_device = mc32_probe(-1);
if (IS_ERR(this_device))
this_device.init = mc32_probe; return PTR_ERR(this_device);
if ((result = register_netdev(&this_device)) != 0)
return result;
return 0; return 0;
} }
...@@ -1718,24 +1723,9 @@ int init_module(void) ...@@ -1718,24 +1723,9 @@ int init_module(void)
void cleanup_module(void) void cleanup_module(void)
{ {
int slot; unregister_netdev(this_device);
cleanup_card(this_device);
unregister_netdev(&this_device); free_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);
} }
#endif /* MODULE */ #endif /* MODULE */
...@@ -90,7 +90,7 @@ extern int mace_probe(struct net_device *dev); ...@@ -90,7 +90,7 @@ extern int mace_probe(struct net_device *dev);
extern int macsonic_probe(struct net_device *dev); extern int macsonic_probe(struct net_device *dev);
extern int mac8390_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev);
extern int mac89x0_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 *cops_probe(int unit);
extern struct net_device *ltpc_probe(void); extern struct net_device *ltpc_probe(void);
...@@ -183,14 +183,14 @@ static struct devprobe mca_probes[] __initdata = { ...@@ -183,14 +183,14 @@ static struct devprobe mca_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_ELMC /* 3c523 */ #ifdef CONFIG_ELMC /* 3c523 */
{elmc_probe, 0}, {elmc_probe, 0},
#endif
#ifdef CONFIG_ELMC_II /* 3c527 */
{mc32_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 mca_probes2[] __initdata = { static struct devprobe2 mca_probes2[] __initdata = {
#ifdef CONFIG_ELMC_II /* 3c527 */
{mc32_probe, 0},
#endif
#ifdef CONFIG_SKMC /* SKnet Microchannel */ #ifdef CONFIG_SKMC /* SKnet Microchannel */
{skmca_probe, 0}, {skmca_probe, 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