diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-29 22:48:03 +1100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-29 22:48:03 +1100 |
commit | 21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (patch) | |
tree | 5d288c1877b1ae9fbe24aa7fabd79565e73d3d2f /arch/mips/sibyte/sb1250/smp.c | |
parent | 5ea293a9048d3a58cb0c840fa719d85ad14cba47 (diff) | |
parent | a9d2517c7a5c8028fbc5296d3af3c75597d3d180 (diff) |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (68 commits)
[MIPS] remove Documentation/mips/GT64120.README
[MIPS] Malta: remaining bits of the board support code cleanup
[MIPS] Malta: make the helper function static
[MIPS] Malta: fix braces at single statement blocks
[MIPS] Malta, Atlas: move an extern function declaration to the header file
[MIPS] Malta: Use C89 style for comments
[MIPS] Malta: else should follow close brace in malta_int.c
[MIPS] Malta: remove a superfluous comment
[MIPS] Malta: include <linux/cpu.h> instead of <asm/cpu.h>
[MIPS] Malta, Atlas, Sead: remove an extern from .c files
[MIPS] Malta: fix oversized lines in malta_int.c
[MIPS] Malta: remove a dead function declaration
[MIPS] Malta: use tabs not spaces
[MIPS] Malta: set up the screen info in a separate function
[MIPS] Malta: check the PCI clock frequency in a separate function
[MIPS] Malta: use the KERN_ facility level in printk()
[MIPS] Malta: use Linux kernel style for structure initialization
[MIPS]: constify function pointer tables
[MIPS] compat: handle argument endianess of sys32_(f)truncate64 with merge_64
[MIPS] Cobalt 64-bits kernels can be safely unmarked experimental
...
Diffstat (limited to 'arch/mips/sibyte/sb1250/smp.c')
-rw-r--r-- | arch/mips/sibyte/sb1250/smp.c | 100 |
1 files changed, 93 insertions, 7 deletions
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 3f52c95a4eb..0734b933e96 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -24,6 +24,7 @@ #include <asm/mmu_context.h> #include <asm/io.h> +#include <asm/fw/cfe/cfe_api.h> #include <asm/sibyte/sb1250.h> #include <asm/sibyte/sb1250_regs.h> #include <asm/sibyte/sb1250_int.h> @@ -55,7 +56,43 @@ void __cpuinit sb1250_smp_init(void) change_c0_status(ST0_IM, imask); } -void __cpuinit sb1250_smp_finish(void) +/* + * These are routines for dealing with the sb1250 smp capabilities + * independent of board/firmware + */ + +/* + * Simple enough; everything is set up, so just poke the appropriate mailbox + * register, and we should be set + */ +static void sb1250_send_ipi_single(int cpu, unsigned int action) +{ + __raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]); +} + +static inline void sb1250_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; + + for_each_cpu_mask(i, mask) + sb1250_send_ipi_single(i, action); +} + +/* + * Code to run on secondary just after probing the CPU + */ +static void __cpuinit sb1250_init_secondary(void) +{ + extern void sb1250_smp_init(void); + + sb1250_smp_init(); +} + +/* + * Do any tidying up before marking online and running the idle + * loop + */ +static void __cpuinit sb1250_smp_finish(void) { extern void sb1250_clockevent_init(void); @@ -64,19 +101,68 @@ void __cpuinit sb1250_smp_finish(void) } /* - * These are routines for dealing with the sb1250 smp capabilities - * independent of board/firmware + * Final cleanup after all secondaries booted */ +static void sb1250_cpus_done(void) +{ +} /* - * Simple enough; everything is set up, so just poke the appropriate mailbox - * register, and we should be set + * Setup the PC, SP, and GP of a secondary processor and start it + * running! */ -void core_send_ipi(int cpu, unsigned int action) +static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) { - __raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]); + int retval; + + retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, + __KSTK_TOS(idle), + (unsigned long)task_thread_info(idle), 0); + if (retval != 0) + printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); } +/* + * Use CFE to find out how many CPUs are available, setting up + * phys_cpu_present_map and the logical/physical mappings. + * XXXKW will the boot CPU ever not be physical 0? + * + * Common setup before any secondaries are started + */ +static void __init sb1250_smp_setup(void) +{ + int i, num; + + cpus_clear(phys_cpu_present_map); + cpu_set(0, phys_cpu_present_map); + __cpu_number_map[0] = 0; + __cpu_logical_map[0] = 0; + + for (i = 1, num = 0; i < NR_CPUS; i++) { + if (cfe_cpu_stop(i) == 0) { + cpu_set(i, phys_cpu_present_map); + __cpu_number_map[i] = ++num; + __cpu_logical_map[num] = i; + } + } + printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); +} + +static void __init sb1250_prepare_cpus(unsigned int max_cpus) +{ +} + +struct plat_smp_ops sb_smp_ops = { + .send_ipi_single = sb1250_send_ipi_single, + .send_ipi_mask = sb1250_send_ipi_mask, + .init_secondary = sb1250_init_secondary, + .smp_finish = sb1250_smp_finish, + .cpus_done = sb1250_cpus_done, + .boot_secondary = sb1250_boot_secondary, + .smp_setup = sb1250_smp_setup, + .prepare_cpus = sb1250_prepare_cpus, +}; + void sb1250_mailbox_interrupt(void) { int cpu = smp_processor_id(); |