|
@@ -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;
|