[PATCH] (21/42) sk_mca

DORMANTno replies

From: Stephen Hemminger <hidden>
Date: 2003-11-13 00:43:48

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_ */
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help