Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee3491ba authored by Matthew R. Ochs's avatar Matthew R. Ochs Committed by James Bottomley
Browse files

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: default avatarMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Acked-by: default avatarManoj Kumar <manoj@linux.vnet.ibm.com>
Reviewed-by: default avatarAndrew Donnellan <andrew.donnellan@au1.ibm.com>
Reviewed-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent aacb4ff6
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -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;
}

/**