diff options
| author | Mitchel Humpherys <mitchelh@codeaurora.org> | 2015-03-13 16:55:23 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-22 11:11:46 -0700 |
| commit | 7ed677cb8e6aa1dbb41bb6e4967de6c0b1afc8f2 (patch) | |
| tree | a08a18aa6e2c34409dec8b85c3b6f4a611715c5e | |
| parent | 9c66ec14770fd39646f63d887607c7d56a126f94 (diff) | |
iommu/arm-smmu: convert atos spinlock to a mutex
Because of a hardware errata, arm_smmu_iova_to_phys_hard will soon be
making a TZ call to do a workaround. However, we're currently using a
spinlock to ensure atomicity of ATOS due to another hardware errata, but
scm_call is a sleeping function, so this results in a sleeping BUG. Fix
this by making the atos lock a mutex instead of a spinlock.
This isn't exactly correct since iommu_iova_to_phys itself might be
called from atomic context, so we really shouldn't be taking a mutex.
However, we don't seem to have any use cases where it will be called
from atomic context, but we should revert all of this and go back to a
spinlock as soon as this hardware errata goes away (which will happen
when Thulium v1 dies).
Change-Id: I61ea37bb3e6989fe5db43c4e828fc6473885db1e
Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 9389e1e8f531..55348bafa988 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -463,7 +463,7 @@ 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 mutex atos_lock; }; struct arm_smmu_cfg { @@ -1948,7 +1948,6 @@ 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; bool need_halt_and_tlb = smmu->options & ARM_SMMU_OPT_HALT_AND_TLB_ON_ATOS; @@ -1956,7 +1955,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->atos_lock, flags); + mutex_lock(&smmu->atos_lock); if (need_halt_and_tlb) { if (arm_smmu_halt(smmu)) @@ -1985,7 +1984,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, if (need_halt_and_tlb) arm_smmu_resume(smmu); - spin_unlock_irqrestore(&smmu->atos_lock, flags); + mutex_unlock(&smmu->atos_lock); if (phys & CB_PAR_F) { dev_err(dev, "translation fault on %s!\n", dev_name(dev)); @@ -2002,7 +2001,7 @@ err_resume: if (need_halt_and_tlb) arm_smmu_resume(smmu); err_unlock: - spin_unlock_irqrestore(&smmu->atos_lock, flags); + mutex_unlock(&smmu->atos_lock); arm_smmu_disable_clocks(smmu); phys = arm_smmu_iova_to_phys_soft(domain, iova); dev_err(dev, @@ -2549,7 +2548,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); + mutex_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; |
