[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.