diff options
| author | Mitchel Humpherys <mitchelh@codeaurora.org> | 2014-09-30 16:15:45 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:11:14 -0700 |
| commit | c52f08085e88a299219cce1476bc38665158fe1b (patch) | |
| tree | 9eb124c1e835216c651a66975991c25730a90c74 | |
| parent | 5ce5498b6628697d34349d063951f2b9e90e69e4 (diff) | |
iommu/arm-smmu: lock the domain during ATOS
Currently there could be races between different domains performing an
ATOS operation. Fix this by taking the domain lock around the ATOS.
Change-Id: I32e6e0a0c67ce82aff5abfc892098c684d399b2d
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index c49a10c27dc6..4fbdda71c987 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -246,7 +246,6 @@ #define ARM_SMMU_CB_ATS1PR_LO 0x800 #define ARM_SMMU_CB_ATS1PR_HI 0x804 #define ARM_SMMU_CB_ATSR 0x8f0 -#define ATSR_LOOP_TIMEOUT 1000000 /* 1s! */ #define SCTLR_S1_ASIDPNE (1 << 12) #define SCTLR_CFCFG (1 << 7) @@ -1817,11 +1816,14 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, void __iomem *cb_base; u32 tmp; u64 phys; + unsigned long flags; arm_smmu_enable_clocks(smmu); cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); + spin_lock_irqsave(&smmu_domain->lock, flags); + if (smmu->version == 1) { u32 reg = iova & ~0xfff; writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO); @@ -1832,8 +1834,9 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_HI); } - if (readl_poll_timeout(cb_base + ARM_SMMU_CB_ATSR, tmp, - !(tmp & ATSR_ACTIVE), 10, ATSR_LOOP_TIMEOUT)) { + if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp, + !(tmp & ATSR_ACTIVE), 10, 5)) { + spin_unlock_irqrestore(&smmu_domain->lock, flags); dev_err(dev, "iova to phys timed out on 0x%pa for %s. Falling back to software table walk.\n", &iova, dev_name(dev)); @@ -1844,6 +1847,8 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, phys = readl_relaxed(cb_base + ARM_SMMU_CB_PAR_LO); phys |= ((u64) readl_relaxed(cb_base + ARM_SMMU_CB_PAR_HI)) << 32; + spin_unlock_irqrestore(&smmu_domain->lock, flags); + if (phys & CB_PAR_F) { dev_err(dev, "translation fault on %s!\n", dev_name(dev)); dev_err(dev, "PAR = 0x%llx\n", phys); |
