Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+34 -42
-1
drivers/cxl/acpi.c
··· 736 736 MODULE_LICENSE("GPL v2"); 737 737 MODULE_IMPORT_NS(CXL); 738 738 MODULE_IMPORT_NS(ACPI); 739 - MODULE_SOFTDEP("pre: cxl_pmem");
+5 -39
drivers/cxl/core/pmem.c
··· 227 227 return cxl_nvd; 228 228 } 229 229 230 - static void cxl_nvd_unregister(void *_cxl_nvd) 231 - { 232 - struct cxl_nvdimm *cxl_nvd = _cxl_nvd; 233 - struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; 234 - struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb; 235 - 236 - /* 237 - * Either the bridge is in ->remove() context under the device_lock(), 238 - * or cxlmd_release_nvdimm() is cancelling the bridge's release action 239 - * for @cxl_nvd and doing it itself (while manually holding the bridge 240 - * lock). 241 - */ 242 - device_lock_assert(&cxl_nvb->dev); 243 - cxl_nvd->cxlmd = NULL; 244 - cxlmd->cxl_nvd = NULL; 245 - device_unregister(&cxl_nvd->dev); 246 - } 247 - 248 230 static void cxlmd_release_nvdimm(void *_cxlmd) 249 231 { 250 232 struct cxl_memdev *cxlmd = _cxlmd; 233 + struct cxl_nvdimm *cxl_nvd = cxlmd->cxl_nvd; 251 234 struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb; 252 235 253 - device_lock(&cxl_nvb->dev); 254 - if (cxlmd->cxl_nvd) 255 - devm_release_action(&cxl_nvb->dev, cxl_nvd_unregister, 256 - cxlmd->cxl_nvd); 257 - device_unlock(&cxl_nvb->dev); 236 + cxl_nvd->cxlmd = NULL; 237 + cxlmd->cxl_nvd = NULL; 238 + cxlmd->cxl_nvb = NULL; 239 + device_unregister(&cxl_nvd->dev); 258 240 put_device(&cxl_nvb->dev); 259 241 } 260 242 ··· 274 292 goto err; 275 293 276 294 dev_dbg(&cxlmd->dev, "register %s\n", dev_name(dev)); 277 - 278 - /* 279 - * The two actions below arrange for @cxl_nvd to be deleted when either 280 - * the top-level PMEM bridge goes down, or the endpoint device goes 281 - * through ->remove(). 282 - */ 283 - device_lock(&cxl_nvb->dev); 284 - if (cxl_nvb->dev.driver) 285 - rc = devm_add_action_or_reset(&cxl_nvb->dev, cxl_nvd_unregister, 286 - cxl_nvd); 287 - else 288 - rc = -ENXIO; 289 - device_unlock(&cxl_nvb->dev); 290 - 291 - if (rc) 292 - goto err_alloc; 293 295 294 296 /* @cxlmd carries a reference on @cxl_nvb until cxlmd_release_nvdimm */ 295 297 return devm_add_action_or_reset(&cxlmd->dev, cxlmd_release_nvdimm, cxlmd);
+5 -2
drivers/cxl/pci.c
··· 554 554 555 555 /* If multiple errors, log header points to first error from ctrl reg */ 556 556 if (hweight32(status) > 1) { 557 - addr = cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET; 558 - fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, readl(addr))); 557 + void __iomem *rcc_addr = 558 + cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET; 559 + 560 + fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, 561 + readl(rcc_addr))); 559 562 } else { 560 563 fe = status; 561 564 }
+24
drivers/cxl/pmem.c
··· 225 225 return cxl_pmem_nvdimm_ctl(nvdimm, cmd, buf, buf_len); 226 226 } 227 227 228 + static int detach_nvdimm(struct device *dev, void *data) 229 + { 230 + struct cxl_nvdimm *cxl_nvd; 231 + bool release = false; 232 + 233 + if (!is_cxl_nvdimm(dev)) 234 + return 0; 235 + 236 + device_lock(dev); 237 + if (!dev->driver) 238 + goto out; 239 + 240 + cxl_nvd = to_cxl_nvdimm(dev); 241 + if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data) 242 + release = true; 243 + out: 244 + device_unlock(dev); 245 + if (release) 246 + device_release_driver(dev); 247 + return 0; 248 + } 249 + 228 250 static void unregister_nvdimm_bus(void *_cxl_nvb) 229 251 { 230 252 struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb; 231 253 struct nvdimm_bus *nvdimm_bus = cxl_nvb->nvdimm_bus; 254 + 255 + bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb, detach_nvdimm); 232 256 233 257 cxl_nvb->nvdimm_bus = NULL; 234 258 nvdimm_bus_unregister(nvdimm_bus);