[MIPS] SMP: Call platform methods via ops structure.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
@ -17,7 +17,6 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/mipsmtregs.h>
|
||||
#include <asm/r4kcache.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/smp-ops.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
|
||||
@ -575,9 +576,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
arch_mem_init(cmdline_p);
|
||||
|
||||
resource_init();
|
||||
#ifdef CONFIG_SMP
|
||||
plat_smp_setup();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __init fpu_disable(char *s)
|
||||
|
@ -215,12 +215,117 @@ static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0)
|
||||
write_tc_c0_tchalt(TCHALT_H);
|
||||
}
|
||||
|
||||
static void vsmp_send_ipi_single(int cpu, unsigned int action)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
int vpflags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */
|
||||
|
||||
switch (action) {
|
||||
case SMP_CALL_FUNCTION:
|
||||
i = C_SW1;
|
||||
break;
|
||||
|
||||
case SMP_RESCHEDULE_YOURSELF:
|
||||
default:
|
||||
i = C_SW0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 1:1 mapping of vpe and tc... */
|
||||
settc(cpu);
|
||||
write_vpe_c0_cause(read_vpe_c0_cause() | i);
|
||||
evpe(vpflags);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void vsmp_send_ipi_mask(cpumask_t mask, unsigned int action)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for_each_cpu_mask(i, mask)
|
||||
vsmp_send_ipi_single(i, action);
|
||||
}
|
||||
|
||||
static void __cpuinit vsmp_init_secondary(void)
|
||||
{
|
||||
/* Enable per-cpu interrupts */
|
||||
|
||||
/* This is Malta specific: IPI,performance and timer inetrrupts */
|
||||
write_c0_status((read_c0_status() & ~ST0_IM ) |
|
||||
(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
|
||||
}
|
||||
|
||||
static void __cpuinit vsmp_smp_finish(void)
|
||||
{
|
||||
write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_FPAFF
|
||||
/* If we have an FPU, enroll ourselves in the FPU-full mask */
|
||||
if (cpu_has_fpu)
|
||||
cpu_set(smp_processor_id(), mt_fpu_cpumask);
|
||||
#endif /* CONFIG_MIPS_MT_FPAFF */
|
||||
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static void vsmp_cpus_done(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the PC, SP, and GP of a secondary processor and start it
|
||||
* running!
|
||||
* smp_bootstrap is the place to resume from
|
||||
* __KSTK_TOS(idle) is apparently the stack pointer
|
||||
* (unsigned long)idle->thread_info the gp
|
||||
* assumes a 1:1 mapping of TC => VPE
|
||||
*/
|
||||
static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle)
|
||||
{
|
||||
struct thread_info *gp = task_thread_info(idle);
|
||||
dvpe();
|
||||
set_c0_mvpcontrol(MVPCONTROL_VPC);
|
||||
|
||||
settc(cpu);
|
||||
|
||||
/* restart */
|
||||
write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
|
||||
|
||||
/* enable the tc this vpe/cpu will be running */
|
||||
write_tc_c0_tcstatus((read_tc_c0_tcstatus() & ~TCSTATUS_IXMT) | TCSTATUS_A);
|
||||
|
||||
write_tc_c0_tchalt(0);
|
||||
|
||||
/* enable the VPE */
|
||||
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
|
||||
|
||||
/* stack pointer */
|
||||
write_tc_gpr_sp( __KSTK_TOS(idle));
|
||||
|
||||
/* global pointer */
|
||||
write_tc_gpr_gp((unsigned long)gp);
|
||||
|
||||
flush_icache_range((unsigned long)gp,
|
||||
(unsigned long)(gp + sizeof(struct thread_info)));
|
||||
|
||||
/* finally out of configuration and into chaos */
|
||||
clear_c0_mvpcontrol(MVPCONTROL_VPC);
|
||||
|
||||
evpe(EVPE_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common setup before any secondaries are started
|
||||
* Make sure all CPU's are in a sensible state before we boot any of the
|
||||
* secondarys
|
||||
*/
|
||||
void __init plat_smp_setup(void)
|
||||
static void __init vsmp_smp_setup(void)
|
||||
{
|
||||
unsigned int mvpconf0, ntc, tc, ncpu = 0;
|
||||
unsigned int nvpe;
|
||||
@ -263,7 +368,7 @@ void __init plat_smp_setup(void)
|
||||
printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu);
|
||||
}
|
||||
|
||||
void __init plat_prepare_cpus(unsigned int max_cpus)
|
||||
static void __init vsmp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
mips_mt_set_cpuoptions();
|
||||
|
||||
@ -283,99 +388,13 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
|
||||
set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the PC, SP, and GP of a secondary processor and start it
|
||||
* running!
|
||||
* smp_bootstrap is the place to resume from
|
||||
* __KSTK_TOS(idle) is apparently the stack pointer
|
||||
* (unsigned long)idle->thread_info the gp
|
||||
* assumes a 1:1 mapping of TC => VPE
|
||||
*/
|
||||
void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle)
|
||||
{
|
||||
struct thread_info *gp = task_thread_info(idle);
|
||||
dvpe();
|
||||
set_c0_mvpcontrol(MVPCONTROL_VPC);
|
||||
|
||||
settc(cpu);
|
||||
|
||||
/* restart */
|
||||
write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
|
||||
|
||||
/* enable the tc this vpe/cpu will be running */
|
||||
write_tc_c0_tcstatus((read_tc_c0_tcstatus() & ~TCSTATUS_IXMT) | TCSTATUS_A);
|
||||
|
||||
write_tc_c0_tchalt(0);
|
||||
|
||||
/* enable the VPE */
|
||||
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
|
||||
|
||||
/* stack pointer */
|
||||
write_tc_gpr_sp( __KSTK_TOS(idle));
|
||||
|
||||
/* global pointer */
|
||||
write_tc_gpr_gp((unsigned long)gp);
|
||||
|
||||
flush_icache_range((unsigned long)gp,
|
||||
(unsigned long)(gp + sizeof(struct thread_info)));
|
||||
|
||||
/* finally out of configuration and into chaos */
|
||||
clear_c0_mvpcontrol(MVPCONTROL_VPC);
|
||||
|
||||
evpe(EVPE_ENABLE);
|
||||
}
|
||||
|
||||
void __cpuinit prom_init_secondary(void)
|
||||
{
|
||||
/* Enable per-cpu interrupts */
|
||||
|
||||
/* This is Malta specific: IPI,performance and timer inetrrupts */
|
||||
write_c0_status((read_c0_status() & ~ST0_IM ) |
|
||||
(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
|
||||
}
|
||||
|
||||
void __cpuinit prom_smp_finish(void)
|
||||
{
|
||||
write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_FPAFF
|
||||
/* If we have an FPU, enroll ourselves in the FPU-full mask */
|
||||
if (cpu_has_fpu)
|
||||
cpu_set(smp_processor_id(), mt_fpu_cpumask);
|
||||
#endif /* CONFIG_MIPS_MT_FPAFF */
|
||||
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void prom_cpus_done(void)
|
||||
{
|
||||
}
|
||||
|
||||
void core_send_ipi(int cpu, unsigned int action)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
int vpflags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */
|
||||
|
||||
switch (action) {
|
||||
case SMP_CALL_FUNCTION:
|
||||
i = C_SW1;
|
||||
break;
|
||||
|
||||
case SMP_RESCHEDULE_YOURSELF:
|
||||
default:
|
||||
i = C_SW0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 1:1 mapping of vpe and tc... */
|
||||
settc(cpu);
|
||||
write_vpe_c0_cause(read_vpe_c0_cause() | i);
|
||||
evpe(vpflags);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
struct plat_smp_ops vsmp_smp_ops = {
|
||||
.send_ipi_single = vsmp_send_ipi_single,
|
||||
.send_ipi_mask = vsmp_send_ipi_mask,
|
||||
.init_secondary = vsmp_init_secondary,
|
||||
.smp_finish = vsmp_smp_finish,
|
||||
.cpus_done = vsmp_cpus_done,
|
||||
.boot_secondary = vsmp_boot_secondary,
|
||||
.smp_setup = vsmp_smp_setup,
|
||||
.prepare_cpus = vsmp_prepare_cpus,
|
||||
};
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
#ifdef CONFIG_MIPS_MT_SMTC
|
||||
@ -84,6 +83,16 @@ static inline void set_cpu_sibling_map(int cpu)
|
||||
cpu_set(cpu, cpu_sibling_map[cpu]);
|
||||
}
|
||||
|
||||
struct plat_smp_ops *mp_ops;
|
||||
|
||||
__cpuinit void register_smp_ops(struct plat_smp_ops *ops)
|
||||
{
|
||||
if (ops)
|
||||
printk(KERN_WARNING "Overriding previous set SMP ops\n");
|
||||
|
||||
mp_ops = ops;
|
||||
}
|
||||
|
||||
/*
|
||||
* First C code run on the secondary CPUs after being started up by
|
||||
* the master.
|
||||
@ -100,7 +109,7 @@ asmlinkage __cpuinit void start_secondary(void)
|
||||
cpu_report();
|
||||
per_cpu_trap_init();
|
||||
mips_clockevent_init();
|
||||
prom_init_secondary();
|
||||
mp_ops->init_secondary();
|
||||
|
||||
/*
|
||||
* XXX parity protection should be folded in here when it's converted
|
||||
@ -112,7 +121,7 @@ asmlinkage __cpuinit void start_secondary(void)
|
||||
cpu = smp_processor_id();
|
||||
cpu_data[cpu].udelay_val = loops_per_jiffy;
|
||||
|
||||
prom_smp_finish();
|
||||
mp_ops->smp_finish();
|
||||
set_cpu_sibling_map(cpu);
|
||||
|
||||
cpu_set(cpu, cpu_callin_map);
|
||||
@ -184,7 +193,7 @@ int smp_call_function_mask(cpumask_t mask, void (*func) (void *info),
|
||||
smp_mb();
|
||||
|
||||
/* Send a message to all other CPUs and wait for them to respond */
|
||||
core_send_ipi_mask(mask, SMP_CALL_FUNCTION);
|
||||
mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
|
||||
|
||||
/* Wait for response */
|
||||
/* FIXME: lock-up detection, backtrace on lock-up */
|
||||
@ -278,7 +287,7 @@ void smp_send_stop(void)
|
||||
|
||||
void __init smp_cpus_done(unsigned int max_cpus)
|
||||
{
|
||||
prom_cpus_done();
|
||||
mp_ops->cpus_done();
|
||||
}
|
||||
|
||||
/* called from main before smp_init() */
|
||||
@ -286,7 +295,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
init_new_context(current, &init_mm);
|
||||
current_thread_info()->cpu = 0;
|
||||
plat_prepare_cpus(max_cpus);
|
||||
mp_ops->prepare_cpus(max_cpus);
|
||||
set_cpu_sibling_map(0);
|
||||
#ifndef CONFIG_HOTPLUG_CPU
|
||||
cpu_present_map = cpu_possible_map;
|
||||
@ -325,7 +334,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||
if (IS_ERR(idle))
|
||||
panic(KERN_ERR "Fork failed for CPU %d", cpu);
|
||||
|
||||
prom_boot_secondary(cpu, idle);
|
||||
mp_ops->boot_secondary(cpu, idle);
|
||||
|
||||
/*
|
||||
* Trust is futile. We should really have timeouts ...
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/hardirq.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <asm/hazards.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mmu_context.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/time.h>
|
||||
|
Reference in New Issue
Block a user