Skip to content

Commit 1fd99fe

Browse files
committed
NVIDIA: VR: SAUCE: cxl/region: Avoid attach action self-deadlock
devm_add_action_or_reset() synchronously invokes endpoint_unregister_region() on allocation failure while cxl_memdev_attach_region() still holds cxl_rwsem.region for read. Region teardown then tries to acquire that lock for write and self-deadlocks. Use devm_add_action() and, on failure, leave the region and DPA read-lock scope before invoking endpoint_unregister_region() directly. Keep the endpoint device locked so the topology remains stable while the failed action registration is unwound. Fixes: a2305bb ("NVIDIA: VR: SAUCE: cxl: Backport the mainline Type-2 memdev lifetime model") Signed-off-by: Nirmoy Das <nirmoyd@nvidia.com>
1 parent a2305bb commit 1fd99fe

1 file changed

Lines changed: 45 additions & 37 deletions

File tree

drivers/cxl/core/region.c

Lines changed: 45 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4322,54 +4322,62 @@ int cxl_memdev_attach_region(struct cxl_memdev *cxlmd)
43224322
struct cxl_endpoint_decoder *cxled;
43234323
struct cxl_region *cxlr;
43244324
int rc;
4325+
43254326
/* hold endpoint lock to setup autoremove of the region */
43264327
guard(device)(&endpoint->dev);
43274328
if (!endpoint->dev.driver)
43284329
return -ENXIO;
4329-
guard(rwsem_read)(&cxl_rwsem.region);
4330-
guard(rwsem_read)(&cxl_rwsem.dpa);
43314330

4332-
/*
4333-
* TODO auto-instantiate a region, for now assume this will find an
4334-
* auto-region
4335-
*/
4336-
struct device *dev __free(put_device) =
4337-
device_find_child(&endpoint->dev, NULL, first_mapped_decoder);
4331+
{
4332+
guard(rwsem_read)(&cxl_rwsem.region);
4333+
guard(rwsem_read)(&cxl_rwsem.dpa);
43384334

4339-
if (!dev) {
4340-
dev_dbg(cxlmd->cxlds->dev, "no region found for memdev %s\n",
4341-
dev_name(&cxlmd->dev));
4342-
return -ENXIO;
4343-
}
4335+
/*
4336+
* TODO auto-instantiate a region, for now assume this will find an
4337+
* auto-region
4338+
*/
4339+
struct device *dev __free(put_device) =
4340+
device_find_child(&endpoint->dev, NULL,
4341+
first_mapped_decoder);
4342+
4343+
if (!dev) {
4344+
dev_dbg(cxlmd->cxlds->dev,
4345+
"no region found for memdev %s\n",
4346+
dev_name(&cxlmd->dev));
4347+
return -ENXIO;
4348+
}
43444349

4345-
cxled = to_cxl_endpoint_decoder(dev);
4346-
cxlr = cxled->cxld.region;
4350+
cxled = to_cxl_endpoint_decoder(dev);
4351+
cxlr = cxled->cxld.region;
43474352

4348-
if (cxlr->params.state < CXL_CONFIG_COMMIT) {
4349-
dev_dbg(cxlmd->cxlds->dev,
4350-
"region %s not committed for memdev %s\n",
4351-
dev_name(&cxlr->dev), dev_name(&cxlmd->dev));
4352-
return -ENXIO;
4353-
}
4353+
if (cxlr->params.state < CXL_CONFIG_COMMIT) {
4354+
dev_dbg(cxlmd->cxlds->dev,
4355+
"region %s not committed for memdev %s\n",
4356+
dev_name(&cxlr->dev), dev_name(&cxlmd->dev));
4357+
return -ENXIO;
4358+
}
43544359

4355-
if (cxlr->params.nr_targets > 1) {
4356-
dev_dbg(cxlmd->cxlds->dev,
4357-
"Only attach to local non-interleaved region\n");
4358-
return -ENXIO;
4359-
}
4360+
if (cxlr->params.nr_targets > 1) {
4361+
dev_dbg(cxlmd->cxlds->dev,
4362+
"Only attach to local non-interleaved region\n");
4363+
return -ENXIO;
4364+
}
43604365

4361-
/* Only teardown regions that pass validation, ignore the rest */
4362-
get_device(&cxlr->dev);
4363-
rc = devm_add_action_or_reset(&endpoint->dev,
4364-
endpoint_unregister_region, cxlr);
4365-
if (rc)
4366-
return rc;
4366+
/* Only teardown regions that pass validation, ignore the rest */
4367+
get_device(&cxlr->dev);
4368+
rc = devm_add_action(&endpoint->dev,
4369+
endpoint_unregister_region, cxlr);
4370+
if (!rc) {
4371+
attach->hpa_range = (struct range) {
4372+
.start = cxlr->params.res->start,
4373+
.end = cxlr->params.res->end,
4374+
};
4375+
return 0;
4376+
}
4377+
}
43674378

4368-
attach->hpa_range = (struct range) {
4369-
.start = cxlr->params.res->start,
4370-
.end = cxlr->params.res->end,
4371-
};
4372-
return 0;
4379+
endpoint_unregister_region(cxlr);
4380+
return rc;
43734381
}
43744382
EXPORT_SYMBOL_FOR_MODULES(cxl_memdev_attach_region, "cxl_mem");
43754383

0 commit comments

Comments
 (0)