From: Ira Weiny <[email protected]> Dynamic capacity partitions are exposed as a singular dynamic ram partition.
Add CXL library support to read this partition information, and use the new partition in cxl-cli. Signed-off-by: Ira Weiny <[email protected]> Signed-off-by: Anisa Su <[email protected]> Reviewed-by: Dave Jiang <[email protected]> --- Documentation/cxl/lib/libcxl.txt | 6 +++-- cxl/json.c | 20 +++++++++++++++ cxl/lib/libcxl.c | 43 ++++++++++++++++++++++++++++++++ cxl/lib/libcxl.sym | 8 ++++++ cxl/lib/private.h | 3 +++ cxl/libcxl.h | 10 +++++++- cxl/memdev.c | 4 ++- cxl/region.c | 27 +++++++++++++++++--- 8 files changed, 114 insertions(+), 7 deletions(-) diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt index 5c3ebd4..59163e4 100644 --- a/Documentation/cxl/lib/libcxl.txt +++ b/Documentation/cxl/lib/libcxl.txt @@ -74,6 +74,7 @@ int cxl_memdev_get_major(struct cxl_memdev *memdev); int cxl_memdev_get_minor(struct cxl_memdev *memdev); unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); +unsigned long long cxl_memdev_get_dynamic_ram_1_size(struct cxl_memdev *memdev); const char *cxl_memdev_get_firmware_version(struct cxl_memdev *memdev); size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev); int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev); @@ -93,8 +94,8 @@ The character device node for command submission can be found by default at /dev/cxl/mem%d, or created with a major / minor returned from cxl_memdev_get_{major,minor}(). -The 'pmem_size' and 'ram_size' attributes return the current -provisioning of DPA (Device Physical Address / local capacity) in the +The 'pmem_size', 'ram_size', and 'dynamic_ram_1_size' attributes return the +current provisioning of DPA (Device Physical Address / local capacity) in the device. cxl_memdev_get_numa_node() returns the affinitized CPU node number if @@ -453,6 +454,7 @@ enum cxl_decoder_mode { CXL_DECODER_MODE_MIXED, CXL_DECODER_MODE_PMEM, CXL_DECODER_MODE_RAM, + CXL_DECODER_MODE_DYNAMIC_RAM_1, }; enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder); int cxl_decoder_set_mode(struct cxl_decoder *decoder, enum cxl_decoder_mode mode); diff --git a/cxl/json.c b/cxl/json.c index a925488..e832982 100644 --- a/cxl/json.c +++ b/cxl/json.c @@ -620,6 +620,20 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev, } } + size = cxl_memdev_get_dynamic_ram_1_size(memdev); + if (size) { + jobj = util_json_object_size(size, flags); + if (jobj) + json_object_object_add(jdev, "dynamic_ram_1_size", jobj); + + qos_class = cxl_memdev_get_dynamic_ram_1_qos_class(memdev); + if (qos_class != CXL_QOS_CLASS_NONE) { + jobj = json_object_new_int(qos_class); + if (jobj) + json_object_object_add(jdev, "dynamic_ram_1_qos_class", jobj); + } + } + if (flags & UTIL_JSON_HEALTH) { jobj = util_cxl_memdev_health_to_json(memdev, flags); if (jobj) @@ -917,6 +931,12 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder, json_object_object_add( jdecoder, "volatile_capable", jobj); } + if (cxl_decoder_is_dynamic_ram_1_capable(decoder)) { + jobj = json_object_new_boolean(true); + if (jobj) + json_object_object_add( + jdecoder, "dynamic_ram_1_capable", jobj); + } } if (cxl_port_is_root(port) && diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c index e55a7b4..240ed75 100644 --- a/cxl/lib/libcxl.c +++ b/cxl/lib/libcxl.c @@ -501,6 +501,9 @@ CXL_EXPORT bool cxl_region_qos_class_mismatch(struct cxl_region *region) } else if (region->mode == CXL_DECODER_MODE_PMEM) { if (root_decoder->qos_class != memdev->pmem_qos_class) return true; + } else if (region->mode == CXL_DECODER_MODE_DYNAMIC_RAM_1) { + if (root_decoder->qos_class != memdev->dynamic_ram_1_qos_class) + return true; } } @@ -1426,6 +1429,10 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) if (sysfs_read_attr(ctx, path, buf) == 0) memdev->ram_size = strtoull(buf, NULL, 0); + sprintf(path, "%s/dynamic_ram_1/size", cxlmem_base); + if (sysfs_read_attr(ctx, path, buf) == 0) + memdev->dynamic_ram_1_size = strtoull(buf, NULL, 0); + sprintf(path, "%s/pmem/qos_class", cxlmem_base); if (sysfs_read_attr(ctx, path, buf) < 0) memdev->pmem_qos_class = CXL_QOS_CLASS_NONE; @@ -1438,6 +1445,12 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base) else memdev->ram_qos_class = atoi(buf); + sprintf(path, "%s/dynamic_ram_1/qos_class", cxlmem_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + memdev->dynamic_ram_1_qos_class = CXL_QOS_CLASS_NONE; + else + memdev->dynamic_ram_1_qos_class = atoi(buf); + sprintf(path, "%s/payload_max", cxlmem_base); if (sysfs_read_attr(ctx, path, buf) == 0) { memdev->payload_max = strtoull(buf, NULL, 0); @@ -1685,6 +1698,11 @@ CXL_EXPORT unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev) return memdev->ram_size; } +CXL_EXPORT unsigned long long cxl_memdev_get_dynamic_ram_1_size(struct cxl_memdev *memdev) +{ + return memdev->dynamic_ram_1_size; +} + CXL_EXPORT int cxl_memdev_get_pmem_qos_class(struct cxl_memdev *memdev) { return memdev->pmem_qos_class; @@ -1695,6 +1713,11 @@ CXL_EXPORT int cxl_memdev_get_ram_qos_class(struct cxl_memdev *memdev) return memdev->ram_qos_class; } +CXL_EXPORT int cxl_memdev_get_dynamic_ram_1_qos_class(struct cxl_memdev *memdev) +{ + return memdev->dynamic_ram_1_qos_class; +} + CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev) { return memdev->firmware_version; @@ -2465,6 +2488,8 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) decoder->mode = CXL_DECODER_MODE_MIXED; else if (strcmp(buf, "none") == 0) decoder->mode = CXL_DECODER_MODE_NONE; + else if (strcmp(buf, "dynamic_ram_1") == 0) + decoder->mode = CXL_DECODER_MODE_DYNAMIC_RAM_1; else decoder->mode = CXL_DECODER_MODE_MIXED; } else @@ -2504,6 +2529,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) case CXL_PORT_SWITCH: decoder->pmem_capable = true; decoder->volatile_capable = true; + decoder->dynamic_ram_1_capable = true; decoder->mem_capable = true; decoder->accelmem_capable = true; sprintf(path, "%s/locked", cxldecoder_base); @@ -2528,6 +2554,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base) { "cap_type3", &decoder->mem_capable }, { "cap_ram", &decoder->volatile_capable }, { "cap_pmem", &decoder->pmem_capable }, + { "cap_dynamic_ram_1", &decoder->dynamic_ram_1_capable }, { "locked", &decoder->locked }, }; @@ -2778,6 +2805,9 @@ CXL_EXPORT int cxl_decoder_set_mode(struct cxl_decoder *decoder, case CXL_DECODER_MODE_RAM: sprintf(buf, "ram"); break; + case CXL_DECODER_MODE_DYNAMIC_RAM_1: + sprintf(buf, "dynamic_ram_1"); + break; default: err(ctx, "%s: unsupported mode: %d\n", cxl_decoder_get_devname(decoder), mode); @@ -2829,6 +2859,11 @@ CXL_EXPORT bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder) return decoder->volatile_capable; } +CXL_EXPORT bool cxl_decoder_is_dynamic_ram_1_capable(struct cxl_decoder *decoder) +{ + return decoder->dynamic_ram_1_capable; +} + CXL_EXPORT bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder) { return decoder->mem_capable; @@ -2903,6 +2938,8 @@ static struct cxl_region *cxl_decoder_create_region(struct cxl_decoder *decoder, sprintf(path, "%s/create_pmem_region", decoder->dev_path); else if (mode == CXL_DECODER_MODE_RAM) sprintf(path, "%s/create_ram_region", decoder->dev_path); + else if (mode == CXL_DECODER_MODE_DYNAMIC_RAM_1) + sprintf(path, "%s/create_dynamic_ram_1_region", decoder->dev_path); rc = sysfs_read_attr(ctx, path, buf); if (rc < 0) { @@ -2954,6 +2991,12 @@ cxl_decoder_create_ram_region(struct cxl_decoder *decoder) return cxl_decoder_create_region(decoder, CXL_DECODER_MODE_RAM); } +CXL_EXPORT struct cxl_region * +cxl_decoder_create_dynamic_ram_1_region(struct cxl_decoder *decoder) +{ + return cxl_decoder_create_region(decoder, CXL_DECODER_MODE_DYNAMIC_RAM_1); +} + CXL_EXPORT int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder) { return decoder->nr_targets; diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym index ed4429f..4a8443c 100644 --- a/cxl/lib/libcxl.sym +++ b/cxl/lib/libcxl.sym @@ -320,3 +320,11 @@ LIBCXL_12 { global: cxl_region_locked_state; } LIBCXL_11; + +LIBCXL_13 { +global: + cxl_memdev_get_dynamic_ram_1_size; + cxl_memdev_get_dynamic_ram_1_qos_class; + cxl_decoder_is_dynamic_ram_1_capable; + cxl_decoder_create_dynamic_ram_1_region; +} LIBCXL_12; diff --git a/cxl/lib/private.h b/cxl/lib/private.h index d2d71fc..fb45e15 100644 --- a/cxl/lib/private.h +++ b/cxl/lib/private.h @@ -52,8 +52,10 @@ struct cxl_memdev { struct list_node list; unsigned long long pmem_size; unsigned long long ram_size; + unsigned long long dynamic_ram_1_size; int ram_qos_class; int pmem_qos_class; + int dynamic_ram_1_qos_class; int payload_max; size_t lsa_size; struct kmod_module *module; @@ -159,6 +161,7 @@ struct cxl_decoder { unsigned int interleave_granularity; bool pmem_capable; bool volatile_capable; + bool dynamic_ram_1_capable; bool mem_capable; bool accelmem_capable; bool locked; diff --git a/cxl/libcxl.h b/cxl/libcxl.h index e91af90..8ee6937 100644 --- a/cxl/libcxl.h +++ b/cxl/libcxl.h @@ -75,8 +75,10 @@ struct cxl_fwctl *cxl_memdev_get_fwctl(struct cxl_memdev *memdev); struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev); unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev); unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev); +unsigned long long cxl_memdev_get_dynamic_ram_1_size(struct cxl_memdev *memdev); int cxl_memdev_get_pmem_qos_class(struct cxl_memdev *memdev); int cxl_memdev_get_ram_qos_class(struct cxl_memdev *memdev); +int cxl_memdev_get_dynamic_ram_1_qos_class(struct cxl_memdev *memdev); const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev); bool cxl_memdev_fw_update_in_progress(struct cxl_memdev *memdev); size_t cxl_memdev_fw_update_get_remaining(struct cxl_memdev *memdev); @@ -210,6 +212,7 @@ enum cxl_decoder_mode { CXL_DECODER_MODE_MIXED, CXL_DECODER_MODE_PMEM, CXL_DECODER_MODE_RAM, + CXL_DECODER_MODE_DYNAMIC_RAM_1, }; static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) @@ -219,9 +222,10 @@ static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode) [CXL_DECODER_MODE_MIXED] = "mixed", [CXL_DECODER_MODE_PMEM] = "pmem", [CXL_DECODER_MODE_RAM] = "ram", + [CXL_DECODER_MODE_DYNAMIC_RAM_1] = "dynamic_ram_1", }; - if (mode < CXL_DECODER_MODE_NONE || mode > CXL_DECODER_MODE_RAM) + if (mode < CXL_DECODER_MODE_NONE || mode > CXL_DECODER_MODE_DYNAMIC_RAM_1) mode = CXL_DECODER_MODE_NONE; return names[mode]; } @@ -235,6 +239,8 @@ cxl_decoder_mode_from_ident(const char *ident) return CXL_DECODER_MODE_RAM; else if (strcmp(ident, "pmem") == 0) return CXL_DECODER_MODE_PMEM; + else if (strcmp(ident, "dynamic_ram_1") == 0) + return CXL_DECODER_MODE_DYNAMIC_RAM_1; return CXL_DECODER_MODE_NONE; } @@ -264,6 +270,7 @@ cxl_decoder_get_target_type(struct cxl_decoder *decoder); bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder); bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder); bool cxl_decoder_is_mem_capable(struct cxl_decoder *decoder); +bool cxl_decoder_is_dynamic_ram_1_capable(struct cxl_decoder *decoder); bool cxl_decoder_is_accelmem_capable(struct cxl_decoder *decoder); bool cxl_decoder_is_locked(struct cxl_decoder *decoder); unsigned int @@ -272,6 +279,7 @@ unsigned int cxl_decoder_get_interleave_ways(struct cxl_decoder *decoder); struct cxl_region *cxl_decoder_get_region(struct cxl_decoder *decoder); struct cxl_region *cxl_decoder_create_pmem_region(struct cxl_decoder *decoder); struct cxl_region *cxl_decoder_create_ram_region(struct cxl_decoder *decoder); +struct cxl_region *cxl_decoder_create_dynamic_ram_1_region(struct cxl_decoder *decoder); struct cxl_decoder *cxl_decoder_get_by_name(struct cxl_ctx *ctx, const char *ident); struct cxl_memdev *cxl_decoder_get_memdev(struct cxl_decoder *decoder); diff --git a/cxl/memdev.c b/cxl/memdev.c index 6e44d15..c9a1d0c 100644 --- a/cxl/memdev.c +++ b/cxl/memdev.c @@ -269,8 +269,10 @@ static int __reserve_dpa(struct cxl_memdev *memdev, if (mode == CXL_DECODER_MODE_RAM) avail_dpa = cxl_memdev_get_ram_size(memdev); - else + else if (mode == CXL_DECODER_MODE_PMEM) avail_dpa = cxl_memdev_get_pmem_size(memdev); + else + avail_dpa = cxl_memdev_get_dynamic_ram_1_size(memdev); cxl_decoder_foreach(port, decoder) { size = cxl_decoder_get_dpa_size(decoder); diff --git a/cxl/region.c b/cxl/region.c index 85d4d9b..0a62a8e 100644 --- a/cxl/region.c +++ b/cxl/region.c @@ -303,7 +303,8 @@ static int parse_create_options(struct cxl_ctx *ctx, int count, if (param.type) { p->mode = cxl_decoder_mode_from_ident(param.type); - if (p->mode == CXL_DECODER_MODE_RAM && param.uuid) { + if ((p->mode == CXL_DECODER_MODE_RAM || + p->mode == CXL_DECODER_MODE_DYNAMIC_RAM_1) && param.uuid) { log_err(&rl, "can't set UUID for ram / volatile regions"); goto err; @@ -417,6 +418,9 @@ static void collect_minsize(struct cxl_ctx *ctx, struct parsed_params *p) case CXL_DECODER_MODE_PMEM: size = cxl_memdev_get_pmem_size(memdev); break; + case CXL_DECODER_MODE_DYNAMIC_RAM_1: + size = cxl_memdev_get_dynamic_ram_1_size(memdev); + break; default: /* Shouldn't ever get here */ ; } @@ -448,8 +452,10 @@ static int create_region_validate_qos_class(struct parsed_params *p) if (p->mode == CXL_DECODER_MODE_RAM) qos_class = cxl_memdev_get_ram_qos_class(memdev); - else + else if (p->mode == CXL_DECODER_MODE_PMEM) qos_class = cxl_memdev_get_pmem_qos_class(memdev); + else + qos_class = cxl_memdev_get_dynamic_ram_1_qos_class(memdev); /* No qos_class entries. Possibly no kernel support */ if (qos_class == CXL_QOS_CLASS_NONE) @@ -488,6 +494,12 @@ static int validate_decoder(struct cxl_decoder *decoder, return -EINVAL; } break; + case CXL_DECODER_MODE_DYNAMIC_RAM_1: + if (!cxl_decoder_is_dynamic_ram_1_capable(decoder)) { + log_err(&rl, "%s is not dynamic_ram_1 capable\n", devname); + return -EINVAL; + } + break; default: log_err(&rl, "unknown type: %s\n", param.type); return -EINVAL; @@ -509,9 +521,11 @@ static void set_type_from_decoder(struct cxl_ctx *ctx, struct parsed_params *p) return; /* - * default to pmem if both types are set, otherwise the single + * default to pmem if all types are set, otherwise the single * capability dominates. */ + if (cxl_decoder_is_dynamic_ram_1_capable(p->root_decoder)) + p->mode = CXL_DECODER_MODE_DYNAMIC_RAM_1; if (cxl_decoder_is_volatile_capable(p->root_decoder)) p->mode = CXL_DECODER_MODE_RAM; if (cxl_decoder_is_pmem_capable(p->root_decoder)) @@ -699,6 +713,13 @@ static int create_region(struct cxl_ctx *ctx, int *count, param.root_decoder); return -ENXIO; } + } else if (p->mode == CXL_DECODER_MODE_DYNAMIC_RAM_1) { + region = cxl_decoder_create_dynamic_ram_1_region(p->root_decoder); + if (!region) { + log_err(&rl, "failed to create region under %s\n", + param.root_decoder); + return -ENXIO; + } } else { log_err(&rl, "region type '%s' is not supported\n", param.type); -- 2.43.0

