
The tce_build* functions currently take a virtual address as an unsigned long.
Each implementation also does its own page alignment of that address.

Create a global tce_build() for all platforms, do the page alignment there.
Also, change the type of uaddr to be an 'unsigned char*' so that we can do
arithmetic on it. 

Create sglist_vaddr() and sglist_size_pages() to hide some of the nasty casting
that goes on.  Note that this will perform the sglist_vaddr() operation an
extra time.  We could get around it by computing it once and passing it into
sglist_size_pages(), but unless this is a hot path, it's probably not worth
it.

Signed-off-by: Dave Hansen <haveblue@us.ibm.com>


---

 memhotplug-dave/arch/ppc64/kernel/iSeries_iommu.c |    2 -
 memhotplug-dave/arch/ppc64/kernel/iommu.c         |   28 +++++++++++++++-------
 memhotplug-dave/arch/ppc64/kernel/pSeries_iommu.c |    2 -
 memhotplug-dave/arch/ppc64/kernel/pSeries_lpar.c  |    4 +--
 memhotplug-dave/arch/ppc64/kernel/pmac_iommu.c    |    2 -
 memhotplug-dave/include/asm-ppc64/machdep.h       |   10 +++++++
 6 files changed, 34 insertions(+), 14 deletions(-)

diff -puN arch/ppc64/kernel/iommu.c~A7-ppc64-tce-build-vaddr arch/ppc64/kernel/iommu.c
--- memhotplug/arch/ppc64/kernel/iommu.c~A7-ppc64-tce-build-vaddr	Thu Aug  5 09:41:03 2004
+++ memhotplug-dave/arch/ppc64/kernel/iommu.c	Thu Aug  5 09:41:03 2004
@@ -159,8 +159,7 @@ static dma_addr_t iommu_alloc(struct iom
 	ret = entry << PAGE_SHIFT;	/* Set the return dma address */
 
 	/* Put the TCEs in the HW table */
-	ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK,
-			 direction);
+	tce_build(tbl, entry, npages, page, direction);
 
 
 	/* Flush/invalidate TLB caches if necessary */
@@ -225,6 +224,21 @@ static void iommu_free(struct iommu_tabl
 	spin_unlock_irqrestore(&(tbl->it_lock), flags);
 }
 
+static inline void *sglist_vaddr(struct scatterlist *s)
+{
+	return (void *)((unsigned long)page_address(s->page) + s->offset);
+}
+
+static inline unsigned long sglist_size_pages(struct scatterlist *s)
+{
+	unsigned long vaddr, len;
+
+	vaddr = (unsigned long)sglist_vaddr(s);
+	len = PAGE_ALIGN(vaddr + s->length) - (vaddr & PAGE_MASK);
+
+	return len >> PAGE_SHIFT;
+}
+
 int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 		struct scatterlist *sglist, int nelems,
 		enum dma_data_direction direction)
@@ -252,7 +266,7 @@ int iommu_map_sg(struct device *dev, str
 	spin_lock_irqsave(&(tbl->it_lock), flags);
 
 	for (s = outs; nelems; nelems--, s++) {
-		unsigned long vaddr, npages, entry, slen;
+		unsigned long npages, entry, slen;
 
 		slen = s->length;
 		/* Sanity check */
@@ -261,9 +275,7 @@ int iommu_map_sg(struct device *dev, str
 			continue;
 		}
 		/* Allocate iommu entries for that segment */
-		vaddr = (unsigned long)page_address(s->page) + s->offset;
-		npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK);
-		npages >>= PAGE_SHIFT;
+		npages = sglist_size_pages(s);
 		entry = iommu_range_alloc(tbl, npages, &handle);
 
 		DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
@@ -272,7 +284,7 @@ int iommu_map_sg(struct device *dev, str
 		if (unlikely(entry == DMA_ERROR_CODE)) {
 			if (printk_ratelimit())
 				printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %lx"
-				       " npages %lx\n", tbl, vaddr, npages);
+				       " npages %lx\n", tbl, sglist_vaddr(s), npages);
 			goto failure;
 		}
 
@@ -285,7 +297,7 @@ int iommu_map_sg(struct device *dev, str
 			    npages, entry, dma_addr);
 
 		/* Insert into HW table */
-		ppc_md.tce_build(tbl, entry, npages, vaddr & PAGE_MASK, direction);
+		tce_build(tbl, entry, npages, sglist_vaddr(s), direction);
 
 		/* If we are in an open segment, try merging */
 		if (segstart != s) {
diff -puN arch/ppc64/kernel/iSeries_iommu.c~A7-ppc64-tce-build-vaddr arch/ppc64/kernel/iSeries_iommu.c
--- memhotplug/arch/ppc64/kernel/iSeries_iommu.c~A7-ppc64-tce-build-vaddr	Thu Aug  5 09:41:03 2004
+++ memhotplug-dave/arch/ppc64/kernel/iSeries_iommu.c	Thu Aug  5 09:41:03 2004
@@ -54,7 +54,7 @@ extern struct list_head iSeries_Global_D
 
 
 static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
-		unsigned long uaddr, enum dma_data_direction direction)
+		unsigned char *uaddr, enum dma_data_direction direction)
 {
 	u64 rc;
 	union tce_entry tce;
diff -puN arch/ppc64/kernel/pSeries_iommu.c~A7-ppc64-tce-build-vaddr arch/ppc64/kernel/pSeries_iommu.c
--- memhotplug/arch/ppc64/kernel/pSeries_iommu.c~A7-ppc64-tce-build-vaddr	Thu Aug  5 09:41:03 2004
+++ memhotplug-dave/arch/ppc64/kernel/pSeries_iommu.c	Thu Aug  5 09:41:03 2004
@@ -46,7 +46,7 @@
 
 
 static void tce_build_pSeries(struct iommu_table *tbl, long index, 
-			      long npages, unsigned long uaddr, 
+			      long npages, unsigned char *uaddr,
 			      enum dma_data_direction direction)
 {
 	union tce_entry t;
diff -puN arch/ppc64/kernel/pmac_iommu.c~A7-ppc64-tce-build-vaddr arch/ppc64/kernel/pmac_iommu.c
--- memhotplug/arch/ppc64/kernel/pmac_iommu.c~A7-ppc64-tce-build-vaddr	Thu Aug  5 09:41:03 2004
+++ memhotplug-dave/arch/ppc64/kernel/pmac_iommu.c	Thu Aug  5 09:41:03 2004
@@ -141,7 +141,7 @@ static void dart_flush(struct iommu_tabl
 }
 
 static void dart_build_pmac(struct iommu_table *tbl, long index, 
-			    long npages, unsigned long uaddr,
+			    long npages, unsigned char *uaddr,
 			    enum dma_data_direction direction)
 {
 	unsigned int *dp;
diff -puN arch/ppc64/kernel/pSeries_lpar.c~A7-ppc64-tce-build-vaddr arch/ppc64/kernel/pSeries_lpar.c
--- memhotplug/arch/ppc64/kernel/pSeries_lpar.c~A7-ppc64-tce-build-vaddr	Thu Aug  5 09:41:03 2004
+++ memhotplug-dave/arch/ppc64/kernel/pSeries_lpar.c	Thu Aug  5 09:41:03 2004
@@ -131,8 +131,8 @@ long plpar_put_term_char(unsigned long t
 }
 
 static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
-		long npages, unsigned long uaddr,
-		enum dma_data_direction direction)
+				long npages, unsigned char *uaddr,
+				enum dma_data_direction direction)
 {
 	u64 rc;
 	union tce_entry tce;
diff -puN include/asm-ppc64/machdep.h~A7-ppc64-tce-build-vaddr include/asm-ppc64/machdep.h
--- memhotplug/include/asm-ppc64/machdep.h~A7-ppc64-tce-build-vaddr	Thu Aug  5 09:41:03 2004
+++ memhotplug-dave/include/asm-ppc64/machdep.h	Thu Aug  5 09:41:03 2004
@@ -60,7 +60,7 @@ struct machdep_calls {
 	void		(*tce_build)(struct iommu_table * tbl,
 				     long index,
 				     long npages,
-				     unsigned long uaddr,
+				     unsigned char *uaddr,
 				     enum dma_data_direction direction);
 	void		(*tce_free)(struct iommu_table *tbl,
 				    long index,
@@ -131,6 +131,14 @@ void ppc64_terminate_msg(unsigned int sr
 void ppc64_attention_msg(unsigned int src, const char *msg);
 /* Print a dump progress message. */
 void ppc64_dump_msg(unsigned int src, const char *msg);
+
+static inline void tce_build(struct iommu_table * tbl, long index, long npages,
+			     void *uaddr, enum dma_data_direction direction)
+{
+	unsigned char *page_addr = (unsigned char *)((unsigned long)uaddr & PAGE_MASK);
+
+	ppc_md.tce_build(tbl, index, npages, page_addr, direction);
+}
 
 static inline void log_error(char *buf, unsigned int err_type, int fatal)
 {
diff -L A8-ppc64-pfn_to_kaddr -puN /dev/null /dev/null

_
