aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/pSeries_iommu.c
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 /arch/ppc64/kernel/pSeries_iommu.c
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>
Diffstat (limited to 'arch/ppc64/kernel/pSeries_iommu.c')
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c25
1 files changed, 20 insertions, 5 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,