summaryrefslogtreecommitdiff
path: root/drivers/acpi/arm64
diff options
context:
space:
mode:
authorHanjun Guo <hanjun.guo@linaro.org>2017-10-13 15:09:47 +0800
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2017-10-16 14:29:45 +0100
commit0a71d8b95f8adc343d986bf3093fc1baf59df4b1 (patch)
treee857218d7a5d9983c8467282a0f1951a0c4b0081 /drivers/acpi/arm64
parent896dd2c3248422e1e7711cc582615844e2f9de86 (diff)
ACPI/IORT: Look up IORT node through struct fwnode_handle pointer
Current IORT code provides a function (ie iort_get_fwnode()) which looks up a struct fwnode_handle pointer through a struct acpi_iort_node pointer for SMMU components but it lacks a function that implements the reverse look-up, namely struct fwnode_handle* -> struct acpi_iort_node*. Devices that are not IORT named components cannot be retrieved through their associated IORT named component scan interface because they just are not represented in the ACPI namespace; the reverse look-up is therefore required for all platform devices that represent IORT nodes (eg SMMUs) so that the struct acpi_iort_node* can be retrieved from the struct device->fwnode pointer. Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org> [lorenzo.pieralisi@arm.com: re-indented/rewrote the commit log] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Diffstat (limited to 'drivers/acpi/arm64')
-rw-r--r--drivers/acpi/arm64/iort.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index c395d6bf44d4..4ff57f2a0fd7 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -126,6 +126,31 @@ static inline void iort_delete_fwnode(struct acpi_iort_node *node)
spin_unlock(&iort_fwnode_lock);
}
+/**
+ * iort_get_iort_node() - Retrieve iort_node associated with an fwnode
+ *
+ * @fwnode: fwnode associated with device to be looked-up
+ *
+ * Returns: iort_node pointer on success, NULL on failure
+ */
+static inline struct acpi_iort_node *iort_get_iort_node(
+ struct fwnode_handle *fwnode)
+{
+ struct iort_fwnode *curr;
+ struct acpi_iort_node *iort_node = NULL;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ if (curr->fwnode == fwnode) {
+ iort_node = curr->iort_node;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+
+ return iort_node;
+}
+
typedef acpi_status (*iort_find_node_callback)
(struct acpi_iort_node *node, void *context);
@@ -422,9 +447,25 @@ static struct acpi_iort_node *iort_find_dev_node(struct device *dev)
{
struct pci_bus *pbus;
- if (!dev_is_pci(dev))
+ if (!dev_is_pci(dev)) {
+ struct acpi_iort_node *node;
+ /*
+ * scan iort_fwnode_list to see if it's an iort platform
+ * device (such as SMMU, PMCG),its iort node already cached
+ * and associated with fwnode when iort platform devices
+ * were initialized.
+ */
+ node = iort_get_iort_node(dev->fwnode);
+ if (node)
+ return node;
+
+ /*
+ * if not, then it should be a platform device defined in
+ * DSDT/SSDT (with Named Component node in IORT)
+ */
return iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
iort_match_node_callback, dev);
+ }
/* Find a PCI root bus */
pbus = to_pci_dev(dev)->bus;