anitazha / rpms / ndctl

Forked from rpms/ndctl 2 years ago
Clone
Jeff Moyer 2c91dc
From 8a35aa8fd3e1db06228329a0ca900ce246ca329e Mon Sep 17 00:00:00 2001
Jeff Moyer 2c91dc
From: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Date: Thu, 28 Apr 2022 15:10:27 -0700
Jeff Moyer 2c91dc
Subject: [PATCH 159/217] cxl/bus: Add bus disable support
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Route requests to disable the root back to unbinding the platform firmware
Jeff Moyer 2c91dc
device, ACPI0017 for ACPI.CXL platforms.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Link: https://lore.kernel.org/r/165118382738.1676208.16851880881648171660.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-disable-bus.txt |  37 ++++++
Jeff Moyer 2c91dc
 Documentation/cxl/lib/libcxl.txt      |  12 ++
Jeff Moyer 2c91dc
 Documentation/cxl/meson.build         |   1 +
Jeff Moyer 2c91dc
 cxl/builtin.h                         |   1 +
Jeff Moyer 2c91dc
 cxl/bus.c                             | 159 ++++++++++++++++++++++++++
Jeff Moyer 2c91dc
 cxl/cxl.c                             |   1 +
Jeff Moyer 2c91dc
 cxl/filter.c                          |   3 +-
Jeff Moyer 2c91dc
 cxl/filter.h                          |   1 +
Jeff Moyer 2c91dc
 cxl/lib/libcxl.c                      |  15 +++
Jeff Moyer 2c91dc
 cxl/lib/libcxl.sym                    |   1 +
Jeff Moyer 2c91dc
 cxl/libcxl.h                          |   1 +
Jeff Moyer 2c91dc
 cxl/meson.build                       |   1 +
Jeff Moyer 2c91dc
 12 files changed, 231 insertions(+), 2 deletions(-)
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/cxl-disable-bus.txt
Jeff Moyer 2c91dc
 create mode 100644 cxl/bus.c
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-disable-bus.txt b/Documentation/cxl/cxl-disable-bus.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..65f695c
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-disable-bus.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,37 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+cxl-disable-bus(1)
Jeff Moyer 2c91dc
+===================
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+NAME
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+cxl-disable-bus - Shutdown an entire tree of CXL devices
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SYNOPSIS
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+[verse]
Jeff Moyer 2c91dc
+'cxl disable-bus' <root0> [<root1>..<rootN>] [<options>]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+For test and debug scenarios, disable a CXL bus and any associated
Jeff Moyer 2c91dc
+memory devices from CXL.mem operations.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+OPTIONS
Jeff Moyer 2c91dc
+-------
Jeff Moyer 2c91dc
+-f::
Jeff Moyer 2c91dc
+--force::
Jeff Moyer 2c91dc
+	DANGEROUS: Override the safety measure that blocks attempts to disable a
Jeff Moyer 2c91dc
+	bus if the tool determines a descendent memdev is in active usage.
Jeff Moyer 2c91dc
+	Recall that CXL memory ranges might have been established by platform
Jeff Moyer 2c91dc
+	firmware and disabling an active device is akin to force removing memory
Jeff Moyer 2c91dc
+	from a running system.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+--debug::
Jeff Moyer 2c91dc
+	If the cxl tool was built with debug disabled, turn on debug
Jeff Moyer 2c91dc
+	messages.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+include::../copyright.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SEE ALSO
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+linkcxl:cxl-disable-port[1]
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
index 7b223cb..f8f0e66 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
@@ -216,6 +216,18 @@ discovery order. The possible provider names are 'ACPI.CXL' and
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
+=== BUS: Control
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+int cxl_bus_disable_invalidate(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+An entire CXL topology can be torn down with this API. Like other
Jeff Moyer 2c91dc
+_invalidate APIs callers must assume that all library objects have been
Jeff Moyer 2c91dc
+freed. This one goes one step further and also frees the @bus argument.
Jeff Moyer 2c91dc
+This may crash the system and is only useful in kernel driver
Jeff Moyer 2c91dc
+development scenarios.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 PORTS
Jeff Moyer 2c91dc
 -----
Jeff Moyer 2c91dc
 CXL ports track the PCIe hierarchy between a platform firmware CXL root
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build
Jeff Moyer 2c91dc
index e927644..974a5a4 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/meson.build
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/meson.build
Jeff Moyer 2c91dc
@@ -34,6 +34,7 @@ cxl_manpages = [
Jeff Moyer 2c91dc
   'cxl-disable-memdev.txt',
Jeff Moyer 2c91dc
   'cxl-enable-port.txt',
Jeff Moyer 2c91dc
   'cxl-disable-port.txt',
Jeff Moyer 2c91dc
+  'cxl-disable-bus.txt',
Jeff Moyer 2c91dc
   'cxl-set-partition.txt',
Jeff Moyer 2c91dc
 ]
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
diff --git a/cxl/builtin.h b/cxl/builtin.h
Jeff Moyer 2c91dc
index 7bbad98..a437bc3 100644
Jeff Moyer 2c91dc
--- a/cxl/builtin.h
Jeff Moyer 2c91dc
+++ b/cxl/builtin.h
Jeff Moyer 2c91dc
@@ -15,4 +15,5 @@ int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 int cmd_disable_port(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 int cmd_enable_port(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_disable_bus(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 #endif /* _CXL_BUILTIN_H_ */
Jeff Moyer 2c91dc
diff --git a/cxl/bus.c b/cxl/bus.c
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..3321295
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/cxl/bus.c
Jeff Moyer 2c91dc
@@ -0,0 +1,159 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
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
+#include <unistd.h>
Jeff Moyer 2c91dc
+#include <limits.h>
Jeff Moyer 2c91dc
+#include <util/log.h>
Jeff Moyer 2c91dc
+#include <cxl/libcxl.h>
Jeff Moyer 2c91dc
+#include <util/parse-options.h>
Jeff Moyer 2c91dc
+#include <ccan/minmax/minmax.h>
Jeff Moyer 2c91dc
+#include <ccan/array_size/array_size.h>
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#include "filter.h"
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static struct parameters {
Jeff Moyer 2c91dc
+	bool debug;
Jeff Moyer 2c91dc
+	bool force;
Jeff Moyer 2c91dc
+} param;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static struct log_ctx bl;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define BASE_OPTIONS()                                                 \
Jeff Moyer 2c91dc
+OPT_BOOLEAN(0, "debug", &param.debug, "turn on debug")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define DISABLE_OPTIONS()                                              \
Jeff Moyer 2c91dc
+OPT_BOOLEAN('f', "force", &param.force,                                \
Jeff Moyer 2c91dc
+	    "DANGEROUS: override active memdev safety checks")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static const struct option disable_options[] = {
Jeff Moyer 2c91dc
+	BASE_OPTIONS(),
Jeff Moyer 2c91dc
+	DISABLE_OPTIONS(),
Jeff Moyer 2c91dc
+	OPT_END(),
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int action_disable(struct cxl_bus *bus)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	const char *devname = cxl_bus_get_devname(bus);
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_bus_get_ctx(bus);
Jeff Moyer 2c91dc
+	struct cxl_memdev *memdev;
Jeff Moyer 2c91dc
+	int active_memdevs = 0;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_memdev_foreach(ctx, memdev)
Jeff Moyer 2c91dc
+		if (bus == cxl_memdev_get_bus(memdev))
Jeff Moyer 2c91dc
+			active_memdevs++;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (active_memdevs && !param.force) {
Jeff Moyer 2c91dc
+		/*
Jeff Moyer 2c91dc
+		 * TODO: actually detect rather than assume active just
Jeff Moyer 2c91dc
+		 * because the memdev is enabled
Jeff Moyer 2c91dc
+		 */
Jeff Moyer 2c91dc
+		log_err(&bl,
Jeff Moyer 2c91dc
+			"%s hosts %d memdev%s which %s part of an active region\n",
Jeff Moyer 2c91dc
+			devname, active_memdevs, active_memdevs > 1 ? "s" : "",
Jeff Moyer 2c91dc
+			active_memdevs > 1 ? "are" : "is");
Jeff Moyer 2c91dc
+		log_err(&bl,
Jeff Moyer 2c91dc
+			"See 'cxl list -M -b %s' to see impacted device%s\n",
Jeff Moyer 2c91dc
+			devname, active_memdevs > 1 ? "s" : "");
Jeff Moyer 2c91dc
+		return -EBUSY;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return cxl_bus_disable_invalidate(bus);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static struct cxl_bus *find_cxl_bus(struct cxl_ctx *ctx, const char *ident)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_bus *bus;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_bus_foreach(ctx, bus)
Jeff Moyer 2c91dc
+		if (util_cxl_bus_filter(bus, ident))
Jeff Moyer 2c91dc
+			return bus;
Jeff Moyer 2c91dc
+	return NULL;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int bus_action(int argc, const char **argv, struct cxl_ctx *ctx,
Jeff Moyer 2c91dc
+		      int (*action)(struct cxl_bus *bus),
Jeff Moyer 2c91dc
+		      const struct option *options, const char *usage)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	int i, rc = 0, count = 0, err = 0;
Jeff Moyer 2c91dc
+	const char * const u[] = {
Jeff Moyer 2c91dc
+		usage,
Jeff Moyer 2c91dc
+		NULL
Jeff Moyer 2c91dc
+	};
Jeff Moyer 2c91dc
+	unsigned long id;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	log_init(&bl, "cxl bus", "CXL_PORT_LOG");
Jeff Moyer 2c91dc
+	argc = parse_options(argc, argv, options, u, 0);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (argc == 0)
Jeff Moyer 2c91dc
+		usage_with_options(u, options);
Jeff Moyer 2c91dc
+	for (i = 0; i < argc; i++) {
Jeff Moyer 2c91dc
+		if (strcmp(argv[i], "all") == 0) {
Jeff Moyer 2c91dc
+			argv[0] = "all";
Jeff Moyer 2c91dc
+			argc = 1;
Jeff Moyer 2c91dc
+			break;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (sscanf(argv[i], "root%lu", &id) == 1)
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+		if (sscanf(argv[i], "%lu", &id) == 1)
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		log_err(&bl, "'%s' is not a valid bus identifer\n", argv[i]);
Jeff Moyer 2c91dc
+		err++;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (err == argc) {
Jeff Moyer 2c91dc
+		usage_with_options(u, options);
Jeff Moyer 2c91dc
+		return -EINVAL;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (param.debug) {
Jeff Moyer 2c91dc
+		cxl_set_log_priority(ctx, LOG_DEBUG);
Jeff Moyer 2c91dc
+		bl.log_priority = LOG_DEBUG;
Jeff Moyer 2c91dc
+	} else
Jeff Moyer 2c91dc
+		bl.log_priority = LOG_INFO;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = 0;
Jeff Moyer 2c91dc
+	err = 0;
Jeff Moyer 2c91dc
+	count = 0;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	for (i = 0; i < argc; i++) {
Jeff Moyer 2c91dc
+		struct cxl_bus *bus;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		bus = find_cxl_bus(ctx, argv[i]);
Jeff Moyer 2c91dc
+		if (!bus) {
Jeff Moyer 2c91dc
+			log_dbg(&bl, "bus: %s not found\n", argv[i]);
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		log_dbg(&bl, "run action on bus: %s\n",
Jeff Moyer 2c91dc
+			cxl_bus_get_devname(bus));
Jeff Moyer 2c91dc
+		rc = action(bus);
Jeff Moyer 2c91dc
+		if (rc == 0)
Jeff Moyer 2c91dc
+			count++;
Jeff Moyer 2c91dc
+		else if (rc && !err)
Jeff Moyer 2c91dc
+			err = rc;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+	rc = err;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	/*
Jeff Moyer 2c91dc
+	 * count if some actions succeeded, 0 if none were attempted,
Jeff Moyer 2c91dc
+	 * negative error code otherwise.
Jeff Moyer 2c91dc
+	 */
Jeff Moyer 2c91dc
+	if (count > 0)
Jeff Moyer 2c91dc
+		return count;
Jeff Moyer 2c91dc
+	return rc;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+ int cmd_disable_bus(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+ {
Jeff Moyer 2c91dc
+	 int count = bus_action(
Jeff Moyer 2c91dc
+		 argc, argv, ctx, action_disable, disable_options,
Jeff Moyer 2c91dc
+		 "cxl disable-bus <bus0> [<bus1>..<busN>] [<options>]");
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	 log_info(&bl, "disabled %d bus%s\n", count >= 0 ? count : 0,
Jeff Moyer 2c91dc
+		  count > 1 ? "s" : "");
Jeff Moyer 2c91dc
+	 return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
+ }
Jeff Moyer 2c91dc
diff --git a/cxl/cxl.c b/cxl/cxl.c
Jeff Moyer 2c91dc
index ab4bbec..aa4ce61 100644
Jeff Moyer 2c91dc
--- a/cxl/cxl.c
Jeff Moyer 2c91dc
+++ b/cxl/cxl.c
Jeff Moyer 2c91dc
@@ -69,6 +69,7 @@ static struct cmd_struct commands[] = {
Jeff Moyer 2c91dc
 	{ "disable-port", .c_fn = cmd_disable_port },
Jeff Moyer 2c91dc
 	{ "enable-port", .c_fn = cmd_enable_port },
Jeff Moyer 2c91dc
 	{ "set-partition", .c_fn = cmd_set_partition },
Jeff Moyer 2c91dc
+	{ "disable-bus", .c_fn = cmd_disable_bus },
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 int main(int argc, const char **argv)
Jeff Moyer 2c91dc
diff --git a/cxl/filter.c b/cxl/filter.c
Jeff Moyer 2c91dc
index b339642..c6ab9eb 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.c
Jeff Moyer 2c91dc
+++ b/cxl/filter.c
Jeff Moyer 2c91dc
@@ -176,8 +176,7 @@ util_cxl_decoder_filter_by_port(struct cxl_decoder *decoder, const char *ident,
Jeff Moyer 2c91dc
 	return NULL;
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
+struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, const char *__ident)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	char *ident, *save;
Jeff Moyer 2c91dc
 	const char *arg;
Jeff Moyer 2c91dc
diff --git a/cxl/filter.h b/cxl/filter.h
Jeff Moyer 2c91dc
index 697b777..9557943 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.h
Jeff Moyer 2c91dc
+++ b/cxl/filter.h
Jeff Moyer 2c91dc
@@ -41,6 +41,7 @@ enum cxl_port_filter_mode {
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 struct cxl_port *util_cxl_port_filter(struct cxl_port *port, const char *ident,
Jeff Moyer 2c91dc
 				      enum cxl_port_filter_mode mode);
Jeff Moyer 2c91dc
+struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus, const char *__ident);
Jeff Moyer 2c91dc
 struct cxl_endpoint *util_cxl_endpoint_filter(struct cxl_endpoint *endpoint,
Jeff Moyer 2c91dc
 					      const char *__ident);
Jeff Moyer 2c91dc
 struct cxl_target *util_cxl_target_filter_by_memdev(struct cxl_target *target,
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
index 59e1644..0e8dd20 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
@@ -556,6 +556,21 @@ static void bus_invalidate(struct cxl_bus *bus)
Jeff Moyer 2c91dc
 	cxl_flush(ctx);
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+CXL_EXPORT int cxl_bus_disable_invalidate(struct cxl_bus *bus)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_bus_get_ctx(bus);
Jeff Moyer 2c91dc
+	struct cxl_port *port = cxl_bus_get_port(bus);
Jeff Moyer 2c91dc
+	int rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = util_unbind(port->uport, ctx);
Jeff Moyer 2c91dc
+	if (rc)
Jeff Moyer 2c91dc
+		return rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	free_bus(bus, &ctx->buses);
Jeff Moyer 2c91dc
+	cxl_flush(ctx);
Jeff Moyer 2c91dc
+	return 0;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
index aab1112..dffcb60 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
@@ -86,6 +86,7 @@ global:
Jeff Moyer 2c91dc
 	cxl_bus_get_id;
Jeff Moyer 2c91dc
 	cxl_bus_get_port;
Jeff Moyer 2c91dc
 	cxl_bus_get_ctx;
Jeff Moyer 2c91dc
+	cxl_bus_disable_invalidate;
Jeff Moyer 2c91dc
 	cxl_port_get_first;
Jeff Moyer 2c91dc
 	cxl_port_get_next;
Jeff Moyer 2c91dc
 	cxl_port_get_devname;
Jeff Moyer 2c91dc
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
Jeff Moyer 2c91dc
index 0063d31..0007f4d 100644
Jeff Moyer 2c91dc
--- a/cxl/libcxl.h
Jeff Moyer 2c91dc
+++ b/cxl/libcxl.h
Jeff Moyer 2c91dc
@@ -73,6 +73,7 @@ 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
 struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus);
Jeff Moyer 2c91dc
 struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus);
Jeff Moyer 2c91dc
+int cxl_bus_disable_invalidate(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
diff --git a/cxl/meson.build b/cxl/meson.build
Jeff Moyer 2c91dc
index 671c8e1..d63dcb1 100644
Jeff Moyer 2c91dc
--- a/cxl/meson.build
Jeff Moyer 2c91dc
+++ b/cxl/meson.build
Jeff Moyer 2c91dc
@@ -2,6 +2,7 @@ cxl_src = [
Jeff Moyer 2c91dc
   'cxl.c',
Jeff Moyer 2c91dc
   'list.c',
Jeff Moyer 2c91dc
   'port.c',
Jeff Moyer 2c91dc
+  'bus.c',
Jeff Moyer 2c91dc
   'memdev.c',
Jeff Moyer 2c91dc
   'json.c',
Jeff Moyer 2c91dc
   'filter.c',
Jeff Moyer 2c91dc
-- 
Jeff Moyer 2c91dc
2.27.0
Jeff Moyer 2c91dc