mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-14 16:46:15 -04:00
iommu/arm-smmu: fix out of bound iova fault handling
qsmmuv500_iova_to_phys checks for out of bound iova and skips ECATS operations. While this is optimal, this also skips resuming stalled CB. As part of S1 context fault handling iova_to_phys is followed by tlb invalidation and sync. With context bank in stall state, the sync operation will timeout. Example: arm-smmu: FAR = 0x000102325429beb4 arm-smmu: PAR = 0x0000000000000000 arm-smmu: FSR = 0x40000402 [TF R SS ] arm-smmu: ECATS: address out of bounds: 0x000102325429beb4 arm-smmu: ECATS: address out of bounds: 0x000102325429beb4 arm-smmu: TLB sync timed out -- SMMU may be deadlocked Call trace: qsmmuv500_tlb_sync_timeout+0x360 __arm_smmu_tlb_sync+0x2b4 arm_smmu_tlb_sync_context+0x4c arm_smmu_tlb_inv_context_s1+0x1ec arm_smmu_context_fault+0xb84 irq_thread_fn+0x44 irq_thread+0x160 kthread+0x16c ret_from_fork+0x10 Fix this by resuming the context bank before bailing out for out of bound iova. Change-Id: I754b38a3761869a5f0c00688211d26f1b0f47eec Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
This commit is contained in:
parent
4afb66961f
commit
da907495ce
1 changed files with 10 additions and 9 deletions
|
|
@ -1388,7 +1388,6 @@ static struct qsmmuv500_tbu_device *qsmmuv500_find_tbu(
|
|||
static int qsmmuv500_ecats_lock(struct arm_smmu_domain *smmu_domain,
|
||||
struct qsmmuv500_tbu_device *tbu,
|
||||
unsigned long *flags)
|
||||
__acquires(&smmu->atos_lock)
|
||||
{
|
||||
struct arm_smmu_device *smmu = tbu->smmu;
|
||||
struct qsmmuv500_archdata *data = to_qsmmuv500_archdata(smmu);
|
||||
|
|
@ -1413,7 +1412,6 @@ static int qsmmuv500_ecats_lock(struct arm_smmu_domain *smmu_domain,
|
|||
static void qsmmuv500_ecats_unlock(struct arm_smmu_domain *smmu_domain,
|
||||
struct qsmmuv500_tbu_device *tbu,
|
||||
unsigned long *flags)
|
||||
__releases(&smmu->atos_lock)
|
||||
{
|
||||
struct arm_smmu_device *smmu = tbu->smmu;
|
||||
struct qsmmuv500_archdata *data = to_qsmmuv500_archdata(smmu);
|
||||
|
|
@ -1449,12 +1447,6 @@ static phys_addr_t qsmmuv500_iova_to_phys(
|
|||
if (iova_ext_bits && split_tables)
|
||||
iova_ext_bits = ~iova_ext_bits;
|
||||
|
||||
if (iova_ext_bits) {
|
||||
dev_err_ratelimited(smmu->dev, "ECATS: address out of bounds: %pad\n",
|
||||
&iova);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tbu = qsmmuv500_find_tbu(smmu, sid);
|
||||
if (!tbu)
|
||||
return 0;
|
||||
|
|
@ -1494,6 +1486,15 @@ static phys_addr_t qsmmuv500_iova_to_phys(
|
|||
RESUME_TERMINATE);
|
||||
}
|
||||
|
||||
/* checking out of bound fault after resuming stalled transactions */
|
||||
if (iova_ext_bits) {
|
||||
dev_err_ratelimited(smmu->dev,
|
||||
"ECATS: address out of bounds: %pad\n",
|
||||
&iova);
|
||||
goto out_resume;
|
||||
}
|
||||
|
||||
|
||||
/* Only one concurrent atos operation */
|
||||
ret = qsmmuv500_ecats_lock(smmu_domain, tbu, &flags);
|
||||
if (ret)
|
||||
|
|
@ -1587,10 +1588,10 @@ redo:
|
|||
if (!phys && needs_redo++ < 2)
|
||||
goto redo;
|
||||
|
||||
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, sctlr_orig);
|
||||
qsmmuv500_ecats_unlock(smmu_domain, tbu, &flags);
|
||||
|
||||
out_resume:
|
||||
arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, sctlr_orig);
|
||||
qsmmuv500_tbu_resume(tbu);
|
||||
|
||||
out_power_off:
|
||||
|
|
|
|||
Loading…
Reference in a new issue