diff options
author | Matthew Wilcox <matthew@wil.cx> | 2007-07-30 10:04:53 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:39:08 -0400 |
commit | 71f36115d20e8d8b0ef10479ff0cde877ec56f98 (patch) | |
tree | adf0da802ca05e404ae6e6a9170e81e92dd0f3d0 /drivers/scsi/advansys.c | |
parent | c304ec94733aec764396813f3f05dfbe02f4a6da (diff) |
[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: Matthew Wilcox <matthew@wil.cx>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/advansys.c')
-rw-r--r-- | drivers/scsi/advansys.c | 70 |
1 files changed, 33 insertions, 37 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index eda41f245bb4..d51ca86bda74 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -17681,14 +17681,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type) | |||
17681 | boardp->id, pci_memory_address, iolen); | 17681 | boardp->id, pci_memory_address, iolen); |
17682 | goto err_shost; | 17682 | goto err_shost; |
17683 | } | 17683 | } |
17684 | ASC_DBG1(1, | 17684 | ASC_DBG1(1, "advansys_board_found: ioremap_addr: 0x%lx\n", |
17685 | "advansys_board_found: ioremap_addr: 0x%lx\n", | ||
17686 | (ulong)boardp->ioremap_addr); | 17685 | (ulong)boardp->ioremap_addr); |
17687 | adv_dvc_varp->iop_base = (AdvPortAddr) | 17686 | adv_dvc_varp->iop_base = (AdvPortAddr) |
17688 | (boardp->ioremap_addr + | 17687 | (boardp->ioremap_addr + |
17689 | (pci_memory_address - (pci_memory_address & PAGE_MASK))); | 17688 | (pci_memory_address - (pci_memory_address & PAGE_MASK))); |
17690 | ASC_DBG1(1, | 17689 | ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n", |
17691 | "advansys_board_found: iop_base: 0x%lx\n", | ||
17692 | adv_dvc_varp->iop_base); | 17690 | adv_dvc_varp->iop_base); |
17693 | #endif /* CONFIG_PCI */ | 17691 | #endif /* CONFIG_PCI */ |
17694 | 17692 | ||
@@ -18169,25 +18167,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) | |||
18169 | * Register Board Resources - I/O Port, DMA, IRQ | 18167 | * Register Board Resources - I/O Port, DMA, IRQ |
18170 | */ | 18168 | */ |
18171 | 18169 | ||
18172 | /* | ||
18173 | * Register I/O port range. | ||
18174 | * | ||
18175 | * For Wide boards the I/O ports are not used to access | ||
18176 | * the board, but request the region anyway. | ||
18177 | * | ||
18178 | * 'shost->n_io_port' is not referenced, because it may be truncated. | ||
18179 | */ | ||
18180 | ASC_DBG2(2, | ||
18181 | "advansys_board_found: request_region port 0x%lx, len 0x%x\n", | ||
18182 | (ulong)shost->io_port, boardp->asc_n_io_port); | ||
18183 | if (request_region(shost->io_port, boardp->asc_n_io_port, | ||
18184 | "advansys") == NULL) { | ||
18185 | ASC_PRINT3 | ||
18186 | ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n", | ||
18187 | boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port); | ||
18188 | goto err_free_proc; | ||
18189 | } | ||
18190 | |||
18191 | /* Register DMA Channel for Narrow boards. */ | 18170 | /* Register DMA Channel for Narrow boards. */ |
18192 | shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ | 18171 | shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ |
18193 | #ifdef CONFIG_ISA | 18172 | #ifdef CONFIG_ISA |
@@ -18200,7 +18179,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type) | |||
18200 | ASC_PRINT3 | 18179 | ASC_PRINT3 |
18201 | ("advansys_board_found: board %d: request_dma() %d failed %d\n", | 18180 | ("advansys_board_found: board %d: request_dma() %d failed %d\n", |
18202 | boardp->id, shost->dma_channel, ret); | 18181 | boardp->id, shost->dma_channel, ret); |
18203 | goto err_free_region; | 18182 | goto err_free_proc; |
18204 | } | 18183 | } |
18205 | AscEnableIsaDma(shost->dma_channel); | 18184 | AscEnableIsaDma(shost->dma_channel); |
18206 | } | 18185 | } |
@@ -18266,8 +18245,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) | |||
18266 | err_free_dma: | 18245 | err_free_dma: |
18267 | if (shost->dma_channel != NO_ISA_DMA) | 18246 | if (shost->dma_channel != NO_ISA_DMA) |
18268 | free_dma(shost->dma_channel); | 18247 | free_dma(shost->dma_channel); |
18269 | err_free_region: | ||
18270 | release_region(shost->io_port, boardp->asc_n_io_port); | ||
18271 | err_free_proc: | 18248 | err_free_proc: |
18272 | kfree(boardp->prtbuf); | 18249 | kfree(boardp->prtbuf); |
18273 | err_unmap: | 18250 | err_unmap: |
@@ -18295,7 +18272,6 @@ static int advansys_release(struct Scsi_Host *shost) | |||
18295 | ASC_DBG(1, "advansys_release: free_dma()\n"); | 18272 | ASC_DBG(1, "advansys_release: free_dma()\n"); |
18296 | free_dma(shost->dma_channel); | 18273 | free_dma(shost->dma_channel); |
18297 | } | 18274 | } |
18298 | release_region(shost->io_port, boardp->asc_n_io_port); | ||
18299 | if (ASC_WIDE_BOARD(boardp)) { | 18275 | if (ASC_WIDE_BOARD(boardp)) { |
18300 | iounmap(boardp->ioremap_addr); | 18276 | iounmap(boardp->ioremap_addr); |
18301 | advansys_wide_free_mem(boardp); | 18277 | advansys_wide_free_mem(boardp); |
@@ -18317,19 +18293,17 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id) | |||
18317 | struct Scsi_Host *shost; | 18293 | struct Scsi_Host *shost; |
18318 | 18294 | ||
18319 | if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { | 18295 | if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { |
18320 | ASC_DBG1(1, "advansys_isa_match: check_region() failed " | 18296 | ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n", |
18321 | "I/O port 0x%x\n", iop_base); | 18297 | iop_base); |
18322 | return -ENODEV; | 18298 | return -ENODEV; |
18323 | } | 18299 | } |
18324 | ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base); | 18300 | ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base); |
18325 | release_region(iop_base, ASC_IOADR_GAP); | ||
18326 | if (!AscFindSignature(iop_base)) | 18301 | if (!AscFindSignature(iop_base)) |
18327 | goto nodev; | 18302 | goto nodev; |
18328 | if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT)) | 18303 | if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT)) |
18329 | goto nodev; | 18304 | goto nodev; |
18330 | 18305 | ||
18331 | shost = advansys_board_found(iop_base, dev, ASC_IS_ISA); | 18306 | shost = advansys_board_found(iop_base, dev, ASC_IS_ISA); |
18332 | |||
18333 | if (!shost) | 18307 | if (!shost) |
18334 | goto nodev; | 18308 | goto nodev; |
18335 | 18309 | ||
@@ -18337,12 +18311,15 @@ static int __devinit advansys_isa_probe(struct device *dev, unsigned int id) | |||
18337 | return 0; | 18311 | return 0; |
18338 | 18312 | ||
18339 | nodev: | 18313 | nodev: |
18314 | release_region(iop_base, ASC_IOADR_GAP); | ||
18340 | return -ENODEV; | 18315 | return -ENODEV; |
18341 | } | 18316 | } |
18342 | 18317 | ||
18343 | static int __devexit advansys_isa_remove(struct device *dev, unsigned int id) | 18318 | static int __devexit advansys_isa_remove(struct device *dev, unsigned int id) |
18344 | { | 18319 | { |
18320 | int ioport = _asc_def_iop_base[id]; | ||
18345 | advansys_release(dev_get_drvdata(dev)); | 18321 | advansys_release(dev_get_drvdata(dev)); |
18322 | release_region(ioport, ASC_IOADR_GAP); | ||
18346 | return 0; | 18323 | return 0; |
18347 | } | 18324 | } |
18348 | 18325 | ||
@@ -18361,12 +18338,11 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) | |||
18361 | struct Scsi_Host *shost; | 18338 | struct Scsi_Host *shost; |
18362 | 18339 | ||
18363 | if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { | 18340 | if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { |
18364 | ASC_DBG1(1, "advansys_vlb_match: check_region() failed " | 18341 | ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n", |
18365 | "I/O port 0x%x\n", iop_base); | 18342 | iop_base); |
18366 | return -ENODEV; | 18343 | return -ENODEV; |
18367 | } | 18344 | } |
18368 | ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base); | 18345 | ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base); |
18369 | release_region(iop_base, ASC_IOADR_GAP); | ||
18370 | if (!AscFindSignature(iop_base)) | 18346 | if (!AscFindSignature(iop_base)) |
18371 | goto nodev; | 18347 | goto nodev; |
18372 | /* | 18348 | /* |
@@ -18378,7 +18354,6 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) | |||
18378 | goto nodev; | 18354 | goto nodev; |
18379 | 18355 | ||
18380 | shost = advansys_board_found(iop_base, dev, ASC_IS_VL); | 18356 | shost = advansys_board_found(iop_base, dev, ASC_IS_VL); |
18381 | |||
18382 | if (!shost) | 18357 | if (!shost) |
18383 | goto nodev; | 18358 | goto nodev; |
18384 | 18359 | ||
@@ -18386,6 +18361,7 @@ static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) | |||
18386 | return 0; | 18361 | return 0; |
18387 | 18362 | ||
18388 | nodev: | 18363 | nodev: |
18364 | release_region(iop_base, ASC_IOADR_GAP); | ||
18389 | return -ENODEV; | 18365 | return -ENODEV; |
18390 | } | 18366 | } |
18391 | 18367 | ||
@@ -18429,8 +18405,16 @@ static int __devinit advansys_eisa_probe(struct device *dev) | |||
18429 | 18405 | ||
18430 | err = -ENODEV; | 18406 | err = -ENODEV; |
18431 | for (i = 0; i < 2; i++, ioport += 0x20) { | 18407 | for (i = 0; i < 2; i++, ioport += 0x20) { |
18432 | if (!AscFindSignature(ioport)) | 18408 | if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) { |
18409 | printk(KERN_WARNING "Region %x-%x busy\n", ioport, | ||
18410 | ioport + ASC_IOADR_GAP - 1); | ||
18411 | continue; | ||
18412 | } | ||
18413 | if (!AscFindSignature(ioport)) { | ||
18414 | release_region(ioport, ASC_IOADR_GAP); | ||
18433 | continue; | 18415 | continue; |
18416 | } | ||
18417 | |||
18434 | /* | 18418 | /* |
18435 | * I don't know why we need to do this for EISA chips, but | 18419 | * I don't know why we need to do this for EISA chips, but |
18436 | * not for any others. It looks to be equivalent to | 18420 | * not for any others. It looks to be equivalent to |
@@ -18440,8 +18424,11 @@ static int __devinit advansys_eisa_probe(struct device *dev) | |||
18440 | */ | 18424 | */ |
18441 | inw(ioport + 4); | 18425 | inw(ioport + 4); |
18442 | data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA); | 18426 | data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA); |
18443 | if (data->host[i]) | 18427 | if (data->host[i]) { |
18444 | err = 0; | 18428 | err = 0; |
18429 | } else { | ||
18430 | release_region(ioport, ASC_IOADR_GAP); | ||
18431 | } | ||
18445 | } | 18432 | } |
18446 | 18433 | ||
18447 | if (err) { | 18434 | if (err) { |
@@ -18460,10 +18447,13 @@ static __devexit int advansys_eisa_remove(struct device *dev) | |||
18460 | struct eisa_scsi_data *data = dev_get_drvdata(dev); | 18447 | struct eisa_scsi_data *data = dev_get_drvdata(dev); |
18461 | 18448 | ||
18462 | for (i = 0; i < 2; i++) { | 18449 | for (i = 0; i < 2; i++) { |
18450 | int ioport; | ||
18463 | struct Scsi_Host *shost = data->host[i]; | 18451 | struct Scsi_Host *shost = data->host[i]; |
18464 | if (!shost) | 18452 | if (!shost) |
18465 | continue; | 18453 | continue; |
18454 | ioport = shost->io_port; | ||
18466 | advansys_release(shost); | 18455 | advansys_release(shost); |
18456 | release_region(ioport, ASC_IOADR_GAP); | ||
18467 | } | 18457 | } |
18468 | 18458 | ||
18469 | kfree(data); | 18459 | kfree(data); |
@@ -18507,6 +18497,9 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
18507 | err = pci_enable_device(pdev); | 18497 | err = pci_enable_device(pdev); |
18508 | if (err) | 18498 | if (err) |
18509 | goto fail; | 18499 | goto fail; |
18500 | err = pci_request_regions(pdev, "advansys"); | ||
18501 | if (err) | ||
18502 | goto disable_device; | ||
18510 | 18503 | ||
18511 | if (pci_resource_len(pdev, 0) == 0) | 18504 | if (pci_resource_len(pdev, 0) == 0) |
18512 | goto nodev; | 18505 | goto nodev; |
@@ -18522,6 +18515,8 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
18522 | 18515 | ||
18523 | nodev: | 18516 | nodev: |
18524 | err = -ENODEV; | 18517 | err = -ENODEV; |
18518 | pci_release_regions(pdev); | ||
18519 | disable_device: | ||
18525 | pci_disable_device(pdev); | 18520 | pci_disable_device(pdev); |
18526 | fail: | 18521 | fail: |
18527 | return err; | 18522 | return err; |
@@ -18530,6 +18525,7 @@ advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
18530 | static void __devexit advansys_pci_remove(struct pci_dev *pdev) | 18525 | static void __devexit advansys_pci_remove(struct pci_dev *pdev) |
18531 | { | 18526 | { |
18532 | advansys_release(pci_get_drvdata(pdev)); | 18527 | advansys_release(pci_get_drvdata(pdev)); |
18528 | pci_release_regions(pdev); | ||
18533 | pci_disable_device(pdev); | 18529 | pci_disable_device(pdev); |
18534 | } | 18530 | } |
18535 | 18531 | ||