diff options
| author | Mitchel Humpherys <mitchelh@codeaurora.org> | 2014-12-04 11:46:24 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:11:27 -0700 |
| commit | 03ce410e94bd44cd7873fe3addf8842958a2d98e (patch) | |
| tree | f60226653440ff99e31cde9b6fd6664e88da008b | |
| parent | 57c6531afc90152ee3160f15ce31dff9f2bfcf1f (diff) | |
iommu/arm-smmu: only allow one ATOS operation at a time
Some hardware prohibits multiple ATOS commands from being issued
concurrently. Add a lock to avoid concurrent ATOS commands from being
issued.
Change-Id: Ie728464f8f03b3d60807a75b9e7c2b50ab62fa43
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e8f2a36fb5bc..e7fd50a00987 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -445,6 +445,8 @@ struct arm_smmu_device { struct arm_smmu_impl_def_reg *impl_def_attach_registers; unsigned int num_impl_def_attach_registers; + + spinlock_t atos_lock; }; struct arm_smmu_cfg { @@ -1848,7 +1850,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); - spin_lock_irqsave(&smmu_domain->lock, flags); + spin_lock_irqsave(&smmu->atos_lock, flags); if (smmu->version == 1) { u32 reg = iova & ~0xfff; @@ -1862,7 +1864,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp, !(tmp & ATSR_ACTIVE), 5, 50)) { - spin_unlock_irqrestore(&smmu_domain->lock, flags); + spin_unlock_irqrestore(&smmu->atos_lock, flags); dev_err(dev, "iova to phys timed out on 0x%pa. Falling back to software table walk.\n", &iova); @@ -1873,7 +1875,7 @@ 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); + spin_unlock_irqrestore(&smmu->atos_lock, flags); if (phys & CB_PAR_F) { dev_err(dev, "translation fault on %s!\n", dev_name(dev)); @@ -2411,6 +2413,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) } smmu->dev = dev; mutex_init(&smmu->attach_lock); + spin_lock_init(&smmu->atos_lock); of_id = of_match_node(arm_smmu_of_match, dev->of_node); smmu->version = (enum arm_smmu_arch_version)of_id->data; |
