]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
cxl: Introduce callback for HPA address ranges translation
authorRobert Richter <rrichter@amd.com>
Wed, 14 Jan 2026 16:48:24 +0000 (17:48 +0100)
committerDave Jiang <dave.jiang@intel.com>
Tue, 3 Feb 2026 17:52:58 +0000 (10:52 -0700)
Introduce a callback to translate an endpoint's HPA range to the
address range of the root port which is the System Physical Address
(SPA) range used by a region. The callback can be set if a platform
needs to handle address translation.

The callback is attached to the root port. An endpoint's root port can
easily be determined in the PCI hierarchy without any CXL specific
knowledge. This allows the early use of address translation for CXL
enumeration. Address translation is esp. needed for the detection of
the root decoders. Thus, the callback is embedded in struct
cxl_root_ops instead of struct cxl_rd_ops.

Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Alison Schofield <alison.schofield@intel.com>
Tested-by: Gregory Price <gourry@gourry.net>
Signed-off-by: Robert Richter <rrichter@amd.com>
Link: https://patch.msgid.link/20260114164837.1076338-9-rrichter@amd.com
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
drivers/cxl/core/region.c
drivers/cxl/cxl.h

index 912796fd708e76e4c941df79ee12d2aac21e0036..ed8469fa55a906922b0d3ed21d5e69892ab5ea69 100644 (file)
@@ -3483,6 +3483,15 @@ static int match_root_decoder(struct device *dev, const void *data)
        return range_contains(r1, r2);
 }
 
+static int cxl_root_setup_translation(struct cxl_root *cxl_root,
+                                     struct cxl_region_context *ctx)
+{
+       if (!cxl_root->ops.translation_setup_root)
+               return 0;
+
+       return cxl_root->ops.translation_setup_root(cxl_root, ctx);
+}
+
 /*
  * Note, when finished with the device, drop the reference with
  * put_device() or use the put_cxl_root_decoder helper.
@@ -3495,6 +3504,21 @@ get_cxl_root_decoder(struct cxl_endpoint_decoder *cxled,
        struct cxl_port *port = cxled_to_port(cxled);
        struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port);
        struct device *cxlrd_dev;
+       int rc;
+
+       /*
+        * Adjust the endpoint's HPA range and interleaving
+        * configuration to the root decoder’s memory space before
+        * setting up the root decoder.
+        */
+       rc = cxl_root_setup_translation(cxl_root, ctx);
+       if (rc) {
+               dev_err(cxlmd->dev.parent,
+                       "%s:%s Failed to setup translation for address range %#llx:%#llx\n",
+                       dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev),
+                       ctx->hpa_range.start, ctx->hpa_range.end);
+               return ERR_PTR(rc);
+       }
 
        cxlrd_dev = device_find_child(&cxl_root->port.dev, &ctx->hpa_range,
                                      match_root_decoder);
index 0e15dc6e169f2fdeb2786b0e16b234b9d12a01a9..8ea334d81edfec0c2201bf99ac823bd08c9ce5bb 100644 (file)
@@ -652,6 +652,7 @@ struct cxl_root_ops {
        int (*qos_class)(struct cxl_root *cxl_root,
                         struct access_coordinate *coord, int entries,
                         int *qos_class);
+       int (*translation_setup_root)(struct cxl_root *cxl_root, void *data);
 };
 
 /**