summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuixin Liu <kanie@linux.alibaba.com>2026-08-31 14:11:20 +0800
committerDave Jiang <dave.jiang@intel.com>2026-09-17 20:05:17 -0700
commitbb26797c08d408ea7e8d3625045f0fe28714a425 (patch)
tree448064924812364b646f5624c64f0f041c8520d7
parent0de71a1ab211694be7e88d56fc35c9bf72078ad1 (diff)
downloadlinux-next-bb26797c08d408ea7e8d3625045f0fe28714a425.tar.gz
linux-next-bb26797c08d408ea7e8d3625045f0fe28714a425.zip
cxl/region: Unregister the pmem region when the bridge is unbound
Removing cxl_acpi unbinds the nvdimm bridge before the regions it serves. A region probe can therefore register its cxl_pmem_region and only then find the bridge unbound, which leaves the new device with nothing to remove it. The orphan outlives the teardown and pins its region and its memdevs, so a later cxl_acpi bind renumbers the root port, ports, endpoints, decoders and the memdev. Unregister the cxl_pmem_region when the bridge is unbound. Found by code inspection. Racing a cxl_region bind against a cxl_acpi unbind leaked a pmem_region device on 12 of 12 attempts, and none with this patch. Fixes: f17b558d6663 ("cxl/pmem: Refactor nvdimm device registration, delete the workqueue") Signed-off-by: Guixin Liu <kanie@linux.alibaba.com> Reviewed-by: Richard Cheng <icheng@nvidia.com> Reviewed-by: Li Ming <ming.li@zohomail.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://patch.msgid.link/20260831061120.200790-1-kanie@linux.alibaba.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
-rw-r--r--drivers/cxl/core/region_pmem.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/cxl/core/region_pmem.c b/drivers/cxl/core/region_pmem.c
index 23d97e3d78b6..7ab1373a95e0 100644
--- a/drivers/cxl/core/region_pmem.c
+++ b/drivers/cxl/core/region_pmem.c
@@ -168,12 +168,14 @@ int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
dev_name(dev));
scoped_guard(device, &cxl_nvb->dev) {
- if (cxl_nvb->dev.driver)
+ if (cxl_nvb->dev.driver) {
rc = devm_add_action_or_reset(&cxl_nvb->dev,
cxlr_pmem_unregister,
cxlr_pmem);
- else
+ } else {
rc = -ENXIO;
+ cxlr_pmem_unregister(cxlr_pmem);
+ }
}
if (rc)