cxl/core: Define a 'struct cxl_endpoint_decoder'
authorDan Williams <dan.j.williams@intel.com>
Sat, 21 May 2022 23:24:14 +0000 (16:24 -0700)
committerDan Williams <dan.j.williams@intel.com>
Thu, 21 Jul 2022 15:41:20 +0000 (08:41 -0700)
Previously the target routing specifics of switch decoders and platform
CXL window resource tracking of root decoders were factored out of
'struct cxl_decoder'. While switch decoders translate from SPA to
downstream ports, endpoint decoders translate from SPA to DPA.

This patch, 3 of 3, adds a 'struct cxl_endpoint_decoder' that tracks an
endpoint-specific Device Physical Address (DPA) resource. For now this
just defines ->dpa_res, a follow-on patch will handle requesting DPA
resource ranges from a device-DPA resource tree.

Co-developed-by: Ben Widawsky <bwidawsk@kernel.org>
Signed-off-by: Ben Widawsky <bwidawsk@kernel.org>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/165784327088.1758207.15502834501671201192.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/hdm.c
drivers/cxl/core/port.c
drivers/cxl/cxl.h
tools/testing/cxl/test/cxl.c

index 2f10d42..650363d 100644 (file)
@@ -256,12 +256,15 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
                struct cxl_decoder *cxld;
 
                if (is_cxl_endpoint(port)) {
-                       cxld = cxl_endpoint_decoder_alloc(port);
-                       if (IS_ERR(cxld)) {
+                       struct cxl_endpoint_decoder *cxled;
+
+                       cxled = cxl_endpoint_decoder_alloc(port);
+                       if (IS_ERR(cxled)) {
                                dev_warn(&port->dev,
                                         "Failed to allocate the decoder\n");
-                               return PTR_ERR(cxld);
+                               return PTR_ERR(cxled);
                        }
+                       cxld = &cxled->cxld;
                } else {
                        struct cxl_switch_decoder *cxlsd;
 
index 972bca7..2cfa870 100644 (file)
@@ -244,12 +244,12 @@ static void __cxl_decoder_release(struct cxl_decoder *cxld)
        put_device(&port->dev);
 }
 
-static void cxl_decoder_release(struct device *dev)
+static void cxl_endpoint_decoder_release(struct device *dev)
 {
-       struct cxl_decoder *cxld = to_cxl_decoder(dev);
+       struct cxl_endpoint_decoder *cxled = to_cxl_endpoint_decoder(dev);
 
-       __cxl_decoder_release(cxld);
-       kfree(cxld);
+       __cxl_decoder_release(&cxled->cxld);
+       kfree(cxled);
 }
 
 static void cxl_switch_decoder_release(struct device *dev)
@@ -279,7 +279,7 @@ static void cxl_root_decoder_release(struct device *dev)
 
 static const struct device_type cxl_decoder_endpoint_type = {
        .name = "cxl_decoder_endpoint",
-       .release = cxl_decoder_release,
+       .release = cxl_endpoint_decoder_release,
        .groups = cxl_decoder_endpoint_attribute_groups,
 };
 
@@ -321,6 +321,15 @@ struct cxl_decoder *to_cxl_decoder(struct device *dev)
 }
 EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, CXL);
 
+struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev)
+{
+       if (dev_WARN_ONCE(dev, !is_endpoint_decoder(dev),
+                         "not a cxl_endpoint_decoder device\n"))
+               return NULL;
+       return container_of(dev, struct cxl_endpoint_decoder, cxld.dev);
+}
+EXPORT_SYMBOL_NS_GPL(to_cxl_endpoint_decoder, CXL);
+
 static struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
 {
        if (dev_WARN_ONCE(dev, !is_switch_decoder(dev),
@@ -1360,26 +1369,28 @@ EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL);
  *
  * Return: A new cxl decoder to be registered by cxl_decoder_add()
  */
-struct cxl_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port)
+struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port)
 {
+       struct cxl_endpoint_decoder *cxled;
        struct cxl_decoder *cxld;
        int rc;
 
        if (!is_cxl_endpoint(port))
                return ERR_PTR(-EINVAL);
 
-       cxld = kzalloc(sizeof(*cxld), GFP_KERNEL);
-       if (!cxld)
+       cxled = kzalloc(sizeof(*cxled), GFP_KERNEL);
+       if (!cxled)
                return ERR_PTR(-ENOMEM);
 
+       cxld = &cxled->cxld;
        rc = cxl_decoder_init(port, cxld);
        if (rc)  {
-               kfree(cxld);
+               kfree(cxled);
                return ERR_PTR(rc);
        }
 
        cxld->dev.type = &cxl_decoder_endpoint_type;
-       return cxld;
+       return cxled;
 }
 EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_alloc, CXL);
 
index e05a3e6..e0b1e2e 100644 (file)
@@ -240,6 +240,18 @@ struct cxl_decoder {
 };
 
 /**
+ * struct cxl_endpoint_decoder - Endpoint  / SPA to DPA decoder
+ * @cxld: base cxl_decoder_object
+ * @dpa_res: actively claimed DPA span of this decoder
+ * @skip: offset into @dpa_res where @cxld.hpa_range maps
+ */
+struct cxl_endpoint_decoder {
+       struct cxl_decoder cxld;
+       struct resource *dpa_res;
+       resource_size_t skip;
+};
+
+/**
  * struct cxl_switch_decoder - Switch specific CXL HDM Decoder
  * @cxld: base cxl_decoder object
  * @target_lock: coordinate coherent reads of the target list
@@ -394,6 +406,7 @@ struct cxl_dport *cxl_find_dport_by_dev(struct cxl_port *port,
 
 struct cxl_decoder *to_cxl_decoder(struct device *dev);
 struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
+struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
 bool is_root_decoder(struct device *dev);
 bool is_endpoint_decoder(struct device *dev);
 struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
@@ -401,7 +414,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
 struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
                                                    unsigned int nr_targets);
 int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);
-struct cxl_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port);
+struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port);
 int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map);
 int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld);
 int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint);
index 7991ddc..4dad0fa 100644 (file)
@@ -462,12 +462,16 @@ static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm)
                        }
                        cxld = &cxlsd->cxld;
                } else {
-                       cxld = cxl_endpoint_decoder_alloc(port);
-                       if (IS_ERR(cxld)) {
+                       struct cxl_endpoint_decoder *cxled;
+
+                       cxled = cxl_endpoint_decoder_alloc(port);
+
+                       if (IS_ERR(cxled)) {
                                dev_warn(&port->dev,
                                         "Failed to allocate the decoder\n");
-                               return PTR_ERR(cxld);
+                               return PTR_ERR(cxled);
                        }
+                       cxld = &cxled->cxld;
                }
 
                cxld->hpa_range = (struct range) {