From: Matt Porter <mporter@kernel.crashing.org>

This fixes a memory leak when freeing pgds on PPC44x.


---

 25-akpm/arch/ppc/kernel/misc.S |    7 +++++--
 25-akpm/arch/ppc/mm/pgtable.c  |    4 ++--
 25-akpm/include/asm-ppc/page.h |    3 ++-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff -puN arch/ppc/kernel/misc.S~ppc64-memleak-fix arch/ppc/kernel/misc.S
--- 25/arch/ppc/kernel/misc.S~ppc64-memleak-fix	Tue Apr  6 15:55:37 2004
+++ 25-akpm/arch/ppc/kernel/misc.S	Tue Apr  6 15:55:37 2004
@@ -738,12 +738,15 @@ _GLOBAL(__flush_dcache_icache_phys)
 	blr
 
 /*
- * Clear a page using the dcbz instruction, which doesn't cause any
+ * Clear pages using the dcbz instruction, which doesn't cause any
  * memory traffic (except to write out any cache lines which get
  * displaced).  This only works on cacheable memory.
+ *
+ * void clear_pages(void *page, int order) ;
  */
-_GLOBAL(clear_page)
+_GLOBAL(clear_pages)
 	li	r0,4096/L1_CACHE_LINE_SIZE
+	slw	r0,r0,r4
 	mtctr	r0
 #ifdef CONFIG_8xx
 	li	r4, 0
diff -puN arch/ppc/mm/pgtable.c~ppc64-memleak-fix arch/ppc/mm/pgtable.c
--- 25/arch/ppc/mm/pgtable.c~ppc64-memleak-fix	Tue Apr  6 15:55:37 2004
+++ 25-akpm/arch/ppc/mm/pgtable.c	Tue Apr  6 15:55:37 2004
@@ -71,13 +71,13 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 	pgd_t *ret;
 
 	if ((ret = (pgd_t *)__get_free_pages(GFP_KERNEL, PGDIR_ORDER)) != NULL)
-		clear_page(ret);
+		clear_pages(ret, PGDIR_ORDER);
 	return ret;
 }
 
 void pgd_free(pgd_t *pgd)
 {
-	free_page((unsigned long)pgd);
+	free_pages((unsigned long)pgd, PGDIR_ORDER);
 }
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
diff -puN include/asm-ppc/page.h~ppc64-memleak-fix include/asm-ppc/page.h
--- 25/include/asm-ppc/page.h~ppc64-memleak-fix	Tue Apr  6 15:55:37 2004
+++ 25-akpm/include/asm-ppc/page.h	Tue Apr  6 15:55:37 2004
@@ -84,7 +84,8 @@ typedef unsigned long pgprot_t;
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
 struct page;
-extern void clear_page(void *page);
+extern void clear_pages(void *page, int order);
+static inline void clear_page(void *page) { clear_pages(page, 0); }
 extern void copy_page(void *to, void *from);
 extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr,

_