* [ndctl PATCH v8 0/7] Add error injection support
@ 2026-02-06 21:50 Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 1/7] libcxl: Add debugfs path to CXL context Ben Cheatham
` (8 more replies)
0 siblings, 9 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
v8 Changes:
- Split inject-error command into 'inject-protocol-error', 'inject-media-poison' (Vishal, Alison)
- Rename 'cxl-clear-error' command to 'cxl-clear-media-poison' (Alison)
- Documentation rework to reflect new commands
- Cleaned up a few error prints
- Updated help messages
- Change "clear" param of poison_action() to "inj" and reverse usage accordingly
- Change cxl_memdev_has_poison_injection() to cxl_memdev_has_poison_support()
- Used in poison_action() (cxl/inject-error.c) to report missing functionality
more accurately
- Print usage when '-a' option is missing for media-poison commands
- Remove checking if '-a' option is empty in poison_action() (no longer needed)
- Allow clearing poison when 'inject_poison' file is missing in debugfs (and vice versa)
- Updated cover letter and commit messages
v7 Changes:
- Use PATH_MAX instead of strlen(ctx->cxl_debugfs) for debugfs paths (Dave)
- Add goto for error paths to memdev poison functions in patch 3/7 (Dave)
- Add Dave's Reviewed-by tags
v6 Changes:
- Rebase to pending branch (Alison)
- Drop const for ctx->debugfs (Alison)
- Rename get_debugfs_dir() to get_cxl_debugfs_dir() and return cxl directory in debugfs
(i.e. "/sys/kernel/debug" -> "/sys/kernel/debug/cxl")
- Rename ctx->debugfs to ctx->cxl_debugfs
- Fix missing free of einj path (Alison)
- Add protocol errors in order to perrors list (Alison)
- Use hex constants instead of BIT() for protocol errors (Alison)
- Add symbols to LIBCXL_11 instead of LIBCXL_10 (Alison)
- Update commit message to reflect util_cxl_dport_filter() behavior (Alison)
- Remove EINJ_TYPES_BUF_SIZE #ifdef (Alison)
- Fix type mismatch of addr in poison_action() (Alison)
- Fix inject_action() to catch missing 'type' option (Alison)
- Remove '-N' option and show the information behind that option by default when
CXL debugfs is present (Alison)
- Add 'protocol_injectable' attribute for dports (Alison)
- Update inject-error man page with port injection example (Alison)
- Add warning to inject-error man page (Alison)
v5 Changes:
- Use setmntent()/getmntent() instead of open-coding getting the
debugfs path (Dave)
- Use correct return code for sysfs_read_attr() (Dave)
This series adds support for injecting CXL protocol (CXL.cache/mem)
errors[1] into CXL RCH Downstream ports and VH root ports[2] and
poison into CXL memory devices through the CXL debugfs. Protocol errors
are injected using a new 'inject-protocol-error' command. Device poison
can be injected and cleared using the 'inject-media-poison' and
'clear-media-poison' commands, respectively. All three commands require
access to the CXL driver's debugfs.
The documentation for the new commands show both usage and the possible
device/error types, as well as how to retrieve them using cxl-list. cxl-list
has been updated to include the possible error types for protocol error
injection (under the "bus" object) and which CXL dports and memory devices
support injection.
[1]: ACPI v6.5 spec, section 18.6.4
[2]: ACPI v6.5 spec, table 18.31
Ben Cheatham (7):
libcxl: Add debugfs path to CXL context
libcxl: Add CXL protocol errors
libcxl: Add poison injection support
cxl: Add inject-protocol-error command
cxl: Add poison injection/clear commands
cxl/list: Add injectable errors in output
Documentation: Add docs for protocol and poison injection commands
Documentation/cxl/cxl-clear-media-poison.txt | 85 +++++
Documentation/cxl/cxl-inject-media-poison.txt | 85 +++++
.../cxl/cxl-inject-protocol-error.txt | 105 ++++++
Documentation/cxl/meson.build | 3 +
cxl/builtin.h | 3 +
cxl/cxl.c | 3 +
cxl/filter.c | 26 ++
cxl/filter.h | 2 +
cxl/inject-error.c | 312 +++++++++++++++++
cxl/json.c | 38 ++
cxl/lib/libcxl.c | 329 ++++++++++++++++++
cxl/lib/libcxl.sym | 10 +
cxl/lib/private.h | 14 +
cxl/libcxl.h | 18 +
cxl/meson.build | 1 +
15 files changed, 1034 insertions(+)
create mode 100644 Documentation/cxl/cxl-clear-media-poison.txt
create mode 100644 Documentation/cxl/cxl-inject-media-poison.txt
create mode 100644 Documentation/cxl/cxl-inject-protocol-error.txt
create mode 100644 cxl/inject-error.c
base-commit: 39085f76b6a9d3ac349c3c5dab1cb820c86a293d
--
2.52.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v8 1/7] libcxl: Add debugfs path to CXL context
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 2/7] libcxl: Add CXL protocol errors Ben Cheatham
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
Find the CXL debugfs mount point and add it to the CXL library context.
This will be used by poison and procotol error library functions to
access the information presented by the filesystem.
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
cxl/lib/libcxl.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index 32728de..6b7e92c 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -8,6 +8,8 @@
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
+#include <mntent.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -54,6 +56,7 @@ struct cxl_ctx {
struct kmod_ctx *kmod_ctx;
struct daxctl_ctx *daxctl_ctx;
void *private_data;
+ char *cxl_debugfs;
};
static void free_pmem(struct cxl_pmem *pmem)
@@ -240,6 +243,38 @@ CXL_EXPORT void *cxl_get_private_data(struct cxl_ctx *ctx)
return ctx->private_data;
}
+static char* get_cxl_debugfs_dir(void)
+{
+ char *debugfs_dir = NULL;
+ struct mntent *ent;
+ FILE *mntf;
+
+ mntf = setmntent("/proc/mounts", "r");
+ if (!mntf)
+ return NULL;
+
+ while ((ent = getmntent(mntf)) != NULL) {
+ if (!strcmp(ent->mnt_type, "debugfs")) {
+ /* Magic '5' here is length of "/cxl" + NULL terminator */
+ debugfs_dir = calloc(strlen(ent->mnt_dir) + 5, 1);
+ if (!debugfs_dir)
+ return NULL;
+
+ strcpy(debugfs_dir, ent->mnt_dir);
+ strcat(debugfs_dir, "/cxl");
+ if (access(debugfs_dir, F_OK) != 0) {
+ free(debugfs_dir);
+ debugfs_dir = NULL;
+ }
+
+ break;
+ }
+ }
+
+ endmntent(mntf);
+ return debugfs_dir;
+}
+
/**
* cxl_new - instantiate a new library context
* @ctx: context to establish
@@ -295,6 +330,7 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
c->udev = udev;
c->udev_queue = udev_queue;
c->timeout = 5000;
+ c->cxl_debugfs = get_cxl_debugfs_dir();
return 0;
@@ -350,6 +386,7 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
kmod_unref(ctx->kmod_ctx);
daxctl_unref(ctx->daxctl_ctx);
info(ctx, "context %p released\n", ctx);
+ free((void *)ctx->cxl_debugfs);
free(ctx);
}
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v8 2/7] libcxl: Add CXL protocol errors
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 1/7] libcxl: Add debugfs path to CXL context Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 3/7] libcxl: Add poison injection support Ben Cheatham
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
The v6.11 Linux kernel adds CXL protocl (CXL.cache & CXL.mem) error
injection for platforms that implement the error types as according to
the v6.5+ ACPI specification. The interface for injecting these errors
are provided by the kernel under the CXL debugfs. The relevant files in
the interface are the einj_types file, which provides the available CXL
error types for injection, and the einj_inject file, which injects the
error into a CXL VH root port or CXL RCH downstream port.
Add a library API to retrieve the CXL error types and inject them. This
API will be used in a later commit by the 'cxl-inject-protocol-error'
and 'cxl-list' commands.
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
cxl/lib/libcxl.c | 193 +++++++++++++++++++++++++++++++++++++++++++++
cxl/lib/libcxl.sym | 5 ++
cxl/lib/private.h | 14 ++++
cxl/libcxl.h | 13 +++
4 files changed, 225 insertions(+)
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index 6b7e92c..be134a1 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -48,11 +48,13 @@ struct cxl_ctx {
void *userdata;
int memdevs_init;
int buses_init;
+ int perrors_init;
unsigned long timeout;
struct udev *udev;
struct udev_queue *udev_queue;
struct list_head memdevs;
struct list_head buses;
+ struct list_head perrors;
struct kmod_ctx *kmod_ctx;
struct daxctl_ctx *daxctl_ctx;
void *private_data;
@@ -207,6 +209,14 @@ static void free_bus(struct cxl_bus *bus, struct list_head *head)
free(bus);
}
+static void free_protocol_error(struct cxl_protocol_error *perror,
+ struct list_head *head)
+{
+ if (head)
+ list_del_from(head, &perror->list);
+ free(perror);
+}
+
/**
* cxl_get_userdata - retrieve stored data pointer from library context
* @ctx: cxl library context
@@ -325,6 +335,7 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
*ctx = c;
list_head_init(&c->memdevs);
list_head_init(&c->buses);
+ list_head_init(&c->perrors);
c->kmod_ctx = kmod_ctx;
c->daxctl_ctx = daxctl_ctx;
c->udev = udev;
@@ -366,6 +377,7 @@ CXL_EXPORT struct cxl_ctx *cxl_ref(struct cxl_ctx *ctx)
*/
CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
{
+ struct cxl_protocol_error *perror, *_p;
struct cxl_memdev *memdev, *_d;
struct cxl_bus *bus, *_b;
@@ -381,6 +393,9 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
list_for_each_safe(&ctx->buses, bus, _b, port.list)
free_bus(bus, &ctx->buses);
+ list_for_each_safe(&ctx->perrors, perror, _p, list)
+ free_protocol_error(perror, &ctx->perrors);
+
udev_queue_unref(ctx->udev_queue);
udev_unref(ctx->udev);
kmod_unref(ctx->kmod_ctx);
@@ -3423,6 +3438,184 @@ CXL_EXPORT int cxl_port_decoders_committed(struct cxl_port *port)
return port->decoders_committed;
}
+const struct cxl_protocol_error cxl_protocol_errors[] = {
+ CXL_PROTOCOL_ERROR(0x1000, "cache-correctable"),
+ CXL_PROTOCOL_ERROR(0x2000, "cache-uncorrectable"),
+ CXL_PROTOCOL_ERROR(0x4000, "cache-fatal"),
+ CXL_PROTOCOL_ERROR(0x8000, "mem-correctable"),
+ CXL_PROTOCOL_ERROR(0x10000, "mem-uncorrectable"),
+ CXL_PROTOCOL_ERROR(0x20000, "mem-fatal")
+};
+
+static struct cxl_protocol_error *create_cxl_protocol_error(struct cxl_ctx *ctx,
+ unsigned int n)
+{
+ struct cxl_protocol_error *perror;
+
+ for (unsigned long i = 0; i < ARRAY_SIZE(cxl_protocol_errors); i++) {
+ if (n != cxl_protocol_errors[i].num)
+ continue;
+
+ perror = calloc(1, sizeof(*perror));
+ if (!perror)
+ return NULL;
+
+ *perror = cxl_protocol_errors[i];
+ perror->ctx = ctx;
+ return perror;
+ }
+
+ return NULL;
+}
+
+static void cxl_add_protocol_errors(struct cxl_ctx *ctx)
+{
+ struct cxl_protocol_error *perror;
+ char buf[SYSFS_ATTR_SIZE];
+ char *path, *num, *save;
+ unsigned long n;
+ size_t len;
+ int rc = 0;
+
+ if (!ctx->cxl_debugfs)
+ return;
+
+ path = calloc(1, PATH_MAX);
+ if (!path)
+ return;
+
+ len = snprintf(path, PATH_MAX, "%s/einj_types", ctx->cxl_debugfs);
+ if (len >= PATH_MAX) {
+ err(ctx, "Buffer too small\n");
+ goto err;
+ }
+
+ rc = access(path, F_OK);
+ if (rc) {
+ err(ctx, "failed to access %s: %s\n", path, strerror(errno));
+ goto err;
+ }
+
+ rc = sysfs_read_attr(ctx, path, buf);
+ if (rc) {
+ err(ctx, "failed to read %s: %s\n", path, strerror(-rc));
+ goto err;
+ }
+
+ /*
+ * The format of the output of the einj_types attr is:
+ * <Error number in hex 1> <Error name 1>
+ * <Error number in hex 2> <Error name 2>
+ * ...
+ *
+ * We only need the number, so parse that and skip the rest of
+ * the line.
+ */
+ num = strtok_r(buf, " \n", &save);
+ while (num) {
+ n = strtoul(num, NULL, 16);
+ perror = create_cxl_protocol_error(ctx, n);
+ if (perror)
+ list_add_tail(&ctx->perrors, &perror->list);
+
+ num = strtok_r(NULL, "\n", &save);
+ if (!num)
+ break;
+
+ num = strtok_r(NULL, " \n", &save);
+ }
+
+err:
+ free(path);
+}
+
+static void cxl_protocol_errors_init(struct cxl_ctx *ctx)
+{
+ if (ctx->perrors_init)
+ return;
+
+ ctx->perrors_init = 1;
+ cxl_add_protocol_errors(ctx);
+}
+
+CXL_EXPORT struct cxl_protocol_error *
+cxl_protocol_error_get_first(struct cxl_ctx *ctx)
+{
+ cxl_protocol_errors_init(ctx);
+
+ return list_top(&ctx->perrors, struct cxl_protocol_error, list);
+}
+
+CXL_EXPORT struct cxl_protocol_error *
+cxl_protocol_error_get_next(struct cxl_protocol_error *perror)
+{
+ struct cxl_ctx *ctx = perror->ctx;
+
+ return list_next(&ctx->perrors, perror, list);
+}
+
+CXL_EXPORT unsigned int
+cxl_protocol_error_get_num(struct cxl_protocol_error *perror)
+{
+ return perror->num;
+}
+
+CXL_EXPORT const char *
+cxl_protocol_error_get_str(struct cxl_protocol_error *perror)
+{
+ return perror->string;
+}
+
+CXL_EXPORT int cxl_dport_protocol_error_inject(struct cxl_dport *dport,
+ unsigned int error)
+{
+ struct cxl_ctx *ctx = dport->port->ctx;
+ char buf[32] = { 0 };
+ size_t path_len, len;
+ char *path;
+ int rc;
+
+ if (!ctx->cxl_debugfs)
+ return -ENOENT;
+
+ path_len = strlen(ctx->cxl_debugfs) + 100;
+ path = calloc(path_len, sizeof(char));
+ if (!path)
+ return -ENOMEM;
+
+ len = snprintf(path, path_len, "%s/%s/einj_inject", ctx->cxl_debugfs,
+ cxl_dport_get_devname(dport));
+ if (len >= path_len) {
+ err(ctx, "%s: buffer too small\n", cxl_dport_get_devname(dport));
+ free(path);
+ return -ENOMEM;
+ }
+
+ rc = access(path, F_OK);
+ if (rc) {
+ err(ctx, "failed to access %s: %s\n", path, strerror(errno));
+ free(path);
+ return -errno;
+ }
+
+ len = snprintf(buf, sizeof(buf), "0x%x\n", error);
+ if (len >= sizeof(buf)) {
+ err(ctx, "%s: buffer too small\n", cxl_dport_get_devname(dport));
+ free(path);
+ return -ENOMEM;
+ }
+
+ rc = sysfs_write_attr(ctx, path, buf);
+ if (rc) {
+ err(ctx, "failed to write %s: %s\n", path, strerror(-rc));
+ free(path);
+ return -errno;
+ }
+
+ free(path);
+ return 0;
+}
+
static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base)
{
const char *devname = devpath_to_devname(cxlbus_base);
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index 36a93c3..c683b83 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -304,4 +304,9 @@ global:
LIBCXL_11 {
global:
cxl_region_get_extended_linear_cache_size;
+ cxl_protocol_error_get_first;
+ cxl_protocol_error_get_next;
+ cxl_protocol_error_get_num;
+ cxl_protocol_error_get_str;
+ cxl_dport_protocol_error_inject;
} LIBCXL_10;
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
index 542cdb7..582eebf 100644
--- a/cxl/lib/private.h
+++ b/cxl/lib/private.h
@@ -108,6 +108,20 @@ struct cxl_port {
struct list_head dports;
};
+struct cxl_protocol_error {
+ unsigned int num;
+ const char *string;
+ struct cxl_ctx *ctx;
+ struct list_node list;
+};
+
+#define CXL_PROTOCOL_ERROR(n, str) \
+ ((struct cxl_protocol_error){ \
+ .num = (n), \
+ .string = (str), \
+ .ctx = NULL, \
+ })
+
struct cxl_bus {
struct cxl_port port;
};
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index 9371aac..faef62e 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -498,6 +498,19 @@ int cxl_cmd_alert_config_set_enable_alert_actions(struct cxl_cmd *cmd,
int enable);
struct cxl_cmd *cxl_cmd_new_set_alert_config(struct cxl_memdev *memdev);
+struct cxl_protocol_error;
+struct cxl_protocol_error *cxl_protocol_error_get_first(struct cxl_ctx *ctx);
+struct cxl_protocol_error *
+cxl_protocol_error_get_next(struct cxl_protocol_error *perror);
+unsigned int cxl_protocol_error_get_num(struct cxl_protocol_error *perror);
+const char *cxl_protocol_error_get_str(struct cxl_protocol_error *perror);
+int cxl_dport_protocol_error_inject(struct cxl_dport *dport,
+ unsigned int error);
+
+#define cxl_protocol_error_foreach(ctx, perror) \
+ for (perror = cxl_protocol_error_get_first(ctx); perror != NULL; \
+ perror = cxl_protocol_error_get_next(perror))
+
#ifdef __cplusplus
} /* extern "C" */
#endif
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v8 3/7] libcxl: Add poison injection support
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 1/7] libcxl: Add debugfs path to CXL context Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 2/7] libcxl: Add CXL protocol errors Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 4/7] cxl: Add inject-protocol-error command Ben Cheatham
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
Add a library API for clearing and injecting poison into a CXL memory
device through the CXL debugfs.
This API will be used by the 'cxl-inject-media-poison' and
'cxl-clear-media-poison' commands in later commits.
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
cxl/lib/libcxl.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++
cxl/lib/libcxl.sym | 3 ++
cxl/libcxl.h | 3 ++
3 files changed, 89 insertions(+)
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index be134a1..308c123 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -5045,3 +5045,86 @@ CXL_EXPORT struct cxl_cmd *cxl_cmd_new_set_alert_config(struct cxl_memdev *memde
{
return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_SET_ALERT_CONFIG);
}
+
+CXL_EXPORT bool cxl_memdev_has_poison_support(struct cxl_memdev *memdev,
+ bool inj)
+{
+ struct cxl_ctx *ctx = memdev->ctx;
+ bool exists = false;
+ size_t len;
+ char *path;
+
+ if (!ctx->cxl_debugfs)
+ return false;
+
+ path = calloc(PATH_MAX, sizeof(char));
+ if (!path)
+ return false;
+
+ len = snprintf(path, PATH_MAX, "%s/%s/%s", ctx->cxl_debugfs,
+ cxl_memdev_get_devname(memdev),
+ inj ? "inject_poison" : "clear_poison");
+ if (len >= PATH_MAX) {
+ err(ctx, "%s: buffer too small\n",
+ cxl_memdev_get_devname(memdev));
+ goto out;
+ }
+
+ if (!access(path, F_OK))
+ exists = true;
+
+out:
+ free(path);
+ return exists;
+}
+
+static int cxl_memdev_poison_action(struct cxl_memdev *memdev, size_t dpa,
+ bool clear)
+{
+ struct cxl_ctx *ctx = memdev->ctx;
+ char addr[32];
+ size_t len;
+ char *path;
+ int rc;
+
+ if (!ctx->cxl_debugfs)
+ return -ENOENT;
+
+ path = calloc(PATH_MAX, sizeof(char));
+ if (!path)
+ return -ENOMEM;
+
+ len = snprintf(path, PATH_MAX, "%s/%s/%s", ctx->cxl_debugfs,
+ cxl_memdev_get_devname(memdev),
+ clear ? "clear_poison" : "inject_poison");
+ if (len >= PATH_MAX) {
+ err(ctx, "%s: buffer too small\n",
+ cxl_memdev_get_devname(memdev));
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ len = snprintf(addr, sizeof(addr), "0x%lx\n", dpa);
+ if (len >= sizeof(addr)) {
+ err(ctx, "%s: buffer too small\n",
+ cxl_memdev_get_devname(memdev));
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ rc = sysfs_write_attr(ctx, path, addr);
+
+out:
+ free(path);
+ return rc;
+}
+
+CXL_EXPORT int cxl_memdev_inject_poison(struct cxl_memdev *memdev, size_t addr)
+{
+ return cxl_memdev_poison_action(memdev, addr, false);
+}
+
+CXL_EXPORT int cxl_memdev_clear_poison(struct cxl_memdev *memdev, size_t addr)
+{
+ return cxl_memdev_poison_action(memdev, addr, true);
+}
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index c683b83..e52f7f1 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -309,4 +309,7 @@ global:
cxl_protocol_error_get_num;
cxl_protocol_error_get_str;
cxl_dport_protocol_error_inject;
+ cxl_memdev_has_poison_support;
+ cxl_memdev_inject_poison;
+ cxl_memdev_clear_poison;
} LIBCXL_10;
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index faef62e..aece822 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -105,6 +105,9 @@ int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length,
size_t offset);
int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
size_t offset);
+bool cxl_memdev_has_poison_support(struct cxl_memdev *memdev, bool inj);
+int cxl_memdev_inject_poison(struct cxl_memdev *memdev, size_t dpa);
+int cxl_memdev_clear_poison(struct cxl_memdev *memdev, size_t dpa);
struct cxl_cmd *cxl_cmd_new_get_fw_info(struct cxl_memdev *memdev);
unsigned int cxl_cmd_fw_info_get_num_slots(struct cxl_cmd *cmd);
unsigned int cxl_cmd_fw_info_get_active_slot(struct cxl_cmd *cmd);
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v8 4/7] cxl: Add inject-protocol-error command
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
` (2 preceding siblings ...)
2026-02-06 21:50 ` [PATCH v8 3/7] libcxl: Add poison injection support Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 5/7] cxl: Add poison injection/clear commands Ben Cheatham
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
Add the 'cxl-inject-protocol-error' command. This command provides CXL
protocol error injection for CXL VH root ports and CXL RCH downstream
ports.
Add util_cxl_dport_filter() to find downstream ports by device name.
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
cxl/builtin.h | 1 +
cxl/cxl.c | 1 +
cxl/filter.c | 26 +++++++++
cxl/filter.h | 2 +
cxl/inject-error.c | 143 +++++++++++++++++++++++++++++++++++++++++++++
cxl/meson.build | 1 +
6 files changed, 174 insertions(+)
create mode 100644 cxl/inject-error.c
diff --git a/cxl/builtin.h b/cxl/builtin.h
index c483f30..ca2e4d1 100644
--- a/cxl/builtin.h
+++ b/cxl/builtin.h
@@ -25,6 +25,7 @@ int cmd_create_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_enable_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_disable_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_destroy_region(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_inject_protocol_error(int argc, const char **argv, struct cxl_ctx *ctx);
#ifdef ENABLE_LIBTRACEFS
int cmd_monitor(int argc, const char **argv, struct cxl_ctx *ctx);
#else
diff --git a/cxl/cxl.c b/cxl/cxl.c
index 1643667..00ecda0 100644
--- a/cxl/cxl.c
+++ b/cxl/cxl.c
@@ -80,6 +80,7 @@ static struct cmd_struct commands[] = {
{ "disable-region", .c_fn = cmd_disable_region },
{ "destroy-region", .c_fn = cmd_destroy_region },
{ "monitor", .c_fn = cmd_monitor },
+ { "inject-protocol-error", .c_fn = cmd_inject_protocol_error },
};
int main(int argc, const char **argv)
diff --git a/cxl/filter.c b/cxl/filter.c
index b135c04..8c7dc6e 100644
--- a/cxl/filter.c
+++ b/cxl/filter.c
@@ -171,6 +171,32 @@ util_cxl_endpoint_filter_by_port(struct cxl_endpoint *endpoint,
return NULL;
}
+struct cxl_dport *util_cxl_dport_filter(struct cxl_dport *dport,
+ const char *__ident)
+{
+
+ char *ident, *save;
+ const char *arg;
+
+ if (!__ident)
+ return dport;
+
+ ident = strdup(__ident);
+ if (!ident)
+ return NULL;
+
+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg;
+ arg = strtok_r(NULL, which_sep(__ident), &save)) {
+ if (strcmp(arg, cxl_dport_get_devname(dport)) == 0)
+ break;
+ }
+
+ free(ident);
+ if (arg)
+ return dport;
+ return NULL;
+}
+
static struct cxl_decoder *
util_cxl_decoder_filter_by_port(struct cxl_decoder *decoder, const char *ident,
enum cxl_port_filter_mode mode)
diff --git a/cxl/filter.h b/cxl/filter.h
index 956a46e..70463c4 100644
--- a/cxl/filter.h
+++ b/cxl/filter.h
@@ -55,6 +55,8 @@ enum cxl_port_filter_mode {
struct cxl_port *util_cxl_port_filter(struct cxl_port *port, const char *ident,
enum cxl_port_filter_mode mode);
+struct cxl_dport *util_cxl_dport_filter(struct cxl_dport *dport,
+ const char *__ident);
struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, const char *__ident);
struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint,
const char *__ident);
diff --git a/cxl/inject-error.c b/cxl/inject-error.c
new file mode 100644
index 0000000..ed6fb36
--- /dev/null
+++ b/cxl/inject-error.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2025 AMD. All rights reserved. */
+#include <util/parse-options.h>
+#include <cxl/libcxl.h>
+#include <cxl/filter.h>
+#include <util/log.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+static bool debug;
+
+static struct proto_inject_params {
+ const char *proto;
+ const char *severity;
+} proto_inj_param;
+
+static const struct option proto_inject_options[] = {
+ OPT_STRING('p', "protocol", &proto_inj_param.proto, "mem/cache",
+ "Which CXL protocol error to inject into <dport>"),
+ OPT_STRING('s', "severity", &proto_inj_param.severity,
+ "correctable/uncorrectable/fatal",
+ "Severity of CXL protocol to inject into <dport>"),
+#ifdef ENABLE_DEBUG
+ OPT_BOOLEAN(0, "debug", &debug, "turn on debug output"),
+#endif
+ OPT_END(),
+};
+
+static struct log_ctx iel;
+
+static struct cxl_protocol_error *find_cxl_proto_err(struct cxl_ctx *ctx,
+ const char *type,
+ const char *severity)
+{
+ struct cxl_protocol_error *pe;
+ char perror[256] = { 0 };
+ size_t len;
+
+ len = snprintf(perror, sizeof(perror), "%s-%s", type,
+ severity);
+ if (len >= sizeof(perror)) {
+ log_err(&iel, "Buffer too small\n");
+ return NULL;
+ }
+
+ cxl_protocol_error_foreach(ctx, pe) {
+ if (strcmp(perror, cxl_protocol_error_get_str(pe)) == 0)
+ return pe;
+ }
+
+ log_err(&iel, "Invalid CXL protocol error type: %s\n", perror);
+ return NULL;
+}
+
+static struct cxl_dport *find_cxl_dport(struct cxl_ctx *ctx, const char *devname)
+{
+ struct cxl_dport *dport;
+ struct cxl_port *port;
+ struct cxl_bus *bus;
+
+ cxl_bus_foreach(ctx, bus)
+ cxl_port_foreach_all(cxl_bus_get_port(bus), port)
+ cxl_dport_foreach(port, dport)
+ if (util_cxl_dport_filter(dport, devname))
+ return dport;
+
+ log_err(&iel, "Downstream port \"%s\" not found\n", devname);
+ return NULL;
+}
+
+static int inject_proto_err(struct cxl_ctx *ctx, const char *devname,
+ struct cxl_protocol_error *perror)
+{
+ struct cxl_dport *dport;
+ int rc;
+
+ if (!devname) {
+ log_err(&iel, "No downstream port specified for injection\n");
+ return -EINVAL;
+ }
+
+ dport = find_cxl_dport(ctx, devname);
+ if (!dport)
+ return -ENODEV;
+
+ rc = cxl_dport_protocol_error_inject(dport,
+ cxl_protocol_error_get_num(perror));
+ if (rc)
+ return rc;
+
+ log_info(&iel, "injected %s protocol error.\n",
+ cxl_protocol_error_get_str(perror));
+ return 0;
+}
+
+static int inject_protocol_action(int argc, const char **argv,
+ struct cxl_ctx *ctx,
+ const struct option *options,
+ const char *usage)
+{
+ struct cxl_protocol_error *perr;
+ const char * const u[] = {
+ usage,
+ NULL
+ };
+ int rc = -EINVAL;
+
+ log_init(&iel, "cxl inject-protocol-error", "CXL_INJECT_LOG");
+ argc = parse_options(argc, argv, options, u, 0);
+
+ if (debug) {
+ cxl_set_log_priority(ctx, LOG_DEBUG);
+ iel.log_priority = LOG_DEBUG;
+ } else {
+ iel.log_priority = LOG_INFO;
+ }
+
+ if (argc != 1 || proto_inj_param.proto == NULL ||
+ proto_inj_param.severity == NULL) {
+ usage_with_options(u, options);
+ return rc;
+ }
+
+ perr = find_cxl_proto_err(ctx, proto_inj_param.proto,
+ proto_inj_param.severity);
+ if (perr) {
+ rc = inject_proto_err(ctx, argv[0], perr);
+ if (rc)
+ log_err(&iel, "Failed to inject error: %d\n", rc);
+ }
+
+ return rc;
+}
+
+int cmd_inject_protocol_error(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = inject_protocol_action(argc, argv, ctx, proto_inject_options,
+ "inject-protocol-error <dport> -p <protocol> -s <severity> [<options>]");
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/cxl/meson.build b/cxl/meson.build
index b9924ae..92031b5 100644
--- a/cxl/meson.build
+++ b/cxl/meson.build
@@ -7,6 +7,7 @@ cxl_src = [
'memdev.c',
'json.c',
'filter.c',
+ 'inject-error.c',
'../daxctl/json.c',
'../daxctl/filter.c',
]
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v8 5/7] cxl: Add poison injection/clear commands
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
` (3 preceding siblings ...)
2026-02-06 21:50 ` [PATCH v8 4/7] cxl: Add inject-protocol-error command Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 6/7] cxl/list: Add injectable errors in output Ben Cheatham
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
Add the 'cxl-inject-media-poison' and 'cxl-clear-media-poison' commands.
These commands allow the user to inject and clear device poison from CXL
memory devices at a given device physical address.
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
cxl/builtin.h | 2 +
cxl/cxl.c | 2 +
cxl/inject-error.c | 169 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 173 insertions(+)
diff --git a/cxl/builtin.h b/cxl/builtin.h
index ca2e4d1..578f33b 100644
--- a/cxl/builtin.h
+++ b/cxl/builtin.h
@@ -26,6 +26,8 @@ int cmd_enable_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_disable_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_destroy_region(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_inject_protocol_error(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_inject_media_poison(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_clear_media_poison(int argc, const char **argv, struct cxl_ctx *ctx);
#ifdef ENABLE_LIBTRACEFS
int cmd_monitor(int argc, const char **argv, struct cxl_ctx *ctx);
#else
diff --git a/cxl/cxl.c b/cxl/cxl.c
index 00ecda0..8dd86ca 100644
--- a/cxl/cxl.c
+++ b/cxl/cxl.c
@@ -81,6 +81,8 @@ static struct cmd_struct commands[] = {
{ "destroy-region", .c_fn = cmd_destroy_region },
{ "monitor", .c_fn = cmd_monitor },
{ "inject-protocol-error", .c_fn = cmd_inject_protocol_error },
+ { "inject-media-poison", .c_fn = cmd_inject_media_poison },
+ { "clear-media-poison", .c_fn = cmd_clear_media_poison },
};
int main(int argc, const char **argv)
diff --git a/cxl/inject-error.c b/cxl/inject-error.c
index ed6fb36..aa15eb6 100644
--- a/cxl/inject-error.c
+++ b/cxl/inject-error.c
@@ -28,6 +28,34 @@ static const struct option proto_inject_options[] = {
OPT_END(),
};
+static struct inject_poison_params {
+ const char *address;
+} poison_inj_param;
+
+static struct clear_params {
+ const char *address;
+} poison_clear_param;
+
+static const struct option poison_inject_options[] = {
+ OPT_STRING('a', "address", &poison_inj_param.address,
+ "Address for poison injection",
+ "Device physical address for poison injection in hex or decimal"),
+#ifdef ENABLE_DEBUG
+ OPT_BOOLEAN(0, "debug", &debug, "turn on debug output"),
+#endif
+ OPT_END(),
+};
+
+static const struct option poison_clear_options[] = {
+ OPT_STRING('a', "address", &poison_clear_param.address,
+ "Address for poison clearing",
+ "Device physical address to clear poison from in hex or decimal"),
+#ifdef ENABLE_DEBUG
+ OPT_BOOLEAN(0, "debug", &debug, "turn on debug output"),
+#endif
+ OPT_END(),
+};
+
static struct log_ctx iel;
static struct cxl_protocol_error *find_cxl_proto_err(struct cxl_ctx *ctx,
@@ -70,6 +98,20 @@ static struct cxl_dport *find_cxl_dport(struct cxl_ctx *ctx, const char *devname
return NULL;
}
+static struct cxl_memdev *find_cxl_memdev(struct cxl_ctx *ctx,
+ const char *filter)
+{
+ struct cxl_memdev *memdev;
+
+ cxl_memdev_foreach(ctx, memdev) {
+ if (util_cxl_memdev_filter(memdev, filter, NULL))
+ return memdev;
+ }
+
+ log_err(&iel, "Memdev \"%s\" not found\n", filter);
+ return NULL;
+}
+
static int inject_proto_err(struct cxl_ctx *ctx, const char *devname,
struct cxl_protocol_error *perror)
{
@@ -141,3 +183,130 @@ int cmd_inject_protocol_error(int argc, const char **argv, struct cxl_ctx *ctx)
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
+
+static int poison_action(struct cxl_ctx *ctx, const char *filter,
+ const char *addr_str, bool inj)
+{
+ struct cxl_memdev *memdev;
+ unsigned long long addr;
+ int rc;
+
+ memdev = find_cxl_memdev(ctx, filter);
+ if (!memdev)
+ return -ENODEV;
+
+ if (!cxl_memdev_has_poison_support(memdev, inj)) {
+ log_err(&iel, "%s does not support %s\n",
+ cxl_memdev_get_devname(memdev),
+ inj ? "poison injection" : "clearing poison");
+ return -EINVAL;
+ }
+
+ errno = 0;
+ addr = strtoull(addr_str, NULL, 0);
+ if (addr == ULLONG_MAX && errno == ERANGE) {
+ log_err(&iel, "invalid address: %s", addr_str);
+ return -EINVAL;
+ }
+
+ if (inj)
+ rc = cxl_memdev_inject_poison(memdev, addr);
+ else
+ rc = cxl_memdev_clear_poison(memdev, addr);
+
+ if (rc)
+ log_err(&iel, "failed to %s %s:%s: %s\n",
+ inj ? "inject poison at" : "clear poison at",
+ cxl_memdev_get_devname(memdev), addr_str, strerror(-rc));
+ else
+ log_info(&iel,
+ "poison %s at %s:%s\n", inj ? "injected" : "cleared",
+ cxl_memdev_get_devname(memdev), addr_str);
+
+ return rc;
+}
+
+static int inject_poison_action(int argc, const char **argv,
+ struct cxl_ctx *ctx,
+ const struct option *options, const char *usage)
+{
+ const char * const u[] = {
+ usage,
+ NULL
+ };
+ int rc = -EINVAL;
+
+ log_init(&iel, "cxl inject-media-poison", "CXL_CLEAR_LOG");
+ argc = parse_options(argc, argv, options, u, 0);
+
+ if (debug) {
+ cxl_set_log_priority(ctx, LOG_DEBUG);
+ iel.log_priority = LOG_DEBUG;
+ } else {
+ iel.log_priority = LOG_INFO;
+ }
+
+ if (argc != 1 || !poison_inj_param.address) {
+ usage_with_options(u, options);
+ return rc;
+ }
+
+ rc = poison_action(ctx, argv[0], poison_inj_param.address, true);
+ if (rc) {
+ log_err(&iel, "Failed to inject poison on %s: %s\n", argv[0],
+ strerror(-rc));
+ return rc;
+ }
+
+ return rc;
+}
+
+int cmd_inject_media_poison(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = inject_poison_action(argc, argv, ctx, poison_inject_options,
+ "inject-media-poison <memdev> -a <address> [<options>]");
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+static int clear_poison_action(int argc, const char **argv, struct cxl_ctx *ctx,
+ const struct option *options, const char *usage)
+{
+ const char * const u[] = {
+ usage,
+ NULL
+ };
+ int rc = -EINVAL;
+
+ log_init(&iel, "cxl clear-media-poison", "CXL_CLEAR_LOG");
+ argc = parse_options(argc, argv, options, u, 0);
+
+ if (debug) {
+ cxl_set_log_priority(ctx, LOG_DEBUG);
+ iel.log_priority = LOG_DEBUG;
+ } else {
+ iel.log_priority = LOG_INFO;
+ }
+
+ if (argc != 1 || !poison_clear_param.address) {
+ usage_with_options(u, options);
+ return rc;
+ }
+
+ rc = poison_action(ctx, argv[0], poison_clear_param.address, false);
+ if (rc) {
+ log_err(&iel, "Failed to clear poison on %s: %s\n", argv[0],
+ strerror(-rc));
+ return rc;
+ }
+
+ return rc;
+}
+
+int cmd_clear_media_poison(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = clear_poison_action(argc, argv, ctx, poison_clear_options,
+ "clear-error <memdev> -a <address> [<options>]");
+
+ return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v8 6/7] cxl/list: Add injectable errors in output
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
` (4 preceding siblings ...)
2026-02-06 21:50 ` [PATCH v8 5/7] cxl: Add poison injection/clear commands Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 7/7] Documentation: Add docs for protocol and poison injection commands Ben Cheatham
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
Add injectable error information for CXL memory devices and busses.
This information is only shown when the CXL debugfs is accessible
(normally mounted at /sys/kernel/debug/cxl).
For CXL memory devices and dports this reports whether the device
supports poison injection. The "--media-errors"/"-L" option shows
injected poison for memory devices.
For CXL busses this 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.
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
cxl/json.c | 38 ++++++++++++++++++++++++++++++++++++++
cxl/lib/libcxl.c | 34 +++++++++++++++++++++++++---------
cxl/lib/libcxl.sym | 2 ++
cxl/libcxl.h | 2 ++
4 files changed, 67 insertions(+), 9 deletions(-)
diff --git a/cxl/json.c b/cxl/json.c
index e9cb88a..a0dc343 100644
--- a/cxl/json.c
+++ b/cxl/json.c
@@ -663,6 +663,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
json_object_object_add(jdev, "state", jobj);
}
+ if (cxl_debugfs_exists(cxl_memdev_get_ctx(memdev))) {
+ jobj = json_object_new_boolean(cxl_memdev_has_poison_support(memdev, true));
+ if (jobj)
+ json_object_object_add(jdev, "poison_injectable", jobj);
+ }
+
if (flags & UTIL_JSON_PARTITION) {
jobj = util_cxl_memdev_partition_to_json(memdev, flags);
if (jobj)
@@ -691,6 +697,7 @@ void util_cxl_dports_append_json(struct json_object *jport,
{
struct json_object *jobj, *jdports;
struct cxl_dport *dport;
+ char *einj_path;
int val;
val = cxl_port_get_nr_dports(port);
@@ -739,6 +746,13 @@ void util_cxl_dports_append_json(struct json_object *jport,
if (jobj)
json_object_object_add(jdport, "id", jobj);
+ einj_path = cxl_dport_get_einj_path(dport);
+ jobj = json_object_new_boolean(einj_path != NULL);
+ if (jobj)
+ json_object_object_add(jdport, "protocol_injectable",
+ jobj);
+ free(einj_path);
+
json_object_array_add(jdports, jdport);
json_object_set_userdata(jdport, dport, NULL);
}
@@ -750,6 +764,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 +781,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 (cxl_debugfs_exists(ctx)) {
+ 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/lib/libcxl.c b/cxl/lib/libcxl.c
index 308c123..d86884b 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -285,6 +285,11 @@ static char* get_cxl_debugfs_dir(void)
return debugfs_dir;
}
+CXL_EXPORT bool cxl_debugfs_exists(struct cxl_ctx *ctx)
+{
+ return ctx->cxl_debugfs != NULL;
+}
+
/**
* cxl_new - instantiate a new library context
* @ctx: context to establish
@@ -3566,38 +3571,49 @@ cxl_protocol_error_get_str(struct cxl_protocol_error *perror)
return perror->string;
}
-CXL_EXPORT int cxl_dport_protocol_error_inject(struct cxl_dport *dport,
- unsigned int error)
+CXL_EXPORT char *cxl_dport_get_einj_path(struct cxl_dport *dport)
{
struct cxl_ctx *ctx = dport->port->ctx;
- char buf[32] = { 0 };
size_t path_len, len;
char *path;
int rc;
- if (!ctx->cxl_debugfs)
- return -ENOENT;
-
path_len = strlen(ctx->cxl_debugfs) + 100;
path = calloc(path_len, sizeof(char));
if (!path)
- return -ENOMEM;
+ return NULL;
len = snprintf(path, path_len, "%s/%s/einj_inject", ctx->cxl_debugfs,
cxl_dport_get_devname(dport));
if (len >= path_len) {
err(ctx, "%s: buffer too small\n", cxl_dport_get_devname(dport));
free(path);
- return -ENOMEM;
+ return NULL;
}
rc = access(path, F_OK);
if (rc) {
err(ctx, "failed to access %s: %s\n", path, strerror(errno));
free(path);
- return -errno;
+ return NULL;
}
+ return path;
+}
+
+CXL_EXPORT int cxl_dport_protocol_error_inject(struct cxl_dport *dport,
+ unsigned int error)
+{
+ struct cxl_ctx *ctx = dport->port->ctx;
+ char buf[32] = { 0 };
+ char *path;
+ size_t len;
+ int rc;
+
+ path = cxl_dport_get_einj_path(dport);
+ if (!path)
+ return -ENOENT;
+
len = snprintf(buf, sizeof(buf), "0x%x\n", error);
if (len >= sizeof(buf)) {
err(ctx, "%s: buffer too small\n", cxl_dport_get_devname(dport));
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index e52f7f1..797e398 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -308,8 +308,10 @@ global:
cxl_protocol_error_get_next;
cxl_protocol_error_get_num;
cxl_protocol_error_get_str;
+ cxl_dport_get_einj_path;
cxl_dport_protocol_error_inject;
cxl_memdev_has_poison_support;
cxl_memdev_inject_poison;
cxl_memdev_clear_poison;
+ cxl_debugfs_exists;
} LIBCXL_10;
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index aece822..a853ab6 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -32,6 +32,7 @@ void cxl_set_userdata(struct cxl_ctx *ctx, void *userdata);
void *cxl_get_userdata(struct cxl_ctx *ctx);
void cxl_set_private_data(struct cxl_ctx *ctx, void *data);
void *cxl_get_private_data(struct cxl_ctx *ctx);
+bool cxl_debugfs_exists(struct cxl_ctx *ctx);
enum cxl_fwl_status {
CXL_FWL_STATUS_UNKNOWN,
@@ -507,6 +508,7 @@ struct cxl_protocol_error *
cxl_protocol_error_get_next(struct cxl_protocol_error *perror);
unsigned int cxl_protocol_error_get_num(struct cxl_protocol_error *perror);
const char *cxl_protocol_error_get_str(struct cxl_protocol_error *perror);
+char *cxl_dport_get_einj_path(struct cxl_dport *dport);
int cxl_dport_protocol_error_inject(struct cxl_dport *dport,
unsigned int error);
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v8 7/7] Documentation: Add docs for protocol and poison injection commands
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
` (5 preceding siblings ...)
2026-02-06 21:50 ` [PATCH v8 6/7] cxl/list: Add injectable errors in output Ben Cheatham
@ 2026-02-06 21:50 ` Ben Cheatham
2026-02-10 17:52 ` [ndctl PATCH v8 0/7] Add error injection support Verma, Vishal L
2026-02-13 0:12 ` Alison Schofield
8 siblings, 0 replies; 11+ messages in thread
From: Ben Cheatham @ 2026-02-06 21:50 UTC (permalink / raw)
To: nvdimm, alison.schofield, dave.jiang, vishal.l.verma
Cc: linux-cxl, benjamin.cheatham
Add man pages for the 'cxl-inject-protocol-error', 'cxl-inject-media-poison',
and 'cxl-clear-media-poison' commands. These man pages show usage and examples
for each of their use cases.
Signed-off-by: Ben Cheatham <Benjamin.Cheatham@amd.com>
---
Documentation/cxl/cxl-clear-media-poison.txt | 85 ++++++++++++++
Documentation/cxl/cxl-inject-media-poison.txt | 85 ++++++++++++++
.../cxl/cxl-inject-protocol-error.txt | 105 ++++++++++++++++++
Documentation/cxl/meson.build | 3 +
4 files changed, 278 insertions(+)
create mode 100644 Documentation/cxl/cxl-clear-media-poison.txt
create mode 100644 Documentation/cxl/cxl-inject-media-poison.txt
create mode 100644 Documentation/cxl/cxl-inject-protocol-error.txt
diff --git a/Documentation/cxl/cxl-clear-media-poison.txt b/Documentation/cxl/cxl-clear-media-poison.txt
new file mode 100644
index 0000000..3c997b5
--- /dev/null
+++ b/Documentation/cxl/cxl-clear-media-poison.txt
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+
+cxl-clear-media-poison(1)
+=========================
+
+NAME
+----
+cxl-clear-media-poison - Clear poison from CXL memory
+
+SYNOPSIS
+--------
+[verse]
+'cxl clear-media-poison' <memdev> [<options>]
+
+Clear poison from a CXL memory device's memory. CXL memdevs can be specified
+by device name (e.g. "mem0"), device id ("X" in "memX"), or host device name
+("0000:35:00.0").
+
+To see if a device has poison that can be cleared use the 'cxl-list' command
+with the '-L'/'--media-errors' option. An example of a device that has had
+poison injected at device physical address (a.k.a. "offset") 0x1000:
+
+----
+# cxl list -m mem0 -L -u
+{
+ "memdev":"mem0",
+ "ram_size":"1024.00 MiB (1073.74 MB)",
+ "ram_qos_class":42,
+ "serial":"0x0",
+ "numa_node:1,
+ "host":"0000:35:00.0",
+ "media_errors":[
+ {
+ "offset":"0x1000",
+ "length":64,
+ "source":"Injected"
+ }
+ ]
+}
+
+----
+
+A device physical address is required to clear poison from a CXL memdev. The
+'-a'/'--address' option is used to specify the address to clear poison at.
+The address can be given in either decimal or hexadecimal. An example using
+the example device above:
+
+----
+# cxl clear-media-poison mem0 -a 0x1000
+poison cleared at mem0:0x1000
+
+# cxl list -m mem0 -L -u
+{
+ "memdev":"mem0",
+ "ram_size":"1024.00 MiB (1073.74 MB)",
+ "ram_qos_class":42,
+ "serial":"0x0",
+ "numa_node:1,
+ "host":"0000:35:00.0",
+ "media_errors":[
+ ]
+}
+
+----
+
+See the 'inject-media-poison' command for how to inject poison into a CXL
+memory device.
+
+This command depends on the CXL debug filesystem (normally mounted at
+"/sys/kernel/debug/cxl") to clear device poison.
+
+OPTIONS
+-------
+-a::
+--address::
+ Device physical address (DPA) to clear poison at. Address can
+ be specified in hex or decimal.
+
+--debug::
+ Enable debug output
+
+SEE ALSO
+--------
+linkcxl:cxl-list[1]
+linkcxl:cxl-clear-media-poison[1]
diff --git a/Documentation/cxl/cxl-inject-media-poison.txt b/Documentation/cxl/cxl-inject-media-poison.txt
new file mode 100644
index 0000000..d35f1dc
--- /dev/null
+++ b/Documentation/cxl/cxl-inject-media-poison.txt
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+
+cxl-inject-media-poison(1)
+==========================
+
+NAME
+----
+cxl-inject-media-poison - Inject poison into CXL memory
+
+SYNOPSIS
+--------
+[verse]
+'cxl inject-media-poison' <memdev> [<options>]
+
+WARNING: Poison injection can cause system instability and should only be used
+for debugging hardware and software error recovery flows. Use at your own risk!
+
+Inject poison into a CXL memory device's memory. CXL memdevs can be specified
+by device name (e.g. "mem0"), device id ("X" in "memX"), or host device name
+("0000:35:00.0").
+
+Poison can only be used with CXL memory devices with poison injection support.
+To see which CXL devices support poison injection, see the "poison_injectable"
+attribute under the device in 'cxl-list'. An example of a device that
+supports poison injection:
+
+----
+# cxl list -u -m mem0
+{
+ "memdev":"mem0",
+ "ram_size":"256.00 MiB (268.44 MB)",
+ "serial":"0",
+ "host":"0000:0d:00.0",
+ "firmware_version":"BWFW VERSION 00",
+ "poison_injectable":true
+}
+
+----
+
+A device physical address is required for poison injection. The '-a'/'--address'
+option is used to specify the device physical address to inject poison to. The
+address can be given in either decimal or hexadecimal. For example:
+
+----
+# cxl inject-media-poison mem0 -a 0x1000
+poison inject at mem0:0x1000
+# cxl list -m mem0 -u --media-errors
+{
+ "memdev":"mem0",
+ "ram_size":"256.00 MiB (268.44 MB)",
+ "serial":"0",
+ "host":"0000:0d:00.0",
+ "firmware_version":"BWFW VERSION 00",
+ "media_errors":[
+ {
+ "offset":"0x1000",
+ "length":64,
+ "source":"Injected"
+ }
+ ]
+}
+
+----
+
+See the 'clear-media-poison' command for how to clear poison from a CXL
+memory device.
+
+This command relies on the CXL debugfs to inject poison (normally mounted
+at "/sys/kernel/debug/cxl"). If the CXL debugfs is inaccesible, the
+"poison_injectable" attribute will always be set to "false".
+
+OPTIONS
+-------
+-a::
+--address::
+ Device physical address (DPA) to use for poison injection. Address can
+ be specified in hex or decimal. Required for poison injection.
+
+--debug::
+ Enable debug output
+
+SEE ALSO
+--------
+linkcxl:cxl-list[1]
+linkcxl:cxl-clear-media-poison[1]
diff --git a/Documentation/cxl/cxl-inject-protocol-error.txt b/Documentation/cxl/cxl-inject-protocol-error.txt
new file mode 100644
index 0000000..196b6f6
--- /dev/null
+++ b/Documentation/cxl/cxl-inject-protocol-error.txt
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+
+cxl-inject-protocol-error(1)
+============================
+
+NAME
+----
+cxl-inject-protocol-error - Inject CXL protocol errors into CXL downstream ports
+
+SYNOPSIS
+--------
+[verse]
+'cxl inject-protocol-error' <dport> [<options>]
+
+WARNING: Error injection can cause system instability and should only be used
+for debugging hardware and software error recovery flows. Use at your own risk!
+
+Inject a CXL protocol error into a CXL downstream port (dport). Donwstream ports
+that support error injection will have their 'protocol_injectable' attribute
+in 'cxl-list' set to true.
+
+The '-p'/'--protocol' and '-s'/'--severity' options are required for error injection.
+The '-p' option is used to specify the CXL protocol to inject an error on; either
+"mem" (CXL.mem) or "cache" (CXL.cache). The '-s' option specifies the severity
+of the error and can be one of: "correctable", "uncorrectable", or "fatal".
+
+The types of errors (and severities) available depends on the platform. To find
+the available error types for injection, see the "injectable_protocol_errors"
+attribute under the applicable CXL bus object in the output of 'cxl-list'.
+For example:
+
+----
+
+# cxl list -B
+[
+ {
+ "bus":"root0",
+ "provider":"ACPI.CXL",
+ "injectable_protocol_errors":[
+ "mem-correctable",
+ "mem-fatal",
+ ]
+ }
+]
+
+----
+
+The dport to inject an error into is specified by host name (e.g. "0000:0e:01.1").
+Here's an example injection using the example bus listing above:
+
+----
+
+# cxl list -TP
+ [
+ {
+ "port":"port1",
+ "host":"pci0000:e0",
+ "depth":1,
+ "decoders_committed":1,
+ "nr_dports":1,
+ "dports":[
+ {
+ "dport":"0000:e0:01.1",
+ "alias":"device:02",
+ "id":0,
+ "protocol_injectable":true
+ }
+ ]
+ }
+]
+
+# cxl inject-protocol-error "0000:e0:01.1" -p mem -s correctable
+cxl inject-protocol-error: inject_proto_err: injected mem-correctable protocol error.
+
+----
+
+CXL protocol (CXL.cache/mem) error injection requires the platform to support
+ACPI v6.5+ error injection (EINJ). In addition to platform support, the
+CONFIG_ACPI_APEI_EINJ and CONFIG_ACPI_APEI_EINJ_CXL kernel configuration options
+must be enabled. For more information, view the Linux kernel documentation on EINJ.
+
+This command depends on the CXL debug filesystem (normally mounted at
+"/sys/kernel/debug/cxl") to inject protocol errors. If the CXL debugfs is not
+accessible the "protocol_injectable" attribute of dports will always be
+set to false, and the "injectable_protocol_errors" attribute of CXL busses
+will always be empty.
+
+OPTIONS
+-------
+-p::
+--protocol::
+ Which CXL protocol to inject an error on. Can be either "mem" (CXL.mem)
+ or "cache (CXL.cache).
+
+-s::
+--severity::
+ Severity level of error to be injected. Can be one of the following:
+ "correctable", "uncorrectable", or "fatal".
+
+--debug::
+ Enable debug output
+
+SEE ALSO
+--------
+linkcxl:cxl-list[1]
diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build
index 8085c1c..c4b22ab 100644
--- a/Documentation/cxl/meson.build
+++ b/Documentation/cxl/meson.build
@@ -50,6 +50,9 @@ cxl_manpages = [
'cxl-update-firmware.txt',
'cxl-set-alert-config.txt',
'cxl-wait-sanitize.txt',
+ 'cxl-inject-protocol-error.txt',
+ 'cxl-inject-media-poison.txt',
+ 'cxl-clear-media-poison.txt',
]
foreach man : cxl_manpages
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [ndctl PATCH v8 0/7] Add error injection support
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
` (6 preceding siblings ...)
2026-02-06 21:50 ` [PATCH v8 7/7] Documentation: Add docs for protocol and poison injection commands Ben Cheatham
@ 2026-02-10 17:52 ` Verma, Vishal L
2026-02-13 0:12 ` Alison Schofield
8 siblings, 0 replies; 11+ messages in thread
From: Verma, Vishal L @ 2026-02-10 17:52 UTC (permalink / raw)
To: Schofield, Alison, Benjamin.Cheatham@amd.com,
nvdimm@lists.linux.dev, Jiang, Dave
Cc: linux-cxl@vger.kernel.org
On Fri, 2026-02-06 at 15:50 -0600, Ben Cheatham wrote:
> v8 Changes:
> - Split inject-error command into 'inject-protocol-error', 'inject-media-poison' (Vishal, Alison)
> - Rename 'cxl-clear-error' command to 'cxl-clear-media-poison' (Alison)
> - Documentation rework to reflect new commands
> - Cleaned up a few error prints
> - Updated help messages
> - Change "clear" param of poison_action() to "inj" and reverse usage accordingly
> - Change cxl_memdev_has_poison_injection() to cxl_memdev_has_poison_support()
> - Used in poison_action() (cxl/inject-error.c) to report missing functionality
> more accurately
> - Print usage when '-a' option is missing for media-poison commands
> - Remove checking if '-a' option is empty in poison_action() (no longer needed)
> - Allow clearing poison when 'inject_poison' file is missing in debugfs (and vice versa)
> - Updated cover letter and commit messages
Thanks for the reworks - this looks good to me.
For the series,
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [ndctl PATCH v8 0/7] Add error injection support
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
` (7 preceding siblings ...)
2026-02-10 17:52 ` [ndctl PATCH v8 0/7] Add error injection support Verma, Vishal L
@ 2026-02-13 0:12 ` Alison Schofield
2026-02-16 14:28 ` Cheatham, Benjamin
8 siblings, 1 reply; 11+ messages in thread
From: Alison Schofield @ 2026-02-13 0:12 UTC (permalink / raw)
To: Ben Cheatham; +Cc: nvdimm, dave.jiang, vishal.l.verma, linux-cxl
On Fri, Feb 06, 2026 at 03:50:01PM -0600, Ben Cheatham wrote:
snip
>
> Ben Cheatham (7):
> libcxl: Add debugfs path to CXL context
> libcxl: Add CXL protocol errors
> libcxl: Add poison injection support
> cxl: Add inject-protocol-error command
> cxl: Add poison injection/clear commands
> cxl/list: Add injectable errors in output
> Documentation: Add docs for protocol and poison injection commands
Hi Ben,
Same concern touches 2 patches, so commenting here:
libcxl: Add CXL protocol errors
cxl/list: Add injectable errors in output
I'm seeing some unwanted complaining with cxl list when protocol inject
is not supported. Here is a sample:
# cxl list -P -v
libcxl: cxl_add_protocol_errors: failed to access /sys/kernel/debug/cxl/einj_types: No such file or directory
libcxl: cxl_dport_get_einj_path: failed to access /sys/kernel/debug/cxl/cxl_host_bridge.0/einj_inject: No such file or directory
libcxl: cxl_dport_get_einj_path: failed to access /sys/kernel/debug/cxl/cxl_root_port.0/einj_inject: No such file or directory
libcxl: cxl_dport_get_einj_path: failed to access /sys/kernel/debug/cxl/cxl_switch_dport.0/einj_inject: No such file or directory
I believe it is not an error for the path not to exist. With the device poison,
you already treat search for debugfs file as an existence test and no
error is emitted on failure to find.
If the diff below works for you, and nothing else comes up, I can fix it up
when merging. Let me know -
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index d86884bc2de1..5e8deb6e297b 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -3496,10 +3496,8 @@ static void cxl_add_protocol_errors(struct cxl_ctx *ctx)
}
rc = access(path, F_OK);
- if (rc) {
- err(ctx, "failed to access %s: %s\n", path, strerror(errno));
+ if (rc)
goto err;
- }
rc = sysfs_read_attr(ctx, path, buf);
if (rc) {
@@ -3593,7 +3591,6 @@ CXL_EXPORT char *cxl_dport_get_einj_path(struct cxl_dport *dport)
rc = access(path, F_OK);
if (rc) {
- err(ctx, "failed to access %s: %s\n", path, strerror(errno));
free(path);
return NULL;
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [ndctl PATCH v8 0/7] Add error injection support
2026-02-13 0:12 ` Alison Schofield
@ 2026-02-16 14:28 ` Cheatham, Benjamin
0 siblings, 0 replies; 11+ messages in thread
From: Cheatham, Benjamin @ 2026-02-16 14:28 UTC (permalink / raw)
To: Alison Schofield; +Cc: nvdimm, dave.jiang, vishal.l.verma, linux-cxl
On 2/12/2026 6:12 PM, Alison Schofield wrote:
> On Fri, Feb 06, 2026 at 03:50:01PM -0600, Ben Cheatham wrote:
>
> snip
>>
>> Ben Cheatham (7):
>> libcxl: Add debugfs path to CXL context
>> libcxl: Add CXL protocol errors
>> libcxl: Add poison injection support
>> cxl: Add inject-protocol-error command
>> cxl: Add poison injection/clear commands
>> cxl/list: Add injectable errors in output
>> Documentation: Add docs for protocol and poison injection commands
>
> Hi Ben,
>
> Same concern touches 2 patches, so commenting here:
> libcxl: Add CXL protocol errors
> cxl/list: Add injectable errors in output
>
> I'm seeing some unwanted complaining with cxl list when protocol inject
> is not supported. Here is a sample:
>
> # cxl list -P -v
> libcxl: cxl_add_protocol_errors: failed to access /sys/kernel/debug/cxl/einj_types: No such file or directory
> libcxl: cxl_dport_get_einj_path: failed to access /sys/kernel/debug/cxl/cxl_host_bridge.0/einj_inject: No such file or directory
> libcxl: cxl_dport_get_einj_path: failed to access /sys/kernel/debug/cxl/cxl_root_port.0/einj_inject: No such file or directory
> libcxl: cxl_dport_get_einj_path: failed to access /sys/kernel/debug/cxl/cxl_switch_dport.0/einj_inject: No such file or directory
>
> I believe it is not an error for the path not to exist. With the device poison,
> you already treat search for debugfs file as an existence test and no
> error is emitted on failure to find.
>
> If the diff below works for you, and nothing else comes up, I can fix it up
> when merging. Let me know -
>
Sorry about that, below looks good to me!
Thanks,
Ben
> diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
> index d86884bc2de1..5e8deb6e297b 100644
> --- a/cxl/lib/libcxl.c
> +++ b/cxl/lib/libcxl.c
> @@ -3496,10 +3496,8 @@ static void cxl_add_protocol_errors(struct cxl_ctx *ctx)
> }
>
> rc = access(path, F_OK);
> - if (rc) {
> - err(ctx, "failed to access %s: %s\n", path, strerror(errno));
> + if (rc)
> goto err;
> - }
>
> rc = sysfs_read_attr(ctx, path, buf);
> if (rc) {
> @@ -3593,7 +3591,6 @@ CXL_EXPORT char *cxl_dport_get_einj_path(struct cxl_dport *dport)
>
> rc = access(path, F_OK);
> if (rc) {
> - err(ctx, "failed to access %s: %s\n", path, strerror(errno));
> free(path);
> return NULL;
> }
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-02-16 14:28 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-06 21:50 [ndctl PATCH v8 0/7] Add error injection support Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 1/7] libcxl: Add debugfs path to CXL context Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 2/7] libcxl: Add CXL protocol errors Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 3/7] libcxl: Add poison injection support Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 4/7] cxl: Add inject-protocol-error command Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 5/7] cxl: Add poison injection/clear commands Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 6/7] cxl/list: Add injectable errors in output Ben Cheatham
2026-02-06 21:50 ` [PATCH v8 7/7] Documentation: Add docs for protocol and poison injection commands Ben Cheatham
2026-02-10 17:52 ` [ndctl PATCH v8 0/7] Add error injection support Verma, Vishal L
2026-02-13 0:12 ` Alison Schofield
2026-02-16 14:28 ` Cheatham, Benjamin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox