Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d22899a2 authored by Prakash Gupta's avatar Prakash Gupta
Browse files

iommu/arm-smmu: take ECATS lock before halting TBU



ECATS lock ensures that exclusive access to common ECATS HW access between
asynchronous execution environment.  We are halting the TBU before taking
the ECATS lock. This is not a pre requisite for ECATS lock.
Additionally, the current locking scheme can lead to the following error:

CB1-TBU_A-EL1              CB2-TBU_A-EL2
Halt TBU   -- success
ECATS lock -- success
                           Halt TBU -- success (CB1-TBU_A-EL1 Halt ACK)
                           ECATS lock -- fail
                           Resume TBU -- success
ECATS operations - Fail

To avoid above sequence, we need to take ECATS lock before halting the TBU.

Change-Id: Idb620131aba9ff6010823d9f79ac31a11459104c
Signed-off-by: default avatarPrakash Gupta <guptap@codeaurora.org>
parent 74d166b4
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -5568,10 +5568,15 @@ static phys_addr_t qsmmuv500_iova_to_phys(
	if (ret)
		return 0;

	ret = qsmmuv500_tbu_halt(tbu, smmu_domain);
	/* Only one concurrent atos operation */
	ret = qsmmuv500_ecats_lock(smmu_domain, tbu, &flags);
	if (ret)
		goto out_power_off;

	ret = qsmmuv500_tbu_halt(tbu, smmu_domain);
	if (ret)
		goto out_ecats_unlock;

	/*
	 * ECATS can trigger the fault interrupt, so disable it temporarily
	 * and check for an interrupt manually.
@@ -5599,11 +5604,6 @@ static phys_addr_t qsmmuv500_iova_to_phys(
				       ARM_SMMU_CB_RESUME);
	}

	/* Only one concurrent atos operation */
	ret = qsmmuv500_ecats_lock(smmu_domain, tbu, &flags);
	if (ret)
		goto out_resume;

redo:
	/* Set address and stream-id */
	val = readq_relaxed(tbu->base + DEBUG_SID_HALT_REG);
@@ -5683,11 +5683,11 @@ static phys_addr_t qsmmuv500_iova_to_phys(
		goto redo;

	writel_relaxed(sctlr_orig, cb_base + ARM_SMMU_CB_SCTLR);
	qsmmuv500_ecats_unlock(smmu_domain, tbu, &flags);

out_resume:
	qsmmuv500_tbu_resume(tbu);

out_ecats_unlock:
	qsmmuv500_ecats_unlock(smmu_domain, tbu, &flags);

out_power_off:
	/* Read to complete prior write transcations */
	val = readl_relaxed(tbu->base + DEBUG_SR_HALT_ACK_REG);