Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+33 −37
Original line number Diff line number Diff line
@@ -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);
}