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>
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index d602394..411fe60 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_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 @@
 	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;