From: Matthew R. Ochs Date: Wed, 21 Oct 2015 20:16:00 +0000 (-0500) Subject: cxlflash: Fix to avoid leaving dangling interrupt resources X-Git-Tag: v4.4-rc1~12^2~37 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ee3491ba8f1f7e7cc1302d727ee7055e5c748524;p=platform%2Fkernel%2Flinux-exynos.git cxlflash: Fix to avoid leaving dangling interrupt resources When running with an unsupported AFU, the cxlflash driver fails the probe. When the driver is removed, the following Oops is encountered on a show_interrupts() thread: Call Trace: [c000001fba5a7a10] [0000000000000003] 0x3 (unreliable) [c000001fba5a7a60] [c00000000053dcf4] vsnprintf+0x204/0x4c0 [c000001fba5a7ae0] [c00000000030045c] seq_vprintf+0x5c/0xd0 [c000001fba5a7b20] [c00000000030051c] seq_printf+0x4c/0x60 [c000001fba5a7b50] [c00000000013e140] show_interrupts+0x370/0x4f0 [c000001fba5a7c10] [c0000000002ff898] seq_read+0xe8/0x530 [c000001fba5a7ca0] [c00000000035d5c0] proc_reg_read+0xb0/0x110 [c000001fba5a7cf0] [c0000000002ca74c] __vfs_read+0x6c/0x180 [c000001fba5a7d90] [c0000000002cb464] vfs_read+0xa4/0x1c0 [c000001fba5a7de0] [c0000000002cc51c] SyS_read+0x6c/0x110 [c000001fba5a7e30] [c000000000009204] system_call+0x38/0xb4 The Oops is due to not cleaning up correctly on the unsupported AFU error path, leaving various allocated and registered resources. In this case, interrupts are in a semi-allocated/registered state, which the show_interrupts() thread attempts to use. To fix, the cleanup logic in init_afu() is consolidated to error gates at the bottom of the function and the appropriate goto is added to each error path. As a mini side fix while refactoring in this routine, the else statement following the AFU version evaluation is eliminated as it is not needed. Signed-off-by: Matthew R. Ochs Acked-by: Manoj Kumar Reviewed-by: Andrew Donnellan Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 998373e..c152703 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -1721,15 +1721,14 @@ static int init_afu(struct cxlflash_cfg *cfg) if (rc) { dev_err(dev, "%s: call to init_mc failed, rc=%d!\n", __func__, rc); - goto err1; + goto out; } /* Map the entire MMIO space of the AFU */ afu->afu_map = cxl_psa_map(cfg->mcctx); if (!afu->afu_map) { - rc = -ENOMEM; - term_mc(cfg, UNDO_START); dev_err(dev, "%s: call to cxl_psa_map failed!\n", __func__); + rc = -ENOMEM; goto err1; } @@ -1743,19 +1742,17 @@ static int init_afu(struct cxlflash_cfg *cfg) "interface version 0x%llx\n", afu->version, afu->interface_version); rc = -EINVAL; - goto err1; - } else - pr_debug("%s: afu version %s, interface version 0x%llX\n", - __func__, afu->version, afu->interface_version); + goto err2; + } + + pr_debug("%s: afu version %s, interface version 0x%llX\n", __func__, + afu->version, afu->interface_version); rc = start_afu(cfg); if (rc) { dev_err(dev, "%s: call to start_afu failed, rc=%d!\n", __func__, rc); - term_mc(cfg, UNDO_START); - cxl_psa_unmap((void __iomem *)afu->afu_map); - afu->afu_map = NULL; - goto err1; + goto err2; } afu_err_intr_init(cfg->afu); @@ -1763,9 +1760,16 @@ static int init_afu(struct cxlflash_cfg *cfg) /* Restore the LUN mappings */ cxlflash_restore_luntable(cfg); -err1: +out: pr_debug("%s: returning rc=%d\n", __func__, rc); return rc; + +err2: + cxl_psa_unmap((void __iomem *)afu->afu_map); + afu->afu_map = NULL; +err1: + term_mc(cfg, UNDO_START); + goto out; } /**