iommu/arm-smmu: Fix ATS1* register writes
The ATS1* address translation registers only support being written atomically - in SMMUv2 where they are 64 bits wide, 32-bit writes to the lower half are automatically zero-extended, whilst 32-bit writes to the upper half are ignored. Thus, the current logic of performing 64-bit writes as two 32-bit accesses is wrong. Since we already limit IOVAs to 32 bits on 32-bit ARM, the lack of a suitable writeq() implementation there is not an issue, and we only need a little preprocessor ugliness to safely hide the 64-bit case. Change-Id: Ice82b1276d30605d335f9400f8cc3da3e3348bb6 Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Joerg Roedel <jroedel@suse.de> [pdaly@codeaurora.org Resolve minor conflicts]
This commit is contained in:
parent
4efda8dbdd
commit
590f6b97ce
1 changed files with 9 additions and 6 deletions
|
@ -216,8 +216,7 @@
|
|||
#define ARM_SMMU_CB_TLBSYNC 0x7f0
|
||||
#define ARM_SMMU_CB_TLBSTATUS 0x7f4
|
||||
#define TLBSTATUS_SACTIVE (1 << 0)
|
||||
#define ARM_SMMU_CB_ATS1PR_LO 0x800
|
||||
#define ARM_SMMU_CB_ATS1PR_HI 0x804
|
||||
#define ARM_SMMU_CB_ATS1PR 0x800
|
||||
#define ARM_SMMU_CB_ATSR 0x8f0
|
||||
#define ARM_SMMU_GR1_CBFRSYNRA(n) (0x400 + ((n) << 2))
|
||||
|
||||
|
@ -2409,6 +2408,7 @@ static phys_addr_t __arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
|
|||
void __iomem *cb_base;
|
||||
u32 tmp;
|
||||
u64 phys;
|
||||
unsigned long va;
|
||||
unsigned long flags;
|
||||
|
||||
if (arm_smmu_enable_clocks(smmu))
|
||||
|
@ -2421,11 +2421,14 @@ static phys_addr_t __arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
|
|||
if (do_halt && arm_smmu_halt(smmu))
|
||||
goto err_unlock;
|
||||
|
||||
if (smmu->version == 1)
|
||||
writel_relaxed(iova & ~0xfff, cb_base + ARM_SMMU_CB_ATS1PR_LO);
|
||||
/* ATS1 registers can only be written atomically */
|
||||
va = iova & ~0xfffUL;
|
||||
#ifdef CONFIG_64BIT
|
||||
if (smmu->version == ARM_SMMU_V2)
|
||||
writeq_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR);
|
||||
else
|
||||
writeq_relaxed(iova & ~0xfffULL,
|
||||
cb_base + ARM_SMMU_CB_ATS1PR_LO);
|
||||
#endif
|
||||
writel_relaxed(va, cb_base + ARM_SMMU_CB_ATS1PR);
|
||||
|
||||
if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,
|
||||
!(tmp & ATSR_ACTIVE), 5, 50)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue