Skip to content

Commit 0c634ba

Browse files
LeoBrasmpe
authored andcommitted
powerpc/pseries/iommu: Replace hard-coded page shift
Some functions assume IOMMU page size can only be 4K (pageshift == 12). Update them to accept any page size passed, so we can use 64K pages. In the process, some defines like TCE_SHIFT were made obsolete, and then removed. IODA3 Revision 3.0_prd1 (OpenPowerFoundation), Figures 3.4 and 3.5 show a RPN of 52-bit, and considers a 12-bit pageshift, so there should be no need of using TCE_RPN_MASK, which masks out any bit after 40 in rpn. It's usage removed from tce_build_pSeries(), tce_build_pSeriesLP(), and tce_buildmulti_pSeriesLP(). Most places had a tbl struct, so using tbl->it_page_shift was simple. tce_free_pSeriesLP() was a special case, since callers not always have a tbl struct, so adding a tceshift parameter seems the right thing to do. Signed-off-by: Leonardo Bras <[email protected]> Reviewed-by: Alexey Kardashevskiy <[email protected]> Reviewed-by: Frederic Barrat <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 9a245d0 commit 0c634ba

File tree

2 files changed

+23
-24
lines changed

2 files changed

+23
-24
lines changed

arch/powerpc/include/asm/tce.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,7 @@
1919
#define TCE_VB 0
2020
#define TCE_PCI 1
2121

22-
/* TCE page size is 4096 bytes (1 << 12) */
23-
24-
#define TCE_SHIFT 12
25-
#define TCE_PAGE_SIZE (1 << TCE_SHIFT)
26-
2722
#define TCE_ENTRY_SIZE 8 /* each TCE is 64 bits */
28-
29-
#define TCE_RPN_MASK 0xfffffffffful /* 40-bit RPN (4K pages) */
30-
#define TCE_RPN_SHIFT 12
3123
#define TCE_VALID 0x800 /* TCE valid */
3224
#define TCE_ALLIO 0x400 /* TCE valid for all lpars */
3325
#define TCE_PCI_WRITE 0x2 /* write from PCI allowed */

arch/powerpc/platforms/pseries/iommu.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
107107
u64 proto_tce;
108108
__be64 *tcep;
109109
u64 rpn;
110+
const unsigned long tceshift = tbl->it_page_shift;
111+
const unsigned long pagesize = IOMMU_PAGE_SIZE(tbl);
110112

111113
proto_tce = TCE_PCI_READ; // Read allowed
112114

@@ -117,10 +119,10 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
117119

118120
while (npages--) {
119121
/* can't move this out since we might cross MEMBLOCK boundary */
120-
rpn = __pa(uaddr) >> TCE_SHIFT;
121-
*tcep = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
122+
rpn = __pa(uaddr) >> tceshift;
123+
*tcep = cpu_to_be64(proto_tce | rpn << tceshift);
122124

123-
uaddr += TCE_PAGE_SIZE;
125+
uaddr += pagesize;
124126
tcep++;
125127
}
126128
return 0;
@@ -146,7 +148,7 @@ static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
146148
return be64_to_cpu(*tcep);
147149
}
148150

149-
static void tce_free_pSeriesLP(unsigned long liobn, long, long);
151+
static void tce_free_pSeriesLP(unsigned long liobn, long, long, long);
150152
static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
151153

152154
static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
@@ -166,12 +168,12 @@ static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
166168
proto_tce |= TCE_PCI_WRITE;
167169

168170
while (npages--) {
169-
tce = proto_tce | (rpn & TCE_RPN_MASK) << tceshift;
171+
tce = proto_tce | rpn << tceshift;
170172
rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, tce);
171173

172174
if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
173175
ret = (int)rc;
174-
tce_free_pSeriesLP(liobn, tcenum_start,
176+
tce_free_pSeriesLP(liobn, tcenum_start, tceshift,
175177
(npages_start - (npages + 1)));
176178
break;
177179
}
@@ -205,10 +207,11 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
205207
long tcenum_start = tcenum, npages_start = npages;
206208
int ret = 0;
207209
unsigned long flags;
210+
const unsigned long tceshift = tbl->it_page_shift;
208211

209212
if ((npages == 1) || !firmware_has_feature(FW_FEATURE_PUT_TCE_IND)) {
210213
return tce_build_pSeriesLP(tbl->it_index, tcenum,
211-
tbl->it_page_shift, npages, uaddr,
214+
tceshift, npages, uaddr,
212215
direction, attrs);
213216
}
214217

@@ -225,13 +228,13 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
225228
if (!tcep) {
226229
local_irq_restore(flags);
227230
return tce_build_pSeriesLP(tbl->it_index, tcenum,
228-
tbl->it_page_shift,
231+
tceshift,
229232
npages, uaddr, direction, attrs);
230233
}
231234
__this_cpu_write(tce_page, tcep);
232235
}
233236

234-
rpn = __pa(uaddr) >> TCE_SHIFT;
237+
rpn = __pa(uaddr) >> tceshift;
235238
proto_tce = TCE_PCI_READ;
236239
if (direction != DMA_TO_DEVICE)
237240
proto_tce |= TCE_PCI_WRITE;
@@ -245,12 +248,12 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
245248
limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
246249

247250
for (l = 0; l < limit; l++) {
248-
tcep[l] = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
251+
tcep[l] = cpu_to_be64(proto_tce | rpn << tceshift);
249252
rpn++;
250253
}
251254

252255
rc = plpar_tce_put_indirect((u64)tbl->it_index,
253-
(u64)tcenum << 12,
256+
(u64)tcenum << tceshift,
254257
(u64)__pa(tcep),
255258
limit);
256259

@@ -277,12 +280,13 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
277280
return ret;
278281
}
279282

280-
static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long npages)
283+
static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
284+
long npages)
281285
{
282286
u64 rc;
283287

284288
while (npages--) {
285-
rc = plpar_tce_put((u64)liobn, (u64)tcenum << 12, 0);
289+
rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, 0);
286290

287291
if (rc && printk_ratelimit()) {
288292
printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
@@ -301,9 +305,11 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
301305
u64 rc;
302306

303307
if (!firmware_has_feature(FW_FEATURE_STUFF_TCE))
304-
return tce_free_pSeriesLP(tbl->it_index, tcenum, npages);
308+
return tce_free_pSeriesLP(tbl->it_index, tcenum,
309+
tbl->it_page_shift, npages);
305310

306-
rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
311+
rc = plpar_tce_stuff((u64)tbl->it_index,
312+
(u64)tcenum << tbl->it_page_shift, 0, npages);
307313

308314
if (rc && printk_ratelimit()) {
309315
printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
@@ -319,7 +325,8 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
319325
u64 rc;
320326
unsigned long tce_ret;
321327

322-
rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret);
328+
rc = plpar_tce_get((u64)tbl->it_index,
329+
(u64)tcenum << tbl->it_page_shift, &tce_ret);
323330

324331
if (rc && printk_ratelimit()) {
325332
printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc);

0 commit comments

Comments
 (0)