diff options
author | Olof Johansson <olof@lixom.net> | 2005-09-19 23:46:44 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-09-21 05:21:07 -0400 |
commit | d0035c62d9145a2ce3057c8182a7ff0b4921a41c (patch) | |
tree | 0a55703d5e71668f61439649f4963daba55401c3 /arch/ppc64/kernel/pSeries_iommu.c | |
parent | c707ffcf3a44914f30e5f2fd53089ad5586c9e42 (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.c | 25 |
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, |