diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-03 13:49:45 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-03 13:49:45 -0400 |
| commit | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (patch) | |
| tree | 2624a44924c625c367f3cebf937853b9da2de282 /arch/powerpc/sysdev/dart_iommu.c | |
| parent | 9f2fa466383ce100b90fe52cb4489d7a26bf72a9 (diff) | |
| parent | 29454dde27d8e340bb1987bad9aa504af7081eba (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'arch/powerpc/sysdev/dart_iommu.c')
| -rw-r--r-- | arch/powerpc/sysdev/dart_iommu.c | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 6232091cc72b..e32fadde1f77 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 32 | #include <linux/types.h> | 31 | #include <linux/types.h> |
| 33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| @@ -101,8 +100,8 @@ retry: | |||
| 101 | if (l == (1L << limit)) { | 100 | if (l == (1L << limit)) { |
| 102 | if (limit < 4) { | 101 | if (limit < 4) { |
| 103 | limit++; | 102 | limit++; |
| 104 | reg = DART_IN(DART_CNTL); | 103 | reg = DART_IN(DART_CNTL); |
| 105 | reg &= ~inv_bit; | 104 | reg &= ~inv_bit; |
| 106 | DART_OUT(DART_CNTL, reg); | 105 | DART_OUT(DART_CNTL, reg); |
| 107 | goto retry; | 106 | goto retry; |
| 108 | } else | 107 | } else |
| @@ -111,11 +110,39 @@ retry: | |||
| 111 | } | 110 | } |
| 112 | } | 111 | } |
| 113 | 112 | ||
| 113 | static inline void dart_tlb_invalidate_one(unsigned long bus_rpn) | ||
| 114 | { | ||
| 115 | unsigned int reg; | ||
| 116 | unsigned int l, limit; | ||
| 117 | |||
| 118 | reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE | | ||
| 119 | (bus_rpn & DART_CNTL_U4_IONE_MASK); | ||
| 120 | DART_OUT(DART_CNTL, reg); | ||
| 121 | |||
| 122 | limit = 0; | ||
| 123 | wait_more: | ||
| 124 | l = 0; | ||
| 125 | while ((DART_IN(DART_CNTL) & DART_CNTL_U4_IONE) && l < (1L << limit)) { | ||
| 126 | rmb(); | ||
| 127 | l++; | ||
| 128 | } | ||
| 129 | |||
| 130 | if (l == (1L << limit)) { | ||
| 131 | if (limit < 4) { | ||
| 132 | limit++; | ||
| 133 | goto wait_more; | ||
| 134 | } else | ||
| 135 | panic("DART: TLB did not flush after waiting a long " | ||
| 136 | "time. Buggy U4 ?"); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 114 | static void dart_flush(struct iommu_table *tbl) | 140 | static void dart_flush(struct iommu_table *tbl) |
| 115 | { | 141 | { |
| 116 | if (dart_dirty) | 142 | if (dart_dirty) { |
| 117 | dart_tlb_invalidate_all(); | 143 | dart_tlb_invalidate_all(); |
| 118 | dart_dirty = 0; | 144 | dart_dirty = 0; |
| 145 | } | ||
| 119 | } | 146 | } |
| 120 | 147 | ||
| 121 | static void dart_build(struct iommu_table *tbl, long index, | 148 | static void dart_build(struct iommu_table *tbl, long index, |
| @@ -124,6 +151,7 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 124 | { | 151 | { |
| 125 | unsigned int *dp; | 152 | unsigned int *dp; |
| 126 | unsigned int rpn; | 153 | unsigned int rpn; |
| 154 | long l; | ||
| 127 | 155 | ||
| 128 | DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); | 156 | DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); |
| 129 | 157 | ||
| @@ -135,7 +163,8 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 135 | /* On U3, all memory is contigous, so we can move this | 163 | /* On U3, all memory is contigous, so we can move this |
| 136 | * out of the loop. | 164 | * out of the loop. |
| 137 | */ | 165 | */ |
| 138 | while (npages--) { | 166 | l = npages; |
| 167 | while (l--) { | ||
| 139 | rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT; | 168 | rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT; |
| 140 | 169 | ||
| 141 | *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); | 170 | *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); |
| @@ -143,7 +172,14 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 143 | uaddr += DART_PAGE_SIZE; | 172 | uaddr += DART_PAGE_SIZE; |
| 144 | } | 173 | } |
| 145 | 174 | ||
| 146 | dart_dirty = 1; | 175 | if (dart_is_u4) { |
| 176 | rpn = index; | ||
| 177 | mb(); /* make sure all updates have reached memory */ | ||
| 178 | while (npages--) | ||
| 179 | dart_tlb_invalidate_one(rpn++); | ||
| 180 | } else { | ||
| 181 | dart_dirty = 1; | ||
| 182 | } | ||
| 147 | } | 183 | } |
| 148 | 184 | ||
| 149 | 185 | ||
