mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 07:23:14 +00:00
cxl fixes for 6.2-rc6
- Fix a crash regression due to module load order of cxl_pmem.ko - Fix wrong register offset read in CXL AER handling path -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQSbo+XnGs+rwLz9XGXfioYZHlFsZwUCY9W0XwAKCRDfioYZHlFs Z9y9AQDQXnlfFuVrSZ27lM53U+ZKQJWXV8SnPlcvbWbnVJb5owEA9J5p5ZCT0mHq sRFVgJoAlU73p39lcJoX8/ZP6OI6sgU= =bzei -----END PGP SIGNATURE----- Merge tag 'cxl-fixes-for-6.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl Pull cxl fixes from Dan Williams: "A couple of fixes for bugs introduced during the merge window. One is a regression, the other was a bug in the CXL AER handler: - Fix a crash regression due to module load order of cxl_pmem.ko - Fix wrong register offset read in CXL AER handling path" * tag 'cxl-fixes-for-6.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: cxl/pmem: Fix nvdimm unregistration when cxl_pmem driver is absent cxl: fix cxl_report_and_clear() RAS UE addr mis-assignment
This commit is contained in:
commit
803929285a
@ -736,4 +736,3 @@ module_exit(cxl_acpi_exit);
|
|||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_IMPORT_NS(CXL);
|
MODULE_IMPORT_NS(CXL);
|
||||||
MODULE_IMPORT_NS(ACPI);
|
MODULE_IMPORT_NS(ACPI);
|
||||||
MODULE_SOFTDEP("pre: cxl_pmem");
|
|
||||||
|
@ -227,34 +227,16 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_nvdimm_bridge *cxl_nvb,
|
|||||||
return cxl_nvd;
|
return cxl_nvd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cxl_nvd_unregister(void *_cxl_nvd)
|
|
||||||
{
|
|
||||||
struct cxl_nvdimm *cxl_nvd = _cxl_nvd;
|
|
||||||
struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
|
|
||||||
struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Either the bridge is in ->remove() context under the device_lock(),
|
|
||||||
* or cxlmd_release_nvdimm() is cancelling the bridge's release action
|
|
||||||
* for @cxl_nvd and doing it itself (while manually holding the bridge
|
|
||||||
* lock).
|
|
||||||
*/
|
|
||||||
device_lock_assert(&cxl_nvb->dev);
|
|
||||||
cxl_nvd->cxlmd = NULL;
|
|
||||||
cxlmd->cxl_nvd = NULL;
|
|
||||||
device_unregister(&cxl_nvd->dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cxlmd_release_nvdimm(void *_cxlmd)
|
static void cxlmd_release_nvdimm(void *_cxlmd)
|
||||||
{
|
{
|
||||||
struct cxl_memdev *cxlmd = _cxlmd;
|
struct cxl_memdev *cxlmd = _cxlmd;
|
||||||
|
struct cxl_nvdimm *cxl_nvd = cxlmd->cxl_nvd;
|
||||||
struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
|
struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
|
||||||
|
|
||||||
device_lock(&cxl_nvb->dev);
|
cxl_nvd->cxlmd = NULL;
|
||||||
if (cxlmd->cxl_nvd)
|
cxlmd->cxl_nvd = NULL;
|
||||||
devm_release_action(&cxl_nvb->dev, cxl_nvd_unregister,
|
cxlmd->cxl_nvb = NULL;
|
||||||
cxlmd->cxl_nvd);
|
device_unregister(&cxl_nvd->dev);
|
||||||
device_unlock(&cxl_nvb->dev);
|
|
||||||
put_device(&cxl_nvb->dev);
|
put_device(&cxl_nvb->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,22 +275,6 @@ int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd)
|
|||||||
|
|
||||||
dev_dbg(&cxlmd->dev, "register %s\n", dev_name(dev));
|
dev_dbg(&cxlmd->dev, "register %s\n", dev_name(dev));
|
||||||
|
|
||||||
/*
|
|
||||||
* The two actions below arrange for @cxl_nvd to be deleted when either
|
|
||||||
* the top-level PMEM bridge goes down, or the endpoint device goes
|
|
||||||
* through ->remove().
|
|
||||||
*/
|
|
||||||
device_lock(&cxl_nvb->dev);
|
|
||||||
if (cxl_nvb->dev.driver)
|
|
||||||
rc = devm_add_action_or_reset(&cxl_nvb->dev, cxl_nvd_unregister,
|
|
||||||
cxl_nvd);
|
|
||||||
else
|
|
||||||
rc = -ENXIO;
|
|
||||||
device_unlock(&cxl_nvb->dev);
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
goto err_alloc;
|
|
||||||
|
|
||||||
/* @cxlmd carries a reference on @cxl_nvb until cxlmd_release_nvdimm */
|
/* @cxlmd carries a reference on @cxl_nvb until cxlmd_release_nvdimm */
|
||||||
return devm_add_action_or_reset(&cxlmd->dev, cxlmd_release_nvdimm, cxlmd);
|
return devm_add_action_or_reset(&cxlmd->dev, cxlmd_release_nvdimm, cxlmd);
|
||||||
|
|
||||||
|
@ -554,8 +554,11 @@ static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
|
|||||||
|
|
||||||
/* If multiple errors, log header points to first error from ctrl reg */
|
/* If multiple errors, log header points to first error from ctrl reg */
|
||||||
if (hweight32(status) > 1) {
|
if (hweight32(status) > 1) {
|
||||||
addr = cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
|
void __iomem *rcc_addr =
|
||||||
fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, readl(addr)));
|
cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
|
||||||
|
|
||||||
|
fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK,
|
||||||
|
readl(rcc_addr)));
|
||||||
} else {
|
} else {
|
||||||
fe = status;
|
fe = status;
|
||||||
}
|
}
|
||||||
|
@ -225,11 +225,35 @@ static int cxl_pmem_ctl(struct nvdimm_bus_descriptor *nd_desc,
|
|||||||
return cxl_pmem_nvdimm_ctl(nvdimm, cmd, buf, buf_len);
|
return cxl_pmem_nvdimm_ctl(nvdimm, cmd, buf, buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int detach_nvdimm(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
struct cxl_nvdimm *cxl_nvd;
|
||||||
|
bool release = false;
|
||||||
|
|
||||||
|
if (!is_cxl_nvdimm(dev))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
device_lock(dev);
|
||||||
|
if (!dev->driver)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
cxl_nvd = to_cxl_nvdimm(dev);
|
||||||
|
if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data)
|
||||||
|
release = true;
|
||||||
|
out:
|
||||||
|
device_unlock(dev);
|
||||||
|
if (release)
|
||||||
|
device_release_driver(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void unregister_nvdimm_bus(void *_cxl_nvb)
|
static void unregister_nvdimm_bus(void *_cxl_nvb)
|
||||||
{
|
{
|
||||||
struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb;
|
struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb;
|
||||||
struct nvdimm_bus *nvdimm_bus = cxl_nvb->nvdimm_bus;
|
struct nvdimm_bus *nvdimm_bus = cxl_nvb->nvdimm_bus;
|
||||||
|
|
||||||
|
bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb, detach_nvdimm);
|
||||||
|
|
||||||
cxl_nvb->nvdimm_bus = NULL;
|
cxl_nvb->nvdimm_bus = NULL;
|
||||||
nvdimm_bus_unregister(nvdimm_bus);
|
nvdimm_bus_unregister(nvdimm_bus);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user