Re: [RFC PATCH 2/3] cxl/region: Auto-create a region for memdev attach
[email protected] Wed, 05 Aug 2026 08:05:36 +0000
| Newsgroups | org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: New issues: - [Medium] Mixing goto-based error handling with __free() or guard() cleanup in the same function. Pre-existing issues: - [High] Self-deadlock in find_committed_attach_region() on the devm_add_action_or_reset() error path due to function-scoped read lock on cxl_rwsem.region. -- --- Patch [2]: [RFC PATCH 2/3] cxl/region: Auto-create a region for memdev attach --- commit 5faea7eff07e5a585a3f3dc3abd38f41084338fd Author: Richard Cheng <[email protected]> cxl/region: Auto-create a region for memdev attach devm_cxl_probe_mem() currently fails when FW has not committed a region, even when a Type-2 accelerator has usable CXL.mem capacity. This patch auto-creates a region when no mapped decoder exists by selecting a manual DEVMEM decoder and a compatible root decoder. > diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c > index 7fcaddc61180d..4ceabdfdd3b6a 100644 > --- a/drivers/cxl/core/region.c > +++ b/drivers/cxl/core/region.c [ ... ] > +static struct cxl_region * > +create_attach_region(struct cxl_endpoint_decoder *cxled, > + struct cxl_root_decoder *cxlrd, resource_size_t size) > +{ > + struct cxl_region *cxlr; > + int rc; > + > + guard(mutex)(&cxlrd->regions_lock); > + do { [ ... ] > + rc = device_attach(&cxlr->dev); > + if (rc <= 0) { > + if (!rc) > + rc = -ENXIO; > + goto err_unregister; > + } > + > + get_device(&cxlr->dev); > + return cxlr; > + > +err_unregister: > + unregister_region(cxlr, CXL_REGION_RESET_MANAGED_DETACH); > + return ERR_PTR(rc); > +} [Severity: Medium] Is it acceptable to mix guard() based cleanup with goto-based error handling in this function? According to the cleanup subsystem guidelines, functions should ideally use scope-based cleanup exclusively or goto-based cleanup exclusively to prevent complex ownership and LIFO ordering bugs. [ ... ] > +static int create_memdev_attach_region(struct cxl_memdev *cxlmd, > + struct cxl_attach_region *attach) > +{ > + struct cxl_port *endpoint = cxlmd->endpoint; > + struct device *decoder_dev __free(put_device) = NULL; > + struct cxl_endpoint_decoder *cxled; [ ... ] > + cxlrd = find_attach_root_decoder(cxled); > + if (IS_ERR(cxlrd)) { > + rc = PTR_ERR(cxlrd); > + dev_dbg(cxlmd->cxlds->dev, > + "no compatible Type-2 root decoder to auto-create a region for %s: %d\n", > + dev_name(&cxlmd->dev), rc); > + goto err_cleanup_dpa; > + } [Severity: Medium] Similar to create_attach_region() above, does mixing __free() and goto labels in the same function conflict with the cleanup subsystem expectations? [ ... ] > /* > - * Runs in cxl_mem_probe context after successful endpoint probe, assumes the > - * simple case of single mapped decoder per memdev. > + * Attach to a firmware-precommitted region already mapped to the endpoint. > + * Return 0 on success, -ENODEV when no region is present (the caller then > + * auto-creates one), or a negative errno for a present-but-unusable region. > */ > -int cxl_memdev_attach_region(struct cxl_memdev *cxlmd) > +static int find_committed_attach_region(struct cxl_memdev *cxlmd, > + struct cxl_attach_region *attach) > { > - struct cxl_attach_region *attach = > - container_of(cxlmd->attach, typeof(*attach), attach); > struct cxl_port *endpoint = cxlmd->endpoint; > struct cxl_endpoint_decoder *cxled; > struct cxl_region *cxlr; > int rc; > > - /* hold endpoint lock to setup autoremove of the region */ > - guard(device)(&endpoint->dev); > - if (!endpoint->dev.driver) > - return -ENXIO; > guard(rwsem_read)(&cxl_rwsem.region); > guard(rwsem_read)(&cxl_rwsem.dpa); [ ... ] > - /* Only teardown regions that pass validation, ignore the rest */ > + /* Only teardown regions that pass validation. */ > get_device(&cxlr->dev); > - rc = devm_add_action_or_reset(&endpoint->dev, > - endpoint_unregister_region, cxlr); > + rc = devm_add_action_or_reset(&endpoint->dev, endpoint_unregister_region, > + cxlr); > if (rc) > return rc; [Severity: High] This is a pre-existing issue, but can this devm_add_action_or_reset() trigger a self-deadlock on failure? Because the function scope is guarded by a read lock on cxl_rwsem.region: guard(rwsem_read)(&cxl_rwsem.region); If devm_add_action_or_reset() fails, it immediately executes its callback endpoint_unregister_region() inline. This callback eventually calls unregister_region() and detach_target(), which attempts to acquire a write lock on the same semaphore: ACQUIRE(rwsem_write_kill, rwsem)(&cxl_rwsem.region) Since the current thread already holds the function-scoped read lock, wouldn't this result in an ABBA-style self-deadlock? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=2