[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>
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 7f7947c..2b5e622 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -60,6 +60,9 @@
 	union tce_entry t;
 	union tce_entry *tp;
 
+	index <<= TCE_PAGE_FACTOR;
+	npages <<= TCE_PAGE_FACTOR;
+
 	t.te_word = 0;
 	t.te_rdwr = 1; // Read allowed 
 
@@ -70,11 +73,11 @@
 
 	while (npages--) {
 		/* can't move this out since we might cross LMB boundary */
-		t.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+		t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
 	
 		tp->te_word = t.te_word;
 
-		uaddr += PAGE_SIZE;
+		uaddr += TCE_PAGE_SIZE;
 		tp++;
 	}
 }
@@ -85,6 +88,9 @@
 	union tce_entry t;
 	union tce_entry *tp;
 
+	npages <<= TCE_PAGE_FACTOR;
+	index <<= TCE_PAGE_FACTOR;
+
 	t.te_word = 0;
 	tp  = ((union tce_entry *)tbl->it_base) + index;
 		
@@ -104,7 +110,7 @@
 	union tce_entry tce;
 
 	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
 	tce.te_rdwr = 1;
 	if (direction != DMA_TO_DEVICE)
 		tce.te_pciwr = 1;
@@ -137,6 +143,9 @@
 	union tce_entry tce, *tcep;
 	long l, limit;
 
+	tcenum <<= TCE_PAGE_FACTOR;
+	npages <<= TCE_PAGE_FACTOR;
+
 	if (npages == 1)
 		return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
 					   direction);
@@ -156,7 +165,7 @@
 	}
 
 	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
 	tce.te_rdwr = 1;
 	if (direction != DMA_TO_DEVICE)
 		tce.te_pciwr = 1;
@@ -167,7 +176,7 @@
 		 * Set up the page with TCE data, looping through and setting
 		 * the values.
 		 */
-		limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry));
+		limit = min_t(long, npages, 4096/sizeof(union tce_entry));
 
 		for (l = 0; l < limit; l++) {
 			tcep[l] = tce;
@@ -197,6 +206,9 @@
 	u64 rc;
 	union tce_entry tce;
 
+	tcenum <<= TCE_PAGE_FACTOR;
+	npages <<= TCE_PAGE_FACTOR;
+
 	tce.te_word = 0;
 
 	while (npages--) {
@@ -222,6 +234,9 @@
 	u64 rc;
 	union tce_entry tce;
 
+	tcenum <<= TCE_PAGE_FACTOR;
+	npages <<= TCE_PAGE_FACTOR;
+
 	tce.te_word = 0;
 
 	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 115cbdf..df9c775 100644
--- a/arch/ppc64/kernel/u3_iommu.c
+++ b/arch/ppc64/kernel/u3_iommu.c
@@ -125,18 +125,21 @@
 
 	DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
 
+	index <<= DART_PAGE_FACTOR;
+	npages <<= DART_PAGE_FACTOR;
+
 	dp = ((unsigned int*)tbl->it_base) + index;
 	
 	/* On U3, all memory is contigous, so we can move this
 	 * out of the loop.
 	 */
 	while (npages--) {
-		rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
+		rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
 
 		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
 
 		rpn++;
-		uaddr += PAGE_SIZE;
+		uaddr += DART_PAGE_SIZE;
 	}
 
 	dart_dirty = 1;
@@ -154,6 +157,9 @@
 
 	DBG("dart: free at: %lx, %lx\n", index, npages);
 
+	index <<= DART_PAGE_FACTOR;
+	npages <<= DART_PAGE_FACTOR;
+
 	dp  = ((unsigned int *)tbl->it_base) + index;
 		
 	while (npages--)
@@ -182,10 +188,10 @@
 	 * that to work around what looks like a problem with the HT bridge
 	 * prefetching into invalid pages and corrupting data
 	 */
-	tmp = lmb_alloc(PAGE_SIZE, PAGE_SIZE);
+	tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
 	if (!tmp)
 		panic("U3-DART: Cannot allocate spare page!");
-	dart_emptyval = DARTMAP_VALID | ((tmp >> PAGE_SHIFT) & DARTMAP_RPNMASK);
+	dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK);
 
 	/* Map in DART registers. FIXME: Use device node to get base address */
 	dart = ioremap(DART_BASE, 0x7000);
@@ -196,8 +202,8 @@
 	 * table size and enable bit
 	 */
 	regword = DARTCNTL_ENABLE | 
-		((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
-		(((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
+		((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
+		(((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
 				 << DARTCNTL_SIZE_SHIFT);
 	dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);