aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>2019-04-17 14:24:42 -0400
committerWill Deacon <will.deacon@arm.com>2019-04-23 07:23:03 -0400
commit5702ee24182f9b3e33476b74b5c92a4f913ad9bd (patch)
tree0a12593d1c1fa1979364e43bba53bc383a298840
parentb9ae16d80a357c88fcb7ff6831cfdc196f0a34dd (diff)
ACPI/IORT: Check ATS capability in root complex nodes
Root complex node in IORT has a bit telling whether it supports ATS or not. Store this bit in the IOMMU fwspec when setting up a device, so it can be accessed later by an IOMMU driver. In the future we'll probably want to store this bit at the host bridge or SMMU rather than in each endpoint. Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--drivers/acpi/arm64/iort.c11
-rw-r--r--include/linux/iommu.h4
2 files changed, 15 insertions, 0 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e48894e002ba..4000902e57f0 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1028,6 +1028,14 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
1028 dev_dbg(dev, "dma_pfn_offset(%#08llx)\n", offset); 1028 dev_dbg(dev, "dma_pfn_offset(%#08llx)\n", offset);
1029} 1029}
1030 1030
1031static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)
1032{
1033 struct acpi_iort_root_complex *pci_rc;
1034
1035 pci_rc = (struct acpi_iort_root_complex *)node->node_data;
1036 return pci_rc->ats_attribute & ACPI_IORT_ATS_SUPPORTED;
1037}
1038
1031/** 1039/**
1032 * iort_iommu_configure - Set-up IOMMU configuration for a device. 1040 * iort_iommu_configure - Set-up IOMMU configuration for a device.
1033 * 1041 *
@@ -1063,6 +1071,9 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
1063 info.node = node; 1071 info.node = node;
1064 err = pci_for_each_dma_alias(to_pci_dev(dev), 1072 err = pci_for_each_dma_alias(to_pci_dev(dev),
1065 iort_pci_iommu_init, &info); 1073 iort_pci_iommu_init, &info);
1074
1075 if (!err && iort_pci_rc_supports_ats(node))
1076 dev->iommu_fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
1066 } else { 1077 } else {
1067 int i = 0; 1078 int i = 0;
1068 1079
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index ffbbc7e39cee..6c1b4c900191 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -392,10 +392,14 @@ struct iommu_fwspec {
392 const struct iommu_ops *ops; 392 const struct iommu_ops *ops;
393 struct fwnode_handle *iommu_fwnode; 393 struct fwnode_handle *iommu_fwnode;
394 void *iommu_priv; 394 void *iommu_priv;
395 u32 flags;
395 unsigned int num_ids; 396 unsigned int num_ids;
396 u32 ids[1]; 397 u32 ids[1];
397}; 398};
398 399
400/* ATS is supported */
401#define IOMMU_FWSPEC_PCI_RC_ATS (1 << 0)
402
399int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, 403int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
400 const struct iommu_ops *ops); 404 const struct iommu_ops *ops);
401void iommu_fwspec_free(struct device *dev); 405void iommu_fwspec_free(struct device *dev);