@@ -575,6 +575,7 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
u64 proto_tce;
__be64 *tcep, *tces;
u64 rpn;
+ long i;
proto_tce = TCE_PCI_READ; // Read allowed
@@ -584,9 +585,13 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
rpn = __pa(uaddr) >> tbl->it_page_shift;
- while (npages--)
- *(tcep++) = cpu_to_be64(proto_tce |
- (rpn++ << tbl->it_page_shift));
+ for (i = 0; i < npages; i++) {
+ unsigned long oldtce = xchg(tcep, cpu_to_be64(proto_tce |
+ (rpn++ << tbl->it_page_shift)));
+ if (old_tces)
+ old_tces[i] = (unsigned long) __va(oldtce);
+ tcep++;
+ }
pnv_tce_invalidate(tbl, tces, tcep - 1, rm);
This returns old TCE values to the caller if requested. The caller is expectded to call put_page() for them. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> --- arch/powerpc/platforms/powernv/pci.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)