
Fixes a bug with permanent kmaps.  It keeps a pte to a page for long
after a kunmap() has been done to keep global tlb flushes to a minimum.
This is OK, except that it works out a pfn and a struct page from that
pte when it flushes, which can be long after the page is removed.  

This flushes before removal

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

 memhotplug-dave/include/asm-i386/highmem.h |    1 +
 memhotplug-dave/include/linux/highmem.h    |    1 +
 memhotplug-dave/include/linux/memory.h     |    2 ++
 memhotplug-dave/mm/highmem.c               |    2 +-
 memhotplug-dave/mm/memory_hotplug.c        |    8 ++++++++
 5 files changed, 13 insertions(+), 1 deletion(-)

diff -puN mm/memory_hotplug.c~N3-i386-invalidate-kmap-ptes mm/memory_hotplug.c
--- memhotplug/mm/memory_hotplug.c~N3-i386-invalidate-kmap-ptes	2004-12-10 13:53:00.000000000 -0800
+++ memhotplug-dave/mm/memory_hotplug.c	2004-12-10 13:53:00.000000000 -0800
@@ -20,6 +20,7 @@
 #include <linux/nonlinear.h>
 #include <linux/memory.h>
 #include <linux/memory_hotplug.h>
+#include <linux/highmem.h>
 
 #include <asm/tlbflush.h>
 
@@ -163,6 +164,13 @@ int __remove_pages(struct zone *zone, un
 		unregister_memory_section(phys_section);
 	}
 
+	/*
+	 * Permanent kmaps keep ptes to a page long after a kunmap() to
+	 * keep global tlb flushes to a minimum.  When it flushes, it
+	 * works out a pfn and a struct page from that pte which can be
+	 * long after the page is removed.  Flush before removal.
+	 */
+	flush_all_zero_pkmaps();
 	invalidate_phys_mapping(start_pfn, nr_pages);
 
 	return 0;
diff -puN mm/highmem.c~N3-i386-invalidate-kmap-ptes mm/highmem.c
--- memhotplug/mm/highmem.c~N3-i386-invalidate-kmap-ptes	2004-12-10 13:53:00.000000000 -0800
+++ memhotplug-dave/mm/highmem.c	2004-12-10 13:53:00.000000000 -0800
@@ -59,7 +59,7 @@ pte_t * pkmap_page_table;
 
 static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);
 
-static void flush_all_zero_pkmaps(void)
+void flush_all_zero_pkmaps(void)
 {
 	int i;
 
diff -puN include/asm-i386/highmem.h~N3-i386-invalidate-kmap-ptes include/asm-i386/highmem.h
--- memhotplug/include/asm-i386/highmem.h~N3-i386-invalidate-kmap-ptes	2004-12-10 13:53:00.000000000 -0800
+++ memhotplug-dave/include/asm-i386/highmem.h	2004-12-10 13:53:00.000000000 -0800
@@ -67,6 +67,7 @@ extern void kmap_init(void);
 
 extern void * FASTCALL(kmap_high(struct page *page));
 extern void FASTCALL(kunmap_high(struct page *page));
+extern void flush_all_zero_pkmaps(void);
 
 void *kmap(struct page *page);
 void kunmap(struct page *page);
diff -puN include/linux/highmem.h~N3-i386-invalidate-kmap-ptes include/linux/highmem.h
--- memhotplug/include/linux/highmem.h~N3-i386-invalidate-kmap-ptes	2004-12-10 13:53:00.000000000 -0800
+++ memhotplug-dave/include/linux/highmem.h	2004-12-10 13:53:00.000000000 -0800
@@ -30,6 +30,7 @@ static inline void *kmap(struct page *pa
 #define kunmap_atomic(addr, idx) do { char *p = addr; (void)p; } while (0)
 #define kmap_atomic_pfn(pfn, idx) ((char *)page_address(pfn_to_page(pfn)))
 #define kmap_atomic_to_page(ptr) virt_to_page(ptr)
+#define flush_all_zero_pkmaps()		do { } while (0)
 
 #endif /* CONFIG_HIGHMEM */
 
diff -puN include/linux/memory.h~N3-i386-invalidate-kmap-ptes include/linux/memory.h
--- memhotplug/include/linux/memory.h~N3-i386-invalidate-kmap-ptes	2004-12-10 13:53:00.000000000 -0800
+++ memhotplug-dave/include/linux/memory.h	2004-12-10 13:53:00.000000000 -0800
@@ -56,6 +56,8 @@ struct memory_block {
 
 extern int register_memory(struct memory_block *, unsigned int, struct node *);
 extern int register_new_memory(unsigned int section);
+extern int unregister_memory_section(unsigned int phys_section_nr);
+extern int invalidate_phys_mapping(unsigned long pfn, unsigned long nr_pages);
 struct notifier_block;
 
 extern int register_memory_notifier(struct notifier_block *nb);
_
