Skip to content

Commit 5558b92

Browse files
AlisonSchofielddjbw
authored andcommitted
cxl/core: Always hold region_rwsem while reading poison lists
A read of a device poison list is triggered via a sysfs attribute and the results are logged as kernel trace events of type cxl_poison. The work is managed by either: a) the region driver when one of more regions map the device, or by b) the memdev driver when no regions map the device. In the case of a) the region driver holds the region_rwsem while reading the poison by committed endpoint decoder mappings and for any unmapped resources. This makes sure that the cxl_poison trace event trace reports valid region info. (Region name, HPA, and UUID). In the case of b) the memdev driver holds the dpa_rwsem preventing new DPA resources from being attached to a region. However, it leaves a gap between region attach and decoder commit actions. If a DPA in the gap is in the poison list, the cxl_poison trace event will omit the region info. Close the gap by holding the region_rwsem and the dpa_rwsem when reading poison per memdev. Since both methods now hold both locks, down_read both from the caller. Doing so also addresses the lockdep assert that found this issue: Commit 458ba81 ("cxl: Add cxl_decoders_committed() helper") Fixes: f0832a5 ("cxl/region: Provide region info to the cxl_poison trace event") Signed-off-by: Alison Schofield <alison.schofield@intel.com> Reviewed-by: Davidlohr Bueso <dave@stgolabs.net> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/08e8e7ec9a3413b91d51de39e385653494b1eed0.1701041440.git.alison.schofield@intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 36a1c2e commit 5558b92

File tree

2 files changed

+8
-6
lines changed

2 files changed

+8
-6
lines changed

drivers/cxl/core/memdev.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,16 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
227227
if (!port || !is_cxl_endpoint(port))
228228
return -EINVAL;
229229

230-
rc = down_read_interruptible(&cxl_dpa_rwsem);
230+
rc = down_read_interruptible(&cxl_region_rwsem);
231231
if (rc)
232232
return rc;
233233

234+
rc = down_read_interruptible(&cxl_dpa_rwsem);
235+
if (rc) {
236+
up_read(&cxl_region_rwsem);
237+
return rc;
238+
}
239+
234240
if (cxl_num_decoders_committed(port) == 0) {
235241
/* No regions mapped to this memdev */
236242
rc = cxl_get_poison_by_memdev(cxlmd);
@@ -239,6 +245,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
239245
rc = cxl_get_poison_by_endpoint(port);
240246
}
241247
up_read(&cxl_dpa_rwsem);
248+
up_read(&cxl_region_rwsem);
242249

243250
return rc;
244251
}

drivers/cxl/core/region.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,10 +2467,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
24672467
struct cxl_poison_context ctx;
24682468
int rc = 0;
24692469

2470-
rc = down_read_interruptible(&cxl_region_rwsem);
2471-
if (rc)
2472-
return rc;
2473-
24742470
ctx = (struct cxl_poison_context) {
24752471
.port = port
24762472
};
@@ -2480,7 +2476,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
24802476
rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
24812477
&ctx);
24822478

2483-
up_read(&cxl_region_rwsem);
24842479
return rc;
24852480
}
24862481

0 commit comments

Comments
 (0)