@@ -380,6 +380,37 @@ OPTIONS
--regions::
Include region objects in the listing.
+-X::
+--dax::
+ Append DAX information to region listings
+----
+# cxl list -RXu
+{
+ "region":"region4",
+ "resource":"0xf010000000",
+ "size":"512.00 MiB (536.87 MB)",
+ "interleave_ways":2,
+ "interleave_granularity":4096,
+ "decode_state":"commit",
+ "daxregion":{
+ "id":4,
+ "size":"512.00 MiB (536.87 MB)",
+ "align":2097152,
+ "devices":[
+ {
+ "chardev":"dax4.0",
+ "size":"512.00 MiB (536.87 MB)",
+ "target_node":0,
+ "align":2097152,
+ "mode":"system-ram",
+ "online_memblocks":0,
+ "total_memblocks":4
+ }
+ ]
+ }
+}
+----
+
-r::
--region::
Specify CXL region device name(s), or device id(s), to filter the listing.
@@ -568,6 +568,7 @@ int cxl_region_clear_target(struct cxl_region *region, int position);
int cxl_region_clear_all_targets(struct cxl_region *region);
int cxl_region_decode_commit(struct cxl_region *region);
int cxl_region_decode_reset(struct cxl_region *region);
+struct daxctl_region *cxl_region_get_daxctl_region(struct cxl_region *region);
----
A region's resource attribute is the Host Physical Address at which the region's
@@ -587,6 +588,12 @@ The 'decode_commit' and 'decode_reset' attributes reserve and free DPA space
on a given memdev by allocating an endpoint decoder, and programming it based
on the region's interleave geometry.
+Once a region is active it is attached to either the NVDIMM subsystem
+where its properties can be interrogated by ndctl, or the DAX subsystem
+where its properties can be interrogated by daxctl. The helper
+cxl_region_get_daxctl_region() returns an 'struct daxctl_region *' that
+can be used with other libdaxctl APIs.
+
include::../../copyright.txt[]
SEE ALSO
@@ -150,6 +150,7 @@ struct cxl_region {
unsigned int interleave_granularity;
enum cxl_decode_state decode_state;
enum cxl_decoder_mode mode;
+ struct daxctl_region *dax_region;
struct kmod_module *module;
struct list_head mappings;
};
@@ -26,6 +26,7 @@
#include <util/bitmap.h>
#include <cxl/cxl_mem.h>
#include <cxl/libcxl.h>
+#include <daxctl/libdaxctl.h>
#include "private.h"
/**
@@ -49,6 +50,7 @@ struct cxl_ctx {
struct list_head memdevs;
struct list_head buses;
struct kmod_ctx *kmod_ctx;
+ struct daxctl_ctx *daxctl_ctx;
void *private_data;
};
@@ -231,6 +233,7 @@ CXL_EXPORT void *cxl_get_private_data(struct cxl_ctx *ctx)
*/
CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
{
+ struct daxctl_ctx *daxctl_ctx;
struct udev_queue *udev_queue;
struct kmod_ctx *kmod_ctx;
struct udev *udev;
@@ -241,6 +244,10 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
if (!c)
return -ENOMEM;
+ rc = daxctl_new(&daxctl_ctx);
+ if (rc)
+ goto err_daxctl;
+
kmod_ctx = kmod_new(NULL, NULL);
if (check_kmod(kmod_ctx) != 0) {
rc = -ENXIO;
@@ -267,6 +274,7 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
list_head_init(&c->memdevs);
list_head_init(&c->buses);
c->kmod_ctx = kmod_ctx;
+ c->daxctl_ctx = daxctl_ctx;
c->udev = udev;
c->udev_queue = udev_queue;
c->timeout = 5000;
@@ -278,6 +286,8 @@ err_udev_queue:
err_udev:
kmod_unref(kmod_ctx);
err_kmod:
+ daxctl_unref(daxctl_ctx);
+err_daxctl:
free(c);
return rc;
}
@@ -321,6 +331,7 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
udev_queue_unref(ctx->udev_queue);
udev_unref(ctx->udev);
kmod_unref(ctx->kmod_ctx);
+ daxctl_unref(ctx->daxctl_ctx);
info(ctx, "context %p released\n", ctx);
free(ctx);
}
@@ -746,6 +757,34 @@ cxl_region_get_target_decoder(struct cxl_region *region, int position)
return decoder;
}
+CXL_EXPORT struct daxctl_region *
+cxl_region_get_daxctl_region(struct cxl_region *region)
+{
+ const char *devname = cxl_region_get_devname(region);
+ struct cxl_ctx *ctx = cxl_region_get_ctx(region);
+ char *path = region->dev_buf;
+ int len = region->buf_len;
+ uuid_t uuid = { 0 };
+ struct stat st;
+
+ if (region->dax_region)
+ return region->dax_region;
+
+ if (snprintf(region->dev_buf, len, "%s/dax_region%d", region->dev_path,
+ region->id) >= len) {
+ err(ctx, "%s: buffer too small!\n", devname);
+ return NULL;
+ }
+
+ if (stat(path, &st) < 0)
+ return NULL;
+
+ region->dax_region =
+ daxctl_new_region(ctx->daxctl_ctx, region->id, uuid, path);
+
+ return region->dax_region;
+}
+
CXL_EXPORT int cxl_region_set_size(struct cxl_region *region,
unsigned long long size)
{
@@ -28,6 +28,7 @@ struct cxl_filter_params {
bool health;
bool partition;
bool alert_config;
+ bool dax;
int verbose;
struct log_ctx ctx;
};
@@ -80,6 +81,8 @@ static inline unsigned long cxl_filter_to_flags(struct cxl_filter_params *param)
flags |= UTIL_JSON_PARTITION;
if (param->alert_config)
flags |= UTIL_JSON_ALERT_CONFIG;
+ if (param->dax)
+ flags |= UTIL_JSON_DAX | UTIL_JSON_DAX_DEVS;
return flags;
}
@@ -279,6 +279,7 @@ unsigned int cxl_region_get_interleave_ways(struct cxl_region *region);
unsigned int cxl_region_get_interleave_granularity(struct cxl_region *region);
struct cxl_decoder *cxl_region_get_target_decoder(struct cxl_region *region,
int position);
+struct daxctl_region *cxl_region_get_daxctl_region(struct cxl_region *region);
int cxl_region_set_size(struct cxl_region *region, unsigned long long size);
int cxl_region_set_uuid(struct cxl_region *region, uuid_t uu);
int cxl_region_set_interleave_ways(struct cxl_region *region,
@@ -11,6 +11,7 @@
#include "filter.h"
#include "json.h"
+#include "../daxctl/json.h"
static const char *which_sep(const char *filter)
{
@@ -10,6 +10,7 @@
#include "filter.h"
#include "json.h"
+#include "../daxctl/json.h"
static struct json_object *util_cxl_memdev_health_to_json(
struct cxl_memdev *memdev, unsigned long flags)
@@ -889,7 +890,22 @@ struct json_object *util_cxl_region_to_json(struct cxl_region *region,
util_cxl_mappings_append_json(jregion, region, flags);
+ if (flags & UTIL_JSON_DAX) {
+ struct daxctl_region *dax_region;
+
+ dax_region = cxl_region_get_daxctl_region(region);
+ if (dax_region) {
+ jobj = util_daxctl_region_to_json(dax_region, NULL,
+ flags);
+ if (jobj)
+ json_object_object_add(jregion, "daxregion",
+ jobj);
+ }
+ }
+
json_object_set_userdata(jregion, region, NULL);
+
+
return jregion;
}
@@ -45,6 +45,7 @@ static const struct option options[] = {
OPT_STRING('r', "region", ¶m.region_filter, "region name",
"filter by CXL region name(s)"),
OPT_BOOLEAN('R', "regions", ¶m.regions, "include CXL regions"),
+ OPT_BOOLEAN('X', "dax", ¶m.dax, "include CXL DAX region enumeration"),
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
OPT_BOOLEAN('u', "human", ¶m.human,
"use human friendly number formats"),
@@ -116,6 +117,7 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
param.health = true;
param.partition = true;
param.alert_config = true;
+ param.dax = true;
/* fallthrough */
case 2:
param.idle = true;
@@ -247,4 +247,5 @@ LIBCXL_5 {
global:
cxl_region_get_mode;
cxl_decoder_create_ram_region;
+ cxl_region_get_daxctl_region;
} LIBCXL_4;
@@ -16,6 +16,7 @@ cxl = library('cxl',
uuid,
kmod,
libudev,
+ daxctl_dep,
],
version : libcxl_version,
install : true,
@@ -7,6 +7,8 @@ cxl_src = [
'memdev.c',
'json.c',
'filter.c',
+ '../daxctl/json.c',
+ '../daxctl/filter.c',
]
cxl_tool = executable('cxl',
@@ -14,6 +16,7 @@ cxl_tool = executable('cxl',
include_directories : root_inc,
dependencies : [
cxl_dep,
+ daxctl_dep,
util_dep,
uuid,
kmod,