summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiaxing Hu <gahing@gahingwoo.com>2026-07-18 15:11:43 +1200
committerWill Deacon <will@kernel.org>2026-07-26 13:10:27 +0000
commitb10d5920cafa292ee3cab9c20f813da4fe4f00b8 (patch)
treef6cdb423de2f98d40de0d58f261ff972c42a4258
parent841363ebb5082a06c69ac34719e26659fe63dbd6 (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.c13
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,