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-error' and 'cxl-clear-error' commands in later commits. Signed-off-by: Ben Cheatham <benjamin.cheat...@amd.com> --- cxl/lib/libcxl.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++ cxl/lib/libcxl.sym | 3 +++ cxl/libcxl.h | 3 +++ 3 files changed, 66 insertions(+) diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c index 0403fa9..e1c9951 100644 --- a/cxl/lib/libcxl.c +++ b/cxl/lib/libcxl.c @@ -4897,3 +4897,63 @@ 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_injection(struct cxl_memdev *memdev) +{ + struct cxl_ctx *ctx = memdev->ctx; + size_t path_len; + bool exists; + char *path; + + if (!ctx->debugfs) + return false; + + path_len = strlen(ctx->debugfs) + 100; + path = calloc(path_len, sizeof(char)); + if (!path) + return false; + + snprintf(path, path_len, "%s/cxl/%s/inject_poison", ctx->debugfs, + cxl_memdev_get_devname(memdev)); + exists = access(path, F_OK) == 0; + + 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; + size_t path_len; + char addr[32]; + char *path; + int rc; + + if (!ctx->debugfs) + return -ENOENT; + + path_len = strlen(ctx->debugfs) + 100; + path = calloc(path_len, sizeof(char)); + if (!path) + return -ENOMEM; + + snprintf(path, path_len, "%s/cxl/%s/%s", ctx->debugfs, + cxl_memdev_get_devname(memdev), + clear ? "clear_poison" : "inject_poison"); + snprintf(addr, 32, "0x%lx\n", dpa); + + rc = sysfs_write_attr(ctx, path, addr); + 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 61ed0db..012d344 100644 --- a/cxl/lib/libcxl.sym +++ b/cxl/lib/libcxl.sym @@ -295,4 +295,7 @@ global: cxl_protocol_error_get_num; cxl_protocol_error_get_str; cxl_dport_protocol_error_inject; + cxl_memdev_has_poison_injection; + cxl_memdev_inject_poison; + cxl_memdev_clear_poison; } LIBECXL_8; diff --git a/cxl/libcxl.h b/cxl/libcxl.h index afa076a..fa007d0 100644 --- a/cxl/libcxl.h +++ b/cxl/libcxl.h @@ -100,6 +100,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_injection(struct cxl_memdev *memdev); +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.34.1