@@ -2,6 +2,7 @@
/* Copyright(c) 2020 Intel Corporation. All rights reserved. */
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/workqueue.h>
+#include <linux/genalloc.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -503,6 +504,59 @@ struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_port, CXL);
+static int *gen_pool_vcookie;
+static int *gen_pool_pcookie;
+
+struct cxl_port *devm_cxl_add_endpoint_port(struct device *host,
+ struct device *uport,
+ resource_size_t component_reg_phys,
+ u64 capacity, u64 pmem_offset,
+ struct cxl_port *parent_port)
+{
+ int rc;
+ struct cxl_port *ep =
+ devm_cxl_add_port(host, uport, component_reg_phys, parent_port);
+ if (IS_ERR(ep) || !capacity)
+ return ep;
+
+ ep->media = devm_gen_pool_create(&ep->dev, ilog2(SZ_256M), NUMA_NO_NODE, NULL);
+ if (IS_ERR(ep->media)) {
+ ep = ERR_CAST(ep->media);
+ goto err_out;
+ }
+
+ if (pmem_offset) {
+ rc = gen_pool_add_owner(ep->media, 0, -1, pmem_offset,
+ NUMA_NO_NODE, &gen_pool_vcookie);
+ if (rc) {
+ ep = ERR_PTR(rc);
+ goto err_out;
+ }
+ dev_dbg(&ep->dev, "Created volatile capacity pool: %zx\n",
+ gen_pool_avail(ep->media));
+ }
+
+ if (pmem_offset < capacity) {
+ rc = gen_pool_add_owner(ep->media, pmem_offset, -1,
+ capacity - pmem_offset, NUMA_NO_NODE,
+ &gen_pool_pcookie);
+ if (rc) {
+ ep = ERR_PTR(rc);
+ goto err_out;
+ }
+ dev_dbg(&ep->dev, "Created persistent capacity pool: %zx\n",
+ gen_pool_avail(ep->media));
+ }
+
+ return ep;
+
+err_out:
+ dev_err(&ep->dev, "Failed to allocated gen pools\n");
+ put_device(&ep->dev);
+ return ep;
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_endpoint_port, CXL);
+
struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port)
{
/* There is no pci_bus associated with a CXL platform-root port */
@@ -330,6 +330,7 @@ struct cxl_nvdimm {
* @component_reg_phys: component register capability base address (optional)
* @dead: last ep has been removed, force port re-creation
* @depth: How deep this port is relative to the root. depth 0 is the root.
+ * @media: Media's address space (endpoint only)
*/
struct cxl_port {
struct device dev;
@@ -341,6 +342,7 @@ struct cxl_port {
resource_size_t component_reg_phys;
bool dead;
unsigned int depth;
+ struct gen_pool *media;
};
/**
@@ -389,6 +391,11 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port);
struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
resource_size_t component_reg_phys,
struct cxl_port *parent_port);
+struct cxl_port *devm_cxl_add_endpoint_port(struct device *host,
+ struct device *uport,
+ resource_size_t component_reg_phys,
+ u64 capacity, u64 pmem_offset,
+ struct cxl_port *parent_port);
struct cxl_port *find_cxl_root(struct device *dev);
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
int cxl_bus_rescan(void);
@@ -50,9 +50,12 @@ static int create_endpoint(struct cxl_memdev *cxlmd,
{
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_port *endpoint;
+ u64 partition = range_len(&cxlds->ram_range);
+ u64 size = range_len(&cxlds->ram_range) + range_len(&cxlds->pmem_range);
- endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
- cxlds->component_reg_phys, parent_port);
+ endpoint = devm_cxl_add_endpoint_port(&parent_port->dev, &cxlmd->dev,
+ cxlds->component_reg_phys, size,
+ partition, parent_port);
if (IS_ERR(endpoint))
return PTR_ERR(endpoint);
CXL Type 2 and 3 endpoints may contain Host-managed Device Memory (HDM). This memory can be either volatile, persistent, or some combination of both. Similar to the root decoder the port's resources can be considered the host memory of which decoders allocate out of. Unlike the root decoder resource, device resources are in the device physical address space domain. Signed-off-by: Ben Widawsky <ben.widawsky@intel.com> --- drivers/cxl/core/port.c | 54 +++++++++++++++++++++++++++++++++++++++++ drivers/cxl/cxl.h | 7 ++++++ drivers/cxl/mem.c | 7 ++++-- 3 files changed, 66 insertions(+), 2 deletions(-)