anitazha / rpms / ndctl

Forked from rpms/ndctl 2 years ago
Clone

Blame 0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch

Jeff Moyer 2c91dc
From 41d6769393f449008abf934e815f137360889633 Mon Sep 17 00:00:00 2001
Jeff Moyer 2c91dc
From: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Date: Sun, 23 Jan 2022 16:53:45 -0800
Jeff Moyer 2c91dc
Subject: [PATCH 108/217] cxl/list: Move enabled memdevs underneath their
Jeff Moyer 2c91dc
 endpoint
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
When a memdev is enabled it means that the kernel was able to validate a
Jeff Moyer 2c91dc
CXL connection from the CXL root, through intervening switches, and to the
Jeff Moyer 2c91dc
endpoint. Reflect that state by listing memdevs as child objects of
Jeff Moyer 2c91dc
endpoints, or aggregated into an array if individual endpoints are not
Jeff Moyer 2c91dc
listed.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Link: https://lore.kernel.org/r/164298562531.3021641.10620937879296964476.stgit@dwillia2-desk3.amr.corp.intel.com
Jeff Moyer 2c91dc
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Jeff Moyer 2c91dc
---
Jeff Moyer 2c91dc
 Documentation/cxl/cxl-list.txt   |  11 ++-
Jeff Moyer 2c91dc
 Documentation/cxl/lib/libcxl.txt |   2 +
Jeff Moyer 2c91dc
 cxl/filter.c                     | 130 ++++++++++++++++++++++++-------
Jeff Moyer 2c91dc
 cxl/json.c                       |   6 ++
Jeff Moyer 2c91dc
 cxl/lib/libcxl.c                 |  97 +++++++++++++++++++++++
Jeff Moyer 2c91dc
 cxl/lib/libcxl.sym               |   3 +
Jeff Moyer 2c91dc
 cxl/libcxl.h                     |   4 +
Jeff Moyer 2c91dc
 7 files changed, 223 insertions(+), 30 deletions(-)
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
Jeff Moyer 2c91dc
index 9c21ab7..1751868 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/cxl-list.txt
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-list.txt
Jeff Moyer 2c91dc
@@ -19,7 +19,16 @@ Options can be specified to limit the output to specific objects. When a
Jeff Moyer 2c91dc
 single object type is specified the return json object is an array of
Jeff Moyer 2c91dc
 just those objects, when multiple objects types are specified the
Jeff Moyer 2c91dc
 returned the returned object may be an array of arrays with the inner
Jeff Moyer 2c91dc
-array named for the given object type.
Jeff Moyer 2c91dc
+array named for the given object type. The top-level arrays are ellided
Jeff Moyer 2c91dc
+when the objects can nest under a higher object-type in the hierararchy.
Jeff Moyer 2c91dc
+The potential top-level array names and their nesting properties are:
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+"anon memdevs":: (disabled memory devices) do not nest
Jeff Moyer 2c91dc
+"buses":: do not nest
Jeff Moyer 2c91dc
+"ports":: nest under buses
Jeff Moyer 2c91dc
+"endpoints":: nest under ports or buses (if ports are not emitted)
Jeff Moyer 2c91dc
+"memdevs":: nest under endpoints or ports (if endpoints are not
Jeff Moyer 2c91dc
+   emitted) or buses (if endpoints and ports are not emitted)
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 Filters can by specifed as either a single identidier, a space separated
Jeff Moyer 2c91dc
 quoted string, or a comma separated list. When multiple filter
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
index 91fd33e..73b0fb9 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
@@ -41,6 +41,7 @@ struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 const char *cxl_memdev_get_host(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
+struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 #define cxl_memdev_foreach(ctx, memdev) \
Jeff Moyer 2c91dc
         for (memdev = cxl_memdev_get_first(ctx); \
Jeff Moyer 2c91dc
@@ -231,6 +232,7 @@ struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
+struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 #define cxl_endpoint_foreach(port, endpoint)                                 \
Jeff Moyer 2c91dc
        for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL;       \
Jeff Moyer 2c91dc
diff --git a/cxl/filter.c b/cxl/filter.c
Jeff Moyer 2c91dc
index 5d80d1b..2130816 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.c
Jeff Moyer 2c91dc
+++ b/cxl/filter.c
Jeff Moyer 2c91dc
@@ -381,13 +381,16 @@ static struct json_object *pick_array(struct json_object *child,
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
Jeff Moyer 2c91dc
-			   struct json_object *jeps, unsigned long flags)
Jeff Moyer 2c91dc
+			   struct json_object *jeps, struct json_object *jdevs,
Jeff Moyer 2c91dc
+			   unsigned long flags)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct cxl_endpoint *endpoint;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	cxl_endpoint_foreach(port, endpoint) {
Jeff Moyer 2c91dc
 		struct cxl_port *ep_port = cxl_endpoint_get_port(endpoint);
Jeff Moyer 2c91dc
-		struct json_object *jendpoint;
Jeff Moyer 2c91dc
+		const char *devname = cxl_endpoint_get_devname(endpoint);
Jeff Moyer 2c91dc
+		struct json_object *jendpoint = NULL;
Jeff Moyer 2c91dc
+		struct cxl_memdev *memdev;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 		if (!util_cxl_endpoint_filter(endpoint, p->endpoint_filter))
Jeff Moyer 2c91dc
 			continue;
Jeff Moyer 2c91dc
@@ -398,24 +401,54 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
Jeff Moyer 2c91dc
 			continue;
Jeff Moyer 2c91dc
 		if (!p->idle && !cxl_endpoint_is_enabled(endpoint))
Jeff Moyer 2c91dc
 			continue;
Jeff Moyer 2c91dc
-		jendpoint = util_cxl_endpoint_to_json(endpoint, flags);
Jeff Moyer 2c91dc
-		if (jendpoint)
Jeff Moyer 2c91dc
+		if (p->endpoints) {
Jeff Moyer 2c91dc
+			jendpoint = util_cxl_endpoint_to_json(endpoint, flags);
Jeff Moyer 2c91dc
+			if (!jendpoint) {
Jeff Moyer 2c91dc
+				err(p, "%s: failed to list\n", devname);
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
 			json_object_array_add(jeps, jendpoint);
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+		if (p->memdevs) {
Jeff Moyer 2c91dc
+			struct json_object *jobj;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+			memdev = cxl_endpoint_get_memdev(endpoint);
Jeff Moyer 2c91dc
+			if (!memdev)
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			if (!util_cxl_memdev_filter(memdev, p->memdev_filter,
Jeff Moyer 2c91dc
+						    p->serial_filter))
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			if (!p->idle && !cxl_memdev_is_enabled(memdev))
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			jobj = util_cxl_memdev_to_json(memdev, flags);
Jeff Moyer 2c91dc
+			if (!jobj) {
Jeff Moyer 2c91dc
+				err(p, "failed to json serialize %s\n",
Jeff Moyer 2c91dc
+				    cxl_memdev_get_devname(memdev));
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+			if (p->endpoints)
Jeff Moyer 2c91dc
+				json_object_object_add(jendpoint, "memdev",
Jeff Moyer 2c91dc
+						       jobj);
Jeff Moyer 2c91dc
+			else
Jeff Moyer 2c91dc
+				json_object_array_add(jdevs, jobj);
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 static void walk_child_ports(struct cxl_port *parent_port,
Jeff Moyer 2c91dc
 			     struct cxl_filter_params *p,
Jeff Moyer 2c91dc
 			     struct json_object *jports,
Jeff Moyer 2c91dc
-			     struct json_object *jeps, unsigned long flags)
Jeff Moyer 2c91dc
+			     struct json_object *jeps,
Jeff Moyer 2c91dc
+			     struct json_object *jdevs, unsigned long flags)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct cxl_port *port;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	cxl_port_foreach(parent_port, port) {
Jeff Moyer 2c91dc
 		const char *devname = cxl_port_get_devname(port);
Jeff Moyer 2c91dc
 		struct json_object *jport = NULL;
Jeff Moyer 2c91dc
+		struct json_object *jchilddevs = NULL;
Jeff Moyer 2c91dc
 		struct json_object *jchildports = NULL;
Jeff Moyer 2c91dc
-		struct json_object *jchildendpoints = NULL;
Jeff Moyer 2c91dc
+		struct json_object *jchildeps = NULL;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 		if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
Jeff Moyer 2c91dc
 			goto walk_children;
Jeff Moyer 2c91dc
@@ -436,28 +469,41 @@ static void walk_child_ports(struct cxl_port *parent_port,
Jeff Moyer 2c91dc
 				    devname);
Jeff Moyer 2c91dc
 				continue;
Jeff Moyer 2c91dc
 			}
Jeff Moyer 2c91dc
-		}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-		if (p->ports && p->endpoints) {
Jeff Moyer 2c91dc
-			jchildendpoints = json_object_new_array();
Jeff Moyer 2c91dc
-			if (!jchildendpoints) {
Jeff Moyer 2c91dc
-				err(p,
Jeff Moyer 2c91dc
-				    "%s: failed to enumerate child endpoints\n",
Jeff Moyer 2c91dc
-				    devname);
Jeff Moyer 2c91dc
-				continue;
Jeff Moyer 2c91dc
+			if (p->memdevs && !p->endpoints) {
Jeff Moyer 2c91dc
+				jchilddevs = json_object_new_array();
Jeff Moyer 2c91dc
+				if (!jchilddevs) {
Jeff Moyer 2c91dc
+					err(p,
Jeff Moyer 2c91dc
+					    "%s: failed to enumerate child memdevs\n",
Jeff Moyer 2c91dc
+					    devname);
Jeff Moyer 2c91dc
+					continue;
Jeff Moyer 2c91dc
+				}
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+			if (p->endpoints) {
Jeff Moyer 2c91dc
+				jchildeps = json_object_new_array();
Jeff Moyer 2c91dc
+				if (!jchildeps) {
Jeff Moyer 2c91dc
+					err(p,
Jeff Moyer 2c91dc
+					    "%s: failed to enumerate child endpoints\n",
Jeff Moyer 2c91dc
+					    devname);
Jeff Moyer 2c91dc
+					continue;
Jeff Moyer 2c91dc
+				}
Jeff Moyer 2c91dc
 			}
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 walk_children:
Jeff Moyer 2c91dc
-		if (p->endpoints)
Jeff Moyer 2c91dc
-			walk_endpoints(port, p, pick_array(jchildendpoints, jeps),
Jeff Moyer 2c91dc
-				       flags);
Jeff Moyer 2c91dc
+		if (p->endpoints || p->memdevs)
Jeff Moyer 2c91dc
+			walk_endpoints(port, p, pick_array(jchildeps, jeps),
Jeff Moyer 2c91dc
+				       pick_array(jchilddevs, jdevs), flags);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 		walk_child_ports(port, p, pick_array(jchildports, jports),
Jeff Moyer 2c91dc
-				 pick_array(jchildendpoints, jeps), flags);
Jeff Moyer 2c91dc
+				 pick_array(jchildeps, jeps),
Jeff Moyer 2c91dc
+				 pick_array(jchilddevs, jdevs), flags);
Jeff Moyer 2c91dc
 		cond_add_put_array_suffix(jport, "ports", devname, jchildports);
Jeff Moyer 2c91dc
 		cond_add_put_array_suffix(jport, "endpoints", devname,
Jeff Moyer 2c91dc
-					  jchildendpoints);
Jeff Moyer 2c91dc
+					  jchildeps);
Jeff Moyer 2c91dc
+		cond_add_put_array_suffix(jport, "memdevs", devname,
Jeff Moyer 2c91dc
+					  jchilddevs);
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
@@ -466,6 +512,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 	struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL;
Jeff Moyer 2c91dc
 	struct json_object *jplatform = json_object_new_array();
Jeff Moyer 2c91dc
 	unsigned long flags = params_to_flags(p);
Jeff Moyer 2c91dc
+	struct json_object *janondevs = NULL;
Jeff Moyer 2c91dc
 	struct json_object *jeps = NULL;
Jeff Moyer 2c91dc
 	struct cxl_memdev *memdev;
Jeff Moyer 2c91dc
 	int top_level_objs = 0;
Jeff Moyer 2c91dc
@@ -476,8 +523,8 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 		return -ENOMEM;
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-	jdevs = json_object_new_array();
Jeff Moyer 2c91dc
-	if (!jdevs)
Jeff Moyer 2c91dc
+	janondevs = json_object_new_array();
Jeff Moyer 2c91dc
+	if (!janondevs)
Jeff Moyer 2c91dc
 		goto err;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	jbuses = json_object_new_array();
Jeff Moyer 2c91dc
@@ -492,20 +539,28 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 	if (!jeps)
Jeff Moyer 2c91dc
 		goto err;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+	jdevs = json_object_new_array();
Jeff Moyer 2c91dc
+	if (!jdevs)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 	dbg(p, "walk memdevs\n");
Jeff Moyer 2c91dc
 	cxl_memdev_foreach(ctx, memdev) {
Jeff Moyer 2c91dc
-		struct json_object *jdev;
Jeff Moyer 2c91dc
+		struct json_object *janondev;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 		if (!util_cxl_memdev_filter(memdev, p->memdev_filter,
Jeff Moyer 2c91dc
 					    p->serial_filter))
Jeff Moyer 2c91dc
 			continue;
Jeff Moyer 2c91dc
+		if (cxl_memdev_is_enabled(memdev))
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+		if (!p->idle)
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
 		if (p->memdevs) {
Jeff Moyer 2c91dc
-			jdev = util_cxl_memdev_to_json(memdev, flags);
Jeff Moyer 2c91dc
-			if (!jdev) {
Jeff Moyer 2c91dc
+			janondev = util_cxl_memdev_to_json(memdev, flags);
Jeff Moyer 2c91dc
+			if (!janondev) {
Jeff Moyer 2c91dc
 				dbg(p, "memdev object allocation failure\n");
Jeff Moyer 2c91dc
 				continue;
Jeff Moyer 2c91dc
 			}
Jeff Moyer 2c91dc
-			json_object_array_add(jdevs, jdev);
Jeff Moyer 2c91dc
+			json_object_array_add(janondevs, janondev);
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
@@ -513,6 +568,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 	cxl_bus_foreach(ctx, bus) {
Jeff Moyer 2c91dc
 		struct json_object *jbus = NULL;
Jeff Moyer 2c91dc
 		struct json_object *jchildports = NULL;
Jeff Moyer 2c91dc
+		struct json_object *jchilddevs = NULL;
Jeff Moyer 2c91dc
 		struct json_object *jchildeps = NULL;
Jeff Moyer 2c91dc
 		struct cxl_port *port = cxl_bus_get_port(bus);
Jeff Moyer 2c91dc
 		const char *devname = cxl_bus_get_devname(bus);
Jeff Moyer 2c91dc
@@ -546,17 +602,29 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 					continue;
Jeff Moyer 2c91dc
 				}
Jeff Moyer 2c91dc
 			}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+			if (p->memdevs && !p->ports && !p->endpoints) {
Jeff Moyer 2c91dc
+				jchilddevs = json_object_new_array();
Jeff Moyer 2c91dc
+				if (!jchilddevs) {
Jeff Moyer 2c91dc
+					err(p,
Jeff Moyer 2c91dc
+					    "%s: failed to enumerate child memdevs\n",
Jeff Moyer 2c91dc
+					    devname);
Jeff Moyer 2c91dc
+					continue;
Jeff Moyer 2c91dc
+				}
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
 walk_children:
Jeff Moyer 2c91dc
 		dbg(p, "walk ports\n");
Jeff Moyer 2c91dc
 		walk_child_ports(port, p, pick_array(jchildports, jports),
Jeff Moyer 2c91dc
-				 pick_array(jchildeps, jeps), flags);
Jeff Moyer 2c91dc
+				 pick_array(jchildeps, jeps),
Jeff Moyer 2c91dc
+				 pick_array(jchilddevs, jdevs), flags);
Jeff Moyer 2c91dc
 		cond_add_put_array_suffix(jbus, "ports", devname, jchildports);
Jeff Moyer 2c91dc
 		cond_add_put_array_suffix(jbus, "endpoints", devname,
Jeff Moyer 2c91dc
 					  jchildeps);
Jeff Moyer 2c91dc
+		cond_add_put_array_suffix(jbus, "memdevs", devname, jchilddevs);
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-	if (json_object_array_length(jdevs))
Jeff Moyer 2c91dc
+	if (json_object_array_length(janondevs))
Jeff Moyer 2c91dc
 		top_level_objs++;
Jeff Moyer 2c91dc
 	if (json_object_array_length(jbuses))
Jeff Moyer 2c91dc
 		top_level_objs++;
Jeff Moyer 2c91dc
@@ -564,20 +632,24 @@ walk_children:
Jeff Moyer 2c91dc
 		top_level_objs++;
Jeff Moyer 2c91dc
 	if (json_object_array_length(jeps))
Jeff Moyer 2c91dc
 		top_level_objs++;
Jeff Moyer 2c91dc
+	if (json_object_array_length(jdevs))
Jeff Moyer 2c91dc
+		top_level_objs++;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-	splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1);
Jeff Moyer 2c91dc
+	splice_array(p, janondevs, jplatform, "anon memdevs", top_level_objs > 1);
Jeff Moyer 2c91dc
 	splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1);
Jeff Moyer 2c91dc
 	splice_array(p, jports, jplatform, "ports", top_level_objs > 1);
Jeff Moyer 2c91dc
 	splice_array(p, jeps, jplatform, "endpoints", top_level_objs > 1);
Jeff Moyer 2c91dc
+	splice_array(p, jdevs, jplatform, "memdevs", top_level_objs > 1);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	util_display_json_array(stdout, jplatform, flags);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	return 0;
Jeff Moyer 2c91dc
 err:
Jeff Moyer 2c91dc
-	json_object_put(jdevs);
Jeff Moyer 2c91dc
+	json_object_put(janondevs);
Jeff Moyer 2c91dc
 	json_object_put(jbuses);
Jeff Moyer 2c91dc
 	json_object_put(jports);
Jeff Moyer 2c91dc
 	json_object_put(jeps);
Jeff Moyer 2c91dc
+	json_object_put(jdevs);
Jeff Moyer 2c91dc
 	json_object_put(jplatform);
Jeff Moyer 2c91dc
 	return -ENOMEM;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
diff --git a/cxl/json.c b/cxl/json.c
Jeff Moyer 2c91dc
index 1868686..b809332 100644
Jeff Moyer 2c91dc
--- a/cxl/json.c
Jeff Moyer 2c91dc
+++ b/cxl/json.c
Jeff Moyer 2c91dc
@@ -224,6 +224,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
Jeff Moyer 2c91dc
 	if (jobj)
Jeff Moyer 2c91dc
 		json_object_object_add(jdev, "host", jobj);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+	if (!cxl_memdev_is_enabled(memdev)) {
Jeff Moyer 2c91dc
+		jobj = json_object_new_string("disabled");
Jeff Moyer 2c91dc
+		if (jobj)
Jeff Moyer 2c91dc
+			json_object_object_add(jdev, "state", jobj);
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 	return jdev;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
index c4ddc7d..4523ca6 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
@@ -480,6 +480,60 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev
Jeff Moyer 2c91dc
 	return memdev->firmware_version;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static struct cxl_endpoint *cxl_port_find_endpoint(struct cxl_port *parent_port,
Jeff Moyer 2c91dc
+						   struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_endpoint *endpoint;
Jeff Moyer 2c91dc
+	struct cxl_port *port;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_port_foreach(parent_port, port) {
Jeff Moyer 2c91dc
+		cxl_endpoint_foreach(port, endpoint)
Jeff Moyer 2c91dc
+			if (strcmp(cxl_endpoint_get_host(endpoint),
Jeff Moyer 2c91dc
+				   cxl_memdev_get_devname(memdev)) == 0)
Jeff Moyer 2c91dc
+				return endpoint;
Jeff Moyer 2c91dc
+		endpoint = cxl_port_find_endpoint(port, memdev);
Jeff Moyer 2c91dc
+		if (endpoint)
Jeff Moyer 2c91dc
+			return endpoint;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return NULL;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT struct cxl_endpoint *
Jeff Moyer 2c91dc
+cxl_memdev_get_endpoint(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
Jeff Moyer 2c91dc
+	struct cxl_endpoint *endpoint = NULL;
Jeff Moyer 2c91dc
+	struct cxl_bus *bus;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (memdev->endpoint)
Jeff Moyer 2c91dc
+		return memdev->endpoint;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!cxl_memdev_is_enabled(memdev))
Jeff Moyer 2c91dc
+		return NULL;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_bus_foreach (ctx, bus) {
Jeff Moyer 2c91dc
+		struct cxl_port *port = cxl_bus_get_port(bus);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		endpoint = cxl_port_find_endpoint(port, memdev);
Jeff Moyer 2c91dc
+		if (endpoint)
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!endpoint)
Jeff Moyer 2c91dc
+		return NULL;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (endpoint->memdev && endpoint->memdev != memdev)
Jeff Moyer 2c91dc
+		err(ctx, "%s assigned to %s not %s\n",
Jeff Moyer 2c91dc
+		    cxl_endpoint_get_devname(endpoint),
Jeff Moyer 2c91dc
+		    cxl_memdev_get_devname(endpoint->memdev),
Jeff Moyer 2c91dc
+		    cxl_memdev_get_devname(memdev));
Jeff Moyer 2c91dc
+	memdev->endpoint = endpoint;
Jeff Moyer 2c91dc
+	endpoint->memdev = memdev;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return endpoint;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	return memdev->lsa_size;
Jeff Moyer 2c91dc
@@ -495,6 +549,21 @@ static int is_enabled(const char *drvpath)
Jeff Moyer 2c91dc
 		return 1;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+CXL_EXPORT int cxl_memdev_is_enabled(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
Jeff Moyer 2c91dc
+	char *path = memdev->dev_buf;
Jeff Moyer 2c91dc
+	int len = memdev->buf_len;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (snprintf(path, len, "%s/driver", memdev->dev_path) >= len) {
Jeff Moyer 2c91dc
+		err(ctx, "%s: buffer too small!\n",
Jeff Moyer 2c91dc
+		    cxl_memdev_get_devname(memdev));
Jeff Moyer 2c91dc
+		return 0;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return is_enabled(path);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
Jeff Moyer 2c91dc
@@ -660,6 +729,34 @@ CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint)
Jeff Moyer 2c91dc
 	return cxl_port_is_enabled(&endpoint->port);
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+CXL_EXPORT struct cxl_memdev *
Jeff Moyer 2c91dc
+cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_endpoint_get_ctx(endpoint);
Jeff Moyer 2c91dc
+	struct cxl_memdev *memdev;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (endpoint->memdev)
Jeff Moyer 2c91dc
+		return endpoint->memdev;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!cxl_endpoint_is_enabled(endpoint))
Jeff Moyer 2c91dc
+		return NULL;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_memdev_foreach(ctx, memdev)
Jeff Moyer 2c91dc
+		if (strcmp(cxl_memdev_get_devname(memdev),
Jeff Moyer 2c91dc
+			   cxl_endpoint_get_host(endpoint)) == 0) {
Jeff Moyer 2c91dc
+			if (memdev->endpoint && memdev->endpoint != endpoint)
Jeff Moyer 2c91dc
+				err(ctx, "%s assigned to %s not %s\n",
Jeff Moyer 2c91dc
+				    cxl_memdev_get_devname(memdev),
Jeff Moyer 2c91dc
+				    cxl_endpoint_get_devname(memdev->endpoint),
Jeff Moyer 2c91dc
+				    cxl_endpoint_get_devname(endpoint));
Jeff Moyer 2c91dc
+			endpoint->memdev = memdev;
Jeff Moyer 2c91dc
+			memdev->endpoint = endpoint;
Jeff Moyer 2c91dc
+			return memdev;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return NULL;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static void *add_cxl_port(void *parent, int id, const char *cxlport_base)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	const char *devname = devpath_to_devname(cxlport_base);
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
index 8f0688a..321acac 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
@@ -106,4 +106,7 @@ global:
Jeff Moyer 2c91dc
 	cxl_endpoint_get_parent;
Jeff Moyer 2c91dc
 	cxl_endpoint_get_port;
Jeff Moyer 2c91dc
 	cxl_endpoint_get_host;
Jeff Moyer 2c91dc
+	cxl_endpoint_get_memdev;
Jeff Moyer 2c91dc
+	cxl_memdev_get_endpoint;
Jeff Moyer 2c91dc
+	cxl_memdev_is_enabled;
Jeff Moyer 2c91dc
 } LIBCXL_1;
Jeff Moyer 2c91dc
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
Jeff Moyer 2c91dc
index 5487b55..790ece8 100644
Jeff Moyer 2c91dc
--- a/cxl/libcxl.h
Jeff Moyer 2c91dc
+++ b/cxl/libcxl.h
Jeff Moyer 2c91dc
@@ -46,6 +46,8 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
+struct cxl_endpoint;
Jeff Moyer 2c91dc
+struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length,
Jeff Moyer 2c91dc
 		size_t offset);
Jeff Moyer 2c91dc
@@ -100,6 +102,8 @@ int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
 const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
+struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint);
Jeff Moyer 2c91dc
+int cxl_memdev_is_enabled(struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 #define cxl_endpoint_foreach(port, endpoint)                                   \
Jeff Moyer 2c91dc
 	for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL;        \
Jeff Moyer 2c91dc
-- 
Jeff Moyer 2c91dc
2.27.0
Jeff Moyer 2c91dc