[PATCH] (7/42) cs89x0

DORMANTno replies

From: Stephen Hemminger <hidden>
Date: 2003-11-13 00:41:28

Based on viro NE31-cs89x0
	* switched cs89x0 to dynamic allocation
	* cs89x0: embedded ->priv
	* cs89x0: fixed resource leaks on failure exits
	* cs89x0: fixed clobbering on autoprobe
	* NB: cs89x0 calls request_region() with very odd arguments.  Somebody
	  ought to check WTF is going on there.

diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	Tue Nov 11 09:35:40 2003
+++ b/drivers/net/Space.c	Tue Nov 11 09:35:40 2003
@@ -81,7 +81,7 @@
 extern int apne_probe(struct net_device *);
 extern int bionet_probe(struct net_device *);
 extern int pamsnet_probe(struct net_device *);
-extern int cs89x0_probe(struct net_device *dev);
+extern struct net_device *cs89x0_probe(int unit);
 extern int hplance_probe(struct net_device *dev);
 extern int bagetlance_probe(struct net_device *);
 extern int mvme147lance_probe(struct net_device *dev);
@@ -238,13 +238,13 @@
 #ifdef CONFIG_AT1500
 	{at1500_probe, 0},
 #endif
-#ifdef CONFIG_CS89x0
- 	{cs89x0_probe, 0},
-#endif
 	{NULL, 0},
 };
 
 static struct devprobe2 isa_probes2[] __initdata = {
+#ifdef CONFIG_CS89x0
+ 	{cs89x0_probe, 0},
+#endif
 #ifdef CONFIG_AT1700
 	{at1700_probe, 0},
 #endif
diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
--- a/drivers/net/cs89x0.c	Tue Nov 11 09:35:40 2003
+++ b/drivers/net/cs89x0.c	Tue Nov 11 09:35:40 2003
@@ -212,9 +212,7 @@
 
 /* Index to functions, as function prototypes. */
 
-extern int cs89x0_probe(struct net_device *dev);
-
-static int cs89x0_probe1(struct net_device *dev, int ioaddr);
+static int cs89x0_probe1(struct net_device *dev, int ioaddr, int modular);
 static int net_open(struct net_device *dev);
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -274,27 +272,51 @@
    Return 0 on success.
    */
 
-int __init cs89x0_probe(struct net_device *dev)
+struct net_device * __init cs89x0_probe(int unit)
 {
-	int i;
-	int base_addr = dev ? dev->base_addr : 0;
-
-	SET_MODULE_OWNER(dev);
+	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+	unsigned *port;
+	int err = 0;
+	int irq;
+	int io;
+
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	sprintf(dev->name, "eth%d", unit);
+	netdev_boot_setup_check(dev);
+	io = dev->base_addr;
+	irq = dev->irq;
 
 	if (net_debug)
-		printk("cs89x0:cs89x0_probe(0x%x)\n", base_addr);
+		printk("cs89x0:cs89x0_probe(0x%x)\n", io);
 
-	if (base_addr > 0x1ff)		/* Check a single specified location. */
-		return cs89x0_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	for (i = 0; netcard_portlist[i]; i++) {
-		if (cs89x0_probe1(dev, netcard_portlist[i]) == 0)
-			return 0;
+	if (io > 0x1ff)	{	/* Check a single specified location. */
+		err = cs89x0_probe1(dev, io, 0);
+	} else if (io != 0) {	/* Don't probe at all. */
+		err = -ENXIO;
+	} else {
+		for (port = netcard_portlist; *port; port++) {
+			if (cs89x0_probe1(dev, *port, 0) == 0)
+				break;
+			dev->irq = irq;
+		}
+		if (!*port)
+			err = -ENODEV;
 	}
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+	return dev;
+out1:
+	outw(PP_ChipID, dev->base_addr + ADD_PORT);
+	release_region(dev->base_addr, NETCARD_IO_EXTENT);
+out:
+	free_netdev(dev);
 	printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");
-	return -ENODEV;
+	return ERR_PTR(err);
 }
 
 static int
@@ -375,39 +397,34 @@
  */
 
 static int __init
-cs89x0_probe1(struct net_device *dev, int ioaddr)
+cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
 {
-	struct net_local *lp;
+	struct net_local *lp = (struct net_local *)dev->priv;
 	static unsigned version_printed;
 	int i;
 	unsigned rev_type = 0;
 	int eeprom_buff[CHKSUM_LEN];
 	int retval;
 
+	SET_MODULE_OWNER(dev);
 	/* Initialize the device structure. */
-	if (dev->priv == NULL) {
-		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-		if (dev->priv == 0) {
-			retval = -ENOMEM;
-			goto out;
-		}
-		lp = (struct net_local *)dev->priv;
+	if (!modular) {
 		memset(lp, 0, sizeof(*lp));
 		spin_lock_init(&lp->lock);
-#if !defined(MODULE) && (ALLOW_DMA != 0)
+#ifndef MODULE
+#if ALLOW_DMA
 		if (g_cs89x0_dma) {
 			lp->use_dma = 1;
 			lp->dma = g_cs89x0_dma;
 			lp->dmasize = 16;	/* Could make this an option... */
 		}
 #endif
-#ifndef MODULE
 		lp->force = g_cs89x0_media__force;
 #endif
         }
-	lp = (struct net_local *)dev->priv;
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
+	/* WTF is going on here? */
 	if (!request_region(ioaddr & ~3, NETCARD_IO_EXTENT, dev->name)) {
 		printk(KERN_ERR "%s: request_region(0x%x, 0x%x) failed\n",
 				dev->name, ioaddr, NETCARD_IO_EXTENT);
@@ -696,9 +713,6 @@
 	dev->set_multicast_list = set_multicast_list;
 	dev->set_mac_address 	= set_mac_address;
 
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-
 	printk("\n");
 	if (net_debug)
 		printk("cs89x0_probe1() successful\n");
@@ -706,9 +720,6 @@
 out2:
 	release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
 out1:
-	kfree(dev->priv);
-	dev->priv = 0;
-out:
 	return retval;
 }
 
@@ -1655,7 +1666,7 @@
 
 #ifdef MODULE
 
-static struct net_device dev_cs89x0;
+static struct net_device *dev_cs89x0;
 
 /*
  * Support the 'debug' module parm even if we're compiled for non-debug to 
@@ -1733,6 +1744,7 @@
 int
 init_module(void)
 {
+	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
 	struct net_local *lp;
 	int ret = 0;
 
@@ -1741,18 +1753,12 @@
 #else
 	debug = 0;
 #endif
-
-	dev_cs89x0.irq = irq;
-	dev_cs89x0.base_addr = io;
-
-        dev_cs89x0.init = cs89x0_probe;
-        dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-	if (dev_cs89x0.priv == 0) {
-		printk(KERN_ERR "cs89x0.c: Out of memory.\n");
+	if (!dev)
 		return -ENOMEM;
-	}
-	memset(dev_cs89x0.priv, 0, sizeof(struct net_local));
-	lp = (struct net_local *)dev_cs89x0.priv;
+
+	dev->irq = irq;
+	dev->base_addr = io;
+	lp = dev->priv;
 
 #if ALLOW_DMA
 	if (use_dma) {
@@ -1782,7 +1788,10 @@
                 printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n");
                 ret = -EPERM;
 		goto out;
-        }
+        } else if (io <= 0x1ff) {
+		ret = -ENXIO;
+		goto out;
+	}
 
 #if ALLOW_DMA
 	if (use_dma && dmasize != 16 && dmasize != 64) {
@@ -1791,30 +1800,31 @@
 		goto out;
 	}
 #endif
+	ret = cs89x0_probe1(dev, io, 1);
+	if (ret)
+		goto out;
 
-        if (register_netdev(&dev_cs89x0) != 0) {
+        if (register_netdev(dev) != 0) {
                 printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io);
                 ret = -ENXIO;
+		outw(PP_ChipID, dev->base_addr + ADD_PORT);
+		release_region(dev->base_addr, NETCARD_IO_EXTENT);
 		goto out;
         }
+	dev_cs89x0 = dev;
+	return 0;
 out:
-	if (ret)
-		kfree(dev_cs89x0.priv);
+	free_netdev(dev);
 	return ret;
 }
 
 void
 cleanup_module(void)
 {
-        if (dev_cs89x0.priv != NULL) {
-                /* Free up the private structure, or leak memory :-)  */
-                unregister_netdev(&dev_cs89x0);
-		outw(PP_ChipID, dev_cs89x0.base_addr + ADD_PORT);
-                kfree(dev_cs89x0.priv);
-                dev_cs89x0.priv = NULL;	/* gets re-allocated by cs89x0_probe1 */
-                /* If we don't do this, we can't re-insmod it later. */
-                release_region(dev_cs89x0.base_addr, NETCARD_IO_EXTENT);
-        }
+	unregister_netdev(dev_cs89x0);
+	outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT);
+	release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
+	free_netdev(dev_cs89x0);
 }
 #endif /* MODULE */
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help