summaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev/dart_iommu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-29 11:32:34 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-29 11:32:34 -0700
commit3aa590c6b7c89d844f81c2e96f295cf2c6967773 (patch)
tree6f18b295b1ff4cd7fd1880db6f56721599d64439 /arch/powerpc/sysdev/dart_iommu.c
parent4d3ce21fa9d2eaeda113aa2f9c2da80d972bef64 (diff)
parent339d76c54336443f5050b00172beb675f35e3be0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (43 commits) [POWERPC] Use little-endian bit from firmware ibm,pa-features property [POWERPC] Make sure smp_processor_id works very early in boot [POWERPC] U4 DART improvements [POWERPC] todc: add support for Time-Of-Day-Clock [POWERPC] Make lparcfg.c work when both iseries and pseries are selected [POWERPC] Fix idr locking in init_new_context [POWERPC] mpc7448hpc2 (taiga) board config file [POWERPC] Add tsi108 pci and platform device data register function [POWERPC] Add general support for mpc7448hpc2 (Taiga) platform [POWERPC] Correct the MAX_CONTEXT definition powerpc: minor cleanups for mpc86xx [POWERPC] Make sure we select CONFIG_NEW_LEDS if ADB_PMU_LED is set [POWERPC] Simplify the code defining the 64-bit CPU features [POWERPC] powerpc: kconfig warning fix [POWERPC] Consolidate some of kernel/misc*.S [POWERPC] Remove unused function call_with_mmu_off [POWERPC] update asm-powerpc/time.h [POWERPC] Clean up it_lp_queue.h [POWERPC] Skip the "copy down" of the kernel if it is already at zero. [POWERPC] Add the use of the firmware soft-reset-nmi to kdump. ...
Diffstat (limited to 'arch/powerpc/sysdev/dart_iommu.c')
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 6232091cc72b..7c7f34ce4986 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -101,8 +101,8 @@ retry:
if (l == (1L << limit)) {
if (limit < 4) {
limit++;
- reg = DART_IN(DART_CNTL);
- reg &= ~inv_bit;
+ reg = DART_IN(DART_CNTL);
+ reg &= ~inv_bit;
DART_OUT(DART_CNTL, reg);
goto retry;
} else
@@ -111,11 +111,39 @@ retry:
}
}
+static inline void dart_tlb_invalidate_one(unsigned long bus_rpn)
+{
+ unsigned int reg;
+ unsigned int l, limit;
+
+ reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE |
+ (bus_rpn & DART_CNTL_U4_IONE_MASK);
+ DART_OUT(DART_CNTL, reg);
+
+ limit = 0;
+wait_more:
+ l = 0;
+ while ((DART_IN(DART_CNTL) & DART_CNTL_U4_IONE) && l < (1L << limit)) {
+ rmb();
+ l++;
+ }
+
+ if (l == (1L << limit)) {
+ if (limit < 4) {
+ limit++;
+ goto wait_more;
+ } else
+ panic("DART: TLB did not flush after waiting a long "
+ "time. Buggy U4 ?");
+ }
+}
+
static void dart_flush(struct iommu_table *tbl)
{
- if (dart_dirty)
+ if (dart_dirty) {
dart_tlb_invalidate_all();
- dart_dirty = 0;
+ dart_dirty = 0;
+ }
}
static void dart_build(struct iommu_table *tbl, long index,
@@ -124,6 +152,7 @@ static void dart_build(struct iommu_table *tbl, long index,
{
unsigned int *dp;
unsigned int rpn;
+ long l;
DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
@@ -135,7 +164,8 @@ static void dart_build(struct iommu_table *tbl, long index,
/* On U3, all memory is contigous, so we can move this
* out of the loop.
*/
- while (npages--) {
+ l = npages;
+ while (l--) {
rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
@@ -143,7 +173,14 @@ static void dart_build(struct iommu_table *tbl, long index,
uaddr += DART_PAGE_SIZE;
}
- dart_dirty = 1;
+ if (dart_is_u4) {
+ rpn = index;
+ mb(); /* make sure all updates have reached memory */
+ while (npages--)
+ dart_tlb_invalidate_one(rpn++);
+ } else {
+ dart_dirty = 1;
+ }
}