Use the memory hotplug hooks to flush kmaps when hotplug occurs. See the comment for more info. Signed-off-by: Dave Hansen --- memhotplug-dave/mm/highmem.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+) diff -puN include/asm-frv/highmem.h~P2-call-flush_all_zero_pkmaps-on-hotplug-ops include/asm-frv/highmem.h diff -puN include/linux/highmem.h~P2-call-flush_all_zero_pkmaps-on-hotplug-ops include/linux/highmem.h diff -puN mm/highmem.c~P2-call-flush_all_zero_pkmaps-on-hotplug-ops mm/highmem.c --- memhotplug/mm/highmem.c~P2-call-flush_all_zero_pkmaps-on-hotplug-ops 2005-07-28 13:51:17.000000000 -0700 +++ memhotplug-dave/mm/highmem.c 2005-07-28 13:51:17.000000000 -0700 @@ -26,6 +26,7 @@ #include #include #include +#include #include static mempool_t *page_pool, *isa_page_pool; @@ -98,6 +99,31 @@ static void flush_all_zero_pkmaps(void) flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); } +/* + * 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. + */ +static int flush_all_zero_pkmaps_callback(struct notifier_block *nfb, + unsigned long action, + void *unused) +{ + if (action == MEM_OFFLINE) + flush_all_zero_pkmaps(); + + return NOTIFY_OK; +} + +static __init int init_highmem_hotplug_notifier(void) +{ + hotplug_memory_notifier(flush_all_zero_pkmaps_callback, 0); + + return 0; +} + +__initcall(init_highmem_hotplug_notifier); + static inline unsigned long map_new_virtual(struct page *page) { unsigned long vaddr; _