Commit 71f36115 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by James Bottomley

[SCSI] advansys: Update resource management

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: default avatarMatthew Wilcox <matthew@wil.cx>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent c304ec94
...@@ -17681,14 +17681,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type) ...@@ -17681,14 +17681,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
boardp->id, pci_memory_address, iolen); boardp->id, pci_memory_address, iolen);
goto err_shost; goto err_shost;
} }
ASC_DBG1(1, ASC_DBG1(1, "advansys_board_found: ioremap_addr: 0x%lx\n",
"advansys_board_found: ioremap_addr: 0x%lx\n",
(ulong)boardp->ioremap_addr); (ulong)boardp->ioremap_addr);
adv_dvc_varp->iop_base = (AdvPortAddr) adv_dvc_varp->iop_base = (AdvPortAddr)
(boardp->ioremap_addr + (boardp->ioremap_addr +
(pci_memory_address - (pci_memory_address & PAGE_MASK))); (pci_memory_address - (pci_memory_address & PAGE_MASK)));
ASC_DBG1(1, ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
"advansys_board_found: iop_base: 0x%lx\n",
adv_dvc_varp->iop_base); adv_dvc_varp->iop_base);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
...@@ -18169,25 +18167,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) ...@@ -18169,25 +18167,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
* Register Board Resources - I/O Port, DMA, IRQ * 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. */ /* Register DMA Channel for Narrow boards. */
shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
#ifdef CONFIG_ISA #ifdef CONFIG_ISA
...@@ -18200,7 +18179,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type) ...@@ -18200,7 +18179,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
ASC_PRINT3 ASC_PRINT3
("advansys_board_found: board %d: request_dma() %d failed %d\n", ("advansys_board_found: board %d: request_dma() %d failed %d\n",
boardp->id, shost->dma_channel, ret); boardp->id, shost->dma_channel, ret);
goto err_free_region; goto err_free_proc;
} }
AscEnableIsaDma(shost->dma_channel); AscEnableIsaDma(shost->dma_channel);
} }
...@@ -18266,8 +18245,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) ...@@ -18266,8 +18245,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type)
err_free_dma: err_free_dma:
if (shost->dma_channel != NO_ISA_DMA) if (shost->dma_channel != NO_ISA_DMA)
free_dma(shost->dma_channel); free_dma(shost->dma_channel);
err_free_region:
release_region(shost->io_port, boardp->asc_n_io_port);
err_free_proc: err_free_proc:
kfree(boardp->prtbuf); kfree(boardp->prtbuf);
err_unmap: err_unmap:
...@@ -18295,7 +18272,6 @@ static int advansys_release(struct Scsi_Host *shost) ...@@ -18295,7 +18272,6 @@ static int advansys_release(struct Scsi_Host *shost)
ASC_DBG(1, "advansys_release: free_dma()\n"); ASC_DBG(1, "advansys_release: free_dma()\n");
free_dma(shost->dma_channel); free_dma(shost->dma_channel);
} }
release_region(shost->io_port, boardp->asc_n_io_port);
if (ASC_WIDE_BOARD(boardp)) { if (ASC_WIDE_BOARD(boardp)) {
iounmap(boardp->ioremap_addr); iounmap(boardp->ioremap_addr);
advansys_wide_free_mem(boardp); advansys_wide_free_mem(boardp);
...@@ -18317,19 +18293,17 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id) ...@@ -18317,19 +18293,17 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
struct Scsi_Host *shost; struct Scsi_Host *shost;
if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
ASC_DBG1(1, "advansys_isa_match: check_region() failed " ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
"I/O port 0x%x\n", iop_base); iop_base);
return -ENODEV; return -ENODEV;
} }
ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base); 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)) if (!AscFindSignature(iop_base))
goto nodev; goto nodev;
if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT)) if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
goto nodev; goto nodev;
shost = advansys_board_found(iop_base, dev, ASC_IS_ISA); shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
if (!shost) if (!shost)
goto nodev; goto nodev;
...@@ -18337,12 +18311,15 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id) ...@@ -18337,12 +18311,15 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
return 0; return 0;
nodev: nodev:
release_region(iop_base, ASC_IOADR_GAP);
return -ENODEV; return -ENODEV;
} }
static int __devexit advansys_isa_remove(struct device *dev, unsigned int id) 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)); advansys_release(dev_get_drvdata(dev));
release_region(ioport, ASC_IOADR_GAP);
return 0; return 0;
} }
...@@ -18361,12 +18338,11 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) ...@@ -18361,12 +18338,11 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
struct Scsi_Host *shost; struct Scsi_Host *shost;
if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
ASC_DBG1(1, "advansys_vlb_match: check_region() failed " ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
"I/O port 0x%x\n", iop_base); iop_base);
return -ENODEV; return -ENODEV;
} }
ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base); 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)) if (!AscFindSignature(iop_base))
goto nodev; goto nodev;
/* /*
...@@ -18378,7 +18354,6 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) ...@@ -18378,7 +18354,6 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
goto nodev; goto nodev;
shost = advansys_board_found(iop_base, dev, ASC_IS_VL); shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
if (!shost) if (!shost)
goto nodev; goto nodev;
...@@ -18386,6 +18361,7 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) ...@@ -18386,6 +18361,7 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
return 0; return 0;
nodev: nodev:
release_region(iop_base, ASC_IOADR_GAP);
return -ENODEV; return -ENODEV;
} }
...@@ -18429,8 +18405,16 @@ static int __devinit advansys_eisa_probe(struct device *dev) ...@@ -18429,8 +18405,16 @@ static int __devinit advansys_eisa_probe(struct device *dev)
err = -ENODEV; err = -ENODEV;
for (i = 0; i < 2; i++, ioport += 0x20) { 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; continue;
}
/* /*
* I don't know why we need to do this for EISA chips, but * I don't know why we need to do this for EISA chips, but
* not for any others. It looks to be equivalent to * not for any others. It looks to be equivalent to
...@@ -18440,8 +18424,11 @@ static int __devinit advansys_eisa_probe(struct device *dev) ...@@ -18440,8 +18424,11 @@ static int __devinit advansys_eisa_probe(struct device *dev)
*/ */
inw(ioport + 4); inw(ioport + 4);
data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA); data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
if (data->host[i]) if (data->host[i]) {
err = 0; err = 0;
} else {
release_region(ioport, ASC_IOADR_GAP);
}
} }
if (err) { if (err) {
...@@ -18460,10 +18447,13 @@ static __devexit int advansys_eisa_remove(struct device *dev) ...@@ -18460,10 +18447,13 @@ static __devexit int advansys_eisa_remove(struct device *dev)
struct eisa_scsi_data *data = dev_get_drvdata(dev); struct eisa_scsi_data *data = dev_get_drvdata(dev);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
int ioport;
struct Scsi_Host *shost = data->host[i]; struct Scsi_Host *shost = data->host[i];
if (!shost) if (!shost)
continue; continue;
ioport = shost->io_port;
advansys_release(shost); advansys_release(shost);
release_region(ioport, ASC_IOADR_GAP);
} }
kfree(data); kfree(data);
...@@ -18507,6 +18497,9 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -18507,6 +18497,9 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) if (err)
goto fail; goto fail;
err = pci_request_regions(pdev, "advansys");
if (err)
goto disable_device;
if (pci_resource_len(pdev, 0) == 0) if (pci_resource_len(pdev, 0) == 0)
goto nodev; goto nodev;
...@@ -18522,6 +18515,8 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -18522,6 +18515,8 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
nodev: nodev:
err = -ENODEV; err = -ENODEV;
pci_release_regions(pdev);
disable_device:
pci_disable_device(pdev); pci_disable_device(pdev);
fail: fail:
return err; return err;
...@@ -18530,6 +18525,7 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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) static void __devexit advansys_pci_remove(struct pci_dev *pdev)
{ {
advansys_release(pci_get_drvdata(pdev)); advansys_release(pci_get_drvdata(pdev));
pci_release_regions(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment