[PATCH 3/4] iommu/exynos: fix TLB invalidation for no-block SysMMUs
Markuss Broks via B4 Relay <[email protected]>
| Newsgroups | dev.linux.lists.iommu,org.infradead.lists.linux-arm-kernel,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.linux-samsung-soc |
|---|---|
| Message-ID | <[email protected]> |
From: Markuss Broks <[email protected]> sysmmu_block() polls MMU_STATUS for the blocked state, which no-block hardware never reports, so on such SysMMUs it always fails, and both sysmmu_tlb_invalidate_entry() and sysmmu_tlb_invalidate_flpdcache() skip the invalidation entirely when blocking fails. On no-block hardware the invalidation registers are written with the MMU running; the vendor driver never blocks around invalidation. Do the same and write the invalidation directly. In the FLPD cache path no-block implies a v7+ SysMMU, hence the unconditional flush-all. Signed-off-by: Markuss Broks <[email protected]> --- drivers/iommu/exynos-iommu.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index a3a59d8a4cf1..29b27c7e400a 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -685,7 +685,14 @@ static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, spin_lock_irqsave(&data->lock, flags); if (data->active && data->version >= MAKE_MMU_VER(3, 3)) { clk_enable(data->clk_master); - if (sysmmu_block(data)) { + /* + * No-block hardware accepts invalidation writes while the + * MMU is running; it is also v7+, so flush-all covers the + * FLPD cache. + */ + if (data->no_block) { + __sysmmu_tlb_invalidate(data); + } else if (sysmmu_block(data)) { if (data->version >= MAKE_MMU_VER(5, 0)) __sysmmu_tlb_invalidate(data); else @@ -721,7 +728,9 @@ static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data, if (MMU_MAJ_VER(data->version) == 2) num_inv = min_t(unsigned int, size / SPAGE_SIZE, 64); - if (sysmmu_block(data)) { + if (data->no_block) { + __sysmmu_tlb_invalidate_entry(data, iova, num_inv); + } else if (sysmmu_block(data)) { __sysmmu_tlb_invalidate_entry(data, iova, num_inv); sysmmu_unblock(data); } -- 2.55.0