From: Herbert Xu 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[] = { _