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 <[EMAIL PROTECTED]>
---
drivers/scsi/advansys.c | 103 +++++++++++++++++++---------------------------
1 files changed, 43 insertions(+), 60 deletions(-)
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 48dc28d..a4d3372 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -1935,7 +1935,6 @@ static int AscCompareString(uchar *, uchar *, int);
#ifdef CONFIG_ISA
static ushort AscGetEisaChipCfg(PortAddr);
static PortAddr AscSearchIOPortAddr11(PortAddr);
-static PortAddr AscSearchIOPortAddr(PortAddr, ushort);
static void AscSetISAPNPWaitForKey(void);
#endif /* CONFIG_ISA */
static uchar AscGetChipScsiCtrl(PortAddr);
@@ -8261,7 +8260,7 @@ static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX]
__initdata = {
};
#ifdef CONFIG_ISA
-static uchar _isa_pnp_inited __initdata = 0;
+static unsigned char _isa_pnp_inited __initdata = 0;
static PortAddr __init AscSearchIOPortAddr(PortAddr iop_beg, ushort bus_type)
{
@@ -8269,12 +8268,11 @@ static PortAddr __init AscSearchIOPortAddr(PortAddr
iop_beg, ushort bus_type)
while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
if (AscGetChipVersion(iop_beg, bus_type) <=
ASC_CHIP_MAX_VER_VL) {
- return (iop_beg);
+ return iop_beg;
}
+ release_region(iop_beg, ASC_IOADR_GAP);
}
- return (0);
- }
- if (bus_type & ASC_IS_ISA) {
+ } else if (bus_type & ASC_IS_ISA) {
if (_isa_pnp_inited == 0) {
AscSetISAPNPWaitForKey();
_isa_pnp_inited++;
@@ -8282,40 +8280,33 @@ static PortAddr __init AscSearchIOPortAddr(PortAddr
iop_beg, ushort bus_type)
while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
if ((AscGetChipVersion(iop_beg, bus_type) &
ASC_CHIP_VER_ISA_BIT) != 0) {
- return (iop_beg);
+ return iop_beg;
}
+ release_region(iop_beg, ASC_IOADR_GAP);
}
- return (0);
}
- return (0);
+ return 0;
}
static PortAddr __init AscSearchIOPortAddr11(PortAddr s_addr)
{
int i;
- PortAddr iop_base;
for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) {
- if (_asc_def_iop_base[i] > s_addr) {
- break;
- }
- }
- for (; i < ASC_IOADR_TABLE_MAX_IX; i++) {
- iop_base = _asc_def_iop_base[i];
+ PortAddr iop_base = _asc_def_iop_base[i];
+ if (iop_base <= s_addr)
+ continue;
if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
- ASC_DBG1(1,
- "AscSearchIOPortAddr11: check_region() failed
I/O port 0x%x\n",
- iop_base);
+ ASC_DBG1(1, "AscSearchIOPortAddr11: I/O port 0x%x "
+ "in use\n", iop_base);
continue;
}
ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n",
iop_base);
- release_region(iop_base, ASC_IOADR_GAP);
- if (AscFindSignature(iop_base)) {
- return (iop_base);
- }
+ if (AscFindSignature(iop_base))
+ return iop_base;
}
- return (0);
+ return 0;
}
static void __init AscSetISAPNPWaitForKey(void)
@@ -17842,14 +17833,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 */
@@ -18330,25 +18319,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
@@ -18361,7 +18331,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);
}
@@ -18445,8 +18415,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:
@@ -18474,9 +18442,8 @@ advansys_board_found(int iop, struct device *dev, int
bus_type)
static int __init advansys_detect(void)
{
static int detect_called = ASC_FALSE;
- int iop;
- int bus;
- int ioport = 0;
+ int iop, bus, ioport = 0;
+ struct Scsi_Host *shost;
if (detect_called == ASC_FALSE) {
detect_called = ASC_TRUE;
@@ -18533,8 +18500,7 @@ static int __init advansys_detect(void)
case ASC_IS_VL:
#ifdef CONFIG_ISA
if (asc_iopflag == ASC_FALSE) {
- iop =
- AscSearchIOPortAddr(iop,
+ iop = AscSearchIOPortAddr(iop,
asc_bus[bus]);
} else {
/*
@@ -18630,7 +18596,9 @@ static int __init advansys_detect(void)
break;
}
- advansys_board_found(iop, NULL, asc_bus[bus]);
+ shost = advansys_board_found(iop, NULL, asc_bus[bus]);
+ if (!shost)
+ release_region(iop, ASC_IOADR_GAP);
}
}
@@ -18655,7 +18623,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)) {
adv_sgblk_t *sgp = NULL;
@@ -18720,12 +18687,22 @@ static int __devinit advansys_eisa_probe(struct
device *dev)
ioport = edev->base_addr + 0xc30;
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;
+ }
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) {
@@ -18748,6 +18725,7 @@ static __devexit int advansys_eisa_remove(struct device
*dev)
continue;
ioport = shost->io_port;
advansys_remove(data->host[i]);
+ release_region(ioport, ASC_IOADR_GAP);
}
return 0;
@@ -18787,8 +18765,10 @@ advansys_pci_probe(struct pci_dev *pdev, const struct
pci_device_id *ent)
int ioport;
struct Scsi_Host *shost;
- if (pci_enable_device(pdev))
+ if (pci_request_regions(pdev, "advansys"))
goto fail;
+ if (pci_enable_device(pdev))
+ goto release_regions;
ioport = pci_resource_start(pdev, 0);
shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
@@ -18799,6 +18779,8 @@ advansys_pci_probe(struct pci_dev *pdev, const struct
pci_device_id *ent)
}
pci_disable_device(pdev);
+ release_regions:
+ pci_release_regions(pdev);
fail:
return -ENODEV;
}
@@ -18807,6 +18789,7 @@ static void __devexit advansys_pci_remove(struct
pci_dev *pdev)
{
advansys_remove(pci_get_drvdata(pdev));
pci_disable_device(pdev);
+ pci_release_regions(pdev);
}
static struct pci_driver advansys_pci_driver = {
--
1.4.4.4
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html