sparc32: Move cache and TLB flushes over to method ops.
This eliminated most of the remaining users of btfixup.
There are some complications because of the special cases we
have for sun4d, leon, and some flavors of viking.
It was found that there are no cases where a flush_page_for_dma
method was not hooked up to something, so the "noflush" iommu
methods were removed.
Add some documentation to the viking_sun4d_smp_ops to describe exactly
the hardware bug which causes us to need special TLB flushing on
sun4d.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index e57435f..aeb411c 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -427,7 +427,7 @@
*/
local_irq_save(flags);
patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
}
#endif
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 356dfc4..f3e3630 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -75,8 +75,8 @@
{
int cpuid = hard_smpleon_processor_id();
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
leon_configure_cache_smp();
notify_cpu_starting(cpuid);
@@ -87,8 +87,8 @@
calibrate_delay();
smp_store_cpu_info(cpuid);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/*
* Unblock the master CPU _only_ when the scheduler state
@@ -99,8 +99,8 @@
*/
do_swap(&cpu_callin_map[cpuid], 1);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t" : : "r"(¤t_set[cpuid])
@@ -143,8 +143,8 @@
}
}
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
}
void leon_smp_setbroadcast(unsigned int mask)
@@ -199,7 +199,7 @@
leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
leon_configure_cache_smp();
- local_flush_cache_all();
+ local_ops->cache_all();
}
@@ -226,7 +226,7 @@
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d : (irqmp: 0x%x)\n", (unsigned int)i,
(unsigned int)&leon3_irqctrl_regs->mpstatus);
- local_flush_cache_all();
+ local_ops->cache_all();
/* Make sure all IRQs are of from the start for this new CPU */
LEON_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[i], 0);
@@ -251,7 +251,7 @@
leon_enable_irq_cpu(leon_ipi_irq, i);
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -271,7 +271,7 @@
}
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Free unneeded trap tables */
if (!cpu_present(1)) {
@@ -337,7 +337,7 @@
local_irq_save(flags);
trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];
trap_table->inst_three += smpleon_ipi - real_irq_entry;
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
for_each_possible_cpu(cpu) {
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index 7c11439..8cd5c79 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -171,128 +171,6 @@
irq_exit();
}
-void smp_flush_cache_all(void)
-{
- xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all));
- local_flush_cache_all();
-}
-
-void smp_flush_tlb_all(void)
-{
- xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all));
- local_flush_tlb_all();
-}
-
-void smp_flush_cache_mm(struct mm_struct *mm)
-{
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm);
- local_flush_cache_mm(mm);
- }
-}
-
-void smp_flush_tlb_mm(struct mm_struct *mm)
-{
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask)) {
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
- if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
- cpumask_copy(mm_cpumask(mm),
- cpumask_of(smp_processor_id()));
- }
- local_flush_tlb_mm(mm);
- }
-}
-
-void smp_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if (mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) vma, start, end);
- local_flush_cache_range(vma, start, end);
- }
-}
-
-void smp_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if (mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) vma, start, end);
- local_flush_tlb_range(vma, start, end);
- }
-}
-
-void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page);
- local_flush_cache_page(vma, page);
- }
-}
-
-void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- struct mm_struct *mm = vma->vm_mm;
-
- if(mm->context != NO_CONTEXT) {
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page);
- local_flush_tlb_page(vma, page);
- }
-}
-
-void smp_flush_page_to_ram(unsigned long page)
-{
- /* Current theory is that those who call this are the one's
- * who have just dirtied their cache with the pages contents
- * in kernel space, therefore we only run this on local cpu.
- *
- * XXX This experiment failed, research further... -DaveM
- */
-#if 1
- xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_to_ram), page);
-#endif
- local_flush_page_to_ram(page);
-}
-
-void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
-{
- cpumask_t cpu_mask;
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
- if (!cpumask_empty(&cpu_mask))
- xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr);
- local_flush_sig_insns(mm, insn_addr);
-}
-
int setup_profiling_timer(unsigned int multiplier)
{
return -EINVAL;
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 15593ee..b2fdb3d 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -15,6 +15,7 @@
#include <asm/sbi.h>
#include <asm/cacheflush.h>
#include <asm/setup.h>
+#include <asm/oplib.h>
#include "kernel.h"
#include "irq.h"
@@ -411,7 +412,7 @@
trap_table->inst_two = lvl14_save[1];
trap_table->inst_three = lvl14_save[2];
trap_table->inst_four = lvl14_save[3];
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
#endif
}
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 576fe74..f17fd28 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -10,12 +10,14 @@
#include <linux/interrupt.h>
#include <linux/profile.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/switch_to.h>
#include <asm/tlbflush.h>
#include <asm/timer.h>
+#include <asm/oplib.h>
#include <asm/sbi.h>
#include <asm/mmu.h>
@@ -60,8 +62,8 @@
/* Enable level15 interrupt, disable level14 interrupt for now */
cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
notify_cpu_starting(cpuid);
/*
@@ -75,13 +77,13 @@
calibrate_delay();
smp_store_cpu_info(cpuid);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/* Allow master to continue. */
sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
barrier();
@@ -101,8 +103,8 @@
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
local_irq_enable(); /* We don't allow PIL 14 yet */
@@ -124,7 +126,7 @@
smp4d_ipi_init();
if (boot_cpu_id)
current_set[0] = NULL;
- local_flush_cache_all();
+ local_ops->cache_all();
}
int __cpuinit smp4d_boot_one_cpu(int i)
@@ -150,7 +152,7 @@
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
- local_flush_cache_all();
+ local_ops->cache_all();
prom_startcpu(cpu_node,
&smp_penguin_ctable, 0, (char *)entry);
@@ -168,7 +170,7 @@
return -ENODEV;
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -185,7 +187,7 @@
prev = &cpu_data(i).next;
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Ok, they are spinning and ready to go. */
smp_processors_ready = 1;
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 93f4603..32d3a5c 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -431,7 +431,7 @@
trap_table->inst_two = lvl14_save[1];
trap_table->inst_three = lvl14_save[2];
trap_table->inst_four = lvl14_save[3];
- local_flush_cache_all();
+ local_ops->cache_all();
local_irq_restore(flags);
}
#endif
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 29f8ace..afcf674 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -8,12 +8,14 @@
#include <linux/interrupt.h>
#include <linux/profile.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/switch_to.h>
#include <asm/tlbflush.h>
#include <asm/timer.h>
+#include <asm/oplib.h>
#include "irq.h"
#include "kernel.h"
@@ -38,8 +40,8 @@
{
int cpuid = hard_smp_processor_id();
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
notify_cpu_starting(cpuid);
@@ -48,8 +50,8 @@
calibrate_delay();
smp_store_cpu_info(cpuid);
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/*
* Unblock the master CPU _only_ when the scheduler state
@@ -61,8 +63,8 @@
swap_ulong(&cpu_callin_map[cpuid], 1);
/* XXX: What's up with all the flushes? */
- local_flush_cache_all();
- local_flush_tlb_all();
+ local_ops->cache_all();
+ local_ops->tlb_all();
/* Fix idle thread fields. */
__asm__ __volatile__("ld [%0], %%g6\n\t"
@@ -88,7 +90,7 @@
{
smp4m_ipi_init();
sun4m_unmask_profile_irq();
- local_flush_cache_all();
+ local_ops->cache_all();
}
int __cpuinit smp4m_boot_one_cpu(int i)
@@ -117,7 +119,7 @@
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
- local_flush_cache_all();
+ local_ops->cache_all();
prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
/* wheee... it's going... */
@@ -132,7 +134,7 @@
return -ENODEV;
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -149,7 +151,7 @@
prev = &cpu_data(i).next;
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Ok, they are spinning and ready to go. */
}