Commit d3f25fbf authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (21/42) sk_mca

NE45-sk_mca
	* switched sk-mca to dynamic allocation
	* sk-mca: switched to embedded ->priv
	* sk-mca: fixed order of freeing bugs
	* sk-mca: fixed resource leaks on failure exits
parent 1d07e29e
......@@ -61,7 +61,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 int skmca_probe(struct net_device *);
extern struct net_device *skmca_probe(int unit);
extern struct net_device *elplus_probe(int unit);
extern int ac3200_probe(struct net_device *);
extern int es_probe(struct net_device *);
......@@ -187,6 +187,10 @@ static struct devprobe mca_probes[] __initdata = {
#ifdef CONFIG_ELMC_II /* 3c527 */
{mc32_probe, 0},
#endif
{NULL, 0},
};
static struct devprobe2 mca_probes2[] __initdata = {
#ifdef CONFIG_SKMC /* SKnet Microchannel */
{skmca_probe, 0},
#endif
......@@ -394,6 +398,7 @@ static void __init ethif_probe2(int unit)
if (base_addr == 1)
return;
probe_list2(unit, mca_probes2, base_addr == 0) &&
probe_list2(unit, isa_probes2, base_addr == 0) &&
probe_list2(unit, parport_probes, base_addr == 0);
}
......
......@@ -1022,18 +1022,39 @@ static void skmca_set_multicast_list(struct net_device *dev)
static int startslot; /* counts through slots when probing multiple devices */
int __init skmca_probe(struct net_device *dev)
static void cleanup_card(struct net_device *dev)
{
skmca_priv *priv = dev->priv;
DeinitBoard(dev);
if (dev->irq != 0)
free_irq(dev->irq, dev);
mca_mark_as_unused(priv->slot);
mca_set_adapter_procfn(priv->slot, NULL, NULL);
}
struct net_device * __init skmca_probe(int unit)
{
struct net_device *dev;
int force_detect = 0;
int junior, slot, i;
int base = 0, irq = 0;
skmca_priv *priv;
skmca_medium medium;
int err;
/* can't work without an MCA bus ;-) */
if (MCA_bus == 0)
return -ENODEV;
return ERR_PTR(-ENODEV);
dev = alloc_etherdev(sizeof(skmca_priv));
if (!dev)
return ERR_PTR(-ENOMEM);
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
}
SET_MODULE_OWNER(dev);
......@@ -1044,37 +1065,24 @@ int __init skmca_probe(struct net_device *dev)
/* search through slots */
if (dev != NULL) {
base = dev->mem_start;
irq = dev->irq;
}
slot = dofind(&junior, startslot);
while (slot != -1) {
base = dev->mem_start;
irq = dev->base_addr;
for (slot = startslot; (slot = dofind(&junior, slot)) != -1; slot++) {
/* deduce card addresses */
getaddrs(slot, junior, &base, &irq, &medium);
/* slot already in use ? */
if (mca_is_adapter_used(slot)) {
slot = dofind(&junior, slot + 1);
if (mca_is_adapter_used(slot))
continue;
}
/* were we looking for something different ? */
if ((dev->irq != 0) || (dev->mem_start != 0)) {
if ((dev->irq != 0) && (dev->irq != irq)) {
slot = dofind(&junior, slot + 1);
continue;
}
if ((dev->mem_start != 0)
&& (dev->mem_start != base)) {
slot = dofind(&junior, slot + 1);
continue;
}
}
if (dev->irq && dev->irq != irq)
continue;
if (dev->mem_start && dev->mem_start != base)
continue;
/* found something that matches */
......@@ -1083,8 +1091,10 @@ int __init skmca_probe(struct net_device *dev)
/* nothing found ? */
if (slot == -1)
return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV;
if (slot == -1) {
free_netdev(dev);
return (base || irq) ? ERR_PTR(-ENXIO) : ERR_PTR(-ENODEV);
}
/* make procfs entries */
......@@ -1102,17 +1112,14 @@ int __init skmca_probe(struct net_device *dev)
junior ? "Junior MC2" : "MC2+", slot + 1);
/* allocate structure */
priv = dev->priv =
(skmca_priv *) kmalloc(sizeof(skmca_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv = dev->priv;
priv->slot = slot;
priv->macbase = base + 0x3fc0;
priv->ioregaddr = base + 0x3ff0;
priv->ctrladdr = base + 0x3ff2;
priv->cmdaddr = base + 0x3ff3;
priv->medium = medium;
memset(&(priv->stat), 0, sizeof(struct net_device_stats));
memset(&priv->stat, 0, sizeof(struct net_device_stats));
spin_lock_init(&priv->lock);
/* set base + irq for this device (irq not allocated so far) */
......@@ -1146,9 +1153,6 @@ int __init skmca_probe(struct net_device *dev)
dev->set_multicast_list = skmca_set_multicast_list;
dev->flags |= IFF_MULTICAST;
/* generic setup */
ether_setup(dev);
/* copy out MAC address */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = SKMCA_READB(priv->macbase + (i << 1));
......@@ -1167,7 +1171,13 @@ int __init skmca_probe(struct net_device *dev)
startslot = slot + 1;
return 0;
err = register_netdev(dev);
if (err) {
cleanup_card(dev);
free_netdev(dev);
dev = ERR_PTR(err);
}
return dev;
}
/* ------------------------------------------------------------------------
......@@ -1179,51 +1189,34 @@ MODULE_LICENSE("GPL");
#define DEVMAX 5
static struct net_device moddevs[DEVMAX] = {
{ .name = " ", .init = skmca_probe },
{ .name = " ", .init = skmca_probe },
{ .name = " ", .init = skmca_probe },
{ .name = " ", .init = skmca_probe },
{ .name = " ", .init = skmca_probe }
};
int irq;
int io;
static struct net_device *moddevs[DEVMAX];
int init_module(void)
{
int z, res;
int z;
startslot = 0;
for (z = 0; z < DEVMAX; z++) {
strcpy(moddevs[z].name, " ");
res = register_netdev(moddevs + z);
if (res != 0)
return (z > 0) ? 0 : -EIO;
struct net_device *dev = skmca_probe(-1);
if (IS_ERR(dev))
break;
moddevs[z] = dev;
}
if (!z)
return -EIO;
return 0;
}
void cleanup_module(void)
{
struct net_device *dev;
skmca_priv *priv;
int z;
for (z = 0; z < DEVMAX; z++) {
dev = moddevs + z;
if (dev->priv != NULL) {
priv = (skmca_priv *) dev->priv;
DeinitBoard(dev);
if (dev->irq != 0)
free_irq(dev->irq, dev);
dev->irq = 0;
struct net_device *dev = moddevs[z];
if (dev) {
unregister_netdev(dev);
mca_mark_as_unused(priv->slot);
mca_set_adapter_procfn(priv->slot, NULL, NULL);
kfree(dev->priv);
dev->priv = NULL;
cleanup_card(dev);
free_netdev(dev);
}
}
}
......
......@@ -178,7 +178,4 @@ typedef struct { /* LANCE Rx descriptor */
#endif /* _SK_MCA_DRIVER_ */
extern int skmca_probe(struct net_device *);
#endif /* _SK_MCA_INCLUDE_ */
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