diff options
Diffstat (limited to 'arch/mn10300/mm/cache-flush-icache.c')
-rw-r--r-- | arch/mn10300/mm/cache-flush-icache.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/arch/mn10300/mm/cache-flush-icache.c b/arch/mn10300/mm/cache-flush-icache.c index 0e471e1cb2da..fdb1a9db20f0 100644 --- a/arch/mn10300/mm/cache-flush-icache.c +++ b/arch/mn10300/mm/cache-flush-icache.c @@ -11,6 +11,9 @@ #include <linux/module.h> #include <linux/mm.h> #include <asm/cacheflush.h> +#include <asm/smp.h> +#include "cache-smp.h" + /** * flush_icache_page - Flush a page from the dcache and invalidate the icache * @vma: The VMA the page is part of. @@ -22,9 +25,15 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page) { unsigned long start = page_to_phys(page); + unsigned long flags; + + flags = smp_lock_cache(); + + mn10300_local_dcache_flush_page(start); + mn10300_local_icache_inv_page(start); - mn10300_dcache_flush_page(start); - mn10300_icache_inv_page(start); + smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, start + PAGE_SIZE); + smp_unlock_cache(flags); } EXPORT_SYMBOL(flush_icache_page); @@ -82,8 +91,9 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) /* flush the dcache and invalidate the icache coverage on that * region */ - mn10300_dcache_flush_range2(addr + off, size); - mn10300_icache_inv_range2(addr + off, size); + mn10300_local_dcache_flush_range2(addr + off, size); + mn10300_local_icache_inv_range2(addr + off, size); + smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, end); } /** @@ -98,28 +108,32 @@ static void flush_icache_page_range(unsigned long start, unsigned long end) void flush_icache_range(unsigned long start, unsigned long end) { unsigned long start_page, end_page; + unsigned long flags; + + flags = smp_lock_cache(); if (end > 0x80000000UL) { /* addresses above 0xa0000000 do not go through the cache */ if (end > 0xa0000000UL) { end = 0xa0000000UL; if (start >= end) - return; + goto done; } /* kernel addresses between 0x80000000 and 0x9fffffff do not * require page tables, so we just map such addresses * directly */ start_page = (start >= 0x80000000UL) ? start : 0x80000000UL; - mn10300_dcache_flush_range(start_page, end); - mn10300_icache_inv_range(start_page, end); + mn10300_local_dcache_flush_range(start_page, end); + mn10300_local_icache_inv_range(start_page, end); + smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start_page, end); if (start_page == start) - return; + goto done; end = start_page; } start_page = start & PAGE_MASK; - end_page = end & PAGE_MASK; + end_page = (end - 1) & PAGE_MASK; if (start_page == end_page) { /* the first and last bytes are on the same page */ @@ -132,6 +146,10 @@ void flush_icache_range(unsigned long start, unsigned long end) /* more than 2 pages; just flush the entire cache */ mn10300_dcache_flush(); mn10300_icache_inv(); + smp_cache_call(SMP_IDCACHE_INV_FLUSH, 0, 0); } + +done: + smp_unlock_cache(flags); } EXPORT_SYMBOL(flush_icache_range); |