aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sun4m_smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/sun4m_smp.c')
-rw-r--r--arch/sparc/kernel/sun4m_smp.c124
1 files changed, 44 insertions, 80 deletions
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 02db9a0412ce..128af7304288 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -4,14 +4,18 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/clockchips.h>
#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"
@@ -30,26 +34,22 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
return val;
}
-static void smp4m_ipi_init(void);
-static void smp_setup_percpu_timer(void);
-
void __cpuinit smp4m_callin(void)
{
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);
- /* Get our local ticker going. */
- smp_setup_percpu_timer();
+ register_percpu_ce(cpuid);
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 +61,8 @@ void __cpuinit smp4m_callin(void)
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"
@@ -86,23 +86,19 @@ void __cpuinit smp4m_callin(void)
*/
void __init smp4m_boot_cpus(void)
{
- smp4m_ipi_init();
- smp_setup_percpu_timer();
- local_flush_cache_all();
+ sun4m_unmask_profile_irq();
+ local_ops->cache_all();
}
-int __cpuinit smp4m_boot_one_cpu(int i)
+int __cpuinit smp4m_boot_one_cpu(int i, struct task_struct *idle)
{
unsigned long *entry = &sun4m_cpu_startup;
- struct task_struct *p;
int timeout;
int cpu_node;
cpu_find_by_mid(i, &cpu_node);
+ current_set[i] = task_thread_info(idle);
- /* Cook up an idler for this guy. */
- p = fork_idle(i);
- current_set[i] = task_thread_info(p);
/* See trampoline.S for details... */
entry += ((i - 1) * 3);
@@ -117,7 +113,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
/* 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 +128,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
return -ENODEV;
}
- local_flush_cache_all();
+ local_ops->cache_all();
return 0;
}
@@ -149,30 +145,29 @@ void __init smp4m_smp_done(void)
prev = &cpu_data(i).next;
}
*prev = first;
- local_flush_cache_all();
+ local_ops->cache_all();
/* Ok, they are spinning and ready to go. */
}
-
-/* Initialize IPIs on the SUN4M SMP machine */
-static void __init smp4m_ipi_init(void)
+static void sun4m_send_ipi(int cpu, int level)
{
+ sbus_writel(SUN4M_SOFT_INT(level), &sun4m_irq_percpu[cpu]->set);
}
-static void smp4m_ipi_resched(int cpu)
+static void sun4m_ipi_resched(int cpu)
{
- set_cpu_int(cpu, IRQ_IPI_RESCHED);
+ sun4m_send_ipi(cpu, IRQ_IPI_RESCHED);
}
-static void smp4m_ipi_single(int cpu)
+static void sun4m_ipi_single(int cpu)
{
- set_cpu_int(cpu, IRQ_IPI_SINGLE);
+ sun4m_send_ipi(cpu, IRQ_IPI_SINGLE);
}
-static void smp4m_ipi_mask_one(int cpu)
+static void sun4m_ipi_mask_one(int cpu)
{
- set_cpu_int(cpu, IRQ_IPI_MASK);
+ sun4m_send_ipi(cpu, IRQ_IPI_MASK);
}
static struct smp_funcall {
@@ -189,7 +184,7 @@ static struct smp_funcall {
static DEFINE_SPINLOCK(cross_call_lock);
/* Cross calls must be serialized, at least currently. */
-static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
+static void sun4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4)
{
@@ -216,7 +211,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
if (cpumask_test_cpu(i, &mask)) {
ccall_info.processors_in[i] = 0;
ccall_info.processors_out[i] = 0;
- set_cpu_int(i, IRQ_CROSS_CALL);
+ sun4m_send_ipi(i, IRQ_CROSS_CALL);
} else {
ccall_info.processors_in[i] = 1;
ccall_info.processors_out[i] = 1;
@@ -260,64 +255,33 @@ void smp4m_cross_call_irq(void)
void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
{
struct pt_regs *old_regs;
+ struct clock_event_device *ce;
int cpu = smp_processor_id();
old_regs = set_irq_regs(regs);
- sun4m_clear_profile_irq(cpu);
-
- profile_tick(CPU_PROFILING);
+ ce = &per_cpu(sparc32_clockevent, cpu);
- if (!--prof_counter(cpu)) {
- int user = user_mode(regs);
+ if (ce->mode & CLOCK_EVT_MODE_PERIODIC)
+ sun4m_clear_profile_irq(cpu);
+ else
+ sparc_config.load_profile_irq(cpu, 0); /* Is this needless? */
- irq_enter();
- update_process_times(user);
- irq_exit();
+ irq_enter();
+ ce->event_handler(ce);
+ irq_exit();
- prof_counter(cpu) = prof_multiplier(cpu);
- }
set_irq_regs(old_regs);
}
-static void __cpuinit smp_setup_percpu_timer(void)
-{
- int cpu = smp_processor_id();
-
- prof_counter(cpu) = prof_multiplier(cpu) = 1;
- load_profile_irq(cpu, lvl14_resolution);
-
- if (cpu == boot_cpu_id)
- sun4m_unmask_profile_irq();
-}
-
-static void __init smp4m_blackbox_id(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
- addr[1] = 0x8130200c | rd | rs1; /* srl reg, 0xc, reg */
- addr[2] = 0x80082003 | rd | rs1; /* and reg, 3, reg */
-}
-
-static void __init smp4m_blackbox_current(unsigned *addr)
-{
- int rd = *addr & 0x3e000000;
- int rs1 = rd >> 11;
-
- addr[0] = 0x81580000 | rd; /* rd %tbr, reg */
- addr[2] = 0x8130200a | rd | rs1; /* srl reg, 0xa, reg */
- addr[4] = 0x8008200c | rd | rs1; /* and reg, 0xc, reg */
-}
+static const struct sparc32_ipi_ops sun4m_ipi_ops = {
+ .cross_call = sun4m_cross_call,
+ .resched = sun4m_ipi_resched,
+ .single = sun4m_ipi_single,
+ .mask_one = sun4m_ipi_mask_one,
+};
void __init sun4m_init_smp(void)
{
- BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4m_blackbox_id);
- BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
- BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_resched, smp4m_ipi_resched, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_single, smp4m_ipi_single, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(smp_ipi_mask_one, smp4m_ipi_mask_one, BTFIXUPCALL_NORM);
+ sparc32_ipi_ops = &sun4m_ipi_ops;
}