aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/mm/cache.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-08-21 17:23:14 +0900
committerPaul Mundt <lethal@linux-sh.org>2009-08-21 17:23:14 +0900
commitf26b2a562b46ab186c8383993ab1332673ac4a47 (patch)
tree5cf52089da5ca762c07cf6c1364a6aa411fb3038 /arch/sh/mm/cache.c
parentf9bd71f255b4349c4f9f596863161fd5182f67fa (diff)
sh: Make cache flushers SMP-aware.
This does a bit of rework for making the cache flushers SMP-aware. The function pointer-based flushers are renamed to local variants with the exported interface being commonly implemented and wrapping as necessary. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/cache.c')
-rw-r--r--arch/sh/mm/cache.c137
1 files changed, 78 insertions, 59 deletions
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index d6023946043..411fe605842 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -1,5 +1,5 @@
/*
- * arch/sh/mm/pg-mmu.c
+ * arch/sh/mm/cache.c
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
* Copyright (C) 2002 - 2009 Paul Mundt
@@ -10,63 +10,26 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/fs.h>
+#include <linux/smp.h>
#include <linux/highmem.h>
#include <linux/module.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
-void (*flush_cache_all)(void);
-void (*flush_cache_mm)(struct mm_struct *mm);
-void (*flush_cache_dup_mm)(struct mm_struct *mm);
-void (*flush_cache_page)(struct vm_area_struct *vma,
- unsigned long addr, unsigned long pfn);
-void (*flush_cache_range)(struct vm_area_struct *vma,
- unsigned long start, unsigned long end);
-void (*flush_dcache_page)(struct page *page);
-void (*flush_icache_range)(unsigned long start, unsigned long end);
-void (*flush_icache_page)(struct vm_area_struct *vma,
- struct page *page);
-void (*flush_cache_sigtramp)(unsigned long address);
+void (*local_flush_cache_all)(void *args) = cache_noop;
+void (*local_flush_cache_mm)(void *args) = cache_noop;
+void (*local_flush_cache_dup_mm)(void *args) = cache_noop;
+void (*local_flush_cache_page)(void *args) = cache_noop;
+void (*local_flush_cache_range)(void *args) = cache_noop;
+void (*local_flush_dcache_page)(void *args) = cache_noop;
+void (*local_flush_icache_range)(void *args) = cache_noop;
+void (*local_flush_icache_page)(void *args) = cache_noop;
+void (*local_flush_cache_sigtramp)(void *args) = cache_noop;
+
void (*__flush_wback_region)(void *start, int size);
void (*__flush_purge_region)(void *start, int size);
void (*__flush_invalidate_region)(void *start, int size);
-static inline void noop_flush_cache_all(void)
-{
-}
-
-static inline void noop_flush_cache_mm(struct mm_struct *mm)
-{
-}
-
-static inline void noop_flush_cache_page(struct vm_area_struct *vma,
- unsigned long addr, unsigned long pfn)
-{
-}
-
-static inline void noop_flush_cache_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
-}
-
-static inline void noop_flush_dcache_page(struct page *page)
-{
-}
-
-static inline void noop_flush_icache_range(unsigned long start,
- unsigned long end)
-{
-}
-
-static inline void noop_flush_icache_page(struct vm_area_struct *vma,
- struct page *page)
-{
-}
-
-static inline void noop_flush_cache_sigtramp(unsigned long address)
-{
-}
-
static inline void noop__flush_region(void *start, int size)
{
}
@@ -184,6 +147,72 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr)
}
}
+void flush_cache_all(void)
+{
+ on_each_cpu(local_flush_cache_all, NULL, 1);
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+ on_each_cpu(local_flush_cache_mm, mm, 1);
+}
+
+void flush_cache_dup_mm(struct mm_struct *mm)
+{
+ on_each_cpu(local_flush_cache_dup_mm, mm, 1);
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long pfn)
+{
+ struct flusher_data data;
+
+ data.vma = vma;
+ data.addr1 = addr;
+ data.addr2 = pfn;
+
+ on_each_cpu(local_flush_cache_page, (void *)&data, 1);
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct flusher_data data;
+
+ data.vma = vma;
+ data.addr1 = start;
+ data.addr2 = end;
+
+ on_each_cpu(local_flush_cache_range, (void *)&data, 1);
+}
+
+void flush_dcache_page(struct page *page)
+{
+ on_each_cpu(local_flush_dcache_page, page, 1);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ struct flusher_data data;
+
+ data.vma = NULL;
+ data.addr1 = start;
+ data.addr2 = end;
+
+ on_each_cpu(local_flush_icache_range, (void *)&data, 1);
+}
+
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ /* Nothing uses the VMA, so just pass the struct page along */
+ on_each_cpu(local_flush_icache_page, page, 1);
+}
+
+void flush_cache_sigtramp(unsigned long address)
+{
+ on_each_cpu(local_flush_cache_sigtramp, (void *)address, 1);
+}
+
static void compute_alias(struct cache_info *c)
{
c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
@@ -230,16 +259,6 @@ void __init cpu_cache_init(void)
compute_alias(&boot_cpu_data.dcache);
compute_alias(&boot_cpu_data.scache);
- flush_cache_all = noop_flush_cache_all;
- flush_cache_mm = noop_flush_cache_mm;
- flush_cache_dup_mm = noop_flush_cache_mm;
- flush_cache_page = noop_flush_cache_page;
- flush_cache_range = noop_flush_cache_range;
- flush_dcache_page = noop_flush_dcache_page;
- flush_icache_range = noop_flush_icache_range;
- flush_icache_page = noop_flush_icache_page;
- flush_cache_sigtramp = noop_flush_cache_sigtramp;
-
__flush_wback_region = noop__flush_region;
__flush_purge_region = noop__flush_region;
__flush_invalidate_region = noop__flush_region;