From cf9bd21a41bd999ac6a0b72b549839e218ad5f31 Mon Sep 17 00:00:00 2001 From: Joe Lawrence Date: Thu, 8 Aug 2013 16:45:39 -0400 Subject: [PATCH] [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 Acked-by: Sreekanth Reddy Signed-off-by: James Bottomley --- drivers/scsi/mpt3sas/mpt3sas_base.c | 27 +++++++++++++++++---------- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 1 + 2 files changed, 18 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) int i; u8 try_msix = 0; - INIT_LIST_HEAD(&ioc->reply_queue_list); - if (msix_disable == -1 || msix_disable == 0) try_msix = 1; @@ -1790,6 +1788,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) if (pci_enable_device_mem(pdev)) { pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n", ioc->name); + ioc->bars = 0; return -ENODEV; } @@ -1798,6 +1797,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) MPT3SAS_DRIVER_NAME)) { pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", ioc->name); + ioc->bars = 0; r = -ENODEV; goto out_fail; } @@ -4393,18 +4393,25 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, __func__)); - _base_mask_interrupts(ioc); - ioc->shost_recovery = 1; - _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); - ioc->shost_recovery = 0; + if (ioc->chip_phys && ioc->chip) { + _base_mask_interrupts(ioc); + ioc->shost_recovery = 1; + _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); + ioc->shost_recovery = 0; + } + _base_free_irq(ioc); _base_disable_msix(ioc); - if (ioc->chip_phys) + + if (ioc->chip_phys && ioc->chip) iounmap(ioc->chip); ioc->chip_phys = 0; - pci_release_selected_regions(ioc->pdev, ioc->bars); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); + + if (pci_is_enabled(pdev)) { + pci_release_selected_regions(ioc->pdev, ioc->bars); + pci_disable_pcie_error_reporting(pdev); + pci_disable_device(pdev); + } return; } diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 8cbe8fd21fc4..a961fe11b527 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -7779,6 +7779,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); INIT_LIST_HEAD(&ioc->delayed_tr_list); INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); + INIT_LIST_HEAD(&ioc->reply_queue_list); /* init shost parameters */ shost->max_cmd_len = 32; -- 2.20.1