aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2005-09-19 23:46:44 -0400
committerPaul Mackerras <paulus@samba.org>2005-09-21 05:21:07 -0400
commitd0035c62d9145a2ce3057c8182a7ff0b4921a41c (patch)
tree0a55703d5e71668f61439649f4963daba55401c3
parentc707ffcf3a44914f30e5f2fd53089ad5586c9e42 (diff)
[PATCH] ppc64: Updated Olof iommu updates 2/3
There are potential cases in the future where the IOMMU might be mapping smaller pages than the regular MMU is using. Keep the allocator working on MMU pagesizes, but the low-level mapping functions need to map more than one TCE entry per page to deal with this. Signed-off-by: Olof Johansson <olof@lixom.net> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c25
-rw-r--r--arch/ppc64/kernel/u3_iommu.c18
-rw-r--r--include/asm-ppc64/dart.h4
-rw-r--r--include/asm-ppc64/tce.h7
4 files changed, 43 insertions, 11 deletions
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 7f7947c3e12f..2b5e622732f4 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -60,6 +60,9 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index,
60 union tce_entry t; 60 union tce_entry t;
61 union tce_entry *tp; 61 union tce_entry *tp;
62 62
63 index <<= TCE_PAGE_FACTOR;
64 npages <<= TCE_PAGE_FACTOR;
65
63 t.te_word = 0; 66 t.te_word = 0;
64 t.te_rdwr = 1; // Read allowed 67 t.te_rdwr = 1; // Read allowed
65 68
@@ -70,11 +73,11 @@ static void tce_build_pSeries(struct iommu_table *tbl, long index,
70 73
71 while (npages--) { 74 while (npages--) {
72 /* can't move this out since we might cross LMB boundary */ 75 /* can't move this out since we might cross LMB boundary */
73 t.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; 76 t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
74 77
75 tp->te_word = t.te_word; 78 tp->te_word = t.te_word;
76 79
77 uaddr += PAGE_SIZE; 80 uaddr += TCE_PAGE_SIZE;
78 tp++; 81 tp++;
79 } 82 }
80} 83}
@@ -85,6 +88,9 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
85 union tce_entry t; 88 union tce_entry t;
86 union tce_entry *tp; 89 union tce_entry *tp;
87 90
91 npages <<= TCE_PAGE_FACTOR;
92 index <<= TCE_PAGE_FACTOR;
93
88 t.te_word = 0; 94 t.te_word = 0;
89 tp = ((union tce_entry *)tbl->it_base) + index; 95 tp = ((union tce_entry *)tbl->it_base) + index;
90 96
@@ -104,7 +110,7 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
104 union tce_entry tce; 110 union tce_entry tce;
105 111
106 tce.te_word = 0; 112 tce.te_word = 0;
107 tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; 113 tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
108 tce.te_rdwr = 1; 114 tce.te_rdwr = 1;
109 if (direction != DMA_TO_DEVICE) 115 if (direction != DMA_TO_DEVICE)
110 tce.te_pciwr = 1; 116 tce.te_pciwr = 1;
@@ -137,6 +143,9 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
137 union tce_entry tce, *tcep; 143 union tce_entry tce, *tcep;
138 long l, limit; 144 long l, limit;
139 145
146 tcenum <<= TCE_PAGE_FACTOR;
147 npages <<= TCE_PAGE_FACTOR;
148
140 if (npages == 1) 149 if (npages == 1)
141 return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, 150 return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
142 direction); 151 direction);
@@ -156,7 +165,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
156 } 165 }
157 166
158 tce.te_word = 0; 167 tce.te_word = 0;
159 tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT; 168 tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
160 tce.te_rdwr = 1; 169 tce.te_rdwr = 1;
161 if (direction != DMA_TO_DEVICE) 170 if (direction != DMA_TO_DEVICE)
162 tce.te_pciwr = 1; 171 tce.te_pciwr = 1;
@@ -167,7 +176,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
167 * Set up the page with TCE data, looping through and setting 176 * Set up the page with TCE data, looping through and setting
168 * the values. 177 * the values.
169 */ 178 */
170 limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry)); 179 limit = min_t(long, npages, 4096/sizeof(union tce_entry));
171 180
172 for (l = 0; l < limit; l++) { 181 for (l = 0; l < limit; l++) {
173 tcep[l] = tce; 182 tcep[l] = tce;
@@ -197,6 +206,9 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
197 u64 rc; 206 u64 rc;
198 union tce_entry tce; 207 union tce_entry tce;
199 208
209 tcenum <<= TCE_PAGE_FACTOR;
210 npages <<= TCE_PAGE_FACTOR;
211
200 tce.te_word = 0; 212 tce.te_word = 0;
201 213
202 while (npages--) { 214 while (npages--) {
@@ -222,6 +234,9 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
222 u64 rc; 234 u64 rc;
223 union tce_entry tce; 235 union tce_entry tce;
224 236
237 tcenum <<= TCE_PAGE_FACTOR;
238 npages <<= TCE_PAGE_FACTOR;
239
225 tce.te_word = 0; 240 tce.te_word = 0;
226 241
227 rc = plpar_tce_stuff((u64)tbl->it_index, 242 rc = plpar_tce_stuff((u64)tbl->it_index,
diff --git a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
index 115cbdf3b13b..df9c775f4955 100644
--- a/arch/ppc64/kernel/u3_iommu.c
+++ b/arch/ppc64/kernel/u3_iommu.c
@@ -125,18 +125,21 @@ static void dart_build(struct iommu_table *tbl, long index,
125 125
126 DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); 126 DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
127 127
128 index <<= DART_PAGE_FACTOR;
129 npages <<= DART_PAGE_FACTOR;
130
128 dp = ((unsigned int*)tbl->it_base) + index; 131 dp = ((unsigned int*)tbl->it_base) + index;
129 132
130 /* On U3, all memory is contigous, so we can move this 133 /* On U3, all memory is contigous, so we can move this
131 * out of the loop. 134 * out of the loop.
132 */ 135 */
133 while (npages--) { 136 while (npages--) {
134 rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; 137 rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
135 138
136 *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); 139 *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
137 140
138 rpn++; 141 rpn++;
139 uaddr += PAGE_SIZE; 142 uaddr += DART_PAGE_SIZE;
140 } 143 }
141 144
142 dart_dirty = 1; 145 dart_dirty = 1;
@@ -154,6 +157,9 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)
154 157
155 DBG("dart: free at: %lx, %lx\n", index, npages); 158 DBG("dart: free at: %lx, %lx\n", index, npages);
156 159
160 index <<= DART_PAGE_FACTOR;
161 npages <<= DART_PAGE_FACTOR;
162
157 dp = ((unsigned int *)tbl->it_base) + index; 163 dp = ((unsigned int *)tbl->it_base) + index;
158 164
159 while (npages--) 165 while (npages--)
@@ -182,10 +188,10 @@ static int dart_init(struct device_node *dart_node)
182 * that to work around what looks like a problem with the HT bridge 188 * that to work around what looks like a problem with the HT bridge
183 * prefetching into invalid pages and corrupting data 189 * prefetching into invalid pages and corrupting data
184 */ 190 */
185 tmp = lmb_alloc(PAGE_SIZE, PAGE_SIZE); 191 tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
186 if (!tmp) 192 if (!tmp)
187 panic("U3-DART: Cannot allocate spare page!"); 193 panic("U3-DART: Cannot allocate spare page!");
188 dart_emptyval = DARTMAP_VALID | ((tmp >> PAGE_SHIFT) & DARTMAP_RPNMASK); 194 dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK);
189 195
190 /* Map in DART registers. FIXME: Use device node to get base address */ 196 /* Map in DART registers. FIXME: Use device node to get base address */
191 dart = ioremap(DART_BASE, 0x7000); 197 dart = ioremap(DART_BASE, 0x7000);
@@ -196,8 +202,8 @@ static int dart_init(struct device_node *dart_node)
196 * table size and enable bit 202 * table size and enable bit
197 */ 203 */
198 regword = DARTCNTL_ENABLE | 204 regword = DARTCNTL_ENABLE |
199 ((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) | 205 ((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
200 (((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK) 206 (((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
201 << DARTCNTL_SIZE_SHIFT); 207 << DARTCNTL_SIZE_SHIFT);
202 dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize); 208 dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
203 209
diff --git a/include/asm-ppc64/dart.h b/include/asm-ppc64/dart.h
index 306799a31a5d..a9000de8a2e3 100644
--- a/include/asm-ppc64/dart.h
+++ b/include/asm-ppc64/dart.h
@@ -51,5 +51,9 @@
51#define DARTMAP_RPNMASK 0x00ffffff 51#define DARTMAP_RPNMASK 0x00ffffff
52 52
53 53
54#define DART_SHIFT 12
55#define DART_PAGE_SIZE (1 << DART_SHIFT)
56#define DART_PAGE_FACTOR (PAGE_SHIFT - DART_SHIFT)
57
54 58
55#endif 59#endif
diff --git a/include/asm-ppc64/tce.h b/include/asm-ppc64/tce.h
index 636504c62c88..d40b6b42ab35 100644
--- a/include/asm-ppc64/tce.h
+++ b/include/asm-ppc64/tce.h
@@ -28,6 +28,13 @@
28#define TCE_VB 0 28#define TCE_VB 0
29#define TCE_PCI 1 29#define TCE_PCI 1
30 30
31/* TCE page size is 4096 bytes (1 << 12) */
32
33#define TCE_SHIFT 12
34#define TCE_PAGE_SIZE (1 << TCE_SHIFT)
35#define TCE_PAGE_FACTOR (PAGE_SHIFT - TCE_SHIFT)
36
37
31/* tce_entry 38/* tce_entry
32 * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's 39 * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
33 * abstracted so layout is irrelevant. 40 * abstracted so layout is irrelevant.