diff options
author | Joe Lawrence <joe.lawrence@stratus.com> | 2013-08-08 16:45:38 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-08-26 10:53:44 -0400 |
commit | 3b3e6f8df3b03642d6705d1db84842c24415b21f (patch) | |
tree | 3a383b0486eb5f9957e51806d072b513c6e82aa2 /drivers/scsi/mpt2sas | |
parent | 279afdfe78a020b4b1a68bffd0009b961b12982e (diff) |
[SCSI] mpt2sas: fix cleanup on controller resource mapping failure
If mpt2sas_base_map_resources takes an early error path then its
counterpart, mpt2sas_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/mpt2sas')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_base.c | 27 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 1 |
2 files changed, 18 insertions, 10 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index ccd6d5a97ec3..cf131a3de61c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -1409,8 +1409,6 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc) | |||
1409 | int i; | 1409 | int i; |
1410 | u8 try_msix = 0; | 1410 | u8 try_msix = 0; |
1411 | 1411 | ||
1412 | INIT_LIST_HEAD(&ioc->reply_queue_list); | ||
1413 | |||
1414 | if (msix_disable == -1 || msix_disable == 0) | 1412 | if (msix_disable == -1 || msix_disable == 0) |
1415 | try_msix = 1; | 1413 | try_msix = 1; |
1416 | 1414 | ||
@@ -1489,6 +1487,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1489 | if (pci_enable_device_mem(pdev)) { | 1487 | if (pci_enable_device_mem(pdev)) { |
1490 | printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: " | 1488 | printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: " |
1491 | "failed\n", ioc->name); | 1489 | "failed\n", ioc->name); |
1490 | ioc->bars = 0; | ||
1492 | return -ENODEV; | 1491 | return -ENODEV; |
1493 | } | 1492 | } |
1494 | 1493 | ||
@@ -1497,6 +1496,7 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1497 | MPT2SAS_DRIVER_NAME)) { | 1496 | MPT2SAS_DRIVER_NAME)) { |
1498 | printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: " | 1497 | printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: " |
1499 | "failed\n", ioc->name); | 1498 | "failed\n", ioc->name); |
1499 | ioc->bars = 0; | ||
1500 | r = -ENODEV; | 1500 | r = -ENODEV; |
1501 | goto out_fail; | 1501 | goto out_fail; |
1502 | } | 1502 | } |
@@ -4229,18 +4229,25 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
4229 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | 4229 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
4230 | __func__)); | 4230 | __func__)); |
4231 | 4231 | ||
4232 | _base_mask_interrupts(ioc); | 4232 | if (ioc->chip_phys && ioc->chip) { |
4233 | ioc->shost_recovery = 1; | 4233 | _base_mask_interrupts(ioc); |
4234 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); | 4234 | ioc->shost_recovery = 1; |
4235 | ioc->shost_recovery = 0; | 4235 | _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); |
4236 | ioc->shost_recovery = 0; | ||
4237 | } | ||
4238 | |||
4236 | _base_free_irq(ioc); | 4239 | _base_free_irq(ioc); |
4237 | _base_disable_msix(ioc); | 4240 | _base_disable_msix(ioc); |
4238 | if (ioc->chip_phys) | 4241 | |
4242 | if (ioc->chip_phys && ioc->chip) | ||
4239 | iounmap(ioc->chip); | 4243 | iounmap(ioc->chip); |
4240 | ioc->chip_phys = 0; | 4244 | ioc->chip_phys = 0; |
4241 | pci_release_selected_regions(ioc->pdev, ioc->bars); | 4245 | |
4242 | pci_disable_pcie_error_reporting(pdev); | 4246 | if (pci_is_enabled(pdev)) { |
4243 | pci_disable_device(pdev); | 4247 | pci_release_selected_regions(ioc->pdev, ioc->bars); |
4248 | pci_disable_pcie_error_reporting(pdev); | ||
4249 | pci_disable_device(pdev); | ||
4250 | } | ||
4244 | return; | 4251 | return; |
4245 | } | 4252 | } |
4246 | 4253 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 51004768d0f5..389d79290861 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -8175,6 +8175,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
8175 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); | 8175 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); |
8176 | INIT_LIST_HEAD(&ioc->delayed_tr_list); | 8176 | INIT_LIST_HEAD(&ioc->delayed_tr_list); |
8177 | INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); | 8177 | INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); |
8178 | INIT_LIST_HEAD(&ioc->reply_queue_list); | ||
8178 | 8179 | ||
8179 | /* init shost parameters */ | 8180 | /* init shost parameters */ |
8180 | shost->max_cmd_len = 32; | 8181 | shost->max_cmd_len = 32; |