From patchwork Thu Apr 23 14:33:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Don Brace X-Patchwork-Id: 6263371 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 52D269F313 for ; Thu, 23 Apr 2015 14:34:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 41E4320394 for ; Thu, 23 Apr 2015 14:34:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4FC342038D for ; Thu, 23 Apr 2015 14:34:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757964AbbDWOeY (ORCPT ); Thu, 23 Apr 2015 10:34:24 -0400 Received: from g9t5009.houston.hp.com ([15.240.92.67]:45697 "EHLO g9t5009.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965988AbbDWOeY (ORCPT ); Thu, 23 Apr 2015 10:34:24 -0400 Received: from g9t2301.houston.hp.com (g9t2301.houston.hp.com [16.216.185.78]) by g9t5009.houston.hp.com (Postfix) with ESMTP id A168E1BF; Thu, 23 Apr 2015 14:34:23 +0000 (UTC) Received: from [127.0.1.1] (brunhilda.americas.hpqcorp.net [16.100.201.25]) by g9t2301.houston.hp.com (Postfix) with ESMTP id 88F5674; Thu, 23 Apr 2015 14:34:23 +0000 (UTC) Subject: [PATCH v5 17/42] hpsa: clean up error handling From: Don Brace To: scott.teel@pmcs.com, Kevin.Barnett@pmcs.com, james.bottomley@parallels.com, hch@infradead.org, Justin.Lindley@pmcs.com, brace@pmcs.com Cc: linux-scsi@vger.kernel.org Date: Thu, 23 Apr 2015 09:33:17 -0500 Message-ID: <20150423143317.18832.56712.stgit@brunhilda> In-Reply-To: <20150423141637.18832.35621.stgit@brunhilda> References: <20150423141637.18832.35621.stgit@brunhilda> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Robert Elliott refactor error cleanup and shutdown disable interrupts and pci_disable_device on critical failures add hpsa_free_cfgtables function Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Reviewed-by: Tomas Henzl Reviewed-by: Hannes Reinecke Signed-off-by: Robert Elliott Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 92 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 34 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a9b314d..a2c7b43 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6501,6 +6501,17 @@ static int hpsa_find_cfg_addrs(struct pci_dev *pdev, void __iomem *vaddr, return 0; } +static void hpsa_free_cfgtables(struct ctlr_info *h) +{ + if (h->transtable) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); +} + +/* Find and map CISS config table and transfer table ++ * several items must be unmapped (freed) later ++ * */ static int hpsa_find_cfgtables(struct ctlr_info *h) { u64 cfg_offset; @@ -6527,8 +6538,11 @@ static int hpsa_find_cfgtables(struct ctlr_info *h) h->transtable = remap_pci_mem(pci_resource_start(h->pdev, cfg_base_addr_index)+cfg_offset+trans_offset, sizeof(*h->transtable)); - if (!h->transtable) + if (!h->transtable) { + dev_err(&h->pdev->dev, "Failed mapping transfer table\n"); + hpsa_free_cfgtables(h); return -ENOMEM; + } return 0; } @@ -6704,6 +6718,17 @@ error: return -ENODEV; } +/* free items allocated or mapped by hpsa_pci_init */ +static void hpsa_free_pci_init(struct ctlr_info *h) +{ + hpsa_free_cfgtables(h); /* pci_init 4 */ + iounmap(h->vaddr); /* pci_init 3 */ + hpsa_disable_interrupt_mode(h); /* pci_init 2 */ + pci_release_regions(h->pdev); /* pci_init 2 */ + pci_disable_device(h->pdev); /* pci_init 1 */ +} + +/* several items must be freed later */ static int hpsa_pci_init(struct ctlr_info *h) { int prod_index, err; @@ -6722,15 +6747,15 @@ static int hpsa_pci_init(struct ctlr_info *h) err = pci_enable_device(h->pdev); if (err) { - dev_warn(&h->pdev->dev, "unable to enable PCI device\n"); + dev_err(&h->pdev->dev, "failed to enable PCI device\n"); return err; } err = pci_request_regions(h->pdev, HPSA); if (err) { dev_err(&h->pdev->dev, - "cannot obtain PCI resources, aborting\n"); - return err; + "failed to obtain PCI resources\n"); + goto clean1; /* pci */ } pci_set_master(h->pdev); @@ -6738,40 +6763,41 @@ static int hpsa_pci_init(struct ctlr_info *h) hpsa_interrupt_mode(h); err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr); if (err) - goto err_out_free_res; + goto clean2; /* intmode+region, pci */ h->vaddr = remap_pci_mem(h->paddr, 0x250); if (!h->vaddr) { + dev_err(&h->pdev->dev, "failed to remap PCI mem\n"); err = -ENOMEM; - goto err_out_free_res; + goto clean2; /* intmode+region, pci */ } err = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY); if (err) - goto err_out_free_res; + goto clean3; /* vaddr, intmode+region, pci */ err = hpsa_find_cfgtables(h); if (err) - goto err_out_free_res; + goto clean3; /* vaddr, intmode+region, pci */ hpsa_find_board_params(h); if (!hpsa_CISS_signature_present(h)) { err = -ENODEV; - goto err_out_free_res; + goto clean4; /* cfgtables, vaddr, intmode+region, pci */ } hpsa_set_driver_support_bits(h); hpsa_p600_dma_prefetch_quirk(h); err = hpsa_enter_simple_mode(h); if (err) - goto err_out_free_res; + goto clean4; /* cfgtables, vaddr, intmode+region, pci */ return 0; -err_out_free_res: - if (h->transtable) - iounmap(h->transtable); - if (h->cfgtable) - iounmap(h->cfgtable); - if (h->vaddr) - iounmap(h->vaddr); - pci_disable_device(h->pdev); +clean4: /* cfgtables, vaddr, intmode+region, pci */ + hpsa_free_cfgtables(h); +clean3: /* vaddr, intmode+region, pci */ + iounmap(h->vaddr); +clean2: /* intmode+region, pci */ + hpsa_disable_interrupt_mode(h); pci_release_regions(h->pdev); +clean1: /* pci */ + pci_disable_device(h->pdev); return err; } @@ -6980,8 +7006,9 @@ static int hpsa_request_irqs(struct ctlr_info *h, } } if (rc) { - dev_err(&h->pdev->dev, "unable to get irq %d for %s\n", + dev_err(&h->pdev->dev, "failed to get irq %d for %s\n", h->intr[h->intr_mode], h->devname); + hpsa_free_irqs(h); return -ENODEV; } return 0; @@ -7033,15 +7060,11 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) kfree(h->ioaccel1_blockFetchTable); kfree(h->blockFetchTable); hpsa_free_reply_queues(h); - if (h->vaddr) - iounmap(h->vaddr); - if (h->transtable) - iounmap(h->transtable); - if (h->cfgtable) - iounmap(h->cfgtable); - hpsa_disable_interrupt_mode(h); + hpsa_free_cfgtables(h); /* pci_init 4 */ + iounmap(h->vaddr); /* pci_init 3 */ + hpsa_disable_interrupt_mode(h); /* pci_init 2 */ pci_disable_device(h->pdev); - pci_release_regions(h->pdev); + pci_release_regions(h->pdev); /* pci_init 2 */ kfree(h); } @@ -7358,7 +7381,7 @@ reinit_after_soft_reset: dac = 0; } else { dev_err(&pdev->dev, "no suitable DMA available\n"); - goto clean1; + goto clean2; } } @@ -7469,6 +7492,7 @@ clean4: clean2_and_free_irqs: hpsa_free_irqs(h); clean2: + hpsa_free_pci_init(h); clean1: if (h->resubmit_wq) destroy_workqueue(h->resubmit_wq); @@ -7560,12 +7584,10 @@ static void hpsa_remove_one(struct pci_dev *pdev) destroy_workqueue(h->resubmit_wq); hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */ - /* includes hpsa_free_irqs and hpsa_disable_interrupt_mode */ + /* includes hpsa_free_irqs */ + /* includes hpsa_disable_interrupt_mode - pci_init 2 */ hpsa_shutdown(pdev); - iounmap(h->vaddr); - iounmap(h->transtable); - iounmap(h->cfgtable); hpsa_free_device_info(h); hpsa_free_sg_chain_blocks(h); pci_free_consistent(h->pdev, @@ -7580,8 +7602,10 @@ static void hpsa_remove_one(struct pci_dev *pdev) kfree(h->ioaccel1_blockFetchTable); kfree(h->ioaccel2_blockFetchTable); kfree(h->hba_inquiry_data); - pci_disable_device(pdev); - pci_release_regions(pdev); + + /* includes hpsa_disable_interrupt_mode - pci_init 2 */ + hpsa_free_pci_init(h); + free_percpu(h->lockup_detected); kfree(h); }