summaryrefslogtreecommitdiff
path: root/arch/mn10300/mm/cache-flush-icache.c
diff options
context:
space:
mode:
authorAkira Takeuchi <takeuchi.akr@jp.panasonic.com>2010-10-27 17:28:47 +0100
committerDavid Howells <dhowells@redhat.com>2010-10-27 17:28:47 +0100
commit8be062892365b09f41d64cda7fa63d306e95e0c9 (patch)
tree89db630e8d0e8090d09a9dfc6535427456cda631 /arch/mn10300/mm/cache-flush-icache.c
parentb478491f2628114b2eae76587f22ce3789b66012 (diff)
MN10300: Cache: Implement SMP global cache flushing
Implement SMP global cache flushing for MN10300. This will be used by the AM34 which is SMP capable. Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com> Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'arch/mn10300/mm/cache-flush-icache.c')
-rw-r--r--arch/mn10300/mm/cache-flush-icache.c36
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);