Blame SOURCES/0120-cxl-list-Support-filtering-memdevs-by-decoders.patch

e0018b
From aa022d33418021da81a51bc9656931c54043b10b Mon Sep 17 00:00:00 2001
e0018b
From: Dan Williams <dan.j.williams@intel.com>
e0018b
Date: Sun, 23 Jan 2022 16:54:50 -0800
e0018b
Subject: [PATCH 120/217] cxl/list: Support filtering memdevs by decoders
e0018b
e0018b
In order to filter memdevs by decoders all the ports in the hierarchy need
e0018b
to be iterated, so introduce cxl_port_foreach_all() that starts at the bus
e0018b
and does a depth first iteration of all the descendant ports.
e0018b
e0018b
Link: https://lore.kernel.org/r/164298569017.3021641.15558596583530530035.stgit@dwillia2-desk3.amr.corp.intel.com
e0018b
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
e0018b
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
e0018b
---
e0018b
 .clang-format                    |  1 +
e0018b
 Documentation/cxl/cxl-list.txt   | 13 +++++++++
e0018b
 Documentation/cxl/lib/libcxl.txt | 11 ++++++++
e0018b
 cxl/filter.c                     | 48 ++++++++++++++++++++++++++++++++
e0018b
 cxl/lib/libcxl.c                 | 13 +++++++++
e0018b
 cxl/libcxl.h                     |  6 ++++
e0018b
 6 files changed, 92 insertions(+)
e0018b
e0018b
diff --git a/.clang-format b/.clang-format
e0018b
index c753487..6aabcb6 100644
e0018b
--- a/.clang-format
e0018b
+++ b/.clang-format
e0018b
@@ -84,6 +84,7 @@ ForEachMacros:
e0018b
   - 'cxl_target_foreach'
e0018b
   - 'cxl_dport_foreach'
e0018b
   - 'cxl_endpoint_foreach'
e0018b
+  - 'cxl_port_foreach_all'
e0018b
   - 'daxctl_dev_foreach'
e0018b
   - 'daxctl_mapping_foreach'
e0018b
   - 'daxctl_region_foreach'
e0018b
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
e0018b
index e1299d9..04e831e 100644
e0018b
--- a/Documentation/cxl/cxl-list.txt
e0018b
+++ b/Documentation/cxl/cxl-list.txt
e0018b
@@ -61,6 +61,19 @@ one or more memdevs. For example:
e0018b
   }
e0018b
 ]
e0018b
 ----
e0018b
+Additionally, when provisioning new interleave configurations it is
e0018b
+useful to know which memdevs can be referenced by a given decoder like a
e0018b
+root decoder:
e0018b
+----
e0018b
+# cxl list -Mu -d decoder0.0
e0018b
+{
e0018b
+  "memdev":"mem0",
e0018b
+  "pmem_size":"256.00 MiB (268.44 MB)",
e0018b
+  "ram_size":0,
e0018b
+  "serial":"0",
e0018b
+  "host":"0000:35:00.0"
e0018b
+}
e0018b
+----
e0018b
 
e0018b
 The --human option in addition to reformatting some fields to more human
e0018b
 friendly strings also unwraps the array to reduce the number of lines of
e0018b
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
e0018b
index 2e8570d..5ad3027 100644
e0018b
--- a/Documentation/cxl/lib/libcxl.txt
e0018b
+++ b/Documentation/cxl/lib/libcxl.txt
e0018b
@@ -219,10 +219,18 @@ struct cxl_port *cxl_port_get_parent(struct cxl_port *port);
e0018b
 struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port);
e0018b
 const char *cxl_port_get_host(struct cxl_port *port);
e0018b
 struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder);
e0018b
+struct cxl_port *cxl_port_get_next_all(struct cxl_port *port,
e0018b
+                                       const struct cxl_port *top);
e0018b
 
e0018b
 #define cxl_port_foreach(parent, port)                                      \
e0018b
        for (port = cxl_port_get_first(parent); port != NULL;                \
e0018b
             port = cxl_port_get_next(port))
e0018b
+
e0018b
+#define cxl_port_foreach_all(top, port)                                        \
e0018b
+       for (port = cxl_port_get_first(top); port != NULL;                     \
e0018b
+            port = cxl_port_get_next_all(port, top))
e0018b
+
e0018b
+
e0018b
 ----
e0018b
 A bus object encapsulates a CXL port object. Use cxl_bus_get_port() to
e0018b
 use generic port APIs on root objects.
e0018b
@@ -236,6 +244,9 @@ that hierarchy via cxl_port_get_bus().
e0018b
 The host of a port is the corresponding device name of the PCIe Root
e0018b
 Port, or Switch Upstream Port with CXL capabilities.
e0018b
 
e0018b
+The cxl_port_foreach_all() helper does a depth first iteration of all
e0018b
+ports beneath the 'top' port argument.
e0018b
+
e0018b
 === PORT: Attributes
e0018b
 ----
e0018b
 const char *cxl_port_get_devname(struct cxl_port *port);
e0018b
diff --git a/cxl/filter.c b/cxl/filter.c
e0018b
index 05ede91..c972545 100644
e0018b
--- a/cxl/filter.c
e0018b
+++ b/cxl/filter.c
e0018b
@@ -441,6 +441,51 @@ util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder,
e0018b
 	return NULL;
e0018b
 }
e0018b
 
e0018b
+static bool __memdev_filter_by_decoder(struct cxl_memdev *memdev,
e0018b
+				       struct cxl_port *port, const char *ident)
e0018b
+{
e0018b
+	struct cxl_decoder *decoder;
e0018b
+	struct cxl_endpoint *endpoint;
e0018b
+
e0018b
+	cxl_decoder_foreach(port, decoder) {
e0018b
+		if (!util_cxl_decoder_filter(decoder, ident))
e0018b
+			continue;
e0018b
+		if (cxl_decoder_get_target_by_memdev(decoder, memdev))
e0018b
+			return true;
e0018b
+	}
e0018b
+
e0018b
+	cxl_endpoint_foreach(port, endpoint)
e0018b
+		if (__memdev_filter_by_decoder(
e0018b
+			    memdev, cxl_endpoint_get_port(endpoint), ident))
e0018b
+			return true;
e0018b
+	return false;
e0018b
+}
e0018b
+
e0018b
+static struct cxl_memdev *
e0018b
+util_cxl_memdev_filter_by_decoder(struct cxl_memdev *memdev, const char *ident)
e0018b
+{
e0018b
+	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
e0018b
+	struct cxl_bus *bus;
e0018b
+
e0018b
+	if (!ident)
e0018b
+		return memdev;
e0018b
+
e0018b
+	cxl_bus_foreach(ctx, bus) {
e0018b
+		struct cxl_port *port, *top;
e0018b
+
e0018b
+		port = cxl_bus_get_port(bus);
e0018b
+		if (__memdev_filter_by_decoder(memdev, port, ident))
e0018b
+			return memdev;
e0018b
+
e0018b
+		top = port;
e0018b
+		cxl_port_foreach_all(top, port)
e0018b
+			if (__memdev_filter_by_decoder(memdev, port, ident))
e0018b
+				return memdev;
e0018b
+	}
e0018b
+
e0018b
+	return NULL;
e0018b
+}
e0018b
+
e0018b
 static unsigned long params_to_flags(struct cxl_filter_params *param)
e0018b
 {
e0018b
 	unsigned long flags = 0;
e0018b
@@ -599,6 +644,9 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
e0018b
 			if (!util_cxl_memdev_filter(memdev, p->memdev_filter,
e0018b
 						    p->serial_filter))
e0018b
 				continue;
e0018b
+			if (!util_cxl_memdev_filter_by_decoder(
e0018b
+				    memdev, p->decoder_filter))
e0018b
+				continue;
e0018b
 			if (!p->idle && !cxl_memdev_is_enabled(memdev))
e0018b
 				continue;
e0018b
 			jobj = util_cxl_memdev_to_json(memdev, flags);
e0018b
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
e0018b
index d7a3f10..4ebb8b9 100644
e0018b
--- a/cxl/lib/libcxl.c
e0018b
+++ b/cxl/lib/libcxl.c
e0018b
@@ -1257,6 +1257,19 @@ CXL_EXPORT struct cxl_port *cxl_port_get_next(struct cxl_port *port)
e0018b
 	return list_next(&parent_port->child_ports, port, list);
e0018b
 }
e0018b
 
e0018b
+CXL_EXPORT struct cxl_port *cxl_port_get_next_all(struct cxl_port *port,
e0018b
+						  const struct cxl_port *top)
e0018b
+{
e0018b
+	struct cxl_port *child, *iter = port;
e0018b
+
e0018b
+	child = cxl_port_get_first(iter);
e0018b
+	if (child)
e0018b
+		return child;
e0018b
+	while (!cxl_port_get_next(iter) && iter->parent && iter->parent != top)
e0018b
+		iter = iter->parent;
e0018b
+	return cxl_port_get_next(iter);
e0018b
+}
e0018b
+
e0018b
 CXL_EXPORT const char *cxl_port_get_devname(struct cxl_port *port)
e0018b
 {
e0018b
 	return devpath_to_devname(port->dev_path);
e0018b
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
e0018b
index 07f4a31..874c381 100644
e0018b
--- a/cxl/libcxl.h
e0018b
+++ b/cxl/libcxl.h
e0018b
@@ -94,11 +94,17 @@ struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
e0018b
 const char *cxl_port_get_host(struct cxl_port *port);
e0018b
 bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev);
e0018b
 int cxl_port_get_nr_dports(struct cxl_port *port);
e0018b
+struct cxl_port *cxl_port_get_next_all(struct cxl_port *port,
e0018b
+				       const struct cxl_port *top);
e0018b
 
e0018b
 #define cxl_port_foreach(parent, port)                                         \
e0018b
 	for (port = cxl_port_get_first(parent); port != NULL;                  \
e0018b
 	     port = cxl_port_get_next(port))
e0018b
 
e0018b
+#define cxl_port_foreach_all(top, port)                                        \
e0018b
+	for (port = cxl_port_get_first(top); port != NULL;                     \
e0018b
+	     port = cxl_port_get_next_all(port, top))
e0018b
+
e0018b
 struct cxl_dport;
e0018b
 struct cxl_dport *cxl_dport_get_first(struct cxl_port *port);
e0018b
 struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport);
e0018b
-- 
e0018b
2.27.0
e0018b