aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-09-13 08:12:52 -0400
committerPaul Mackerras <paulus@samba.org>2006-09-13 08:12:52 -0400
commiteeac5c142b8687e35780b11b54b4c2f95b1a2436 (patch)
treec0df8f3f5b154d41a63bff1a4e49f2bf5172b079 /arch/powerpc
parentf007cacffc8870702a1473d83ba5e4922d54e17c (diff)
[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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c7
1 files changed, 6 insertions, 1 deletions
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 @@ wait_more:
139 139
140static void dart_flush(struct iommu_table *tbl) 140static void dart_flush(struct iommu_table *tbl)
141{ 141{
142 mb();
142 if (dart_dirty) { 143 if (dart_dirty) {
143 dart_tlb_invalidate_all(); 144 dart_tlb_invalidate_all();
144 dart_dirty = 0; 145 dart_dirty = 0;
@@ -172,9 +173,13 @@ static void dart_build(struct iommu_table *tbl, long index,
172 uaddr += DART_PAGE_SIZE; 173 uaddr += DART_PAGE_SIZE;
173 } 174 }
174 175
176 /* make sure all updates have reached memory */
177 mb();
178 in_be32((unsigned __iomem *)dp);
179 mb();
180
175 if (dart_is_u4) { 181 if (dart_is_u4) {
176 rpn = index; 182 rpn = index;
177 mb(); /* make sure all updates have reached memory */
178 while (npages--) 183 while (npages--)
179 dart_tlb_invalidate_one(rpn++); 184 dart_tlb_invalidate_one(rpn++);
180 } else { 185 } else {