anitazha / rpms / ndctl

Forked from rpms/ndctl a year ago
Clone

Blame 0199-cxl-decoder-add-a-max_available_extent-attribute.patch

Jeff Moyer 2c91dc
From bf0c44e79c0db04b0c1eea884022dfbdc011b979 Mon Sep 17 00:00:00 2001
Jeff Moyer 2c91dc
From: Vishal Verma <vishal.l.verma@intel.com>
Jeff Moyer 2c91dc
Date: Mon, 15 Aug 2022 13:22:14 -0600
Jeff Moyer 2c91dc
Subject: [PATCH 199/217] cxl/decoder: add a max_available_extent attribute
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Add a max_available_extent attribute to cxl_decoder. In order to aid in
Jeff Moyer 2c91dc
its calculation, change the order of regions in the root decoder's list
Jeff Moyer 2c91dc
to be sorted by start HPA of the region.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Additionally, emit this attribute in decoder listings, and consult it
Jeff Moyer 2c91dc
for available space before creating a new region.
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
Link: https://lore.kernel.org/r/20220815192214.545800-12-vishal.l.verma@intel.com
Jeff Moyer 2c91dc
Cc: Dan Williams <dan.j.williams@intel.com>
Jeff Moyer 2c91dc
Reviewed-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
 cxl/json.c         |  8 +++++
Jeff Moyer 2c91dc
 cxl/lib/libcxl.c   | 84 +++++++++++++++++++++++++++++++++++++++++++++-
Jeff Moyer 2c91dc
 cxl/lib/libcxl.sym |  1 +
Jeff Moyer 2c91dc
 cxl/lib/private.h  |  1 +
Jeff Moyer 2c91dc
 cxl/libcxl.h       |  3 ++
Jeff Moyer 2c91dc
 cxl/region.c       | 14 +++++++-
Jeff Moyer 2c91dc
 6 files changed, 109 insertions(+), 2 deletions(-)
Jeff Moyer 2c91dc
Jeff Moyer 2c91dc
diff --git a/cxl/json.c b/cxl/json.c
Jeff Moyer 2c91dc
index 9dc99df..9cec58b 100644
Jeff Moyer 2c91dc
--- a/cxl/json.c
Jeff Moyer 2c91dc
+++ b/cxl/json.c
Jeff Moyer 2c91dc
@@ -499,6 +499,14 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder,
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	if (cxl_port_is_root(port) && cxl_decoder_is_mem_capable(decoder)) {
Jeff Moyer 2c91dc
+		size = cxl_decoder_get_max_available_extent(decoder);
Jeff Moyer 2c91dc
+		if (size < ULLONG_MAX) {
Jeff Moyer 2c91dc
+			jobj = util_json_object_size(size, flags);
Jeff Moyer 2c91dc
+			if (jobj)
Jeff Moyer 2c91dc
+				json_object_object_add(jdecoder,
Jeff Moyer 2c91dc
+						       "max_available_extent",
Jeff Moyer 2c91dc
+						       jobj);
Jeff Moyer 2c91dc
+		}
Jeff Moyer 2c91dc
 		if (cxl_decoder_is_pmem_capable(decoder)) {
Jeff Moyer 2c91dc
 			jobj = json_object_new_boolean(true);
Jeff Moyer 2c91dc
 			if (jobj)
Jeff Moyer 2c91dc
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
index fd2ea4f..c7dc2b0 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.c
Jeff Moyer 2c91dc
@@ -455,6 +455,16 @@ CXL_EXPORT int cxl_region_delete(struct cxl_region *region)
Jeff Moyer 2c91dc
 	return 0;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static int region_start_cmp(struct cxl_region *r1, struct cxl_region *r2)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	if (r1->start == r2->start)
Jeff Moyer 2c91dc
+		return 0;
Jeff Moyer 2c91dc
+	else if (r1->start < r2->start)
Jeff Moyer 2c91dc
+		return -1;
Jeff Moyer 2c91dc
+	else
Jeff Moyer 2c91dc
+		return 1;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static void *add_cxl_region(void *parent, int id, const char *cxlregion_base)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	const char *devname = devpath_to_devname(cxlregion_base);
Jeff Moyer 2c91dc
@@ -539,7 +549,7 @@ static void *add_cxl_region(void *parent, int id, const char *cxlregion_base)
Jeff Moyer 2c91dc
 			break;
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
-	list_add(&decoder->regions, &region->list);
Jeff Moyer 2c91dc
+	list_add_sorted(&decoder->regions, region, list, region_start_cmp);
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	return region;
Jeff Moyer 2c91dc
 err:
Jeff Moyer 2c91dc
@@ -1618,6 +1628,70 @@ cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint)
Jeff Moyer 2c91dc
 	return NULL;
Jeff Moyer 2c91dc
 }
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
+static bool cxl_region_is_configured(struct cxl_region *region)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	return region->size && (region->decode_state != CXL_DECODE_RESET);
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+/**
Jeff Moyer 2c91dc
+ * cxl_decoder_calc_max_available_extent() - calculate max available free space
Jeff Moyer 2c91dc
+ * @decoder - the root decoder to calculate the free extents for
Jeff Moyer 2c91dc
+ *
Jeff Moyer 2c91dc
+ * The add_cxl_region() function  adds regions to the parent decoder's list
Jeff Moyer 2c91dc
+ * sorted by the region's start HPAs. It can also be assumed that regions have
Jeff Moyer 2c91dc
+ * no overlapped / aliased HPA space. Therefore, calculating each extent is as
Jeff Moyer 2c91dc
+ * simple as walking the region list in order, and subtracting the previous
Jeff Moyer 2c91dc
+ * region's end HPA from the next region's start HPA (and taking into account
Jeff Moyer 2c91dc
+ * the decoder's start and end HPAs as well).
Jeff Moyer 2c91dc
+ */
Jeff Moyer 2c91dc
+static unsigned long long
Jeff Moyer 2c91dc
+cxl_decoder_calc_max_available_extent(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	u64 prev_end, decoder_end, cur_extent, max_extent = 0;
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
+	struct cxl_region *region;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	if (!cxl_port_is_root(port)) {
Jeff Moyer 2c91dc
+		err(ctx, "%s: not a root decoder\n",
Jeff Moyer 2c91dc
+		    cxl_decoder_get_devname(decoder));
Jeff Moyer 2c91dc
+		return ULLONG_MAX;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	/*
Jeff Moyer 2c91dc
+	 * Preload prev_end with an imaginary region that ends just before
Jeff Moyer 2c91dc
+	 * the decoder's start, so that the extent calculation for the
Jeff Moyer 2c91dc
+	 * first region Just Works
Jeff Moyer 2c91dc
+	 */
Jeff Moyer 2c91dc
+	prev_end = decoder->start - 1;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	cxl_region_foreach(decoder, region) {
Jeff Moyer 2c91dc
+		if (!cxl_region_is_configured(region))
Jeff Moyer 2c91dc
+			continue;
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+		/*
Jeff Moyer 2c91dc
+		 * region->start - prev_end would get the difference in
Jeff Moyer 2c91dc
+		 * addresses, but a difference of 1 in addresses implies
Jeff Moyer 2c91dc
+		 * an extent of 0. Hence the '-1'.
Jeff Moyer 2c91dc
+		 */
Jeff Moyer 2c91dc
+		cur_extent = region->start - prev_end - 1;
Jeff Moyer 2c91dc
+		max_extent = max(max_extent, cur_extent);
Jeff Moyer 2c91dc
+		prev_end = region->start + region->size - 1;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	/*
Jeff Moyer 2c91dc
+	 * Finally, consider the extent after the last region, up to the end
Jeff Moyer 2c91dc
+	 * of the decoder's address space, if any. If there were no regions,
Jeff Moyer 2c91dc
+	 * this simply reduces to decoder->size.
Jeff Moyer 2c91dc
+	 * Subtracting two addrs gets us a 'size' directly, no need for +/- 1.
Jeff Moyer 2c91dc
+	 */
Jeff Moyer 2c91dc
+	decoder_end = decoder->start + decoder->size - 1;
Jeff Moyer 2c91dc
+	cur_extent = decoder_end - prev_end;
Jeff Moyer 2c91dc
+	max_extent = max(max_extent, cur_extent);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
+	return max_extent;
Jeff Moyer 2c91dc
+}
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 static int decoder_id_cmp(struct cxl_decoder *d1, struct cxl_decoder *d2)
Jeff Moyer 2c91dc
 {
Jeff Moyer 2c91dc
 	return d1->id - d2->id;
Jeff Moyer 2c91dc
@@ -1748,6 +1822,8 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base)
Jeff Moyer 2c91dc
 			if (sysfs_read_attr(ctx, path, buf) == 0)
Jeff Moyer 2c91dc
 				*(flag->flag) = !!strtoul(buf, NULL, 0);
Jeff Moyer 2c91dc
 		}
Jeff Moyer 2c91dc
+		decoder->max_available_extent =
Jeff Moyer 2c91dc
+			cxl_decoder_calc_max_available_extent(decoder);
Jeff Moyer 2c91dc
 		break;
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
@@ -1912,6 +1988,12 @@ 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 unsigned long long
Jeff Moyer 2c91dc
+cxl_decoder_get_max_available_extent(struct cxl_decoder *decoder)
Jeff Moyer 2c91dc
+{
Jeff Moyer 2c91dc
+	return decoder->max_available_extent;
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
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
index cb23a0b..549f88d 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
+++ b/cxl/lib/libcxl.sym
Jeff Moyer 2c91dc
@@ -213,4 +213,5 @@ global:
Jeff Moyer 2c91dc
 	cxl_decoder_get_memdev;
Jeff Moyer 2c91dc
 	cxl_decoder_get_interleave_granularity;
Jeff Moyer 2c91dc
 	cxl_decoder_get_interleave_ways;
Jeff Moyer 2c91dc
+	cxl_decoder_get_max_available_extent;
Jeff Moyer 2c91dc
 } LIBCXL_2;
Jeff Moyer 2c91dc
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
Jeff Moyer 2c91dc
index 8bc9620..437eade 100644
Jeff Moyer 2c91dc
--- a/cxl/lib/private.h
Jeff Moyer 2c91dc
+++ b/cxl/lib/private.h
Jeff Moyer 2c91dc
@@ -104,6 +104,7 @@ struct cxl_decoder {
Jeff Moyer 2c91dc
 	u64 size;
Jeff Moyer 2c91dc
 	u64 dpa_resource;
Jeff Moyer 2c91dc
 	u64 dpa_size;
Jeff Moyer 2c91dc
+	u64 max_available_extent;
Jeff Moyer 2c91dc
 	void *dev_buf;
Jeff Moyer 2c91dc
 	size_t buf_len;
Jeff Moyer 2c91dc
 	char *dev_path;
Jeff Moyer 2c91dc
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
Jeff Moyer 2c91dc
index 69d9c09..61c7fc4 100644
Jeff Moyer 2c91dc
--- a/cxl/libcxl.h
Jeff Moyer 2c91dc
+++ b/cxl/libcxl.h
Jeff Moyer 2c91dc
@@ -134,6 +134,9 @@ 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
+unsigned long long
Jeff Moyer 2c91dc
+cxl_decoder_get_max_available_extent(struct cxl_decoder *decoder);
Jeff Moyer 2c91dc
+
Jeff Moyer 2c91dc
 enum cxl_decoder_mode {
Jeff Moyer 2c91dc
 	CXL_DECODER_MODE_NONE,
Jeff Moyer 2c91dc
 	CXL_DECODER_MODE_MIXED,
Jeff Moyer 2c91dc
diff --git a/cxl/region.c b/cxl/region.c
Jeff Moyer 2c91dc
index b22d3c8..a30313c 100644
Jeff Moyer 2c91dc
--- a/cxl/region.c
Jeff Moyer 2c91dc
+++ b/cxl/region.c
Jeff Moyer 2c91dc
@@ -438,9 +438,9 @@ static int create_region(struct cxl_ctx *ctx, int *count,
Jeff Moyer 2c91dc
 	struct json_object *jregion;
Jeff Moyer 2c91dc
 	unsigned int i, granularity;
Jeff Moyer 2c91dc
 	struct cxl_region *region;
Jeff Moyer 2c91dc
+	u64 size, max_extent;
Jeff Moyer 2c91dc
 	const char *devname;
Jeff Moyer 2c91dc
 	uuid_t uuid;
Jeff Moyer 2c91dc
-	u64 size;
Jeff Moyer 2c91dc
 	int rc;
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	rc = create_region_validate_config(ctx, p);
Jeff Moyer 2c91dc
@@ -455,6 +455,18 @@ static int create_region(struct cxl_ctx *ctx, int *count,
Jeff Moyer 2c91dc
 		log_err(&rl, "%s: unable to determine region size\n", __func__);
Jeff Moyer 2c91dc
 		return -ENXIO;
Jeff Moyer 2c91dc
 	}
Jeff Moyer 2c91dc
+	max_extent = cxl_decoder_get_max_available_extent(p->root_decoder);
Jeff Moyer 2c91dc
+	if (max_extent == ULLONG_MAX) {
Jeff Moyer 2c91dc
+		log_err(&rl, "%s: unable to determine max extent\n",
Jeff Moyer 2c91dc
+			cxl_decoder_get_devname(p->root_decoder));
Jeff Moyer 2c91dc
+		return -EINVAL;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
+	if (size > max_extent) {
Jeff Moyer 2c91dc
+		log_err(&rl,
Jeff Moyer 2c91dc
+			"%s: region size %#lx exceeds max available space\n",
Jeff Moyer 2c91dc
+			cxl_decoder_get_devname(p->root_decoder), size);
Jeff Moyer 2c91dc
+		return -ENOSPC;
Jeff Moyer 2c91dc
+	}
Jeff Moyer 2c91dc
 
Jeff Moyer 2c91dc
 	if (p->mode == CXL_DECODER_MODE_PMEM) {
Jeff Moyer 2c91dc
 		region = cxl_decoder_create_pmem_region(p->root_decoder);
Jeff Moyer 2c91dc
-- 
Jeff Moyer 2c91dc
2.27.0
Jeff Moyer 2c91dc