Message ID | f59b7ae3277342f54bbcf409ac075a9c122ecd79.1696196382.git.alison.schofield@intel.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Vishal Verma |
Headers | show |
Series | Support poison list retrieval | expand |
On Sun, 2023-10-01 at 15:31 -0700, alison.schofield@intel.com wrote: > From: Alison Schofield <alison.schofield@intel.com> > > CXL devices maintain a list of locations that are poisoned or result > in poison if the addresses are accessed by the host. > > Per the spec (CXL 3.0 8.2.9.8.4.1), the device returns the Poison > List as a set of Media Error Records that include the source of the > error, the starting device physical address and length. > > Trigger the retrieval of the poison list by writing to the memory > device sysfs attribute: trigger_poison_list. The CXL driver only > offers triggering per memdev, so the trigger by region interface > offered here is a convenience API that triggers a poison list > retrieval for each memdev contributing to a region. > > int cxl_memdev_trigger_poison_list(struct cxl_memdev *memdev); > int cxl_region_trigger_poison_list(struct cxl_region *region); > > The resulting poison records are logged as kernel trace events > named 'cxl_poison'. > > Signed-off-by: Alison Schofield <alison.schofield@intel.com> > --- > cxl/lib/libcxl.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ > cxl/lib/libcxl.sym | 6 ++++++ > cxl/libcxl.h | 2 ++ > 3 files changed, 55 insertions(+) > > diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c > index af4ca44eae19..2f6e64ea2ae7 100644 > --- a/cxl/lib/libcxl.c > +++ b/cxl/lib/libcxl.c > @@ -1647,6 +1647,53 @@ CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev) > return 0; > } > > +CXL_EXPORT int cxl_memdev_trigger_poison_list(struct cxl_memdev *memdev) > +{ > + struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); > + char *path = memdev->dev_buf; > + int len = memdev->buf_len, rc; > + > + if (snprintf(path, len, "%s/trigger_poison_list", memdev->dev_path) >= > + len) { I see this unfortunate line break Jonathan commented on still crept in, agreed that breaking up snprintf's args would look better.
On Wed, Nov 15, 2023 at 02:08:03AM -0800, Vishal Verma wrote: > On Sun, 2023-10-01 at 15:31 -0700, alison.schofield@intel.com wrote: snip > > +CXL_EXPORT int cxl_memdev_trigger_poison_list(struct cxl_memdev *memdev) > > +{ > > + struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); > > + char *path = memdev->dev_buf; > > + int len = memdev->buf_len, rc; > > + > > + if (snprintf(path, len, "%s/trigger_poison_list", memdev->dev_path) >= > > + len) { > > I see this unfortunate line break Jonathan commented on still crept in, > agreed that breaking up snprintf's args would look better. Fixed up in v3. Thanks! > >
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c index af4ca44eae19..2f6e64ea2ae7 100644 --- a/cxl/lib/libcxl.c +++ b/cxl/lib/libcxl.c @@ -1647,6 +1647,53 @@ CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev) return 0; } +CXL_EXPORT int cxl_memdev_trigger_poison_list(struct cxl_memdev *memdev) +{ + struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); + char *path = memdev->dev_buf; + int len = memdev->buf_len, rc; + + if (snprintf(path, len, "%s/trigger_poison_list", memdev->dev_path) >= + len) { + err(ctx, "%s: buffer too small\n", + cxl_memdev_get_devname(memdev)); + return -ENXIO; + } + rc = sysfs_write_attr(ctx, path, "1\n"); + if (rc < 0) { + fprintf(stderr, + "%s: Failed write sysfs attr trigger_poison_list\n", + cxl_memdev_get_devname(memdev)); + return rc; + } + return 0; +} + +CXL_EXPORT int cxl_region_trigger_poison_list(struct cxl_region *region) +{ + struct cxl_memdev_mapping *mapping; + int rc; + + cxl_mapping_foreach(region, mapping) { + struct cxl_decoder *decoder; + struct cxl_memdev *memdev; + + decoder = cxl_mapping_get_decoder(mapping); + if (!decoder) + continue; + + memdev = cxl_decoder_get_memdev(decoder); + if (!memdev) + continue; + + rc = cxl_memdev_trigger_poison_list(memdev); + if (rc) + return rc; + } + + return 0; +} + CXL_EXPORT int cxl_memdev_enable(struct cxl_memdev *memdev) { struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev); diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym index 8fa1cca3d0d7..277b7e21d6a6 100644 --- a/cxl/lib/libcxl.sym +++ b/cxl/lib/libcxl.sym @@ -264,3 +264,9 @@ global: cxl_memdev_update_fw; cxl_memdev_cancel_fw_update; } LIBCXL_5; + +LIBCXL_7 { +global: + cxl_memdev_trigger_poison_list; + cxl_region_trigger_poison_list; +} LIBCXL_6; diff --git a/cxl/libcxl.h b/cxl/libcxl.h index 0f4f4b2648fb..ecdffe36df2c 100644 --- a/cxl/libcxl.h +++ b/cxl/libcxl.h @@ -460,6 +460,8 @@ enum cxl_setpartition_mode { int cxl_cmd_partition_set_mode(struct cxl_cmd *cmd, enum cxl_setpartition_mode mode); +int cxl_memdev_trigger_poison_list(struct cxl_memdev *memdev); +int cxl_region_trigger_poison_list(struct cxl_region *region); #ifdef __cplusplus } /* extern "C" */