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); };
/* 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 */
......@@ -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
......
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