[ndctl PATCH v3 6/7] cxl/list: Add injectable errors in output

Ben Cheatham
2025-10-21T18:33:14Z

Add the "--injectable-errors"/"-N" option to show injectable error
information for CXL devices. The applicable devices are CXL memory
devices and CXL busses.

For CXL memory devices the option reports whether the device supports
poison injection (the "--media-errors"/"-L" option shows injected
poison).

For CXL busses the option shows injectable CXL protocol error types. The
information will be the same across busses because the error types are
system-wide. The information is presented under the bus for easier
filtering.

Update the man page for 'cxl-list' to show the usage of the new option.

Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
Documentation/cxl/cxl-list.txt | 35 +++++++++++++++++++++++++++++++++-
cxl/filter.h | 3 +++
cxl/json.c | 30 +++++++++++++++++++++++++++++
cxl/list.c | 3 +++
util/json.h | 1 +
5 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
index 0595638..35ff542 100644
--- a/Documentation/cxl/cxl-list.txt
+++ b/Documentation/cxl/cxl-list.txt
@@ -471,6 +471,38 @@ The media-errors option is only available with '-Dlibtracefs=enabled'.
}
----

+-N::
+--injectable-errors::
+ Include injectable error information in the output. For CXL memory devices
+ this includes whether poison is injectable through the kernel debug filesystem.
+ The types of CXL protocol errors available for injection into downstream ports
+ are listed as part of a CXL bus object.
+
+----
+# cxl list -NB
+[
+ {
+ "bus":"root0",
+ "provider":"ACPI.CXL",
+ "injectable_protocol_errors":[
+ "mem-correctable",
+ "mem-fatal",
+ ]
+ }
+]
+
+# cxl list -N
+[
+ {
+ "memdev":"mem0",
+ "pmem_size":268435456,
+ "ram_size":268435456,
+ "serial":2,
+ "poison_injectable":true
+ }
+]
+
+----
-v::
--verbose::
Increase verbosity of the output. This can be specified
@@ -487,7 +519,8 @@ The media-errors option is only available with '-Dlibtracefs=enabled'.
devices with --idle.
- *-vvv*
Everything *-vv* provides, plus enable
- --health, --partition, and --media-errors.
+ --health, --partition, --media-errors, and
+ --injectable-errors.

--debug::
If the cxl tool was built with debug enabled, turn on debug
diff --git a/cxl/filter.h b/cxl/filter.h
index 956a46e..34f8387 100644
--- a/cxl/filter.h
+++ b/cxl/filter.h
@@ -31,6 +31,7 @@ struct cxl_filter_params {
bool alert_config;
bool dax;
bool media_errors;
+ bool inj_errors;
int verbose;
struct log_ctx ctx;
};
@@ -91,6 +92,8 @@ static inline unsigned long cxl_filter_to_flags(struct cxl_filter_params *param)
flags |= UTIL_JSON_DAX | UTIL_JSON_DAX_DEVS;
if (param->media_errors)
flags |= UTIL_JSON_MEDIA_ERRORS;
+ if (param->inj_errors)
+ flags |= UTIL_JSON_INJ_ERRORS;
return flags;
}

diff --git a/cxl/json.c b/cxl/json.c
index bde4589..2917477 100644
--- a/cxl/json.c
+++ b/cxl/json.c
@@ -675,6 +675,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
json_object_object_add(jdev, "firmware", jobj);
}

+ if (flags & UTIL_JSON_INJ_ERRORS) {
+ jobj = json_object_new_boolean(cxl_memdev_has_poison_injection(memdev));
+ if (jobj)
+ json_object_object_add(jdev, "poison_injectable", jobj);
+ }
+
if (flags & UTIL_JSON_MEDIA_ERRORS) {
jobj = util_cxl_poison_list_to_json(NULL, memdev, flags);
if (jobj)
@@ -750,6 +756,8 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
unsigned long flags)
{
const char *devname = cxl_bus_get_devname(bus);
+ struct cxl_ctx *ctx = cxl_bus_get_ctx(bus);
+ struct cxl_protocol_error *perror;
struct json_object *jbus, *jobj;

jbus = json_object_new_object();
@@ -765,6 +773,28 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
json_object_object_add(jbus, "provider", jobj);

json_object_set_userdata(jbus, bus, NULL);
+
+ if (flags & UTIL_JSON_INJ_ERRORS) {
+ jobj = json_object_new_array();
+ if (!jobj)
+ return jbus;
+
+ cxl_protocol_error_foreach(ctx, perror)
+ {
+ struct json_object *jerr_str;
+ const char *perror_str;
+
+ perror_str = cxl_protocol_error_get_str(perror);
+
+ jerr_str = json_object_new_string(perror_str);
+ if (jerr_str)
+ json_object_array_add(jobj, jerr_str);
+ }
+
+ json_object_object_add(jbus, "injectable_protocol_errors",
+ jobj);
+ }
+
return jbus;
}

diff --git a/cxl/list.c b/cxl/list.c
index 0b25d78..a505ed6 100644
--- a/cxl/list.c
+++ b/cxl/list.c
@@ -59,6 +59,8 @@ static const struct option options[] = {
"include alert configuration information"),
OPT_BOOLEAN('L', "media-errors", &param.media_errors,
"include media-error information "),
+ OPT_BOOLEAN('N', "injectable-errors", &param.inj_errors,
+ "include injectable error information"),
OPT_INCR('v', "verbose", &param.verbose, "increase output detail"),
#ifdef ENABLE_DEBUG
OPT_BOOLEAN(0, "debug", &debug, "debug list walk"),
@@ -124,6 +126,7 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
param.alert_config = true;
param.dax = true;
param.media_errors = true;
+ param.inj_errors = true;
/* fallthrough */
case 2:
param.idle = true;
diff --git a/util/json.h b/util/json.h
index 560f845..57278cb 100644
--- a/util/json.h
+++ b/util/json.h
@@ -21,6 +21,7 @@ enum util_json_flags {
UTIL_JSON_TARGETS = (1 << 11),
UTIL_JSON_PARTITION = (1 << 12),
UTIL_JSON_ALERT_CONFIG = (1 << 13),
+ UTIL_JSON_INJ_ERRORS = (1 << 14),
};

void util_display_json_array(FILE *f_out, struct json_object *jarray,
--
2.34.1