From eeac5c142b8687e35780b11b54b4c2f95b1a2436 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Wed, 13 Sep 2006 22:12:52 +1000
Subject: [PATCH] [POWERPC] Fix G5 DART (IOMMU) race causing occasional data
 corruption

It seems that the occasional data corruption observed with the tg3
driver wasn't due to missing barriers after all, but rather seems to
be due to the DART (= IOMMU) in the U4 northbridge reading stale
IOMMU table entries from memory due to a race.  This fixes it by
making the CPU read the entry back from memory before using it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 arch/powerpc/sysdev/dart_iommu.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index e32fadde1f77..03b4477dd7f0 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -139,6 +139,7 @@ static inline void dart_tlb_invalidate_one(unsigned long bus_rpn)
 
 static void dart_flush(struct iommu_table *tbl)
 {
+	mb();
 	if (dart_dirty) {
 		dart_tlb_invalidate_all();
 		dart_dirty = 0;
@@ -172,9 +173,13 @@ static void dart_build(struct iommu_table *tbl, long index,
 		uaddr += DART_PAGE_SIZE;
 	}
 
+	/* make sure all updates have reached memory */
+	mb();
+	in_be32((unsigned __iomem *)dp);
+	mb();
+
 	if (dart_is_u4) {
 		rpn = index;
-		mb(); /* make sure all updates have reached memory */
 		while (npages--)
 			dart_tlb_invalidate_one(rpn++);
 	} else {
-- 
GitLab