anitazha / rpms / ndctl

Forked from rpms/ndctl 2 years ago
Clone

Blame 0100-cxl-list-Add-bus-objects.patch

Jeff Moyer 2c91dc
From 9dce91c303720a336c55ecdc2e01e423589b85b2 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:02 -0800
Jeff Moyer 2c91dc
Subject: [PATCH 100/217] cxl/list: Add bus objects
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
A 'struct cxl_bus' represents a CXL.mem domain. It is the root of a
Jeff Moyer 2c91dc
Host-managed Device Memory (HDM) hierarchy. When memory devices are enabled
Jeff Moyer 2c91dc
for CXL operation they appear underneath a bus in a 'cxl list -BM' listing,
Jeff Moyer 2c91dc
otherwise they display as disconnected.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
A 'bus' is identical to the kernel's CXL root port object, but given the
Jeff Moyer 2c91dc
confusion between CXL root ports, and PCIe root ports, the 'bus' name is
Jeff Moyer 2c91dc
less ambiguous. It also serves a similar role in the object hierarchy as a
Jeff Moyer 2c91dc
'struct ndctl_bus' object. It is also the case that the "root" name will
Jeff Moyer 2c91dc
appear as the kernel device-name, so the association will be clear.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Link: https://lore.kernel.org/r/164298558278.3021641.16323855851736615358.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
 .clang-format                    |   1 +
Jeff Moyer 2c91dc
 Documentation/cxl/cxl-list.txt   |  88 ++++++++++++++++---
Jeff Moyer 2c91dc
 Documentation/cxl/lib/libcxl.txt |  30 +++++++
Jeff Moyer 2c91dc
 cxl/filter.c                     | 117 ++++++++++++++++++++++++-
Jeff Moyer 2c91dc
 cxl/filter.h                     |   2 +
Jeff Moyer 2c91dc
 cxl/json.c                       |  21 +++++
Jeff Moyer 2c91dc
 cxl/json.h                       |   5 +-
Jeff Moyer 2c91dc
 cxl/lib/libcxl.c                 | 142 +++++++++++++++++++++++++++++++
Jeff Moyer 2c91dc
 cxl/lib/libcxl.sym               |   5 ++
Jeff Moyer 2c91dc
 cxl/lib/private.h                |  14 +++
Jeff Moyer 2c91dc
 cxl/libcxl.h                     |  11 +++
Jeff Moyer 2c91dc
 cxl/list.c                       |  19 +++--
Jeff Moyer 2c91dc
 12 files changed, 431 insertions(+), 24 deletions(-)
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
diff --git a/.clang-format b/.clang-format
Jeff Moyer 2c91dc
index d2e77d0..1154c76 100644
Jeff Moyer 2c91dc
--- a/.clang-format
Jeff Moyer 2c91dc
+++ b/.clang-format
Jeff Moyer 2c91dc
@@ -78,6 +78,7 @@ ExperimentalAutoDetectBinPacking: false
Jeff Moyer 2c91dc
 # 	| sort -u)
Jeff Moyer 2c91dc
 ForEachMacros:
Jeff Moyer 2c91dc
   - 'cxl_memdev_foreach'
Jeff Moyer 2c91dc
+  - 'cxl_bus_foreach'
Jeff Moyer 2c91dc
   - 'daxctl_dev_foreach'
Jeff Moyer 2c91dc
   - 'daxctl_mapping_foreach'
Jeff Moyer 2c91dc
   - 'daxctl_region_foreach'
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
Jeff Moyer 2c91dc
index 224c972..be131ae 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/cxl-list.txt
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-list.txt
Jeff Moyer 2c91dc
@@ -15,17 +15,60 @@ SYNOPSIS
Jeff Moyer 2c91dc
 Walk the CXL capable device hierarchy in the system and list all device
Jeff Moyer 2c91dc
 instances along with some of their major attributes.
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-Options can be specified to limit the output to specific objects.
Jeff Moyer 2c91dc
+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
+
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
+identifiers are specified within a filter string, like "-m
Jeff Moyer 2c91dc
+mem0,mem1,mem2", they are combined as an 'OR' filter.  When multiple
Jeff Moyer 2c91dc
+filter string types are specified, like "-m mem0,mem1,mem2 -p port10",
Jeff Moyer 2c91dc
+they are combined as an 'AND' filter. So, "-m mem0,mem1,mem2 -p port10"
Jeff Moyer 2c91dc
+would only list objects that are beneath port10 AND map mem0, mem1, OR
Jeff Moyer 2c91dc
+mem2.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+The --human option in addition to reformatting some fields to more human
Jeff Moyer 2c91dc
+friendly strings also unwraps the array to reduce the number of lines of
Jeff Moyer 2c91dc
+output.
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 EXAMPLE
Jeff Moyer 2c91dc
 -------
Jeff Moyer 2c91dc
 ----
Jeff Moyer 2c91dc
 # cxl list --memdevs
Jeff Moyer 2c91dc
-{
Jeff Moyer 2c91dc
-  "memdev":"mem0",
Jeff Moyer 2c91dc
-  "pmem_size":268435456,
Jeff Moyer 2c91dc
-  "ram_size":0,
Jeff Moyer 2c91dc
-}
Jeff Moyer 2c91dc
+[
Jeff Moyer 2c91dc
+  {
Jeff Moyer 2c91dc
+    "memdev":"mem0",
Jeff Moyer 2c91dc
+    "pmem_size":268435456,
Jeff Moyer 2c91dc
+    "ram_size":0,
Jeff Moyer 2c91dc
+    "serial":0
Jeff Moyer 2c91dc
+  }
Jeff Moyer 2c91dc
+]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+# cxl list -BMu
Jeff Moyer 2c91dc
+[
Jeff Moyer 2c91dc
+  {
Jeff Moyer 2c91dc
+    "anon memdevs":[
Jeff Moyer 2c91dc
+      {
Jeff Moyer 2c91dc
+        "memdev":"mem0",
Jeff Moyer 2c91dc
+        "pmem_size":"256.00 MiB (268.44 MB)",
Jeff Moyer 2c91dc
+        "ram_size":0,
Jeff Moyer 2c91dc
+        "serial":"0"
Jeff Moyer 2c91dc
+      }
Jeff Moyer 2c91dc
+    ]
Jeff Moyer 2c91dc
+  },
Jeff Moyer 2c91dc
+  {
Jeff Moyer 2c91dc
+    "buses":[
Jeff Moyer 2c91dc
+      {
Jeff Moyer 2c91dc
+        "bus":"root0",
Jeff Moyer 2c91dc
+        "provider":"ACPI.CXL"
Jeff Moyer 2c91dc
+      }
Jeff Moyer 2c91dc
+    ]
Jeff Moyer 2c91dc
+  }
Jeff Moyer 2c91dc
+]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 ----
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 OPTIONS
Jeff Moyer 2c91dc
@@ -34,13 +77,6 @@ OPTIONS
Jeff Moyer 2c91dc
 --memdev=::
Jeff Moyer 2c91dc
 	Specify CXL memory device name(s), or device id(s), to filter the listing. For example:
Jeff Moyer 2c91dc
 ----
Jeff Moyer 2c91dc
-# cxl list --memdev=mem0
Jeff Moyer 2c91dc
-{
Jeff Moyer 2c91dc
-  "memdev":"mem0",
Jeff Moyer 2c91dc
-  "pmem_size":268435456,
Jeff Moyer 2c91dc
-  "ram_size":0,
Jeff Moyer 2c91dc
-}
Jeff Moyer 2c91dc
-
Jeff Moyer 2c91dc
 # cxl list -M --memdev="0 mem3 5"
Jeff Moyer 2c91dc
 [
Jeff Moyer 2c91dc
   {
Jeff Moyer 2c91dc
@@ -114,6 +150,32 @@ OPTIONS
Jeff Moyer 2c91dc
 ]
Jeff Moyer 2c91dc
 ----
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+-B::
Jeff Moyer 2c91dc
+--buses::
Jeff Moyer 2c91dc
+	Include 'bus' / CXL root object(s) in the listing. Typically, on ACPI
Jeff Moyer 2c91dc
+	systems the bus object is a singleton associated with the ACPI0017
Jeff Moyer 2c91dc
+	device, but there are test scenerios where there may be multiple CXL
Jeff Moyer 2c91dc
+	memory hierarchies.
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+# cxl list -B
Jeff Moyer 2c91dc
+[
Jeff Moyer 2c91dc
+  {
Jeff Moyer 2c91dc
+    "bus":"root3",
Jeff Moyer 2c91dc
+    "provider":"cxl_test"
Jeff Moyer 2c91dc
+  },
Jeff Moyer 2c91dc
+  {
Jeff Moyer 2c91dc
+    "bus":"root0",
Jeff Moyer 2c91dc
+    "provider":"ACPI.CXL"
Jeff Moyer 2c91dc
+  }
Jeff Moyer 2c91dc
+]
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-b::
Jeff Moyer 2c91dc
+--bus=::
Jeff Moyer 2c91dc
+	Specify CXL root device name(s), device id(s), and / or CXL bus provider
Jeff Moyer 2c91dc
+	names to filter the listing. The supported provider names are "ACPI.CXL"
Jeff Moyer 2c91dc
+	and "cxl_test".
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 include::human-option.txt[]
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 include::verbose-option.txt[]
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
index c127326..84af66a 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
@@ -134,6 +134,36 @@ cxl_memdev{read,write,zero}_label() are helpers for marshaling multiple
Jeff Moyer 2c91dc
 label access commands over an arbitrary extent of the device's label
Jeff Moyer 2c91dc
 area.
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+BUSES
Jeff Moyer 2c91dc
+-----
Jeff Moyer 2c91dc
+The CXL Memory space is CPU and Device coherent. The address ranges that
Jeff Moyer 2c91dc
+support coherent access are described by platform firmware and
Jeff Moyer 2c91dc
+communicated to the operating system via a CXL root object 'struct
Jeff Moyer 2c91dc
+cxl_bus'.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+=== BUS: Enumeration
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define cxl_bus_foreach(ctx, bus)                                           \
Jeff Moyer 2c91dc
+       for (bus = cxl_bus_get_first(ctx); bus != NULL;                      \
Jeff Moyer 2c91dc
+            bus = cxl_bus_get_next(bus))
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+=== BUS: Attributes
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+const char *cxl_bus_get_provider(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+const char *cxl_bus_get_devname(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+int cxl_bus_get_id(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+The provider name of a bus is a persistent name that is independent of
Jeff Moyer 2c91dc
+discovery order. The possible provider names are 'ACPI.CXL' and
Jeff Moyer 2c91dc
+'cxl_test'. The devname and id attributes, like other objects, are just
Jeff Moyer 2c91dc
+the kernel device names that are subject to change based on discovery
Jeff Moyer 2c91dc
+order.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 include::../../copyright.txt[]
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 SEE ALSO
Jeff Moyer 2c91dc
diff --git a/cxl/filter.c b/cxl/filter.c
Jeff Moyer 2c91dc
index 26efc65..5f4844b 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.c
Jeff Moyer 2c91dc
+++ b/cxl/filter.c
Jeff Moyer 2c91dc
@@ -1,5 +1,5 @@
Jeff Moyer 2c91dc
 // SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
-// Copyright (C) 2015-2020 Intel Corporation. All rights reserved.
Jeff Moyer 2c91dc
+// Copyright (C) 2015-2022 Intel Corporation. All rights reserved.
Jeff Moyer 2c91dc
 #include <errno.h>
Jeff Moyer 2c91dc
 #include <stdio.h>
Jeff Moyer 2c91dc
 #include <string.h>
Jeff Moyer 2c91dc
@@ -21,6 +21,43 @@ static const char *which_sep(const char *filter)
Jeff Moyer 2c91dc
 	return " ";
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus,
Jeff Moyer 2c91dc
+					   const char *__ident)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	char *ident, *save;
Jeff Moyer 2c91dc
+	const char *arg;
Jeff Moyer 2c91dc
+	int bus_id;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!__ident)
Jeff Moyer 2c91dc
+		return bus;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	ident = strdup(__ident);
Jeff Moyer 2c91dc
+	if (!ident)
Jeff Moyer 2c91dc
+		return NULL;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	for (arg = strtok_r(ident, which_sep(__ident), &save); arg;
Jeff Moyer 2c91dc
+	     arg = strtok_r(NULL, which_sep(__ident), &save)) {
Jeff Moyer 2c91dc
+		if (strcmp(arg, "all") == 0)
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if ((sscanf(arg, "%d", &bus_id) == 1 ||
Jeff Moyer 2c91dc
+		     sscanf(arg, "root%d", &bus_id) == 1) &&
Jeff Moyer 2c91dc
+		    cxl_bus_get_id(bus) == bus_id)
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (strcmp(arg, cxl_bus_get_devname(bus)) == 0)
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (strcmp(arg, cxl_bus_get_provider(bus)) == 0)
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	free(ident);
Jeff Moyer 2c91dc
+	if (arg)
Jeff Moyer 2c91dc
+		return bus;
Jeff Moyer 2c91dc
+	return NULL;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static struct cxl_memdev *
Jeff Moyer 2c91dc
 util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
@@ -98,21 +135,67 @@ static unsigned long params_to_flags(struct cxl_filter_params *param)
Jeff Moyer 2c91dc
 	return flags;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static void splice_array(struct cxl_filter_params *p, struct json_object *jobjs,
Jeff Moyer 2c91dc
+			 struct json_object *platform,
Jeff Moyer 2c91dc
+			 const char *container_name, bool do_container)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	size_t count;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!json_object_array_length(jobjs)) {
Jeff Moyer 2c91dc
+		json_object_put(jobjs);
Jeff Moyer 2c91dc
+		return;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (do_container) {
Jeff Moyer 2c91dc
+		struct json_object *container = json_object_new_object();
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (!container) {
Jeff Moyer 2c91dc
+			err(p, "failed to list: %s\n", container_name);
Jeff Moyer 2c91dc
+			return;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		json_object_object_add(container, container_name, jobjs);
Jeff Moyer 2c91dc
+		json_object_array_add(platform, container);
Jeff Moyer 2c91dc
+		return;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	for (count = json_object_array_length(jobjs); count; count--) {
Jeff Moyer 2c91dc
+		struct json_object *jobj = json_object_array_get_idx(jobjs, 0);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		json_object_get(jobj);
Jeff Moyer 2c91dc
+		json_object_array_del_idx(jobjs, 0, 1);
Jeff Moyer 2c91dc
+		json_object_array_add(platform, jobj);
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+	json_object_put(jobjs);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct json_object *jplatform = json_object_new_array();
Jeff Moyer 2c91dc
+	struct json_object *jdevs = NULL, *jbuses = NULL;
Jeff Moyer 2c91dc
 	unsigned long flags = params_to_flags(p);
Jeff Moyer 2c91dc
 	struct cxl_memdev *memdev;
Jeff Moyer 2c91dc
+	int top_level_objs = 0;
Jeff Moyer 2c91dc
+	struct cxl_bus *bus;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	if (!jplatform) {
Jeff Moyer 2c91dc
 		dbg(p, "platform object allocation failure\n");
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
+		goto err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	jbuses = json_object_new_array();
Jeff Moyer 2c91dc
+	if (!jbuses)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 	cxl_memdev_foreach(ctx, memdev) {
Jeff Moyer 2c91dc
 		struct json_object *jdev;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-		if (!util_cxl_memdev_filter(memdev, p->memdev_filter, p->serial_filter))
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->memdevs) {
Jeff Moyer 2c91dc
 			jdev = util_cxl_memdev_to_json(memdev, flags);
Jeff Moyer 2c91dc
@@ -120,11 +203,39 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
Jeff Moyer 2c91dc
 				dbg(p, "memdev object allocation failure\n");
Jeff Moyer 2c91dc
 				continue;
Jeff Moyer 2c91dc
 			}
Jeff Moyer 2c91dc
-			json_object_array_add(jplatform, jdev);
Jeff Moyer 2c91dc
+			json_object_array_add(jdevs, jdev);
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_bus_foreach(ctx, bus) {
Jeff Moyer 2c91dc
+		struct json_object *jbus;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (!util_cxl_bus_filter(bus, p->bus_filter))
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+		if (p->buses) {
Jeff Moyer 2c91dc
+			jbus = util_cxl_bus_to_json(bus, flags);
Jeff Moyer 2c91dc
+			if (!jbus) {
Jeff Moyer 2c91dc
+				dbg(p, "bus object allocation failure\n");
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+			json_object_array_add(jbuses, jbus);
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+	if (json_object_array_length(jdevs))
Jeff Moyer 2c91dc
+		top_level_objs++;
Jeff Moyer 2c91dc
+	if (json_object_array_length(jbuses))
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, jbuses, jplatform, "buses", 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(jbuses);
Jeff Moyer 2c91dc
+	json_object_put(jplatform);
Jeff Moyer 2c91dc
+	return -ENOMEM;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
diff --git a/cxl/filter.h b/cxl/filter.h
Jeff Moyer 2c91dc
index 12d9344..d41e757 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.h
Jeff Moyer 2c91dc
+++ b/cxl/filter.h
Jeff Moyer 2c91dc
@@ -9,7 +9,9 @@
Jeff Moyer 2c91dc
 struct cxl_filter_params {
Jeff Moyer 2c91dc
 	const char *memdev_filter;
Jeff Moyer 2c91dc
 	const char *serial_filter;
Jeff Moyer 2c91dc
+	const char *bus_filter;
Jeff Moyer 2c91dc
 	bool memdevs;
Jeff Moyer 2c91dc
+	bool buses;
Jeff Moyer 2c91dc
 	bool idle;
Jeff Moyer 2c91dc
 	bool human;
Jeff Moyer 2c91dc
 	bool health;
Jeff Moyer 2c91dc
diff --git a/cxl/json.c b/cxl/json.c
Jeff Moyer 2c91dc
index d8e65df..a584594 100644
Jeff Moyer 2c91dc
--- a/cxl/json.c
Jeff Moyer 2c91dc
+++ b/cxl/json.c
Jeff Moyer 2c91dc
@@ -221,3 +221,24 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 	return jdev;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
Jeff Moyer 2c91dc
+					 unsigned long flags)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	const char *devname = cxl_bus_get_devname(bus);
Jeff Moyer 2c91dc
+	struct json_object *jbus, *jobj;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	jbus = json_object_new_object();
Jeff Moyer 2c91dc
+	if (!jbus)
Jeff Moyer 2c91dc
+		return NULL;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	jobj = json_object_new_string(devname);
Jeff Moyer 2c91dc
+	if (jobj)
Jeff Moyer 2c91dc
+		json_object_object_add(jbus, "bus", jobj);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	jobj = json_object_new_string(cxl_bus_get_provider(bus));
Jeff Moyer 2c91dc
+	if (jobj)
Jeff Moyer 2c91dc
+		json_object_object_add(jbus, "provider", jobj);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return jbus;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
diff --git a/cxl/json.h b/cxl/json.h
Jeff Moyer 2c91dc
index 3abcfe6..4abf6e5 100644
Jeff Moyer 2c91dc
--- a/cxl/json.h
Jeff Moyer 2c91dc
+++ b/cxl/json.h
Jeff Moyer 2c91dc
@@ -1,8 +1,11 @@
Jeff Moyer 2c91dc
 /* SPDX-License-Identifier: GPL-2.0 */
Jeff Moyer 2c91dc
-/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */
Jeff Moyer 2c91dc
+/* Copyright (C) 2015-2022 Intel Corporation. All rights reserved. */
Jeff Moyer 2c91dc
 #ifndef __CXL_UTIL_JSON_H__
Jeff Moyer 2c91dc
 #define __CXL_UTIL_JSON_H__
Jeff Moyer 2c91dc
 struct cxl_memdev;
Jeff Moyer 2c91dc
 struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
Jeff Moyer 2c91dc
 		unsigned long flags);
Jeff Moyer 2c91dc
+struct cxl_bus;
Jeff Moyer 2c91dc
+struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
Jeff Moyer 2c91dc
+					 unsigned long flags);
Jeff Moyer 2c91dc
 #endif /* __CXL_UTIL_JSON_H__ */
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
index 9839f26..8548a45 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
@@ -40,7 +40,9 @@ struct cxl_ctx {
Jeff Moyer 2c91dc
 	int refcount;
Jeff Moyer 2c91dc
 	void *userdata;
Jeff Moyer 2c91dc
 	int memdevs_init;
Jeff Moyer 2c91dc
+	int buses_init;
Jeff Moyer 2c91dc
 	struct list_head memdevs;
Jeff Moyer 2c91dc
+	struct list_head buses;
Jeff Moyer 2c91dc
 	struct kmod_ctx *kmod_ctx;
Jeff Moyer 2c91dc
 	void *private_data;
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
@@ -64,6 +66,21 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
Jeff Moyer 2c91dc
 	free(memdev);
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static void __free_port(struct cxl_port *port, struct list_head *head)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	if (head)
Jeff Moyer 2c91dc
+		list_del_from(head, &port->list);
Jeff Moyer 2c91dc
+	free(port->dev_buf);
Jeff Moyer 2c91dc
+	free(port->dev_path);
Jeff Moyer 2c91dc
+	free(port->uport);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static void free_bus(struct cxl_bus *bus, struct list_head *head)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	__free_port(&bus->port, head);
Jeff Moyer 2c91dc
+	free(bus);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 /**
Jeff Moyer 2c91dc
  * cxl_get_userdata - retrieve stored data pointer from library context
Jeff Moyer 2c91dc
  * @ctx: cxl library context
Jeff Moyer 2c91dc
@@ -130,6 +147,7 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
Jeff Moyer 2c91dc
 	dbg(c, "log_priority=%d\n", c->ctx.log_priority);
Jeff Moyer 2c91dc
 	*ctx = c;
Jeff Moyer 2c91dc
 	list_head_init(&c->memdevs);
Jeff Moyer 2c91dc
+	list_head_init(&c->buses);
Jeff Moyer 2c91dc
 	c->kmod_ctx = kmod_ctx;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	return 0;
Jeff Moyer 2c91dc
@@ -160,6 +178,7 @@ CXL_EXPORT struct cxl_ctx *cxl_ref(struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
 CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct cxl_memdev *memdev, *_d;
Jeff Moyer 2c91dc
+	struct cxl_bus *bus, *_b;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	if (ctx == NULL)
Jeff Moyer 2c91dc
 		return;
Jeff Moyer 2c91dc
@@ -170,6 +189,9 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
 	list_for_each_safe(&ctx->memdevs, memdev, _d, list)
Jeff Moyer 2c91dc
 		free_memdev(memdev, &ctx->memdevs);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+	list_for_each_safe(&ctx->buses, bus, _b, port.list)
Jeff Moyer 2c91dc
+		free_bus(bus, &ctx->buses);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 	kmod_unref(ctx->kmod_ctx);
Jeff Moyer 2c91dc
 	info(ctx, "context %p released\n", ctx);
Jeff Moyer 2c91dc
 	free(ctx);
Jeff Moyer 2c91dc
@@ -449,6 +471,126 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
 	return is_enabled(path);
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id,
Jeff Moyer 2c91dc
+			 const char *cxlport_base)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	char *path = calloc(1, strlen(cxlport_base) + 100);
Jeff Moyer 2c91dc
+	size_t rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!path)
Jeff Moyer 2c91dc
+		return -ENOMEM;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	port->id = id;
Jeff Moyer 2c91dc
+	port->ctx = ctx;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	port->dev_path = strdup(cxlport_base);
Jeff Moyer 2c91dc
+	if (!port->dev_path)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	port->dev_buf = calloc(1, strlen(cxlport_base) + 50);
Jeff Moyer 2c91dc
+	if (!port->dev_buf)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+	port->buf_len = strlen(cxlport_base) + 50;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = snprintf(port->dev_buf, port->buf_len, "%s/uport", cxlport_base);
Jeff Moyer 2c91dc
+	if (rc >= port->buf_len)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+	port->uport = realpath(port->dev_buf, NULL);
Jeff Moyer 2c91dc
+	if (!port->uport)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return 0;
Jeff Moyer 2c91dc
+err:
Jeff Moyer 2c91dc
+	free(port->dev_path);
Jeff Moyer 2c91dc
+	free(port->dev_buf);
Jeff Moyer 2c91dc
+	free(path);
Jeff Moyer 2c91dc
+	return -ENOMEM;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	const char *devname = devpath_to_devname(cxlbus_base);
Jeff Moyer 2c91dc
+	struct cxl_bus *bus, *bus_dup;
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = parent;
Jeff Moyer 2c91dc
+	struct cxl_port *port;
Jeff Moyer 2c91dc
+	int rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	dbg(ctx, "%s: base: \'%s\'\n", devname, cxlbus_base);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	bus = calloc(1, sizeof(*bus));
Jeff Moyer 2c91dc
+	if (!bus)
Jeff Moyer 2c91dc
+		return NULL;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	port = &bus->port;
Jeff Moyer 2c91dc
+	rc = cxl_port_init(port, ctx, id, cxlbus_base);
Jeff Moyer 2c91dc
+	if (rc)
Jeff Moyer 2c91dc
+		goto err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_bus_foreach(ctx, bus_dup)
Jeff Moyer 2c91dc
+		if (bus_dup->port.id == bus->port.id) {
Jeff Moyer 2c91dc
+			free_bus(bus, NULL);
Jeff Moyer 2c91dc
+			return bus_dup;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	list_add(&ctx->buses, &port->list);
Jeff Moyer 2c91dc
+	return bus;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+err:
Jeff Moyer 2c91dc
+	free(bus);
Jeff Moyer 2c91dc
+	return NULL;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static void cxl_buses_init(struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	if (ctx->buses_init)
Jeff Moyer 2c91dc
+		return;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	ctx->buses_init = 1;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	sysfs_device_parse(ctx, "/sys/bus/cxl/devices", "root", ctx,
Jeff Moyer 2c91dc
+			   add_cxl_bus);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	cxl_buses_init(ctx);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return list_top(&ctx->buses, struct cxl_bus, port.list);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = bus->port.ctx;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return list_next(&ctx->buses, bus, port.list);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT const char *cxl_bus_get_devname(struct cxl_bus *bus)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_port *port = &bus->port;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return devpath_to_devname(port->dev_path);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT int cxl_bus_get_id(struct cxl_bus *bus)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_port *port = &bus->port;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return port->id;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_port *port = &bus->port;
Jeff Moyer 2c91dc
+	const char *devname = devpath_to_devname(port->uport);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (strcmp(devname, "ACPI0017:00") == 0)
Jeff Moyer 2c91dc
+		return "ACPI.CXL";
Jeff Moyer 2c91dc
+	if (strcmp(devname, "cxl_acpi.0") == 0)
Jeff Moyer 2c91dc
+		return "cxl_test";
Jeff Moyer 2c91dc
+	return devname;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	if (!cmd)
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
index 4411035..781ff99 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
@@ -77,4 +77,9 @@ local:
Jeff Moyer 2c91dc
 LIBCXL_2 {
Jeff Moyer 2c91dc
 global:
Jeff Moyer 2c91dc
 	cxl_memdev_get_serial;
Jeff Moyer 2c91dc
+	cxl_bus_get_first;
Jeff Moyer 2c91dc
+	cxl_bus_get_next;
Jeff Moyer 2c91dc
+	cxl_bus_get_provider;
Jeff Moyer 2c91dc
+	cxl_bus_get_devname;
Jeff Moyer 2c91dc
+	cxl_bus_get_id;
Jeff Moyer 2c91dc
 } LIBCXL_1;
Jeff Moyer 2c91dc
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
Jeff Moyer 2c91dc
index 7c81e24..0758d05 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/private.h
Jeff Moyer 2c91dc
+++ b/cxl/lib/private.h
Jeff Moyer 2c91dc
@@ -34,6 +34,20 @@ struct cxl_memdev {
Jeff Moyer 2c91dc
 	unsigned long long serial;
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+struct cxl_port {
Jeff Moyer 2c91dc
+	int id;
Jeff Moyer 2c91dc
+	void *dev_buf;
Jeff Moyer 2c91dc
+	size_t buf_len;
Jeff Moyer 2c91dc
+	char *dev_path;
Jeff Moyer 2c91dc
+	char *uport;
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx;
Jeff Moyer 2c91dc
+	struct list_node list;
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+struct cxl_bus {
Jeff Moyer 2c91dc
+	struct cxl_port port;
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 enum cxl_cmd_query_status {
Jeff Moyer 2c91dc
 	CXL_CMD_QUERY_NOT_RUN = 0,
Jeff Moyer 2c91dc
 	CXL_CMD_QUERY_OK,
Jeff Moyer 2c91dc
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
Jeff Moyer 2c91dc
index bcdede8..da66eb2 100644
Jeff Moyer 2c91dc
--- a/cxl/libcxl.h
Jeff Moyer 2c91dc
+++ b/cxl/libcxl.h
Jeff Moyer 2c91dc
@@ -57,6 +57,17 @@ int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
Jeff Moyer 2c91dc
              memdev != NULL; \
Jeff Moyer 2c91dc
              memdev = cxl_memdev_get_next(memdev))
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+struct cxl_bus;
Jeff Moyer 2c91dc
+struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+const char *cxl_bus_get_provider(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+const char *cxl_bus_get_devname(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+int cxl_bus_get_id(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define cxl_bus_foreach(ctx, bus)                                              \
Jeff Moyer 2c91dc
+	for (bus = cxl_bus_get_first(ctx); bus != NULL;                        \
Jeff Moyer 2c91dc
+	     bus = cxl_bus_get_next(bus))
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 struct cxl_cmd;
Jeff Moyer 2c91dc
 const char *cxl_cmd_get_devname(struct cxl_cmd *cmd);
Jeff Moyer 2c91dc
 struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
Jeff Moyer 2c91dc
diff --git a/cxl/list.c b/cxl/list.c
Jeff Moyer 2c91dc
index 7e2744d..9500e61 100644
Jeff Moyer 2c91dc
--- a/cxl/list.c
Jeff Moyer 2c91dc
+++ b/cxl/list.c
Jeff Moyer 2c91dc
@@ -1,5 +1,5 @@
Jeff Moyer 2c91dc
 // SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
-/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */
Jeff Moyer 2c91dc
+/* Copyright (C) 2020-2022 Intel Corporation. All rights reserved. */
Jeff Moyer 2c91dc
 #include <stdio.h>
Jeff Moyer 2c91dc
 #include <errno.h>
Jeff Moyer 2c91dc
 #include <stdlib.h>
Jeff Moyer 2c91dc
@@ -14,11 +14,6 @@
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 static struct cxl_filter_params param;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-static int num_list_flags(void)
Jeff Moyer 2c91dc
-{
Jeff Moyer 2c91dc
-	return param.memdevs;
Jeff Moyer 2c91dc
-}
Jeff Moyer 2c91dc
-
Jeff Moyer 2c91dc
 static const struct option options[] = {
Jeff Moyer 2c91dc
 	OPT_STRING('m', "memdev", &param.memdev_filter, "memory device name(s)",
Jeff Moyer 2c91dc
 		   "filter by CXL memory device name(s)"),
Jeff Moyer 2c91dc
@@ -27,6 +22,9 @@ static const struct option options[] = {
Jeff Moyer 2c91dc
 		   "filter by CXL memory device serial number(s)"),
Jeff Moyer 2c91dc
 	OPT_BOOLEAN('M', "memdevs", &param.memdevs,
Jeff Moyer 2c91dc
 		    "include CXL memory device info"),
Jeff Moyer 2c91dc
+	OPT_STRING('b', "bus", &param.bus_filter, "bus device name",
Jeff Moyer 2c91dc
+		   "filter by CXL bus device name(s)"),
Jeff Moyer 2c91dc
+	OPT_BOOLEAN('B', "buses", &param.buses, "include CXL bus info"),
Jeff Moyer 2c91dc
 	OPT_BOOLEAN('i', "idle", &param.idle, "include disabled devices"),
Jeff Moyer 2c91dc
 	OPT_BOOLEAN('u', "human", &param.human,
Jeff Moyer 2c91dc
 		    "use human friendly number formats "),
Jeff Moyer 2c91dc
@@ -35,6 +33,11 @@ static const struct option options[] = {
Jeff Moyer 2c91dc
 	OPT_END(),
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static int num_list_flags(void)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+       return !!param.memdevs + !!param.buses;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	const char * const u[] = {
Jeff Moyer 2c91dc
@@ -53,7 +56,9 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
 	if (num_list_flags() == 0) {
Jeff Moyer 2c91dc
 		if (param.memdev_filter || param.serial_filter)
Jeff Moyer 2c91dc
 			param.memdevs = true;
Jeff Moyer 2c91dc
-		else {
Jeff Moyer 2c91dc
+		if (param.bus_filter)
Jeff Moyer 2c91dc
+			param.buses = true;
Jeff Moyer 2c91dc
+		if (num_list_flags() == 0) {
Jeff Moyer 2c91dc
 			/*
Jeff Moyer 2c91dc
 			 * TODO: We likely want to list regions by default if
Jeff Moyer 2c91dc
 			 * nothing was explicitly asked for. But until we have
Jeff Moyer 2c91dc
-- 
Jeff Moyer 2c91dc
2.27.0
Jeff Moyer 2c91dc