summary refs log tree commit diff
path: root/arch/mn10300/include
diff options
context:
space:
mode:
authorAkira Takeuchi <takeuchi.akr@jp.panasonic.com>2010-10-27 17:28:51 +0100
committerDavid Howells <dhowells@redhat.com>2010-10-27 17:28:51 +0100
commit965ea4bbb9ae926358273368144ba838c561bc38 (patch)
treec6ee08f2f2970bb500ccc7cf58de6beea870e4f8 /arch/mn10300/include
parentdccbf4853a31a3f774f38c402209d23388d99f52 (diff)
downloadlinux-965ea4bbb9ae926358273368144ba838c561bc38.tar.gz
MN10300: SMP TLB flushing
Implement global TLB 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/include')
-rw-r--r--arch/mn10300/include/asm/mmu_context.h22
-rw-r--r--arch/mn10300/include/asm/tlbflush.h81
2 files changed, 74 insertions, 29 deletions
diff --git a/arch/mn10300/include/asm/mmu_context.h b/arch/mn10300/include/asm/mmu_context.h
index 5fb3648968ae..c8f6c82672ad 100644
--- a/arch/mn10300/include/asm/mmu_context.h
+++ b/arch/mn10300/include/asm/mmu_context.h
@@ -36,6 +36,22 @@
 
 #define enter_lazy_tlb(mm, tsk)	do {} while (0)
 
+static inline void cpu_ran_vm(int cpu, struct mm_struct *mm)
+{
+#ifdef CONFIG_SMP
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
+#endif
+}
+
+static inline bool cpu_maybe_ran_vm(int cpu, struct mm_struct *mm)
+{
+#ifdef CONFIG_SMP
+	return cpumask_test_and_set_cpu(cpu, mm_cpumask(mm));
+#else
+	return true;
+#endif
+}
+
 #ifdef CONFIG_MN10300_TLB_USE_PIDR
 extern unsigned long mmu_context_cache[NR_CPUS];
 #define mm_context(mm)	(mm->context.tlbpid[smp_processor_id()])
@@ -127,7 +143,13 @@ static inline void activate_context(struct mm_struct *mm)
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk)
 {
+	int cpu = smp_processor_id();
+
 	if (prev != next) {
+#ifdef CONFIG_SMP
+		per_cpu(cpu_tlbstate, cpu).active_mm = next;
+#endif
+		cpu_ran_vm(cpu, next);
 		PTBR = (unsigned long) next->pgd;
 		activate_context(next);
 	}
diff --git a/arch/mn10300/include/asm/tlbflush.h b/arch/mn10300/include/asm/tlbflush.h
index c3c194d4031e..efddd6e1adea 100644
--- a/arch/mn10300/include/asm/tlbflush.h
+++ b/arch/mn10300/include/asm/tlbflush.h
@@ -11,6 +11,7 @@
 #ifndef _ASM_TLBFLUSH_H
 #define _ASM_TLBFLUSH_H
 
+#include <linux/mm.h>
 #include <asm/processor.h>
 
 struct tlb_state {
@@ -93,39 +94,61 @@ void local_flush_tlb_page(struct mm_struct *mm, unsigned long addr)
  *  - flush_tlb_range(mm, start, end) flushes a range of pages
  *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  */
-#define flush_tlb_all()				\
-do {						\
-	preempt_disable();			\
-	local_flush_tlb_all();			\
-	preempt_enable();			\
-} while (0)
-
-#define flush_tlb_mm(mm)			\
-do {						\
-	preempt_disable();			\
-	local_flush_tlb_all();			\
-	preempt_enable();			\
-} while (0)
-
-#define flush_tlb_range(vma, start, end)			\
-do {								\
-	unsigned long __s __attribute__((unused)) = (start);	\
-	unsigned long __e __attribute__((unused)) = (end);	\
-	preempt_disable();					\
-	local_flush_tlb_all();					\
-	preempt_enable();					\
-} while (0)
+#ifdef CONFIG_SMP
+
+#include <asm/smp.h>
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_current_task(void);
+extern void flush_tlb_mm(struct mm_struct *);
+extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+
+#define flush_tlb()		flush_tlb_current_task()
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	flush_tlb_mm(vma->vm_mm);
+}
+
+#else   /* CONFIG_SMP */
+
+static inline void flush_tlb_all(void)
+{
+	preempt_disable();
+	local_flush_tlb_all();
+	preempt_enable();
+}
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	preempt_disable();
+	local_flush_tlb_all();
+	preempt_enable();
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	preempt_disable();
+	local_flush_tlb_all();
+	preempt_enable();
+}
 
 #define flush_tlb_page(vma, addr)	local_flush_tlb_page((vma)->vm_mm, addr)
 #define flush_tlb()			flush_tlb_all()
 
-#define flush_tlb_kernel_range(start, end)			\
-do {								\
-	unsigned long __s __attribute__((unused)) = (start);	\
-	unsigned long __e __attribute__((unused)) = (end);	\
-	flush_tlb_all();					\
-} while (0)
+#endif /* CONFIG_SMP */
 
-#define flush_tlb_pgtables(mm, start, end)	do {} while (0)
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	flush_tlb_all();
+}
+
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+				      unsigned long start, unsigned long end)
+{
+}
 
 #endif /* _ASM_TLBFLUSH_H */