summaryrefslogtreecommitdiff
path: root/drivers/cxl/acpi.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2021-06-09 19:01:46 +0300
committerDan Williams <dan.j.williams@intel.com>2021-06-10 04:02:39 +0300
commit7d4b5ca2e2cb5d28db628ec79c706bcfa832feea (patch)
tree833b93b5d980d417f1bac66dff19607dbb15c409 /drivers/cxl/acpi.c
parent3feaa2d35880de935fc0d02acf808f355564f4e6 (diff)
downloadlinux-7d4b5ca2e2cb5d28db628ec79c706bcfa832feea.tar.xz
cxl/acpi: Add downstream port data to cxl_port instances
In preparation for infrastructure that enumerates and configures the CXL decode mechanism of an upstream port to its downstream ports, add a representation of a CXL downstream port. On ACPI systems the top-most logical downstream ports in the hierarchy are the host bridges (ACPI0016 devices) that decode the memory windows described by the CXL Early Discovery Table Fixed Memory Window Structures (CEDT.CFMWS). Reviewed-by: Alison Schofield <alison.schofield@intel.com> Link: https://lore.kernel.org/r/162325450624.2293126.3533006409920271718.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/cxl/acpi.c')
-rw-r--r--drivers/cxl/acpi.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index 556d25ab6966..5eb9543c587a 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -7,17 +7,58 @@
#include <linux/acpi.h>
#include "cxl.h"
+static struct acpi_device *to_cxl_host_bridge(struct device *dev)
+{
+ struct acpi_device *adev = to_acpi_device(dev);
+
+ if (strcmp(acpi_device_hid(adev), "ACPI0016") == 0)
+ return adev;
+ return NULL;
+}
+
+static int add_host_bridge_dport(struct device *match, void *arg)
+{
+ int rc;
+ acpi_status status;
+ unsigned long long uid;
+ struct cxl_port *root_port = arg;
+ struct device *host = root_port->dev.parent;
+ struct acpi_device *bridge = to_cxl_host_bridge(match);
+
+ if (!bridge)
+ return 0;
+
+ status = acpi_evaluate_integer(bridge->handle, METHOD_NAME__UID, NULL,
+ &uid);
+ if (status != AE_OK) {
+ dev_err(host, "unable to retrieve _UID of %s\n",
+ dev_name(match));
+ return -ENODEV;
+ }
+
+ rc = cxl_add_dport(root_port, match, uid, CXL_RESOURCE_NONE);
+ if (rc) {
+ dev_err(host, "failed to add downstream port: %s\n",
+ dev_name(match));
+ return rc;
+ }
+ dev_dbg(host, "add dport%llu: %s\n", uid, dev_name(match));
+ return 0;
+}
+
static int cxl_acpi_probe(struct platform_device *pdev)
{
struct cxl_port *root_port;
struct device *host = &pdev->dev;
+ struct acpi_device *adev = ACPI_COMPANION(host);
root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL);
if (IS_ERR(root_port))
return PTR_ERR(root_port);
dev_dbg(host, "add: %s\n", dev_name(&root_port->dev));
- return 0;
+ return bus_for_each_dev(adev->dev.bus, NULL, root_port,
+ add_host_bridge_dport);
}
static const struct acpi_device_id cxl_acpi_ids[] = {