|
|
26ccd9 |
From c0f2b36c481119e06eaec60dda17a42100a81ebc Mon Sep 17 00:00:00 2001
|
|
|
26ccd9 |
From: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
26ccd9 |
Date: Mon, 15 Aug 2022 13:22:08 -0600
|
|
|
26ccd9 |
Subject: [PATCH 193/217] cxl-cli: add region listing support
|
|
|
26ccd9 |
|
|
|
26ccd9 |
Add cxl_region -> json and cxl_mapping -> json emitter helpers, and
|
|
|
26ccd9 |
teach cxl_filter_walk about cxl_regions. With these in place, 'cxl-list'
|
|
|
26ccd9 |
can now emit json objects for CXL regions. They can be top-level objects
|
|
|
26ccd9 |
if requested by themselves, or nested under root-decoders, if listed
|
|
|
26ccd9 |
along with decoders. Allow a plain 'cxl list' command to imply
|
|
|
26ccd9 |
'--regions'.
|
|
|
26ccd9 |
|
|
|
26ccd9 |
Link: https://lore.kernel.org/r/20220815192214.545800-6-vishal.l.verma@intel.com
|
|
|
26ccd9 |
Cc: Dan Williams <dan.j.williams@intel.com>
|
|
|
26ccd9 |
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
|
|
26ccd9 |
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
26ccd9 |
---
|
|
|
26ccd9 |
Documentation/cxl/cxl-list.txt | 13 ++-
|
|
|
26ccd9 |
cxl/filter.c | 158 +++++++++++++++++++++++++++++++--
|
|
|
26ccd9 |
cxl/filter.h | 4 +
|
|
|
26ccd9 |
cxl/json.c | 114 ++++++++++++++++++++++++
|
|
|
26ccd9 |
cxl/json.h | 5 ++
|
|
|
26ccd9 |
cxl/list.c | 25 +++---
|
|
|
26ccd9 |
6 files changed, 295 insertions(+), 24 deletions(-)
|
|
|
26ccd9 |
|
|
|
26ccd9 |
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
|
|
26ccd9 |
index 088ea70..b88940a 100644
|
|
|
26ccd9 |
--- a/Documentation/cxl/cxl-list.txt
|
|
|
26ccd9 |
+++ b/Documentation/cxl/cxl-list.txt
|
|
|
26ccd9 |
@@ -317,8 +317,9 @@ OPTIONS
|
|
|
26ccd9 |
|
|
|
26ccd9 |
-T::
|
|
|
26ccd9 |
--targets::
|
|
|
26ccd9 |
- Extend decoder listings with downstream port target information, and /
|
|
|
26ccd9 |
- or port and bus listings with the downstream port information.
|
|
|
26ccd9 |
+ Extend decoder listings with downstream port target information, port
|
|
|
26ccd9 |
+ and bus listings with the downstream port information, and / or regions
|
|
|
26ccd9 |
+ with mapping information.
|
|
|
26ccd9 |
----
|
|
|
26ccd9 |
# cxl list -BTu -b ACPI.CXL
|
|
|
26ccd9 |
{
|
|
|
26ccd9 |
@@ -335,6 +336,14 @@ OPTIONS
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
----
|
|
|
26ccd9 |
|
|
|
26ccd9 |
+-R::
|
|
|
26ccd9 |
+--regions::
|
|
|
26ccd9 |
+ Include region objects in the listing.
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+-r::
|
|
|
26ccd9 |
+--region::
|
|
|
26ccd9 |
+ Specify CXL region device name(s), or device id(s), to filter the listing.
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
--debug::
|
|
|
26ccd9 |
If the cxl tool was built with debug enabled, turn on debug
|
|
|
26ccd9 |
messages.
|
|
|
26ccd9 |
diff --git a/cxl/filter.c b/cxl/filter.c
|
|
|
26ccd9 |
index e5fab19..38ece55 100644
|
|
|
26ccd9 |
--- a/cxl/filter.c
|
|
|
26ccd9 |
+++ b/cxl/filter.c
|
|
|
26ccd9 |
@@ -585,6 +585,73 @@ util_cxl_memdev_filter_by_port(struct cxl_memdev *memdev, const char *bus_ident,
|
|
|
26ccd9 |
return NULL;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
+static struct cxl_region *
|
|
|
26ccd9 |
+util_cxl_region_filter_by_bus(struct cxl_region *region, const char *__ident)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ struct cxl_decoder *decoder = cxl_region_get_decoder(region);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (!util_cxl_decoder_filter_by_bus(decoder, __ident))
|
|
|
26ccd9 |
+ return NULL;
|
|
|
26ccd9 |
+ return region;
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+static struct cxl_region *
|
|
|
26ccd9 |
+util_cxl_region_filter_by_port(struct cxl_region *region, const char *__ident)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ struct cxl_decoder *decoder = cxl_region_get_decoder(region);
|
|
|
26ccd9 |
+ struct cxl_port *port = cxl_decoder_get_port(decoder);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (!util_cxl_port_filter(port, __ident ,CXL_PF_ANCESTRY))
|
|
|
26ccd9 |
+ return NULL;
|
|
|
26ccd9 |
+ return region;
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+static struct cxl_region *
|
|
|
26ccd9 |
+util_cxl_region_filter_by_decoder(struct cxl_region *region,
|
|
|
26ccd9 |
+ const char *__ident)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ struct cxl_decoder *decoder = cxl_region_get_decoder(region);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (!util_cxl_decoder_filter(decoder, __ident))
|
|
|
26ccd9 |
+ return NULL;
|
|
|
26ccd9 |
+ return region;
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+struct cxl_region *util_cxl_region_filter(struct cxl_region *region,
|
|
|
26ccd9 |
+ const char *__ident)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ char *ident, *save;
|
|
|
26ccd9 |
+ const char *name;
|
|
|
26ccd9 |
+ int id;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (!__ident)
|
|
|
26ccd9 |
+ return region;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ ident = strdup(__ident);
|
|
|
26ccd9 |
+ if (!ident)
|
|
|
26ccd9 |
+ return NULL;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ for (name = strtok_r(ident, which_sep(__ident), &save); name;
|
|
|
26ccd9 |
+ name = strtok_r(NULL, which_sep(__ident), &save)) {
|
|
|
26ccd9 |
+ if (strcmp(name, "all") == 0)
|
|
|
26ccd9 |
+ break;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if ((sscanf(name, "%d", &id) == 1 ||
|
|
|
26ccd9 |
+ sscanf(name, "region%d", &id) == 1) &&
|
|
|
26ccd9 |
+ cxl_region_get_id(region) == id)
|
|
|
26ccd9 |
+ break;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (strcmp(name, cxl_region_get_devname(region)) == 0)
|
|
|
26ccd9 |
+ break;
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ free(ident);
|
|
|
26ccd9 |
+ if (name)
|
|
|
26ccd9 |
+ return region;
|
|
|
26ccd9 |
+ return NULL;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
static unsigned long params_to_flags(struct cxl_filter_params *param)
|
|
|
26ccd9 |
{
|
|
|
26ccd9 |
unsigned long flags = 0;
|
|
|
26ccd9 |
@@ -672,26 +739,57 @@ static struct json_object *pick_array(struct json_object *child,
|
|
|
26ccd9 |
return NULL;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
+static void walk_regions(struct cxl_decoder *decoder,
|
|
|
26ccd9 |
+ struct json_object *jregions,
|
|
|
26ccd9 |
+ struct cxl_filter_params *p,
|
|
|
26ccd9 |
+ unsigned long flags)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ struct json_object *jregion;
|
|
|
26ccd9 |
+ struct cxl_region *region;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ cxl_region_foreach(decoder, region) {
|
|
|
26ccd9 |
+ if (!util_cxl_region_filter(region, p->region_filter))
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ if (!util_cxl_region_filter_by_bus(region, p->bus_filter))
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ if (!util_cxl_region_filter_by_port(region, p->port_filter))
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ if (!util_cxl_region_filter_by_decoder(region, p->decoder_filter))
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ if (!p->idle && !cxl_region_is_enabled(region))
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ jregion = util_cxl_region_to_json(region, flags);
|
|
|
26ccd9 |
+ if (!jregion)
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ json_object_array_add(jregions, jregion);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ return;
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p,
|
|
|
26ccd9 |
- struct json_object *jdecoders, unsigned long flags)
|
|
|
26ccd9 |
+ struct json_object *jdecoders,
|
|
|
26ccd9 |
+ struct json_object *jregions, unsigned long flags)
|
|
|
26ccd9 |
{
|
|
|
26ccd9 |
struct cxl_decoder *decoder;
|
|
|
26ccd9 |
|
|
|
26ccd9 |
cxl_decoder_foreach(port, decoder) {
|
|
|
26ccd9 |
+ const char *devname = cxl_decoder_get_devname(decoder);
|
|
|
26ccd9 |
+ struct json_object *jchildregions = NULL;
|
|
|
26ccd9 |
struct json_object *jdecoder;
|
|
|
26ccd9 |
|
|
|
26ccd9 |
if (!p->decoders)
|
|
|
26ccd9 |
- continue;
|
|
|
26ccd9 |
+ goto walk_children;
|
|
|
26ccd9 |
if (!util_cxl_decoder_filter(decoder, p->decoder_filter))
|
|
|
26ccd9 |
- continue;
|
|
|
26ccd9 |
+ goto walk_children;
|
|
|
26ccd9 |
if (!util_cxl_decoder_filter_by_bus(decoder, p->bus_filter))
|
|
|
26ccd9 |
- continue;
|
|
|
26ccd9 |
+ goto walk_children;
|
|
|
26ccd9 |
if (!util_cxl_decoder_filter_by_port(decoder, p->port_filter,
|
|
|
26ccd9 |
pf_mode(p)))
|
|
|
26ccd9 |
- continue;
|
|
|
26ccd9 |
+ goto walk_children;
|
|
|
26ccd9 |
if (!util_cxl_decoder_filter_by_memdev(
|
|
|
26ccd9 |
decoder, p->memdev_filter, p->serial_filter))
|
|
|
26ccd9 |
- continue;
|
|
|
26ccd9 |
+ goto walk_children;
|
|
|
26ccd9 |
if (!p->idle && cxl_decoder_get_size(decoder) == 0)
|
|
|
26ccd9 |
continue;
|
|
|
26ccd9 |
jdecoder = util_cxl_decoder_to_json(decoder, flags);
|
|
|
26ccd9 |
@@ -702,7 +800,27 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p,
|
|
|
26ccd9 |
util_cxl_targets_append_json(jdecoder, decoder,
|
|
|
26ccd9 |
p->memdev_filter, p->serial_filter,
|
|
|
26ccd9 |
flags);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (p->regions) {
|
|
|
26ccd9 |
+ jchildregions = json_object_new_array();
|
|
|
26ccd9 |
+ if (!jchildregions) {
|
|
|
26ccd9 |
+ err(p, "failed to allocate region object\n");
|
|
|
26ccd9 |
+ return;
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
json_object_array_add(jdecoders, jdecoder);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+walk_children:
|
|
|
26ccd9 |
+ if (!p->regions)
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ if (!cxl_port_is_root(port))
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ walk_regions(decoder,
|
|
|
26ccd9 |
+ pick_array(jchildregions, jregions),
|
|
|
26ccd9 |
+ p, flags);
|
|
|
26ccd9 |
+ cond_add_put_array_suffix(jdecoder, "regions", devname,
|
|
|
26ccd9 |
+ jchildregions);
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
@@ -782,7 +900,7 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
|
|
|
26ccd9 |
if (!p->decoders)
|
|
|
26ccd9 |
continue;
|
|
|
26ccd9 |
walk_decoders(cxl_endpoint_get_port(endpoint), p,
|
|
|
26ccd9 |
- pick_array(jchilddecoders, jdecoders), flags);
|
|
|
26ccd9 |
+ pick_array(jchilddecoders, jdecoders), NULL, flags);
|
|
|
26ccd9 |
cond_add_put_array_suffix(jendpoint, "decoders", devname,
|
|
|
26ccd9 |
jchilddecoders);
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
@@ -869,7 +987,8 @@ walk_children:
|
|
|
26ccd9 |
flags);
|
|
|
26ccd9 |
|
|
|
26ccd9 |
walk_decoders(port, p,
|
|
|
26ccd9 |
- pick_array(jchilddecoders, jportdecoders), flags);
|
|
|
26ccd9 |
+ pick_array(jchilddecoders, jportdecoders), NULL,
|
|
|
26ccd9 |
+ flags);
|
|
|
26ccd9 |
walk_child_ports(port, p, pick_array(jchildports, jports),
|
|
|
26ccd9 |
pick_array(jchilddecoders, jportdecoders),
|
|
|
26ccd9 |
pick_array(jchildeps, jeps),
|
|
|
26ccd9 |
@@ -894,6 +1013,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
|
|
26ccd9 |
struct json_object *jbusdecoders = NULL;
|
|
|
26ccd9 |
struct json_object *jepdecoders = NULL;
|
|
|
26ccd9 |
struct json_object *janondevs = NULL;
|
|
|
26ccd9 |
+ struct json_object *jregions = NULL;
|
|
|
26ccd9 |
struct json_object *jeps = NULL;
|
|
|
26ccd9 |
struct cxl_memdev *memdev;
|
|
|
26ccd9 |
int top_level_objs = 0;
|
|
|
26ccd9 |
@@ -936,6 +1056,10 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
|
|
26ccd9 |
if (!jepdecoders)
|
|
|
26ccd9 |
goto err;
|
|
|
26ccd9 |
|
|
|
26ccd9 |
+ jregions = json_object_new_array();
|
|
|
26ccd9 |
+ if (!jregions)
|
|
|
26ccd9 |
+ goto err;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
dbg(p, "walk memdevs\n");
|
|
|
26ccd9 |
cxl_memdev_foreach(ctx, memdev) {
|
|
|
26ccd9 |
struct json_object *janondev;
|
|
|
26ccd9 |
@@ -964,6 +1088,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
|
|
26ccd9 |
struct json_object *jchildports = NULL;
|
|
|
26ccd9 |
struct json_object *jchilddevs = NULL;
|
|
|
26ccd9 |
struct json_object *jchildeps = NULL;
|
|
|
26ccd9 |
+ struct json_object *jchildregions = NULL;
|
|
|
26ccd9 |
struct cxl_port *port = cxl_bus_get_port(bus);
|
|
|
26ccd9 |
const char *devname = cxl_bus_get_devname(bus);
|
|
|
26ccd9 |
|
|
|
26ccd9 |
@@ -1021,11 +1146,20 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
|
|
26ccd9 |
continue;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
+ if (p->regions && !p->decoders) {
|
|
|
26ccd9 |
+ jchildregions = json_object_new_array();
|
|
|
26ccd9 |
+ if (!jchildregions) {
|
|
|
26ccd9 |
+ err(p,
|
|
|
26ccd9 |
+ "%s: failed to enumerate child regions\n",
|
|
|
26ccd9 |
+ devname);
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
walk_children:
|
|
|
26ccd9 |
dbg(p, "walk decoders\n");
|
|
|
26ccd9 |
walk_decoders(port, p, pick_array(jchilddecoders, jbusdecoders),
|
|
|
26ccd9 |
- flags);
|
|
|
26ccd9 |
+ pick_array(jchildregions, jregions), flags);
|
|
|
26ccd9 |
|
|
|
26ccd9 |
dbg(p, "walk ports\n");
|
|
|
26ccd9 |
walk_child_ports(port, p, pick_array(jchildports, jports),
|
|
|
26ccd9 |
@@ -1038,6 +1172,8 @@ walk_children:
|
|
|
26ccd9 |
jchildeps);
|
|
|
26ccd9 |
cond_add_put_array_suffix(jbus, "decoders", devname,
|
|
|
26ccd9 |
jchilddecoders);
|
|
|
26ccd9 |
+ cond_add_put_array_suffix(jbus, "regions", devname,
|
|
|
26ccd9 |
+ jchildregions);
|
|
|
26ccd9 |
cond_add_put_array_suffix(jbus, "memdevs", devname, jchilddevs);
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
@@ -1057,6 +1193,8 @@ walk_children:
|
|
|
26ccd9 |
top_level_objs++;
|
|
|
26ccd9 |
if (json_object_array_length(jepdecoders))
|
|
|
26ccd9 |
top_level_objs++;
|
|
|
26ccd9 |
+ if (json_object_array_length(jregions))
|
|
|
26ccd9 |
+ top_level_objs++;
|
|
|
26ccd9 |
|
|
|
26ccd9 |
splice_array(p, janondevs, jplatform, "anon memdevs", top_level_objs > 1);
|
|
|
26ccd9 |
splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1);
|
|
|
26ccd9 |
@@ -1069,6 +1207,7 @@ walk_children:
|
|
|
26ccd9 |
top_level_objs > 1);
|
|
|
26ccd9 |
splice_array(p, jepdecoders, jplatform, "endpoint decoders",
|
|
|
26ccd9 |
top_level_objs > 1);
|
|
|
26ccd9 |
+ splice_array(p, jregions, jplatform, "regions", top_level_objs > 1);
|
|
|
26ccd9 |
|
|
|
26ccd9 |
util_display_json_array(stdout, jplatform, flags);
|
|
|
26ccd9 |
|
|
|
26ccd9 |
@@ -1082,6 +1221,7 @@ err:
|
|
|
26ccd9 |
json_object_put(jbusdecoders);
|
|
|
26ccd9 |
json_object_put(jportdecoders);
|
|
|
26ccd9 |
json_object_put(jepdecoders);
|
|
|
26ccd9 |
+ json_object_put(jregions);
|
|
|
26ccd9 |
json_object_put(jplatform);
|
|
|
26ccd9 |
return -ENOMEM;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
diff --git a/cxl/filter.h b/cxl/filter.h
|
|
|
26ccd9 |
index c913daf..609433c 100644
|
|
|
26ccd9 |
--- a/cxl/filter.h
|
|
|
26ccd9 |
+++ b/cxl/filter.h
|
|
|
26ccd9 |
@@ -13,9 +13,11 @@ struct cxl_filter_params {
|
|
|
26ccd9 |
const char *port_filter;
|
|
|
26ccd9 |
const char *endpoint_filter;
|
|
|
26ccd9 |
const char *decoder_filter;
|
|
|
26ccd9 |
+ const char *region_filter;
|
|
|
26ccd9 |
bool single;
|
|
|
26ccd9 |
bool endpoints;
|
|
|
26ccd9 |
bool decoders;
|
|
|
26ccd9 |
+ bool regions;
|
|
|
26ccd9 |
bool targets;
|
|
|
26ccd9 |
bool memdevs;
|
|
|
26ccd9 |
bool ports;
|
|
|
26ccd9 |
@@ -33,6 +35,8 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
|
|
26ccd9 |
struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port,
|
|
|
26ccd9 |
const char *ident,
|
|
|
26ccd9 |
const char *serial);
|
|
|
26ccd9 |
+struct cxl_region *util_cxl_region_filter(struct cxl_region *region,
|
|
|
26ccd9 |
+ const char *__ident);
|
|
|
26ccd9 |
|
|
|
26ccd9 |
enum cxl_port_filter_mode {
|
|
|
26ccd9 |
CXL_PF_SINGLE,
|
|
|
26ccd9 |
diff --git a/cxl/json.c b/cxl/json.c
|
|
|
26ccd9 |
index ae9c812..70cf286 100644
|
|
|
26ccd9 |
--- a/cxl/json.c
|
|
|
26ccd9 |
+++ b/cxl/json.c
|
|
|
26ccd9 |
@@ -524,6 +524,120 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder,
|
|
|
26ccd9 |
return jdecoder;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
+void util_cxl_mappings_append_json(struct json_object *jregion,
|
|
|
26ccd9 |
+ struct cxl_region *region,
|
|
|
26ccd9 |
+ unsigned long flags)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ struct json_object *jobj, *jmappings;
|
|
|
26ccd9 |
+ struct cxl_memdev_mapping *mapping;
|
|
|
26ccd9 |
+ unsigned int val, nr_mappings;
|
|
|
26ccd9 |
+ const char *devname;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ nr_mappings = cxl_region_get_interleave_ways(region);
|
|
|
26ccd9 |
+ if (!nr_mappings || (nr_mappings == UINT_MAX))
|
|
|
26ccd9 |
+ return;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (!(flags & UTIL_JSON_TARGETS))
|
|
|
26ccd9 |
+ return;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ jmappings = json_object_new_array();
|
|
|
26ccd9 |
+ if (!jmappings)
|
|
|
26ccd9 |
+ return;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ cxl_mapping_foreach(region, mapping) {
|
|
|
26ccd9 |
+ struct json_object *jmapping;
|
|
|
26ccd9 |
+ struct cxl_decoder *decoder;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ jmapping = json_object_new_object();
|
|
|
26ccd9 |
+ if (!jmapping)
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ val = cxl_mapping_get_position(mapping);
|
|
|
26ccd9 |
+ if (val < UINT_MAX) {
|
|
|
26ccd9 |
+ jobj = json_object_new_int(val);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jmapping, "position",
|
|
|
26ccd9 |
+ jobj);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ decoder = cxl_mapping_get_decoder(mapping);
|
|
|
26ccd9 |
+ if (!decoder)
|
|
|
26ccd9 |
+ continue;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ devname = cxl_decoder_get_devname(decoder);
|
|
|
26ccd9 |
+ jobj = json_object_new_string(devname);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jmapping, "decoder", jobj);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ json_object_array_add(jmappings, jmapping);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ json_object_object_add(jregion, "mappings", jmappings);
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+struct json_object *util_cxl_region_to_json(struct cxl_region *region,
|
|
|
26ccd9 |
+ unsigned long flags)
|
|
|
26ccd9 |
+{
|
|
|
26ccd9 |
+ const char *devname = cxl_region_get_devname(region);
|
|
|
26ccd9 |
+ struct json_object *jregion, *jobj;
|
|
|
26ccd9 |
+ u64 val;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ jregion = json_object_new_object();
|
|
|
26ccd9 |
+ if (!jregion)
|
|
|
26ccd9 |
+ return NULL;
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ jobj = json_object_new_string(devname);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion, "region", jobj);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ val = cxl_region_get_resource(region);
|
|
|
26ccd9 |
+ if (val < ULLONG_MAX) {
|
|
|
26ccd9 |
+ jobj = util_json_object_hex(val, flags);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion, "resource", jobj);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ val = cxl_region_get_size(region);
|
|
|
26ccd9 |
+ if (val < ULLONG_MAX) {
|
|
|
26ccd9 |
+ jobj = util_json_object_size(val, flags);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion, "size", jobj);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ val = cxl_region_get_interleave_ways(region);
|
|
|
26ccd9 |
+ if (val < INT_MAX) {
|
|
|
26ccd9 |
+ jobj = json_object_new_int(val);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion,
|
|
|
26ccd9 |
+ "interleave_ways", jobj);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ val = cxl_region_get_interleave_granularity(region);
|
|
|
26ccd9 |
+ if (val < INT_MAX) {
|
|
|
26ccd9 |
+ jobj = json_object_new_int(val);
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion,
|
|
|
26ccd9 |
+ "interleave_granularity", jobj);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (cxl_region_decode_is_committed(region))
|
|
|
26ccd9 |
+ jobj = json_object_new_string("commit");
|
|
|
26ccd9 |
+ else
|
|
|
26ccd9 |
+ jobj = json_object_new_string("reset");
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion, "decode_state", jobj);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ if (!cxl_region_is_enabled(region)) {
|
|
|
26ccd9 |
+ jobj = json_object_new_string("disabled");
|
|
|
26ccd9 |
+ if (jobj)
|
|
|
26ccd9 |
+ json_object_object_add(jregion, "state", jobj);
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ util_cxl_mappings_append_json(jregion, region, flags);
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ return jregion;
|
|
|
26ccd9 |
+}
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
void util_cxl_targets_append_json(struct json_object *jdecoder,
|
|
|
26ccd9 |
struct cxl_decoder *decoder,
|
|
|
26ccd9 |
const char *ident, const char *serial,
|
|
|
26ccd9 |
diff --git a/cxl/json.h b/cxl/json.h
|
|
|
26ccd9 |
index 9a5a845..eb7572b 100644
|
|
|
26ccd9 |
--- a/cxl/json.h
|
|
|
26ccd9 |
+++ b/cxl/json.h
|
|
|
26ccd9 |
@@ -15,6 +15,11 @@ struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint,
|
|
|
26ccd9 |
unsigned long flags);
|
|
|
26ccd9 |
struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder,
|
|
|
26ccd9 |
unsigned long flags);
|
|
|
26ccd9 |
+struct json_object *util_cxl_region_to_json(struct cxl_region *region,
|
|
|
26ccd9 |
+ unsigned long flags);
|
|
|
26ccd9 |
+void util_cxl_mappings_append_json(struct json_object *jregion,
|
|
|
26ccd9 |
+ struct cxl_region *region,
|
|
|
26ccd9 |
+ unsigned long flags);
|
|
|
26ccd9 |
void util_cxl_targets_append_json(struct json_object *jdecoder,
|
|
|
26ccd9 |
struct cxl_decoder *decoder,
|
|
|
26ccd9 |
const char *ident, const char *serial,
|
|
|
26ccd9 |
diff --git a/cxl/list.c b/cxl/list.c
|
|
|
26ccd9 |
index 1b5f583..88ca9d9 100644
|
|
|
26ccd9 |
--- a/cxl/list.c
|
|
|
26ccd9 |
+++ b/cxl/list.c
|
|
|
26ccd9 |
@@ -41,7 +41,10 @@ static const struct option options[] = {
|
|
|
26ccd9 |
OPT_BOOLEAN('D', "decoders", ¶m.decoders,
|
|
|
26ccd9 |
"include CXL decoder info"),
|
|
|
26ccd9 |
OPT_BOOLEAN('T', "targets", ¶m.targets,
|
|
|
26ccd9 |
- "include CXL target data with decoders or ports"),
|
|
|
26ccd9 |
+ "include CXL target data with decoders, ports, or regions"),
|
|
|
26ccd9 |
+ OPT_STRING('r', "region", ¶m.region_filter, "region name",
|
|
|
26ccd9 |
+ "filter by CXL region name(s)"),
|
|
|
26ccd9 |
+ OPT_BOOLEAN('R', "regions", ¶m.regions, "include CXL regions"),
|
|
|
26ccd9 |
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
|
|
26ccd9 |
OPT_BOOLEAN('u', "human", ¶m.human,
|
|
|
26ccd9 |
"use human friendly number formats"),
|
|
|
26ccd9 |
@@ -58,7 +61,7 @@ static const struct option options[] = {
|
|
|
26ccd9 |
static int num_list_flags(void)
|
|
|
26ccd9 |
{
|
|
|
26ccd9 |
return !!param.memdevs + !!param.buses + !!param.ports +
|
|
|
26ccd9 |
- !!param.endpoints + !!param.decoders;
|
|
|
26ccd9 |
+ !!param.endpoints + !!param.decoders + !!param.regions;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
|
|
26ccd9 |
@@ -92,18 +95,14 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
|
|
26ccd9 |
param.endpoints = true;
|
|
|
26ccd9 |
if (param.decoder_filter)
|
|
|
26ccd9 |
param.decoders = true;
|
|
|
26ccd9 |
- if (num_list_flags() == 0) {
|
|
|
26ccd9 |
- /*
|
|
|
26ccd9 |
- * TODO: We likely want to list regions by default if
|
|
|
26ccd9 |
- * nothing was explicitly asked for. But until we have
|
|
|
26ccd9 |
- * region support, print this error asking for devices
|
|
|
26ccd9 |
- * explicitly. Once region support is added, this TODO
|
|
|
26ccd9 |
- * can be removed.
|
|
|
26ccd9 |
- */
|
|
|
26ccd9 |
- error("please specify entities to list, e.g. using -m/-M\n");
|
|
|
26ccd9 |
- usage_with_options(u, options);
|
|
|
26ccd9 |
- }
|
|
|
26ccd9 |
param.single = true;
|
|
|
26ccd9 |
+ if (param.region_filter)
|
|
|
26ccd9 |
+ param.regions = true;
|
|
|
26ccd9 |
+ }
|
|
|
26ccd9 |
+
|
|
|
26ccd9 |
+ /* List regions by default */
|
|
|
26ccd9 |
+ if (num_list_flags() == 0) {
|
|
|
26ccd9 |
+ param.regions = true;
|
|
|
26ccd9 |
}
|
|
|
26ccd9 |
|
|
|
26ccd9 |
log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG");
|
|
|
26ccd9 |
--
|
|
|
26ccd9 |
2.27.0
|
|
|
26ccd9 |
|