anitazha / rpms / ndctl

Forked from rpms/ndctl a year ago
Clone

Blame SOURCES/0121-cxl-list-Support-filtering-memdevs-by-ports.patch

e0018b
From 15cae420681c5e8efad2b4cbaf0470960e2eba52 Mon Sep 17 00:00:00 2001
e0018b
From: Dan Williams <dan.j.williams@intel.com>
e0018b
Date: Sun, 23 Jan 2022 16:54:55 -0800
e0018b
Subject: [PATCH 121/217] cxl/list: Support filtering memdevs by ports
e0018b
e0018b
The ability to filter memdevs by decoders falls short when the decoder does
e0018b
not have its target list programmed. So, introduce a by port filter to show
e0018b
the potential memdevs that can be targeted by the decoder.
e0018b
e0018b
Link: https://lore.kernel.org/r/164298569568.3021641.888802471376117408.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
 Documentation/cxl/cxl-list.txt   |  3 +-
e0018b
 Documentation/cxl/lib/libcxl.txt |  7 ++++-
e0018b
 cxl/filter.c                     | 50 ++++++++++++++++++++++++++++++++
e0018b
 cxl/lib/libcxl.c                 | 23 +++++++++++++++
e0018b
 cxl/lib/libcxl.sym               |  2 ++
e0018b
 cxl/libcxl.h                     |  3 ++
e0018b
 6 files changed, 86 insertions(+), 2 deletions(-)
e0018b
e0018b
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
e0018b
index 04e831e..90e6d9f 100644
e0018b
--- a/Documentation/cxl/cxl-list.txt
e0018b
+++ b/Documentation/cxl/cxl-list.txt
e0018b
@@ -63,7 +63,8 @@ one or more memdevs. For example:
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
+root decoder, or mapped by a given port if the decoders are not
e0018b
+configured.
e0018b
 ----
e0018b
 # cxl list -Mu -d decoder0.0
e0018b
 {
e0018b
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
e0018b
index 5ad3027..a0fcee9 100644
e0018b
--- a/Documentation/cxl/lib/libcxl.txt
e0018b
+++ b/Documentation/cxl/lib/libcxl.txt
e0018b
@@ -276,11 +276,12 @@ CXL / PCIe host bridge.
e0018b
 ----
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
+struct cxl_dport *cxl_port_get_dport_by_memdev(struct cxl_port *port,
e0018b
+                                               struct cxl_memdev *memdev);
e0018b
 
e0018b
 #define cxl_dport_foreach(port, dport)                                     \
e0018b
        for (dport = cxl_dport_get_first(port); dport != NULL;              \
e0018b
             dport = cxl_dport_get_next(dport))
e0018b
-
e0018b
 ----
e0018b
 
e0018b
 ===== DPORT: Attributes
e0018b
@@ -288,12 +289,16 @@ struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport);
e0018b
 const char *cxl_dport_get_devname(struct cxl_dport *dport);
e0018b
 const char *cxl_dport_get_physical_node(struct cxl_dport *dport);
e0018b
 int cxl_dport_get_id(struct cxl_dport *dport);
e0018b
+bool cxl_dport_maps_memdev(struct cxl_dport *dport, struct cxl_memdev *memdev);
e0018b
 ----
e0018b
 The id of a dport is the hardware idenfifier used by an upstream port to
e0018b
 reference a downstream port. The physical node of a dport is only
e0018b
 available for platform firmware defined downstream ports and alias the
e0018b
 companion object, like a PCI host bridge, in the PCI device hierarchy.
e0018b
 
e0018b
+The cxl_dport_maps_memdev() helper checks if a dport is an ancestor of a
e0018b
+given memdev.
e0018b
+
e0018b
 ENDPOINTS
e0018b
 ---------
e0018b
 CXL endpoint objects encapsulate the set of host-managed device-memory
e0018b
diff --git a/cxl/filter.c b/cxl/filter.c
e0018b
index c972545..c691edf 100644
e0018b
--- a/cxl/filter.c
e0018b
+++ b/cxl/filter.c
e0018b
@@ -486,6 +486,53 @@ util_cxl_memdev_filter_by_decoder(struct cxl_memdev *memdev, const char *ident)
e0018b
 	return NULL;
e0018b
 }
e0018b
 
e0018b
+static bool __memdev_filter_by_port(struct cxl_memdev *memdev,
e0018b
+				    struct cxl_port *port,
e0018b
+				    const char *port_ident)
e0018b
+{
e0018b
+	struct cxl_endpoint *endpoint;
e0018b
+
e0018b
+	if (util_cxl_port_filter(port, port_ident, CXL_PF_SINGLE) &&
e0018b
+	    cxl_port_get_dport_by_memdev(port, memdev))
e0018b
+		return true;
e0018b
+
e0018b
+	cxl_endpoint_foreach(port, endpoint)
e0018b
+		if (__memdev_filter_by_port(memdev,
e0018b
+					    cxl_endpoint_get_port(endpoint),
e0018b
+					    port_ident))
e0018b
+			return true;
e0018b
+	return false;
e0018b
+}
e0018b
+
e0018b
+static struct cxl_memdev *
e0018b
+util_cxl_memdev_filter_by_port(struct cxl_memdev *memdev, const char *bus_ident,
e0018b
+			       const char *port_ident)
e0018b
+{
e0018b
+	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
e0018b
+	struct cxl_bus *bus;
e0018b
+
e0018b
+	if (!bus_ident && !port_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 (util_cxl_bus_filter(bus, bus_ident))
e0018b
+			if (__memdev_filter_by_port(memdev, port,
e0018b
+						    cxl_bus_get_devname(bus)))
e0018b
+				return memdev;
e0018b
+		if (__memdev_filter_by_port(memdev, port, port_ident))
e0018b
+				return memdev;
e0018b
+		top = port;
e0018b
+		cxl_port_foreach_all(top, port)
e0018b
+			if (__memdev_filter_by_port(memdev, port, 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
@@ -647,6 +694,9 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
e0018b
 			if (!util_cxl_memdev_filter_by_decoder(
e0018b
 				    memdev, p->decoder_filter))
e0018b
 				continue;
e0018b
+			if (!util_cxl_memdev_filter_by_port(
e0018b
+				    memdev, p->bus_filter, p->port_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 4ebb8b9..dcfc826 100644
e0018b
--- a/cxl/lib/libcxl.c
e0018b
+++ b/cxl/lib/libcxl.c
e0018b
@@ -1452,6 +1452,29 @@ CXL_EXPORT int cxl_dport_get_id(struct cxl_dport *dport)
e0018b
 	return dport->id;
e0018b
 }
e0018b
 
e0018b
+CXL_EXPORT bool cxl_dport_maps_memdev(struct cxl_dport *dport,
e0018b
+				      struct cxl_memdev *memdev)
e0018b
+{
e0018b
+	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
e0018b
+
e0018b
+	dbg(ctx, "memdev: %s dport: %s\n", memdev->host_path, dport->dev_path);
e0018b
+
e0018b
+	if (dport->phys_path)
e0018b
+		return !!strstr(memdev->host_path, dport->phys_path);
e0018b
+	return !!strstr(memdev->host_path, dport->dev_path);
e0018b
+}
e0018b
+
e0018b
+CXL_EXPORT struct cxl_dport *
e0018b
+cxl_port_get_dport_by_memdev(struct cxl_port *port, struct cxl_memdev *memdev)
e0018b
+{
e0018b
+	struct cxl_dport *dport;
e0018b
+
e0018b
+	cxl_dport_foreach(port, dport)
e0018b
+		if (cxl_dport_maps_memdev(dport, memdev))
e0018b
+			return dport;
e0018b
+	return NULL;
e0018b
+}
e0018b
+
e0018b
 static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base)
e0018b
 {
e0018b
 	const char *devname = devpath_to_devname(cxlbus_base);
e0018b
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
e0018b
index 0190b13..2c8358e 100644
e0018b
--- a/cxl/lib/libcxl.sym
e0018b
+++ b/cxl/lib/libcxl.sym
e0018b
@@ -149,4 +149,6 @@ global:
e0018b
 	cxl_dport_get_devname;
e0018b
 	cxl_dport_get_physical_node;
e0018b
 	cxl_dport_get_id;
e0018b
+	cxl_port_get_dport_by_memdev;
e0018b
+	cxl_dport_maps_memdev;
e0018b
 } LIBCXL_1;
e0018b
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
e0018b
index 874c381..c8d07bb 100644
e0018b
--- a/cxl/libcxl.h
e0018b
+++ b/cxl/libcxl.h
e0018b
@@ -111,6 +111,9 @@ struct cxl_dport *cxl_dport_get_next(struct cxl_dport *dport);
e0018b
 const char *cxl_dport_get_devname(struct cxl_dport *dport);
e0018b
 const char *cxl_dport_get_physical_node(struct cxl_dport *dport);
e0018b
 int cxl_dport_get_id(struct cxl_dport *dport);
e0018b
+bool cxl_dport_maps_memdev(struct cxl_dport *dport, struct cxl_memdev *memdev);
e0018b
+struct cxl_dport *cxl_port_get_dport_by_memdev(struct cxl_port *port,
e0018b
+					       struct cxl_memdev *memdev);
e0018b
 
e0018b
 #define cxl_dport_foreach(port, dport)                                         \
e0018b
 	for (dport = cxl_dport_get_first(port); dport != NULL;                 \
e0018b
-- 
e0018b
2.27.0
e0018b