@@ -1038,11 +1038,49 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
return ops;
}
+
+/**
+ * iort_iommu_update_fwnode - update fwnode of a PCI IOMMU
+ * @dev: the IOMMU device
+ * @fwnode: the fwnode, or NULL to remove an existing fwnode
+ *
+ * A PCI device isn't instantiated by the IORT driver. The IOMMU driver sets or
+ * removes its fwnode using this function.
+ */
+void iort_iommu_update_fwnode(struct device *dev, struct fwnode_handle *fwnode)
+{
+ struct pci_dev *pdev;
+ struct iort_fwnode *curr;
+ struct iort_pci_devid *devid;
+
+ if (!dev_is_pci(dev))
+ return;
+
+ pdev = to_pci_dev(dev);
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ devid = curr->pci_devid;
+ if (devid &&
+ pci_domain_nr(pdev->bus) == devid->segment &&
+ pdev->bus->number == devid->bus &&
+ pdev->devfn == devid->devfn) {
+ WARN_ON(fwnode && curr->fwnode);
+ curr->fwnode = fwnode;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+}
+EXPORT_SYMBOL_GPL(iort_iommu_update_fwnode);
#else
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
{ return 0; }
const struct iommu_ops *iort_iommu_configure(struct device *dev)
{ return NULL; }
+static void iort_iommu_update_fwnode(struct device *dev,
+ struct fwnode_handle *fwnode)
+{ }
#endif
static int nc_dma_get_range(struct device *dev, u64 *size)
@@ -43,6 +43,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
const struct iommu_ops *iort_iommu_configure(struct device *dev);
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head);
+void iort_iommu_update_fwnode(struct device *dev, struct fwnode_handle *fwnode);
#else
static void acpi_iort_register_table(struct acpi_table_header *table,
enum iort_table_source source)
@@ -63,6 +64,9 @@ static inline const struct iommu_ops *iort_iommu_configure(
static inline
int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
{ return 0; }
+static void iort_iommu_update_fwnode(struct device *dev,
+ struct fwnode_handle *fwnode)
+{ }
#endif
#endif /* __ACPI_IORT_H__ */
For a PCI-based IOMMU, IORT isn't in charge of allocating a fwnode. Let the IOMMU driver update the fwnode associated to an IORT node when available. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> --- drivers/acpi/iort.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/acpi_iort.h | 4 ++++ 2 files changed, 42 insertions(+)