[SCSI] advansys: Update resource management
authorMatthew Wilcox <matthew@wil.cx>
Mon, 30 Jul 2007 14:04:53 +0000 (08:04 -0600)
committerJames Bottomley <jejb@mulgrave.localdomain>
Fri, 12 Oct 2007 18:39:08 +0000 (14:39 -0400)
Make sure the resources are reserved and released by all the callers of
advansys_board_found().  This eliminates the check_region-style race.
It also allows us to use the pci_request_regions() API.

Signed-off-by: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/advansys.c

index eda41f245bb433b0dbc5a0f00e8dffe814dc37ff..d51ca86bda74468d4cabcde6e3ec69eca9607a46 100644 (file)
@@ -17681,14 +17681,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                             boardp->id, pci_memory_address, iolen);
                        goto err_shost;
                }
-               ASC_DBG1(1,
-                        "advansys_board_found: ioremap_addr: 0x%lx\n",
+               ASC_DBG1(1, "advansys_board_found: ioremap_addr: 0x%lx\n",
                         (ulong)boardp->ioremap_addr);
                adv_dvc_varp->iop_base = (AdvPortAddr)
                    (boardp->ioremap_addr +
                     (pci_memory_address - (pci_memory_address & PAGE_MASK)));
-               ASC_DBG1(1,
-                        "advansys_board_found: iop_base: 0x%lx\n",
+               ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
                         adv_dvc_varp->iop_base);
 #endif /* CONFIG_PCI */
 
@@ -18169,25 +18167,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
         * Register Board Resources - I/O Port, DMA, IRQ
         */
 
-       /*
-        * Register I/O port range.
-        *
-        * For Wide boards the I/O ports are not used to access
-        * the board, but request the region anyway.
-        *
-        * 'shost->n_io_port' is not referenced, because it may be truncated.
-        */
-       ASC_DBG2(2,
-                "advansys_board_found: request_region port 0x%lx, len 0x%x\n",
-                (ulong)shost->io_port, boardp->asc_n_io_port);
-       if (request_region(shost->io_port, boardp->asc_n_io_port,
-                          "advansys") == NULL) {
-               ASC_PRINT3
-                   ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n",
-                    boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port);
-               goto err_free_proc;
-       }
-
        /* Register DMA Channel for Narrow boards. */
        shost->dma_channel = NO_ISA_DMA;        /* Default to no ISA DMA. */
 #ifdef CONFIG_ISA
@@ -18200,7 +18179,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
                                ASC_PRINT3
                                    ("advansys_board_found: board %d: request_dma() %d failed %d\n",
                                     boardp->id, shost->dma_channel, ret);
-                               goto err_free_region;
+                               goto err_free_proc;
                        }
                        AscEnableIsaDma(shost->dma_channel);
                }
@@ -18266,8 +18245,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
  err_free_dma:
        if (shost->dma_channel != NO_ISA_DMA)
                free_dma(shost->dma_channel);
- err_free_region:
-       release_region(shost->io_port, boardp->asc_n_io_port);
  err_free_proc:
        kfree(boardp->prtbuf);
  err_unmap:
@@ -18295,7 +18272,6 @@ static int advansys_release(struct Scsi_Host *shost)
                ASC_DBG(1, "advansys_release: free_dma()\n");
                free_dma(shost->dma_channel);
        }
-       release_region(shost->io_port, boardp->asc_n_io_port);
        if (ASC_WIDE_BOARD(boardp)) {
                iounmap(boardp->ioremap_addr);
                advansys_wide_free_mem(boardp);
@@ -18317,19 +18293,17 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
        struct Scsi_Host *shost;
 
        if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
-               ASC_DBG1(1, "advansys_isa_match: check_region() failed "
-                        "I/O port 0x%x\n", iop_base);
+               ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
+                        iop_base);
                return -ENODEV;
        }
        ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
-       release_region(iop_base, ASC_IOADR_GAP);
        if (!AscFindSignature(iop_base))
                goto nodev;
        if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
                goto nodev;
 
        shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
-
        if (!shost)
                goto nodev;
 
@@ -18337,12 +18311,15 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
        return 0;
 
  nodev:
+       release_region(iop_base, ASC_IOADR_GAP);
        return -ENODEV;
 }
 
 static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
 {
+       int ioport = _asc_def_iop_base[id];
        advansys_release(dev_get_drvdata(dev));
+       release_region(ioport, ASC_IOADR_GAP);
        return 0;
 }
 
@@ -18361,12 +18338,11 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
        struct Scsi_Host *shost;
 
        if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
-               ASC_DBG1(1, "advansys_vlb_match: check_region() failed "
-                        "I/O port 0x%x\n", iop_base);
+               ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
+                        iop_base);
                return -ENODEV;
        }
        ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
-       release_region(iop_base, ASC_IOADR_GAP);
        if (!AscFindSignature(iop_base))
                goto nodev;
        /*
@@ -18378,7 +18354,6 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
                goto nodev;
 
        shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
-
        if (!shost)
                goto nodev;
 
@@ -18386,6 +18361,7 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
        return 0;
 
  nodev:
+       release_region(iop_base, ASC_IOADR_GAP);
        return -ENODEV;
 }
 
@@ -18429,8 +18405,16 @@ static int __devinit advansys_eisa_probe(struct device *dev)
 
        err = -ENODEV;
        for (i = 0; i < 2; i++, ioport += 0x20) {
-               if (!AscFindSignature(ioport))
+               if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
+                       printk(KERN_WARNING "Region %x-%x busy\n", ioport,
+                              ioport + ASC_IOADR_GAP - 1);
+                       continue;
+               }
+               if (!AscFindSignature(ioport)) {
+                       release_region(ioport, ASC_IOADR_GAP);
                        continue;
+               }
+
                /*
                 * I don't know why we need to do this for EISA chips, but
                 * not for any others.  It looks to be equivalent to
@@ -18440,8 +18424,11 @@ static int __devinit advansys_eisa_probe(struct device *dev)
                 */
                inw(ioport + 4);
                data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
-               if (data->host[i])
+               if (data->host[i]) {
                        err = 0;
+               } else {
+                       release_region(ioport, ASC_IOADR_GAP);
+               }
        }
 
        if (err) {
@@ -18460,10 +18447,13 @@ static __devexit int advansys_eisa_remove(struct device *dev)
        struct eisa_scsi_data *data = dev_get_drvdata(dev);
 
        for (i = 0; i < 2; i++) {
+               int ioport;
                struct Scsi_Host *shost = data->host[i];
                if (!shost)
                        continue;
+               ioport = shost->io_port;
                advansys_release(shost);
+               release_region(ioport, ASC_IOADR_GAP);
        }
 
        kfree(data);
@@ -18507,6 +18497,9 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        err = pci_enable_device(pdev);
        if (err)
                goto fail;
+       err = pci_request_regions(pdev, "advansys");
+       if (err)
+               goto disable_device;
 
        if (pci_resource_len(pdev, 0) == 0)
                goto nodev;
@@ -18522,6 +18515,8 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
  nodev:
        err = -ENODEV;
+       pci_release_regions(pdev);
+ disable_device:
        pci_disable_device(pdev);
  fail:
        return err;
@@ -18530,6 +18525,7 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 static void __devexit advansys_pci_remove(struct pci_dev *pdev)
 {
        advansys_release(pci_get_drvdata(pdev));
+       pci_release_regions(pdev);
        pci_disable_device(pdev);
 }