--- orig/linux-2.6.11.4/arch/ppc/kernel/dma-mapping.c	2005-03-15 16:08:58.000000000 -0800
+++ linux-2.6.11.4/arch/ppc/kernel/dma-mapping.c	2005-05-27 19:06:27.956937000 -0700
@@ -17,6 +17,11 @@
  * implementation. This is pulled straight from ARM and barely
  * modified. -Matt
  *
+ * Changed consistent_pte to consistent_ptes, in order to remove the 
+ * limitation of 2MB consistent DMA memory. Now the size is confined by
+ * CONFIG_CONSISTENT_SIZE. And there are multiple pages containing PTE.
+ * - Xiaogeng (Shawn) Jin (Agilent Technologies), 2005
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -66,11 +71,14 @@
 #define CONSISTENT_BASE	(CONFIG_CONSISTENT_START)
 #define CONSISTENT_END	(CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
 #define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+#define	CONSISTENT_PTE_PAGENR	((CONFIG_CONSISTENT_SIZE >> PAGE_SHIFT) >> PTE_SHIFT)
+#define CONSISTENT_SIZE_PER_PTEPAGE	(1UL << (PAGE_SHIFT + PTE_SHIFT))
 
 /*
- * This is the page table (2MB) covering uncached, DMA consistent allocations
+ * This is page tables covering uncached, DMA consistent allocations,
+ * with the size of CONFIG_CONSISTENT_SIZE
  */
-static pte_t *consistent_pte;
+pte_t **consistent_ptes = NULL;
 static DEFINE_SPINLOCK(consistent_lock);
 
 /*
@@ -180,7 +188,7 @@
 	unsigned long order;
 	u64 mask = 0x00ffffff, limit; /* ISA default */
 
-	if (!consistent_pte) {
+	if (!consistent_ptes) {
 		printk(KERN_ERR "%s: not initialised\n", __func__);
 		dump_stack();
 		return NULL;
@@ -219,9 +227,14 @@
 	c = vm_region_alloc(&consistent_head, size,
 			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
 	if (c) {
-		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+		pte_t *pte;
+		int offset = CONSISTENT_OFFSET(c->vm_start);
+		int idx = offset >> PTE_SHIFT;
 		struct page *end = page + (1 << order);
 
+		offset &= (1 << PTE_SHIFT) - 1;
+		pte = consistent_ptes[idx] + offset;
+
 		/*
 		 * Set the "dma handle"
 		 */
@@ -235,6 +248,11 @@
 			set_pte(pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
 			page++;
 			pte++;
+			offset++;
+			if (offset > ((1 << PTE_SHIFT) - 1)) {
+				pte = consistent_ptes[++idx];
+				offset = 0;
+			}
 		} while (size -= PAGE_SIZE);
 
 		/*
@@ -264,6 +282,7 @@
 	struct vm_region *c;
 	unsigned long flags;
 	pte_t *ptep;
+	int offset, idx;
 
 	size = PAGE_ALIGN(size);
 
@@ -280,12 +299,21 @@
 		size = c->vm_end - c->vm_start;
 	}
 
-	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	offset = CONSISTENT_OFFSET(c->vm_start);
+	idx = offset >> PTE_SHIFT;
+	offset &= (1 << PTE_SHIFT) - 1;
+	ptep = consistent_ptes[idx] + offset;
+
 	do {
 		pte_t pte = ptep_get_and_clear(ptep);
 		unsigned long pfn;
 
 		ptep++;
+		offset++;
+		if (offset > ((1 << PTE_SHIFT) - 1)) {
+			ptep = consistent_ptes[++idx];
+			offset = 0;
+		}
 
 		if (!pte_none(pte) && pte_present(pte)) {
 			pfn = pte_pfn(pte);
@@ -328,13 +356,22 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
-	int ret = 0;
+	int ret = 0, i;
+	unsigned long address;
 
 	spin_lock(&init_mm.page_table_lock);
 
-	do {
-		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
-		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+	consistent_ptes = (pte_t **)kmalloc(sizeof(pte_t **) * 
+					CONSISTENT_PTE_PAGENR, GFP_KERNEL);
+	if (!consistent_ptes) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	
+	for (i = 0, address = CONSISTENT_BASE; i < CONSISTENT_PTE_PAGENR; i++) {
+		pgd = pgd_offset(&init_mm, address);
+		pmd = pmd_alloc(&init_mm, pgd, address);
 		if (!pmd) {
 			printk(KERN_ERR "%s: no pmd tables\n", __func__);
 			ret = -ENOMEM;
@@ -342,16 +379,19 @@
 		}
 		WARN_ON(!pmd_none(*pmd));
 
-		pte = pte_alloc_kernel(&init_mm, pmd, CONSISTENT_BASE);
+		pte = pte_alloc_kernel(&init_mm, pmd, address);
 		if (!pte) {
 			printk(KERN_ERR "%s: no pte tables\n", __func__);
 			ret = -ENOMEM;
 			break;
 		}
 
-		consistent_pte = pte;
-	} while (0);
+		consistent_ptes[i] = pte;
+
+		address += CONSISTENT_SIZE_PER_PTEPAGE;
+	}
 
+out:
 	spin_unlock(&init_mm.page_table_lock);
 
 	return ret;
