diff options
| author | Jiaxing Hu <gahing@gahingwoo.com> | 2026-07-18 15:11:43 +1200 |
|---|---|---|
| committer | Will Deacon <will@kernel.org> | 2026-07-26 13:10:27 +0000 |
| commit | b10d5920cafa292ee3cab9c20f813da4fe4f00b8 (patch) | |
| tree | f6cdb423de2f98d40de0d58f261ff972c42a4258 | |
| parent | 841363ebb5082a06c69ac34719e26659fe63dbd6 (diff) | |
iommu/rockchip: Clear stale page faults before enabling stall
Boot firmware can leave an IOMMU bank in PAGE_FAULT_ACTIVE before the
driver has configured paging:
PAGE_FAULT_ACTIVE=1 STALL_ACTIVE=0 IDLE=1
Such a bank ignores CMD_ENABLE_STALL and never reaches STALL_ACTIVE, so
rk_iommu_enable_stall()'s readx_poll_timeout() spins until it times out
(seen on the RK3576 NPU, whose MMUs share this poll across banks).
Rather than special-casing these banks in the stall path, acknowledge the
stale fault with CMD_PAGE_FAULT_DONE before enabling stall, so every bank
starts from a clean state and the normal stall sequence applies to all of
them. Banks without a pending fault are untouched.
Signed-off-by: Jiaxing Hu <gahing@gahingwoo.com>
Signed-off-by: Will Deacon <will@kernel.org>
| -rw-r--r-- | drivers/iommu/rockchip-iommu.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index d041160d18af..21af2f621c76 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -418,6 +418,19 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu) if (!rk_iommu_is_paging_enabled(iommu)) return 0; + /* + * Boot firmware can leave a bank in PAGE_FAULT_ACTIVE with no handler + * (PAGE_FAULT_ACTIVE & !STALL_ACTIVE & IDLE). Such a bank ignores + * CMD_ENABLE_STALL and never reaches STALL_ACTIVE, timing out the poll + * below. Acknowledge any stale fault first so every bank starts clean. + */ + for (i = 0; i < iommu->num_mmu; i++) { + if (rk_iommu_read(iommu->bases[i], RK_MMU_STATUS) & + RK_MMU_STATUS_PAGE_FAULT_ACTIVE) + writel(RK_MMU_CMD_PAGE_FAULT_DONE, + iommu->bases[i] + RK_MMU_COMMAND); + } + rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL); ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val, |
