Skip to content

Commit

Permalink
cxl/core: Always hold region_rwsem while reading poison lists
Browse files Browse the repository at this point in the history
[ Upstream commit 5558b92 ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
AlisonSchofield authored and gregkh committed Jan 10, 2024
1 parent 07f9a20 commit 4c26935
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 6 deletions.
9 changes: 8 additions & 1 deletion drivers/cxl/core/memdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,16 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
if (!port || !is_cxl_endpoint(port))
return -EINVAL;

rc = down_read_interruptible(&cxl_dpa_rwsem);
rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;

rc = down_read_interruptible(&cxl_dpa_rwsem);
if (rc) {
up_read(&cxl_region_rwsem);
return rc;
}

if (cxl_num_decoders_committed(port) == 0) {
/* No regions mapped to this memdev */
rc = cxl_get_poison_by_memdev(cxlmd);
Expand All @@ -239,6 +245,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
rc = cxl_get_poison_by_endpoint(port);
}
up_read(&cxl_dpa_rwsem);
up_read(&cxl_region_rwsem);

return rc;
}
Expand Down
5 changes: 0 additions & 5 deletions drivers/cxl/core/region.c
Original file line number Diff line number Diff line change
Expand Up @@ -2467,10 +2467,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
struct cxl_poison_context ctx;
int rc = 0;

rc = down_read_interruptible(&cxl_region_rwsem);
if (rc)
return rc;

ctx = (struct cxl_poison_context) {
.port = port
};
Expand All @@ -2480,7 +2476,6 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
&ctx);

up_read(&cxl_region_rwsem);
return rc;
}

Expand Down

0 comments on commit 4c26935

Please sign in to comment.