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
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c Tue Nov 11 13:50:15 2003
+++ b/drivers/net/Space.c Tue Nov 11 13:50:15 2003
@@ -61,7 +61,7 @@
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 @@
#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 @@
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);
}
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c Tue Nov 11 13:50:15 2003
+++ b/drivers/net/sk_mca.c Tue Nov 11 13:50:15 2003
@@ -1022,18 +1022,39 @@
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 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
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 @@
#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);
}
}
}
diff -Nru a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h
--- a/drivers/net/sk_mca.h Tue Nov 11 13:50:15 2003
+++ b/drivers/net/sk_mca.h Tue Nov 11 13:50:15 2003
@@ -178,7 +178,4 @@
#endif /* _SK_MCA_DRIVER_ */
-extern int skmca_probe(struct net_device *);
-
-
#endif /* _SK_MCA_INCLUDE_ */
|