aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2016-04-20 09:53:32 -0400
committerJoerg Roedel <jroedel@suse.de>2016-04-21 10:47:32 -0400
commit5f634956cc550768ebd75cf26fdba01044bc600e (patch)
tree7464458fbf8fb11cc5d866df61d4ac7415a46491 /drivers/iommu/arm-smmu.c
parente3156048346c28c695f5cf9db67a8cf88c90f947 (diff)
iommu/arm-smmu: Fix stream-match conflict with IOMMU_DOMAIN_DMA
Commit cbf8277ef456 ("iommu/arm-smmu: Treat IOMMU_DOMAIN_DMA as bypass for now") ignores requests to attach a device to the default domain since, without IOMMU-basked DMA ops available everywhere, the default domain will just lead to unexpected transaction faults being reported. Unfortunately, the way this was implemented on SMMUv2 causes a regression with VFIO PCI device passthrough under KVM on AMD Seattle. On this system, the host controller device is associated with both a pci_dev *and* a platform_device, and can therefore end up with duplicate SMR entries, resulting in a stream-match conflict at runtime. This patch amends the original fix so that attaching to IOMMU_DOMAIN_DMA is rejected even before configuring the SMRs. This restores the old behaviour for now, but we'll need to look at handing host controllers specially when we come to supporting the default domain fully. Reported-by: Eric Auger <eric.auger@linaro.org> Tested-by: Eric Auger <eric.auger@linaro.org> Tested-by: Yang Shi <yang.shi@linaro.org> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 2409e3bd3df2..5158febd889d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1089,18 +1089,20 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1089 struct arm_smmu_device *smmu = smmu_domain->smmu; 1089 struct arm_smmu_device *smmu = smmu_domain->smmu;
1090 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1090 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1091 1091
1092 /* Devices in an IOMMU group may already be configured */
1093 ret = arm_smmu_master_configure_smrs(smmu, cfg);
1094 if (ret)
1095 return ret == -EEXIST ? 0 : ret;
1096
1097 /* 1092 /*
1098 * FIXME: This won't be needed once we have IOMMU-backed DMA ops 1093 * FIXME: This won't be needed once we have IOMMU-backed DMA ops
1099 * for all devices behind the SMMU. 1094 * for all devices behind the SMMU. Note that we need to take
1095 * care configuring SMRs for devices both a platform_device and
1096 * and a PCI device (i.e. a PCI host controller)
1100 */ 1097 */
1101 if (smmu_domain->domain.type == IOMMU_DOMAIN_DMA) 1098 if (smmu_domain->domain.type == IOMMU_DOMAIN_DMA)
1102 return 0; 1099 return 0;
1103 1100
1101 /* Devices in an IOMMU group may already be configured */
1102 ret = arm_smmu_master_configure_smrs(smmu, cfg);
1103 if (ret)
1104 return ret == -EEXIST ? 0 : ret;
1105
1104 for (i = 0; i < cfg->num_streamids; ++i) { 1106 for (i = 0; i < cfg->num_streamids; ++i) {
1105 u32 idx, s2cr; 1107 u32 idx, s2cr;
1106 1108