anitazha / rpms / ndctl

Forked from rpms/ndctl a year ago
Clone

Blame 0184-cxl-memdev-Add-reserve-free-dpa-commands.patch

Jeff Moyer 2c91dc
From 6624f4fdf7ba43039111c996dfd3982b4fdc43bc Mon Sep 17 00:00:00 2001
Jeff Moyer 2c91dc
From: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Date: Thu, 14 Jul 2022 10:02:44 -0700
Jeff Moyer 2c91dc
Subject: [PATCH 184/217] cxl/memdev: Add {reserve,free}-dpa commands
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Add helper commands for managing allocations of DPA (device physical
Jeff Moyer 2c91dc
address) capacity on a set of CXL memory devices.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
The main convenience this command affords is automatically picking the next
Jeff Moyer 2c91dc
decoder to allocate per-memdev.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
For example, to allocate 256MiB from all endpoints that are covered by a
Jeff Moyer 2c91dc
given root decoder, and collect those resulting endpoint-decoders into an
Jeff Moyer 2c91dc
array:
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
  readarray -t mem < <(cxl list -M -d $decoder | jq -r ".[].memdev")
Jeff Moyer 2c91dc
  readarray -t endpoint < <(cxl reserve-dpa -t pmem ${mem[*]} -s $((256<<20)) |
Jeff Moyer 2c91dc
                            jq -r ".[] | .decoder.decoder")
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Link: https://lore.kernel.org/r/165781816425.1555691.17958897857798325111.stgit@dwillia2-xfh.jf.intel.com
Jeff Moyer 2c91dc
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
[vishal: fix typo pointed out by Jonathan]
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-free-dpa.txt    |  53 +++++
Jeff Moyer 2c91dc
 Documentation/cxl/cxl-reserve-dpa.txt |  67 ++++++
Jeff Moyer 2c91dc
 Documentation/cxl/lib/libcxl.txt      |   2 +
Jeff Moyer 2c91dc
 Documentation/cxl/meson.build         |   2 +
Jeff Moyer 2c91dc
 cxl/builtin.h                         |   2 +
Jeff Moyer 2c91dc
 cxl/cxl.c                             |   2 +
Jeff Moyer 2c91dc
 cxl/filter.c                          |   4 +-
Jeff Moyer 2c91dc
 cxl/filter.h                          |   2 +
Jeff Moyer 2c91dc
 cxl/lib/libcxl.c                      |  86 ++++++++
Jeff Moyer 2c91dc
 cxl/lib/libcxl.sym                    |   4 +
Jeff Moyer 2c91dc
 cxl/libcxl.h                          |   9 +
Jeff Moyer 2c91dc
 cxl/memdev.c                          | 280 +++++++++++++++++++++++++-
Jeff Moyer 2c91dc
 13 files changed, 511 insertions(+), 3 deletions(-)
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/cxl-free-dpa.txt
Jeff Moyer 2c91dc
 create mode 100644 Documentation/cxl/cxl-reserve-dpa.txt
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
diff --git a/.clang-format b/.clang-format
Jeff Moyer 2c91dc
index 6aabcb6..7254a1b 100644
Jeff Moyer 2c91dc
--- a/.clang-format
Jeff Moyer 2c91dc
+++ b/.clang-format
Jeff Moyer 2c91dc
@@ -81,6 +81,7 @@ ForEachMacros:
Jeff Moyer 2c91dc
   - 'cxl_bus_foreach'
Jeff Moyer 2c91dc
   - 'cxl_port_foreach'
Jeff Moyer 2c91dc
   - 'cxl_decoder_foreach'
Jeff Moyer 2c91dc
+  - 'cxl_decoder_foreach_reverse'
Jeff Moyer 2c91dc
   - 'cxl_target_foreach'
Jeff Moyer 2c91dc
   - 'cxl_dport_foreach'
Jeff Moyer 2c91dc
   - 'cxl_endpoint_foreach'
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-free-dpa.txt b/Documentation/cxl/cxl-free-dpa.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..73fb048
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-free-dpa.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,53 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+cxl-free-dpa(1)
Jeff Moyer 2c91dc
+===============
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+NAME
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+cxl-free-dpa - release device-physical address space
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SYNOPSIS
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+[verse]
Jeff Moyer 2c91dc
+'cxl free-dpa' <mem0> [<mem1>..<memN>] [<options>]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+The CXL region provisioning process proceeds in multiple steps. One of
Jeff Moyer 2c91dc
+the steps is identifying and reserving the DPA span that each member of
Jeff Moyer 2c91dc
+the interleave-set (region) contributes in advance of attaching that
Jeff Moyer 2c91dc
+allocation to a region. For development, test, and debug purposes this
Jeff Moyer 2c91dc
+command is a helper to find the last allocated decoder on a device and
Jeff Moyer 2c91dc
+zero-out / free its DPA allocation.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+OPTIONS
Jeff Moyer 2c91dc
+-------
Jeff Moyer 2c91dc
+<memory device(s)>::
Jeff Moyer 2c91dc
+include::memdev-option.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-d::
Jeff Moyer 2c91dc
+--decoder::
Jeff Moyer 2c91dc
+	Specify the decoder to free. The CXL specification
Jeff Moyer 2c91dc
+	mandates that DPA must be released in the reverse order it was
Jeff Moyer 2c91dc
+	allocated. See linkcxl:cxl-reserve-dpa[1]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-t::
Jeff Moyer 2c91dc
+--type::
Jeff Moyer 2c91dc
+	Constrain the search for "last allocated decoder" to decoders targeting
Jeff Moyer 2c91dc
+	the given partition.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-f::
Jeff Moyer 2c91dc
+--force::
Jeff Moyer 2c91dc
+	The kernel enforces CXL DPA ordering constraints on deallocation events,
Jeff Moyer 2c91dc
+	and the tool anticipates those and fails operations that are expected to
Jeff Moyer 2c91dc
+	fail without sending them to the kernel. For test purposes, continue to
Jeff Moyer 2c91dc
+	attempt "expected to fail" operations to exercise the driver.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-v::
Jeff Moyer 2c91dc
+	Turn on verbose debug messages in the library (if libcxl was built with
Jeff Moyer 2c91dc
+	logging and debug enabled).
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-reserve-dpa[1]
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/cxl-reserve-dpa.txt b/Documentation/cxl/cxl-reserve-dpa.txt
Jeff Moyer 2c91dc
new file mode 100644
Jeff Moyer 2c91dc
index 0000000..5e79ef2
Jeff Moyer 2c91dc
--- /dev/null
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/cxl-reserve-dpa.txt
Jeff Moyer 2c91dc
@@ -0,0 +1,67 @@
Jeff Moyer 2c91dc
+// SPDX-License-Identifier: GPL-2.0
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+cxl-reserve-dpa(1)
Jeff Moyer 2c91dc
+==================
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+NAME
Jeff Moyer 2c91dc
+----
Jeff Moyer 2c91dc
+cxl-reserve-dpa - allocate device-physical address space
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+SYNOPSIS
Jeff Moyer 2c91dc
+--------
Jeff Moyer 2c91dc
+[verse]
Jeff Moyer 2c91dc
+'cxl reserve-dpa' <mem0> [<mem1>..<memN>] [<options>]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+The CXL region provisioning process proceeds in multiple steps. One of
Jeff Moyer 2c91dc
+the steps is identifying and reserving the DPA span that each member of
Jeff Moyer 2c91dc
+the interleave-set (region) contributes in advance of attaching that
Jeff Moyer 2c91dc
+allocation to a region. For development, test, and debug purposes this
Jeff Moyer 2c91dc
+command is a helper to find the next available decoder on endpoint
Jeff Moyer 2c91dc
+(memdev) and mark a span of DPA as busy.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+OPTIONS
Jeff Moyer 2c91dc
+-------
Jeff Moyer 2c91dc
+<memory device(s)>::
Jeff Moyer 2c91dc
+include::memdev-option.txt[]
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-d::
Jeff Moyer 2c91dc
+--decoder::
Jeff Moyer 2c91dc
+	Specify the decoder to attempt the allocation. The CXL specification
Jeff Moyer 2c91dc
+	mandates that allocations must be ordered by DPA and decoder instance.
Jeff Moyer 2c91dc
+	I.e. the lowest DPA allocation on the device is covered by decoder0, and
Jeff Moyer 2c91dc
+	the last / highest DPA allocation is covered by the last decoder. This
Jeff Moyer 2c91dc
+	ordering is enforced by the kernel. By default the tool picks the 'next
Jeff Moyer 2c91dc
+	available' decoder.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-t::
Jeff Moyer 2c91dc
+--type::
Jeff Moyer 2c91dc
+	Select the partition for the allocation. CXL devices implement a
Jeff Moyer 2c91dc
+	partition that divdes 'ram' and 'pmem' capacity, where 'pmem' capacity
Jeff Moyer 2c91dc
+	consumes the higher DPA capacity above the partition boundary. The type
Jeff Moyer 2c91dc
+	defaults to 'pmem'. Note that given CXL DPA allocation constraints, once
Jeff Moyer 2c91dc
+	any 'pmem' allocation is established then all remaining 'ram' capacity
Jeff Moyer 2c91dc
+	becomes reserved (skipped).
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-f::
Jeff Moyer 2c91dc
+--force::
Jeff Moyer 2c91dc
+	The kernel enforces CXL DPA allocation ordering constraints, and
Jeff Moyer 2c91dc
+	the tool anticipates those and fails operations that are expected to
Jeff Moyer 2c91dc
+	fail without sending them to the kernel. For test purposes, continue to
Jeff Moyer 2c91dc
+	attempt "expected to fail" operations to exercise the driver.
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-s::
Jeff Moyer 2c91dc
+--size::
Jeff Moyer 2c91dc
+	Specify the size of the allocation. This option supports the suffixes
Jeff Moyer 2c91dc
+	"k" or "K" for KiB, "m" or "M" for MiB, "g" or "G" for GiB and "t" or
Jeff Moyer 2c91dc
+	"T" for TiB. This defaults to "all available capacity of the specified
Jeff Moyer 2c91dc
+	type".
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+-v::
Jeff Moyer 2c91dc
+	Turn on verbose debug messages in the library (if libcxl was built with
Jeff Moyer 2c91dc
+	logging and debug enabled).
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-free-dpa[1]
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
index 90fe338..7a38ce4 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/lib/libcxl.txt
Jeff Moyer 2c91dc
@@ -394,6 +394,7 @@ unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 unsigned long long cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
+int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder, unsigned long long size);
Jeff Moyer 2c91dc
 const char *cxl_decoder_get_devname(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 int cxl_decoder_get_id(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
@@ -413,6 +414,7 @@ enum cxl_decoder_mode {
Jeff Moyer 2c91dc
 	CXL_DECODER_MODE_RAM,
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
 enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
+int cxl_decoder_set_mode(struct cxl_decoder *decoder, enum cxl_decoder_mode mode);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 bool cxl_decoder_is_pmem_capable(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 bool cxl_decoder_is_volatile_capable(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build
Jeff Moyer 2c91dc
index 974a5a4..d019dfc 100644
Jeff Moyer 2c91dc
--- a/Documentation/cxl/meson.build
Jeff Moyer 2c91dc
+++ b/Documentation/cxl/meson.build
Jeff Moyer 2c91dc
@@ -36,6 +36,8 @@ cxl_manpages = [
Jeff Moyer 2c91dc
   'cxl-disable-port.txt',
Jeff Moyer 2c91dc
   'cxl-disable-bus.txt',
Jeff Moyer 2c91dc
   'cxl-set-partition.txt',
Jeff Moyer 2c91dc
+  'cxl-reserve-dpa.txt',
Jeff Moyer 2c91dc
+  'cxl-free-dpa.txt',
Jeff Moyer 2c91dc
 ]
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 foreach man : cxl_manpages
Jeff Moyer 2c91dc
diff --git a/cxl/builtin.h b/cxl/builtin.h
Jeff Moyer 2c91dc
index a437bc3..9e6fc62 100644
Jeff Moyer 2c91dc
--- a/cxl/builtin.h
Jeff Moyer 2c91dc
+++ b/cxl/builtin.h
Jeff Moyer 2c91dc
@@ -12,6 +12,8 @@ int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
 int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_reserve_dpa(int argc, const char **argv, struct cxl_ctx *ctx);
Jeff Moyer 2c91dc
+int cmd_free_dpa(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
diff --git a/cxl/cxl.c b/cxl/cxl.c
Jeff Moyer 2c91dc
index aa4ce61..ef4cda9 100644
Jeff Moyer 2c91dc
--- a/cxl/cxl.c
Jeff Moyer 2c91dc
+++ b/cxl/cxl.c
Jeff Moyer 2c91dc
@@ -66,6 +66,8 @@ static struct cmd_struct commands[] = {
Jeff Moyer 2c91dc
 	{ "write-labels", .c_fn = cmd_write_labels },
Jeff Moyer 2c91dc
 	{ "disable-memdev", .c_fn = cmd_disable_memdev },
Jeff Moyer 2c91dc
 	{ "enable-memdev", .c_fn = cmd_enable_memdev },
Jeff Moyer 2c91dc
+	{ "reserve-dpa", .c_fn = cmd_reserve_dpa },
Jeff Moyer 2c91dc
+	{ "free-dpa", .c_fn = cmd_free_dpa },
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
diff --git a/cxl/filter.c b/cxl/filter.c
Jeff Moyer 2c91dc
index 2f88a9d..e5fab19 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.c
Jeff Moyer 2c91dc
+++ b/cxl/filter.c
Jeff Moyer 2c91dc
@@ -380,8 +380,8 @@ struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port,
Jeff Moyer 2c91dc
 	return NULL;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-static struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
-						   const char *__ident)
Jeff Moyer 2c91dc
+struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
+					    const char *__ident)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	struct cxl_port *port = cxl_decoder_get_port(decoder);
Jeff Moyer 2c91dc
 	int pid, did;
Jeff Moyer 2c91dc
diff --git a/cxl/filter.h b/cxl/filter.h
Jeff Moyer 2c91dc
index 9557943..c913daf 100644
Jeff Moyer 2c91dc
--- a/cxl/filter.h
Jeff Moyer 2c91dc
+++ b/cxl/filter.h
Jeff Moyer 2c91dc
@@ -50,6 +50,8 @@ struct cxl_target *util_cxl_target_filter_by_memdev(struct cxl_target *target,
Jeff Moyer 2c91dc
 struct cxl_dport *util_cxl_dport_filter_by_memdev(struct cxl_dport *dport,
Jeff Moyer 2c91dc
 						  const char *ident,
Jeff Moyer 2c91dc
 						  const char *serial);
Jeff Moyer 2c91dc
+struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
+					    const char *__ident);
Jeff Moyer 2c91dc
 int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param);
Jeff Moyer 2c91dc
 bool cxl_filter_has(const char *needle, const char *__filter);
Jeff Moyer 2c91dc
 #endif /* _CXL_UTIL_FILTER_H_ */
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
index b802e5d..e52896f 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
@@ -1121,6 +1121,20 @@ CXL_EXPORT struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
 	return list_next(&port->decoders, decoder, list);
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_last(struct cxl_port *port)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	cxl_decoders_init(port);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return list_tail(&port->decoders, struct cxl_decoder, list);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT struct cxl_decoder *cxl_decoder_get_prev(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_port *port = decoder->port;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return list_prev(&port->decoders, decoder, list);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 CXL_EXPORT struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	return decoder->ctx;
Jeff Moyer 2c91dc
@@ -1176,6 +1190,78 @@ cxl_decoder_get_dpa_size(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
 	return decoder->dpa_size;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+CXL_EXPORT int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
+					unsigned long long size)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_port *port = cxl_decoder_get_port(decoder);
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder);
Jeff Moyer 2c91dc
+	char *path = decoder->dev_buf;
Jeff Moyer 2c91dc
+	int len = decoder->buf_len, rc;
Jeff Moyer 2c91dc
+	char buf[SYSFS_ATTR_SIZE];
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!cxl_port_is_endpoint(port)) {
Jeff Moyer 2c91dc
+		err(ctx, "%s: not an endpoint decoder\n",
Jeff Moyer 2c91dc
+		    cxl_decoder_get_devname(decoder));
Jeff Moyer 2c91dc
+		return -EINVAL;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (snprintf(path, len, "%s/dpa_size", decoder->dev_path) >= len) {
Jeff Moyer 2c91dc
+		err(ctx, "%s: buffer too small!\n",
Jeff Moyer 2c91dc
+		    cxl_decoder_get_devname(decoder));
Jeff Moyer 2c91dc
+		return -ENOMEM;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	sprintf(buf, "%#llx\n", size);
Jeff Moyer 2c91dc
+	rc = sysfs_write_attr(ctx, path, buf);
Jeff Moyer 2c91dc
+	if (rc < 0)
Jeff Moyer 2c91dc
+		return rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	decoder->dpa_size = size;
Jeff Moyer 2c91dc
+	return 0;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+CXL_EXPORT int cxl_decoder_set_mode(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
+				    enum cxl_decoder_mode mode)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_port *port = cxl_decoder_get_port(decoder);
Jeff Moyer 2c91dc
+	struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder);
Jeff Moyer 2c91dc
+	char *path = decoder->dev_buf;
Jeff Moyer 2c91dc
+	int len = decoder->buf_len, rc;
Jeff Moyer 2c91dc
+	char buf[SYSFS_ATTR_SIZE];
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!cxl_port_is_endpoint(port)) {
Jeff Moyer 2c91dc
+		err(ctx, "%s: not an endpoint decoder\n",
Jeff Moyer 2c91dc
+		    cxl_decoder_get_devname(decoder));
Jeff Moyer 2c91dc
+		return -EINVAL;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	switch (mode) {
Jeff Moyer 2c91dc
+	case CXL_DECODER_MODE_PMEM:
Jeff Moyer 2c91dc
+		sprintf(buf, "pmem");
Jeff Moyer 2c91dc
+		break;
Jeff Moyer 2c91dc
+	case CXL_DECODER_MODE_RAM:
Jeff Moyer 2c91dc
+		sprintf(buf, "ram");
Jeff Moyer 2c91dc
+		break;
Jeff Moyer 2c91dc
+	default:
Jeff Moyer 2c91dc
+		err(ctx, "%s: unsupported mode: %d\n",
Jeff Moyer 2c91dc
+		    cxl_decoder_get_devname(decoder), mode);
Jeff Moyer 2c91dc
+		return -EINVAL;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (snprintf(path, len, "%s/mode", decoder->dev_path) >= len) {
Jeff Moyer 2c91dc
+		err(ctx, "%s: buffer too small!\n",
Jeff Moyer 2c91dc
+		    cxl_decoder_get_devname(decoder));
Jeff Moyer 2c91dc
+		return -ENOMEM;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = sysfs_write_attr(ctx, path, buf);
Jeff Moyer 2c91dc
+	if (rc < 0)
Jeff Moyer 2c91dc
+		return rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	decoder->mode = mode;
Jeff Moyer 2c91dc
+	return 0;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 CXL_EXPORT enum cxl_decoder_mode
Jeff Moyer 2c91dc
 cxl_decoder_get_mode(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
index 88c5a7e..7712de0 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
@@ -173,4 +173,8 @@ global:
Jeff Moyer 2c91dc
 	cxl_decoder_get_dpa_resource;
Jeff Moyer 2c91dc
 	cxl_decoder_get_dpa_size;
Jeff Moyer 2c91dc
 	cxl_decoder_get_mode;
Jeff Moyer 2c91dc
+	cxl_decoder_get_last;
Jeff Moyer 2c91dc
+	cxl_decoder_get_prev;
Jeff Moyer 2c91dc
+	cxl_decoder_set_dpa_size;
Jeff Moyer 2c91dc
+	cxl_decoder_set_mode;
Jeff Moyer 2c91dc
 } LIBCXL_2;
Jeff Moyer 2c91dc
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
Jeff Moyer 2c91dc
index 1436dc4..33a216e 100644
Jeff Moyer 2c91dc
--- a/cxl/libcxl.h
Jeff Moyer 2c91dc
+++ b/cxl/libcxl.h
Jeff Moyer 2c91dc
@@ -139,6 +139,7 @@ enum cxl_decoder_mode {
Jeff Moyer 2c91dc
 	CXL_DECODER_MODE_PMEM,
Jeff Moyer 2c91dc
 	CXL_DECODER_MODE_RAM,
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	static const char *names[] = {
Jeff Moyer 2c91dc
@@ -154,6 +155,10 @@ static inline const char *cxl_decoder_mode_name(enum cxl_decoder_mode mode)
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 enum cxl_decoder_mode cxl_decoder_get_mode(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
+int cxl_decoder_set_mode(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
+			 enum cxl_decoder_mode mode);
Jeff Moyer 2c91dc
+int cxl_decoder_set_dpa_size(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
+			     unsigned long long size);
Jeff Moyer 2c91dc
 const char *cxl_decoder_get_devname(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
 						    struct cxl_memdev *memdev);
Jeff Moyer 2c91dc
@@ -182,6 +187,10 @@ bool cxl_decoder_is_locked(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 	for (decoder = cxl_decoder_get_first(port); decoder != NULL;           \
Jeff Moyer 2c91dc
 	     decoder = cxl_decoder_get_next(decoder))
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+#define cxl_decoder_foreach_reverse(port, decoder)                             \
Jeff Moyer 2c91dc
+	for (decoder = cxl_decoder_get_last(port); decoder != NULL;           \
Jeff Moyer 2c91dc
+	     decoder = cxl_decoder_get_prev(decoder))
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 struct cxl_target;
Jeff Moyer 2c91dc
 struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
 struct cxl_target *cxl_target_get_next(struct cxl_target *target);
Jeff Moyer 2c91dc
diff --git a/cxl/memdev.c b/cxl/memdev.c
Jeff Moyer 2c91dc
index 1cecad2..e42f554 100644
Jeff Moyer 2c91dc
--- a/cxl/memdev.c
Jeff Moyer 2c91dc
+++ b/cxl/memdev.c
Jeff Moyer 2c91dc
@@ -33,6 +33,7 @@ static struct parameters {
Jeff Moyer 2c91dc
 	bool align;
Jeff Moyer 2c91dc
 	const char *type;
Jeff Moyer 2c91dc
 	const char *size;
Jeff Moyer 2c91dc
+	const char *decoder_filter;
Jeff Moyer 2c91dc
 } param;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 static struct log_ctx ml;
Jeff Moyer 2c91dc
@@ -71,6 +72,19 @@ OPT_STRING('s', "size",  &param.size, "size",			\
Jeff Moyer 2c91dc
 OPT_BOOLEAN('a', "align",  &param.align,			\
Jeff Moyer 2c91dc
 	"auto-align --size per device's requirement")
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+#define RESERVE_DPA_OPTIONS()                                          \
Jeff Moyer 2c91dc
+OPT_STRING('s', "size", &param.size, "size",                           \
Jeff Moyer 2c91dc
+	   "size in bytes (Default: all available capacity)")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+#define DPA_OPTIONS()                                          \
Jeff Moyer 2c91dc
+OPT_STRING('d', "decoder", &param.decoder_filter,              \
Jeff Moyer 2c91dc
+   "decoder instance id",                                      \
Jeff Moyer 2c91dc
+   "override the automatic decoder selection"),                \
Jeff Moyer 2c91dc
+OPT_STRING('t', "type", &param.type, "type",                   \
Jeff Moyer 2c91dc
+	   "'pmem' or 'ram' (volatile) (Default: 'pmem')"),    \
Jeff Moyer 2c91dc
+OPT_BOOLEAN('f', "force", &param.force,                        \
Jeff Moyer 2c91dc
+	    "Attempt 'expected to fail' operations")
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static const struct option read_options[] = {
Jeff Moyer 2c91dc
 	BASE_OPTIONS(),
Jeff Moyer 2c91dc
 	LABEL_OPTIONS(),
Jeff Moyer 2c91dc
@@ -108,6 +122,242 @@ static const struct option set_partition_options[] = {
Jeff Moyer 2c91dc
 	OPT_END(),
Jeff Moyer 2c91dc
 };
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static const struct option reserve_dpa_options[] = {
Jeff Moyer 2c91dc
+	BASE_OPTIONS(),
Jeff Moyer 2c91dc
+	RESERVE_DPA_OPTIONS(),
Jeff Moyer 2c91dc
+	DPA_OPTIONS(),
Jeff Moyer 2c91dc
+	OPT_END(),
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static const struct option free_dpa_options[] = {
Jeff Moyer 2c91dc
+	BASE_OPTIONS(),
Jeff Moyer 2c91dc
+	DPA_OPTIONS(),
Jeff Moyer 2c91dc
+	OPT_END(),
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+enum reserve_dpa_mode {
Jeff Moyer 2c91dc
+	DPA_ALLOC,
Jeff Moyer 2c91dc
+	DPA_FREE,
Jeff Moyer 2c91dc
+};
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int __reserve_dpa(struct cxl_memdev *memdev,
Jeff Moyer 2c91dc
+			 enum reserve_dpa_mode alloc_mode,
Jeff Moyer 2c91dc
+			 struct action_context *actx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	struct cxl_decoder *decoder, *auto_target = NULL, *target = NULL;
Jeff Moyer 2c91dc
+	struct cxl_endpoint *endpoint = cxl_memdev_get_endpoint(memdev);
Jeff Moyer 2c91dc
+	const char *devname = cxl_memdev_get_devname(memdev);
Jeff Moyer 2c91dc
+	unsigned long long avail_dpa, size;
Jeff Moyer 2c91dc
+	enum cxl_decoder_mode mode;
Jeff Moyer 2c91dc
+	struct cxl_port *port;
Jeff Moyer 2c91dc
+	char buf[256];
Jeff Moyer 2c91dc
+	int rc;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (param.type) {
Jeff Moyer 2c91dc
+		if (strcmp(param.type, "ram") == 0)
Jeff Moyer 2c91dc
+			mode = CXL_DECODER_MODE_RAM;
Jeff Moyer 2c91dc
+		else if (strcmp(param.type, "volatile") == 0)
Jeff Moyer 2c91dc
+			mode = CXL_DECODER_MODE_RAM;
Jeff Moyer 2c91dc
+		else if (strcmp(param.type, "ram") == 0)
Jeff Moyer 2c91dc
+			mode = CXL_DECODER_MODE_RAM;
Jeff Moyer 2c91dc
+		else if (strcmp(param.type, "pmem") == 0)
Jeff Moyer 2c91dc
+			mode = CXL_DECODER_MODE_PMEM;
Jeff Moyer 2c91dc
+		else {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: unsupported type: %s\n", devname,
Jeff Moyer 2c91dc
+				param.type);
Jeff Moyer 2c91dc
+			return -EINVAL;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	} else
Jeff Moyer 2c91dc
+		mode = CXL_DECODER_MODE_RAM;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!endpoint) {
Jeff Moyer 2c91dc
+		log_err(&ml, "%s: CXL operation disabled\n", devname);
Jeff Moyer 2c91dc
+		return -ENXIO;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	port = cxl_endpoint_get_port(endpoint);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (mode == CXL_DECODER_MODE_RAM)
Jeff Moyer 2c91dc
+		avail_dpa = cxl_memdev_get_ram_size(memdev);
Jeff Moyer 2c91dc
+	else
Jeff Moyer 2c91dc
+		avail_dpa = cxl_memdev_get_pmem_size(memdev);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_decoder_foreach(port, decoder) {
Jeff Moyer 2c91dc
+		size = cxl_decoder_get_dpa_size(decoder);
Jeff Moyer 2c91dc
+		if (size == ULLONG_MAX)
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+		if (cxl_decoder_get_mode(decoder) != mode)
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (size > avail_dpa) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: capacity accounting error\n",
Jeff Moyer 2c91dc
+				devname);
Jeff Moyer 2c91dc
+			return -ENXIO;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+		avail_dpa -= size;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!param.size)
Jeff Moyer 2c91dc
+		if (alloc_mode == DPA_ALLOC) {
Jeff Moyer 2c91dc
+			size = avail_dpa;
Jeff Moyer 2c91dc
+			if (!avail_dpa) {
Jeff Moyer 2c91dc
+				log_err(&ml, "%s: no available capacity\n",
Jeff Moyer 2c91dc
+					devname);
Jeff Moyer 2c91dc
+				return -ENOSPC;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+		} else
Jeff Moyer 2c91dc
+			size = 0;
Jeff Moyer 2c91dc
+	else {
Jeff Moyer 2c91dc
+		size = parse_size64(param.size);
Jeff Moyer 2c91dc
+		if (size == ULLONG_MAX) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: failed to parse size option '%s'\n",
Jeff Moyer 2c91dc
+				devname, param.size);
Jeff Moyer 2c91dc
+			return -EINVAL;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+		if (size > avail_dpa) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: '%s' exceeds available capacity\n",
Jeff Moyer 2c91dc
+				devname, param.size);
Jeff Moyer 2c91dc
+			if (!param.force)
Jeff Moyer 2c91dc
+				return -ENOSPC;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	/*
Jeff Moyer 2c91dc
+	 * Find next free decoder, assumes cxl_decoder_foreach() is in
Jeff Moyer 2c91dc
+	 * hardware instance-id order
Jeff Moyer 2c91dc
+	 */
Jeff Moyer 2c91dc
+	if (alloc_mode == DPA_ALLOC)
Jeff Moyer 2c91dc
+		cxl_decoder_foreach(port, decoder) {
Jeff Moyer 2c91dc
+			/* first 0-dpa_size is our target */
Jeff Moyer 2c91dc
+			if (cxl_decoder_get_dpa_size(decoder) == 0) {
Jeff Moyer 2c91dc
+				auto_target = decoder;
Jeff Moyer 2c91dc
+				break;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	else
Jeff Moyer 2c91dc
+		cxl_decoder_foreach_reverse(port, decoder) {
Jeff Moyer 2c91dc
+			/* nothing to free? */
Jeff Moyer 2c91dc
+			if (!cxl_decoder_get_dpa_size(decoder))
Jeff Moyer 2c91dc
+				continue;
Jeff Moyer 2c91dc
+			/*
Jeff Moyer 2c91dc
+			 * Active decoders can't be freed, and by definition all
Jeff Moyer 2c91dc
+			 * previous decoders must also be active
Jeff Moyer 2c91dc
+			 */
Jeff Moyer 2c91dc
+			if (cxl_decoder_get_size(decoder))
Jeff Moyer 2c91dc
+				break;
Jeff Moyer 2c91dc
+			/* first dpa_size > 0 + disabled decoder is our target */
Jeff Moyer 2c91dc
+			if (cxl_decoder_get_dpa_size(decoder) < ULLONG_MAX) {
Jeff Moyer 2c91dc
+				auto_target = decoder;
Jeff Moyer 2c91dc
+				break;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (param.decoder_filter) {
Jeff Moyer 2c91dc
+		unsigned long id;
Jeff Moyer 2c91dc
+		char *end;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		id = strtoul(param.decoder_filter, &end, 0);
Jeff Moyer 2c91dc
+		/* allow for standalone ordinal decoder ids */
Jeff Moyer 2c91dc
+		if (*end == '\0')
Jeff Moyer 2c91dc
+			rc = snprintf(buf, sizeof(buf), "decoder%d.%ld",
Jeff Moyer 2c91dc
+				      cxl_port_get_id(port), id);
Jeff Moyer 2c91dc
+		else
Jeff Moyer 2c91dc
+			rc = snprintf(buf, sizeof(buf), "%s",
Jeff Moyer 2c91dc
+				      param.decoder_filter);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (rc >= (int)sizeof(buf)) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: decoder filter '%s' too long\n",
Jeff Moyer 2c91dc
+				devname, param.decoder_filter);
Jeff Moyer 2c91dc
+			return -EINVAL;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (alloc_mode == DPA_ALLOC)
Jeff Moyer 2c91dc
+			cxl_decoder_foreach(port, decoder) {
Jeff Moyer 2c91dc
+				target = util_cxl_decoder_filter(decoder, buf);
Jeff Moyer 2c91dc
+				if (target)
Jeff Moyer 2c91dc
+					break;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+		else
Jeff Moyer 2c91dc
+			cxl_decoder_foreach_reverse(port, decoder) {
Jeff Moyer 2c91dc
+				target = util_cxl_decoder_filter(decoder, buf);
Jeff Moyer 2c91dc
+				if (target)
Jeff Moyer 2c91dc
+					break;
Jeff Moyer 2c91dc
+			}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (!target) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: no match for decoder: '%s'\n",
Jeff Moyer 2c91dc
+				devname, param.decoder_filter);
Jeff Moyer 2c91dc
+			return -ENXIO;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (target != auto_target) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: %s is out of sequence\n", devname,
Jeff Moyer 2c91dc
+				cxl_decoder_get_devname(target));
Jeff Moyer 2c91dc
+			if (!param.force)
Jeff Moyer 2c91dc
+				return -EINVAL;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!target)
Jeff Moyer 2c91dc
+		target = auto_target;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!target) {
Jeff Moyer 2c91dc
+		log_err(&ml, "%s: no suitable decoder found\n", devname);
Jeff Moyer 2c91dc
+		return -ENXIO;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (cxl_decoder_get_mode(target) != mode) {
Jeff Moyer 2c91dc
+		rc = cxl_decoder_set_dpa_size(target, 0);
Jeff Moyer 2c91dc
+		if (rc) {
Jeff Moyer 2c91dc
+			log_err(&ml,
Jeff Moyer 2c91dc
+				"%s: %s: failed to clear allocation to set mode\n",
Jeff Moyer 2c91dc
+				devname, cxl_decoder_get_devname(target));
Jeff Moyer 2c91dc
+			return rc;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+		rc = cxl_decoder_set_mode(target, mode);
Jeff Moyer 2c91dc
+		if (rc) {
Jeff Moyer 2c91dc
+			log_err(&ml, "%s: %s: failed to set %s mode\n", devname,
Jeff Moyer 2c91dc
+				cxl_decoder_get_devname(target),
Jeff Moyer 2c91dc
+				mode == CXL_DECODER_MODE_PMEM ? "pmem" : "ram");
Jeff Moyer 2c91dc
+			return rc;
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	rc = cxl_decoder_set_dpa_size(target, size);
Jeff Moyer 2c91dc
+	if (rc)
Jeff Moyer 2c91dc
+		log_err(&ml, "%s: %s: failed to set dpa allocation\n", devname,
Jeff Moyer 2c91dc
+			cxl_decoder_get_devname(target));
Jeff Moyer 2c91dc
+	else {
Jeff Moyer 2c91dc
+		struct json_object *jdev, *jdecoder;
Jeff Moyer 2c91dc
+		unsigned long flags = 0;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		if (actx->f_out == stdout && isatty(1))
Jeff Moyer 2c91dc
+			flags |= UTIL_JSON_HUMAN;
Jeff Moyer 2c91dc
+		jdev = util_cxl_memdev_to_json(memdev, flags);
Jeff Moyer 2c91dc
+		jdecoder = util_cxl_decoder_to_json(target, flags);
Jeff Moyer 2c91dc
+		if (!jdev || !jdecoder) {
Jeff Moyer 2c91dc
+			json_object_put(jdev);
Jeff Moyer 2c91dc
+			json_object_put(jdecoder);
Jeff Moyer 2c91dc
+		} else {
Jeff Moyer 2c91dc
+			json_object_object_add(jdev, "decoder", jdecoder);
Jeff Moyer 2c91dc
+			json_object_array_add(actx->jdevs, jdev);
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+	return rc;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int action_reserve_dpa(struct cxl_memdev *memdev,
Jeff Moyer 2c91dc
+			      struct action_context *actx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	return __reserve_dpa(memdev, DPA_ALLOC, actx);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+static int action_free_dpa(struct cxl_memdev *memdev,
Jeff Moyer 2c91dc
+			   struct action_context *actx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	return __reserve_dpa(memdev, DPA_FREE, actx);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static int action_disable(struct cxl_memdev *memdev, struct action_context *actx)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	if (!cxl_memdev_is_enabled(memdev))
Jeff Moyer 2c91dc
@@ -452,7 +702,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
Jeff Moyer 2c91dc
 		err++;
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-	if (action == action_setpartition)
Jeff Moyer 2c91dc
+	if (action == action_setpartition || action == action_reserve_dpa ||
Jeff Moyer 2c91dc
+	    action == action_free_dpa)
Jeff Moyer 2c91dc
 		actx.jdevs = json_object_new_array();
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	if (err == argc) {
Jeff Moyer 2c91dc
@@ -495,6 +746,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
Jeff Moyer 2c91dc
 	count = 0;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	for (i = 0; i < argc; i++) {
Jeff Moyer 2c91dc
+		bool found = false;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 		cxl_memdev_foreach(ctx, memdev) {
Jeff Moyer 2c91dc
 			const char *memdev_filter = NULL;
Jeff Moyer 2c91dc
 			const char *serial_filter = NULL;
Jeff Moyer 2c91dc
@@ -507,6 +760,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
Jeff Moyer 2c91dc
 			if (!util_cxl_memdev_filter(memdev, memdev_filter,
Jeff Moyer 2c91dc
 						    serial_filter))
Jeff Moyer 2c91dc
 				continue;
Jeff Moyer 2c91dc
+			found = true;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 			if (action == action_write) {
Jeff Moyer 2c91dc
 				single = memdev;
Jeff Moyer 2c91dc
@@ -519,6 +773,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
Jeff Moyer 2c91dc
 			else if (rc && !err)
Jeff Moyer 2c91dc
 				err = rc;
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
+		if (!found)
Jeff Moyer 2c91dc
+			log_info(&ml, "no memdev matches %s\n", argv[i]);
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 	rc = err;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
@@ -622,3 +878,25 @@ int cmd_set_partition(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+int cmd_reserve_dpa(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	int count = memdev_action(
Jeff Moyer 2c91dc
+		argc, argv, ctx, action_reserve_dpa, reserve_dpa_options,
Jeff Moyer 2c91dc
+		"cxl reserve-dpa <mem0> [<mem1>..<memn>] [<options>]");
Jeff Moyer 2c91dc
+	log_info(&ml, "reservation completed on %d mem device%s\n",
Jeff Moyer 2c91dc
+		 count >= 0 ? count : 0, count > 1 ? "s" : "");
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+int cmd_free_dpa(int argc, const char **argv, struct cxl_ctx *ctx)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	int count = memdev_action(
Jeff Moyer 2c91dc
+		argc, argv, ctx, action_free_dpa, free_dpa_options,
Jeff Moyer 2c91dc
+		"cxl free-dpa <mem0> [<mem1>..<memn>] [<options>]");
Jeff Moyer 2c91dc
+	log_info(&ml, "reservation release completed on %d mem device%s\n",
Jeff Moyer 2c91dc
+		 count >= 0 ? count : 0, count > 1 ? "s" : "");
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return count >= 0 ? 0 : EXIT_FAILURE;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
-- 
Jeff Moyer 2c91dc
2.27.0
Jeff Moyer 2c91dc