Inter-revision diff: patch 19

Comparing v20 (message) to v23 (message)

--- v20
+++ v23
@@ -1,36 +1,205 @@
 From: Alejandro Lucero <alucerop@amd.com>
 
-By definition a type2 cxl device will use the host managed memory for
-specific functionality, therefore it should not be available to other
-uses.
+Creating a CXL region requires userspace intervention through the cxl
+sysfs files. Type2 support should allow accelerator drivers to create
+such cxl region from kernel code.
+
+Adding that functionality and integrating it with current support for
+memory expanders.
+
+Based on https://lore.kernel.org/linux-cxl/168592159835.1948938.1647215579839222774.stgit@dwillia2-xfh.jf.intel.com/
 
 Signed-off-by: Alejandro Lucero <alucerop@amd.com>
 Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-Reviewed-by: Davidlohr Bueso <daves@stgolabs.net>
 Reviewed-by: Dave Jiang <dave.jiang@intel.com>
-Reviewed-by: Ben Cheatham <benjamin.cheatham@amd.com>
 ---
- drivers/cxl/core/region.c | 7 +++++++
- 1 file changed, 7 insertions(+)
+ drivers/cxl/core/region.c | 131 ++++++++++++++++++++++++++++++++++++--
+ include/cxl/cxl.h         |   3 +
+ 2 files changed, 127 insertions(+), 7 deletions(-)
 
 diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
-index 63c9c5f92252..5ee40cb9d050 100644
+index 63c2aeb2ee1f..293e63dfef22 100644
 --- a/drivers/cxl/core/region.c
 +++ b/drivers/cxl/core/region.c
-@@ -4135,6 +4135,13 @@ static int cxl_region_probe(struct device *dev)
- 			return rc;
- 	}
- 
+@@ -2944,6 +2944,14 @@ cxl_find_region_by_name(struct cxl_root_decoder *cxlrd, const char *name)
+ 	return to_cxl_region(region_dev);
+ }
+ 
++static void drop_region(struct cxl_region *cxlr)
++{
++	struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent);
++	struct cxl_port *port = cxlrd_to_port(cxlrd);
++
++	devm_release_action(port->uport_dev, __unregister_region, cxlr);
++}
++
+ static ssize_t delete_region_store(struct device *dev,
+ 				   struct device_attribute *attr,
+ 				   const char *buf, size_t len)
+@@ -4047,14 +4055,12 @@ static int __construct_region(struct cxl_region *cxlr,
+ 	return 0;
+ }
+ 
+-/* Establish an empty region covering the given HPA range */
+-static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
+-					   struct cxl_endpoint_decoder *cxled)
++static struct cxl_region *construct_region_begin(struct cxl_root_decoder *cxlrd,
++						 struct cxl_endpoint_decoder *cxled)
+ {
+ 	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
+-	struct cxl_port *port = cxlrd_to_port(cxlrd);
+ 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
+-	int rc, part = READ_ONCE(cxled->part);
++	int part = READ_ONCE(cxled->part);
+ 	struct cxl_region *cxlr;
+ 
+ 	do {
+@@ -4063,13 +4069,26 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
+ 				       cxled->cxld.target_type);
+ 	} while (IS_ERR(cxlr) && PTR_ERR(cxlr) == -EBUSY);
+ 
+-	if (IS_ERR(cxlr)) {
++	if (IS_ERR(cxlr))
+ 		dev_err(cxlmd->dev.parent,
+ 			"%s:%s: %s failed assign region: %ld\n",
+ 			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
+ 			__func__, PTR_ERR(cxlr));
++
++	return cxlr;
++}
++
++/* Establish an empty region covering the given HPA range */
++static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
++					   struct cxl_endpoint_decoder *cxled)
++{
++	struct cxl_port *port = cxlrd_to_port(cxlrd);
++	struct cxl_region *cxlr;
++	int rc;
++
++	cxlr = construct_region_begin(cxlrd, cxled);
++	if (IS_ERR(cxlr))
+ 		return cxlr;
+-	}
+ 
+ 	rc = __construct_region(cxlr, cxlrd, cxled);
+ 	if (rc) {
+@@ -4080,6 +4099,104 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
+ 	return cxlr;
+ }
+ 
++DEFINE_FREE(cxl_region_drop, struct cxl_region *, if (_T) drop_region(_T))
++
++static struct cxl_region *
++__construct_new_region(struct cxl_root_decoder *cxlrd,
++		       struct cxl_endpoint_decoder **cxled, int ways)
++{
++	struct cxl_memdev *cxlmd = cxled_to_memdev(cxled[0]);
++	struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
++	struct cxl_region_params *p;
++	resource_size_t size = 0;
++	int rc, i;
++
++	struct cxl_region *cxlr __free(cxl_region_drop) =
++		construct_region_begin(cxlrd, cxled[0]);
++	if (IS_ERR(cxlr))
++		return cxlr;
++
++	guard(rwsem_write)(&cxl_rwsem.region);
++
 +	/*
-+	 * HDM-D[B] (device-memory) regions have accelerator specific usage.
-+	 * Skip device-dax registration.
++	 * Sanity check. This should not happen with an accel driver handling
++	 * the region creation.
 +	 */
-+	if (cxlr->type == CXL_DECODER_DEVMEM)
-+		return 0;
-+
- 	switch (cxlr->mode) {
- 	case CXL_PARTMODE_PMEM:
- 		rc = devm_cxl_region_edac_register(cxlr);
++	p = &cxlr->params;
++	if (p->state >= CXL_CONFIG_INTERLEAVE_ACTIVE) {
++		dev_err(cxlmd->dev.parent,
++			"%s:%s: %s  unexpected region state\n",
++			dev_name(&cxlmd->dev), dev_name(&cxled[0]->cxld.dev),
++			__func__);
++		return ERR_PTR(-EBUSY);
++	}
++
++	rc = set_interleave_ways(cxlr, ways);
++	if (rc)
++		return ERR_PTR(rc);
++
++	rc = set_interleave_granularity(cxlr, cxld->interleave_granularity);
++	if (rc)
++		return ERR_PTR(rc);
++
++	scoped_guard(rwsem_read, &cxl_rwsem.dpa) {
++		for (i = 0; i < ways; i++) {
++			if (!cxled[i]->dpa_res)
++				return ERR_PTR(-EINVAL);
++			size += resource_size(cxled[i]->dpa_res);
++		}
++
++		rc = alloc_hpa(cxlr, size);
++		if (rc)
++			return ERR_PTR(rc);
++
++		for (i = 0; i < ways; i++) {
++			rc = cxl_region_attach(cxlr, cxled[i], 0);
++			if (rc)
++				return ERR_PTR(rc);
++		}
++	}
++
++	rc = cxl_region_decode_commit(cxlr);
++	if (rc)
++		return ERR_PTR(rc);
++
++	p->state = CXL_CONFIG_COMMIT;
++
++	return no_free_ptr(cxlr);
++}
++
++/**
++ * cxl_create_region - Establish a region given an endpoint decoder
++ * @cxlrd: root decoder to allocate HPA
++ * @cxled: endpoint decoders with reserved DPA capacity
++ * @ways: interleave ways required
++ *
++ * Returns a fully formed region in the commit state and attached to the
++ * cxl_region driver.
++ */
++struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
++				     struct cxl_endpoint_decoder **cxled,
++				     int ways)
++{
++	struct cxl_region *cxlr;
++
++	mutex_lock(&cxlrd->range_lock);
++	cxlr = __construct_new_region(cxlrd, cxled, ways);
++	mutex_unlock(&cxlrd->range_lock);
++	if (IS_ERR(cxlr))
++		return cxlr;
++
++	if (device_attach(&cxlr->dev) <= 0) {
++		dev_err(&cxlr->dev, "failed to create region\n");
++		drop_region(cxlr);
++		return ERR_PTR(-ENODEV);
++	}
++
++	return cxlr;
++}
++EXPORT_SYMBOL_NS_GPL(cxl_create_region, "CXL");
++
+ static struct cxl_region *
+ cxl_find_region_by_range(struct cxl_root_decoder *cxlrd, struct range *hpa)
+ {
+diff --git a/include/cxl/cxl.h b/include/cxl/cxl.h
+index 4802371db00e..50acbd13bcf8 100644
+--- a/include/cxl/cxl.h
++++ b/include/cxl/cxl.h
+@@ -281,4 +281,7 @@ struct cxl_endpoint_decoder *cxl_request_dpa(struct cxl_memdev *cxlmd,
+ 					     enum cxl_partition_mode mode,
+ 					     resource_size_t alloc);
+ int cxl_dpa_free(struct cxl_endpoint_decoder *cxled);
++struct cxl_region *cxl_create_region(struct cxl_root_decoder *cxlrd,
++				     struct cxl_endpoint_decoder **cxled,
++				     int ways);
+ #endif /* __CXL_CXL_H__ */
 -- 
 2.34.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help