summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-06-22 22:42:32 +0100
committerRalf Baechle <ralf@linux-mips.org>2006-07-13 21:25:56 +0100
commit25969354a385f347b55aafb1040dfc21263fa7c3 (patch)
tree1ba512ac5f4984260c32b02594e70fbefa6b9894
parentf1aaee53f2877a7afa55e8245c241ff60a86367d (diff)
downloadlinux-25969354a385f347b55aafb1040dfc21263fa7c3.tar.gz
[MIPS] Avoid interprocessor function calls.
On the 34K where multiple virtual processors are implemented in a single
core and share a single TLB, interprocessor function calls are not needed
to flush a cache, so avoid them.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/smp.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 9096a5ea4229..221895802dca 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -319,6 +319,32 @@ static void flush_tlb_mm_ipi(void *mm)
 }
 
 /*
+ * Special Variant of smp_call_function for use by TLB functions:
+ *
+ *  o No return value
+ *  o collapses to normal function call on UP kernels
+ *  o collapses to normal function call on systems with a single shared
+ *    primary cache.
+ *  o CONFIG_MIPS_MT_SMTC currently implies there is only one physical core.
+ */
+static inline void smp_on_other_tlbs(void (*func) (void *info), void *info)
+{
+#ifndef CONFIG_MIPS_MT_SMTC
+	smp_call_function(func, info, 1, 1);
+#endif
+}
+
+static inline void smp_on_each_tlb(void (*func) (void *info), void *info)
+{
+	preempt_disable();
+
+	smp_on_other_tlbs(func, info);
+	func(info);
+
+	preempt_enable();
+}
+
+/*
  * The following tlb flush calls are invoked when old translations are
  * being torn down, or pte attributes are changing. For single threaded
  * address spaces, a new context is obtained on the current cpu, and tlb
@@ -336,7 +362,7 @@ void flush_tlb_mm(struct mm_struct *mm)
 	preempt_disable();
 
 	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
-		smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1);
+		smp_on_other_tlbs(flush_tlb_mm_ipi, (void *)mm);
 	} else {
 		int i;
 		for (i = 0; i < num_online_cpus(); i++)
@@ -372,7 +398,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l
 		fd.vma = vma;
 		fd.addr1 = start;
 		fd.addr2 = end;
-		smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1);
+		smp_on_other_tlbs(flush_tlb_range_ipi, (void *)&fd);
 	} else {
 		int i;
 		for (i = 0; i < num_online_cpus(); i++)
@@ -414,7 +440,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 
 		fd.vma = vma;
 		fd.addr1 = page;
-		smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1);
+		smp_on_other_tlbs(flush_tlb_page_ipi, (void *)&fd);
 	} else {
 		int i;
 		for (i = 0; i < num_online_cpus(); i++)
@@ -434,8 +460,7 @@ static void flush_tlb_one_ipi(void *info)
 
 void flush_tlb_one(unsigned long vaddr)
 {
-	smp_call_function(flush_tlb_one_ipi, (void *) vaddr, 1, 1);
-	local_flush_tlb_one(vaddr);
+	smp_on_each_tlb(flush_tlb_one_ipi, (void *) vaddr);
 }
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);