From: Herbert Xu <herbert@gondor.apana.org.au>

Currently com20020 and com20020_cs both call request_region on the same
block of ports leading to a conflict.  This patch resolves this by moving
request_region out of the generic driver and into the isa/pci/cs drivers.  


 drivers/net/arcnet/com20020-isa.c |   25 +++++++++++++++++++------
 drivers/net/arcnet/com20020-pci.c |   14 ++++++++------
 drivers/net/arcnet/com20020.c     |    7 -------
 3 files changed, 27 insertions(+), 19 deletions(-)

diff -puN drivers/net/arcnet/com20020.c~com200020-request_region-fix drivers/net/arcnet/com20020.c
--- 25/drivers/net/arcnet/com20020.c~com200020-request_region-fix	2003-09-26 21:11:55.000000000 -0700
+++ 25-akpm/drivers/net/arcnet/com20020.c	2003-09-26 21:11:55.000000000 -0700
@@ -180,10 +180,6 @@ int com20020_found(struct net_device *de
 	if (!dev->dev_addr[0])
 		dev->dev_addr[0] = inb(ioaddr + 8);	/* FIXME: do this some other way! */
 
-	/* reserve the I/O region */
-	if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)"))
-		return -EBUSY;
-
 	SET_SUBADR(SUB_SETUP1);
 	outb(lp->setup, _XREG);
 
@@ -207,7 +203,6 @@ int com20020_found(struct net_device *de
 	if (request_irq(dev->irq, &arcnet_interrupt, shared,
 			"arcnet (COM20020)", dev)) {
 		BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
-		release_region(ioaddr, ARCNET_TOTAL_SIZE);
 		return -ENODEV;
 	}
 
@@ -227,7 +222,6 @@ int com20020_found(struct net_device *de
 	       clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]);
 
 	if (!dev->init && register_netdev(dev)) {
-		release_region(ioaddr, ARCNET_TOTAL_SIZE);
 		free_irq(dev->irq, dev);
 		return -EIO;
 	}
@@ -342,7 +336,6 @@ void com20020_remove(struct net_device *
 {
 	unregister_netdev(dev);
 	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
 	kfree(dev->priv);
 	free_netdev(dev);
 }
diff -puN drivers/net/arcnet/com20020-isa.c~com200020-request_region-fix drivers/net/arcnet/com20020-isa.c
--- 25/drivers/net/arcnet/com20020-isa.c~com200020-request_region-fix	2003-09-26 21:11:55.000000000 -0700
+++ 25-akpm/drivers/net/arcnet/com20020-isa.c	2003-09-26 21:11:55.000000000 -0700
@@ -53,6 +53,7 @@ static int __init com20020isa_probe(stru
 	int ioaddr;
 	unsigned long airqmask;
 	struct arcnet_local *lp = dev->priv;
+	int err;
 
 	BUGLVL(D_NORMAL) printk(VERSION);
 
@@ -62,17 +63,20 @@ static int __init com20020isa_probe(stru
 		       "must specify the base address!\n");
 		return -ENODEV;
 	}
-	if (check_region(ioaddr, ARCNET_TOTAL_SIZE)) {
+	if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
 		BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n",
 		       ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
 		return -ENXIO;
 	}
 	if (ASTATUS() == 0xFF) {
 		BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr);
-		return -ENODEV;
+		err = -ENODEV;
+		goto out;
+	}
+	if (com20020_check(dev)) {
+		err = -ENODEV;
+		goto out;
 	}
-	if (com20020_check(dev))
-		return -ENODEV;
 
 	if (!dev->irq) {
 		/* if we do this, we're sure to get an IRQ since the
@@ -96,13 +100,21 @@ static int __init com20020isa_probe(stru
 			dev->irq = probe_irq_off(airqmask);
 			if (dev->irq <= 0) {
 				BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n");
-				return -ENODEV;
+				err = -ENODEV;
+				goto out;
 			}
 		}
 	}
 
 	lp->card_name = "ISA COM20020";
-	return com20020_found(dev, 0);
+	if ((err = com20020_found(dev, 0)) != 0)
+		goto out;
+
+	return 0;
+
+out:
+	release_region(ioaddr, ARCNET_TOTAL_SIZE);
+	return err;
 }
 
 
@@ -170,6 +182,7 @@ int init_module(void)
 void cleanup_module(void)
 {
 	com20020_remove(my_dev);
+	release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
 }
 
 #else
diff -puN drivers/net/arcnet/com20020-pci.c~com200020-request_region-fix drivers/net/arcnet/com20020-pci.c
--- 25/drivers/net/arcnet/com20020-pci.c~com200020-request_region-fix	2003-09-26 21:11:55.000000000 -0700
+++ 25-akpm/drivers/net/arcnet/com20020-pci.c	2003-09-26 21:11:55.000000000 -0700
@@ -115,20 +115,20 @@ static int __devinit com20020pci_probe(s
 		BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
 		       "but seems empty!\n", ioaddr);
 		err = -EIO;
-		goto out_priv;
+		goto out_port;
 	}
 	if (com20020_check(dev)) {
 		err = -EIO;
-		goto out_priv;
+		goto out_port;
 	}
 
-	release_region(ioaddr, ARCNET_TOTAL_SIZE);
-
 	if ((err = com20020_found(dev, SA_SHIRQ)) != 0)
-	        goto out_priv;
+	        goto out_port;
 
 	return 0;
 
+out_port:
+	release_region(ioaddr, ARCNET_TOTAL_SIZE);
 out_priv:
 	kfree(dev->priv);
 out_dev:
@@ -138,7 +138,9 @@ out_dev:
 
 static void __devexit com20020pci_remove(struct pci_dev *pdev)
 {
-	com20020_remove(pci_get_drvdata(pdev));
+	struct net_device *dev = pci_get_drvdata(pdev);
+	com20020_remove(dev);
+	release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
 }
 
 static struct pci_device_id com20020pci_id_table[] = {

_