diff options
author | Joe Lawrence <joe.lawrence@stratus.com> | 2013-08-08 16:45:39 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-08-26 10:53:45 -0400 |
commit | cf9bd21a41bd999ac6a0b72b549839e218ad5f31 (patch) | |
tree | a92825d8db84b4d9bc6f0b02c3855a2f6bf1f6ea /drivers/scsi/mpt3sas/mpt3sas_base.c | |
parent | 3b3e6f8df3b03642d6705d1db84842c24415b21f (diff) |
[SCSI] mpt3sas: fix cleanup on controller resource mapping failure
If mpt3sas_base_map_resources takes an early error path then its
counterpart, mpt3sas_base_free_resources needs to be careful about
cleaning up:
1 - _base_mask_interrupts and _base_make_ioc_ready require memory
mapped I/O registers, make sure that this is true.
2 - _base_free_irq iterates over the adapter's reply_queue_list, so
move this list head initialization out of _base_enable_msix to
_scsih_probe so this will always be safe.
3 - check that the controller PCI device and its BARs have been
enabled before disabling them.
Signed-off-by: Joe Lawrence <joe.lawrence@stratus.com>
Acked-by: Sreekanth Reddy <Sreekanth.Reddy@lsi.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/mpt3sas/mpt3sas_base.c')
-rw-r--r-- | drivers/scsi/mpt3sas/mpt3sas_base.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 5dc280c75325..34ff896a140d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c | |||
@@ -1709,8 +1709,6 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
1709 | int i; | 1709 | int i; |
1710 | u8 try_msix = 0; | 1710 | u8 try_msix = 0; |
1711 | 1711 | ||
1712 | INIT_LIST_HEAD(&ioc->reply_queue_list); | ||
1713 | |||
1714 | if (msix_disable == -1 || msix_disable == 0) | 1712 | if (msix_disable == -1 || msix_disable == 0) |
1715 | try_msix = 1; | 1713 | try_msix = 1; |
1716 | 1714 | ||
@@ -1790,6 +1788,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) | |||
1790 | if (pci_enable_device_mem(pdev)) { | 1788 | if (pci_enable_device_mem(pdev)) { |
1791 | pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n", | 1789 | pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n", |
1792 | ioc->name); | 1790 | ioc->name); |
1791 | ioc->bars = 0; | ||
1793 | return -ENODEV; | 1792 | return -ENODEV; |
1794 | } | 1793 | } |
1795 | 1794 | ||
@@ -1798,6 +1797,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) | |||
1798 | MPT3SAS_DRIVER_NAME)) { | 1797 | MPT3SAS_DRIVER_NAME)) { |
1799 | pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", | 1798 | pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", |
1800 | ioc->name); | 1799 | ioc->name); |
1800 | ioc->bars = 0; | ||
1801 | r = -ENODEV; | 1801 | r = -ENODEV; |
1802 | goto out_fail; | 1802 | goto out_fail; |
1803 | } | 1803 | } |
@@ -4393,18 +4393,25 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) | |||
4393 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 4393 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
4394 | __func__)); | 4394 | __func__)); |
4395 | 4395 | ||
4396 | _base_mask_interrupts(ioc); | 4396 | if (ioc->chip_phys && ioc->chip) { |
4397 | ioc->shost_recovery = 1; | 4397 | _base_mask_interrupts(ioc); |
4398 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 4398 | ioc->shost_recovery = 1; |
4399 | ioc->shost_recovery = 0; | 4399 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
4400 | ioc->shost_recovery = 0; | ||
4401 | } | ||
4402 | |||
4400 | _base_free_irq(ioc); | 4403 | _base_free_irq(ioc); |
4401 | _base_disable_msix(ioc); | 4404 | _base_disable_msix(ioc); |
4402 | if (ioc->chip_phys) | 4405 | |
4406 | if (ioc->chip_phys && ioc->chip) | ||
4403 | iounmap(ioc->chip); | 4407 | iounmap(ioc->chip); |
4404 | ioc->chip_phys = 0; | 4408 | ioc->chip_phys = 0; |
4405 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 4409 | |
4406 | pci_disable_pcie_error_reporting(pdev); | 4410 | if (pci_is_enabled(pdev)) { |
4407 | pci_disable_device(pdev); | 4411 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
4412 | pci_disable_pcie_error_reporting(pdev); | ||
4413 | pci_disable_device(pdev); | ||
4414 | } | ||
4408 | return; | 4415 | return; |
4409 | } | 4416 | } |
4410 | 4417 | ||