diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-11-19 15:23:51 +0300 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-01-29 13:14:57 +0300 |
commit | 87353d8ac39c52784da605ecbe965ecdfad609ad (patch) | |
tree | c95ce7cbe9b099c21cab71a195621801b04bc05a | |
parent | 19388fb092d89e179575bd0b44f51b57e175edf5 (diff) | |
download | linux-87353d8ac39c52784da605ecbe965ecdfad609ad.tar.xz |
[MIPS] SMP: Call platform methods via ops structure.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
27 files changed, 681 insertions, 485 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 8cbdfd255670..b211e7961f28 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1441,6 +1441,7 @@ config MIPS_MT_SMP select SMP select SYS_SUPPORTS_SCHED_SMT if SMP select SYS_SUPPORTS_SMP + select SMP_UP help This is a kernel model which is also known a VSMP or lately has been marketesed into SMVP. @@ -1457,6 +1458,7 @@ config MIPS_MT_SMTC select NR_CPUS_DEFAULT_8 select SMP select SYS_SUPPORTS_SMP + select SMP_UP help This is a kernel model which is known a SMTC or lately has been marketesed into SMVP. @@ -1735,6 +1737,9 @@ config SMP If you don't know what to do here, say N. +config SMP_UP + bool + config SYS_SUPPORTS_SMP bool diff --git a/arch/mips/fw/arc/init.c b/arch/mips/fw/arc/init.c index e2f75b13312f..3ad8788b6eaa 100644 --- a/arch/mips/fw/arc/init.c +++ b/arch/mips/fw/arc/init.c @@ -12,6 +12,7 @@ #include <asm/bootinfo.h> #include <asm/sgialib.h> +#include <asm/smp-ops.h> #undef DEBUG_PROM_INIT @@ -48,4 +49,11 @@ void __init prom_init(void) ArcRead(0, &c, 1, &cnt); ArcEnterInteractiveMode(); #endif +#ifdef CONFIG_SGI_IP27 + { + extern struct plat_smp_ops ip27_smp_ops; + + register_smp_ops(&ip27_smp_ops); + } +#endif } diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index 3d6b1ec1f328..640fb0cc6e39 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c @@ -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> diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 7b4418dd5857..269c252d956f 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -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) diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 2ab0b7eeaa7e..89e6f6aa5166 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -215,72 +215,67 @@ static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0) write_tc_c0_tchalt(TCHALT_H); } -/* - * 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 vsmp_send_ipi_single(int cpu, unsigned int action) { - unsigned int mvpconf0, ntc, tc, ncpu = 0; - unsigned int nvpe; + int i; + unsigned long flags; + int vpflags; -#ifdef CONFIG_MIPS_MT_FPAFF - /* If we have an FPU, enroll ourselves in the FPU-full mask */ - if (cpu_has_fpu) - cpu_set(0, mt_fpu_cpumask); -#endif /* CONFIG_MIPS_MT_FPAFF */ - if (!cpu_has_mipsmt) - return; + local_irq_save(flags); - /* disable MT so we can configure */ - dvpe(); - dmt(); + vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */ - /* Put MVPE's into 'configuration state' */ - set_c0_mvpcontrol(MVPCONTROL_VPC); + switch (action) { + case SMP_CALL_FUNCTION: + i = C_SW1; + break; - mvpconf0 = read_c0_mvpconf0(); - ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; + case SMP_RESCHEDULE_YOURSELF: + default: + i = C_SW0; + break; + } - nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; - smp_num_siblings = nvpe; + /* 1:1 mapping of vpe and tc... */ + settc(cpu); + write_vpe_c0_cause(read_vpe_c0_cause() | i); + evpe(vpflags); - /* we'll always have more TC's than VPE's, so loop setting everything - to a sensible state */ - for (tc = 0; tc <= ntc; tc++) { - settc(tc); + local_irq_restore(flags); +} - smp_tc_init(tc, mvpconf0); - ncpu = smp_vpe_init(tc, mvpconf0, ncpu); - } +static void vsmp_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; - /* Release config state */ - clear_c0_mvpcontrol(MVPCONTROL_VPC); + for_each_cpu_mask(i, mask) + vsmp_send_ipi_single(i, action); +} - /* We'll wait until starting the secondaries before starting MVPE */ +static void __cpuinit vsmp_init_secondary(void) +{ + /* Enable per-cpu interrupts */ - printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); + /* 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 __init plat_prepare_cpus(unsigned int max_cpus) +static void __cpuinit vsmp_smp_finish(void) { - mips_mt_set_cpuoptions(); - - /* set up ipi interrupts */ - if (cpu_has_vint) { - set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); - set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); - } + write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); - cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; - cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; +#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 */ - setup_irq(cpu_ipi_resched_irq, &irq_resched); - setup_irq(cpu_ipi_call_irq, &irq_call); + local_irq_enable(); +} - set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); - set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); +static void vsmp_cpus_done(void) +{ } /* @@ -291,7 +286,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) * (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) +static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle) { struct thread_info *gp = task_thread_info(idle); dvpe(); @@ -325,57 +320,81 @@ void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) 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) +/* + * Common setup before any secondaries are started + * Make sure all CPU's are in a sensible state before we boot any of the + * secondarys + */ +static void __init vsmp_smp_setup(void) { - write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); + unsigned int mvpconf0, ntc, tc, ncpu = 0; + unsigned int nvpe; #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); + cpu_set(0, mt_fpu_cpumask); #endif /* CONFIG_MIPS_MT_FPAFF */ + if (!cpu_has_mipsmt) + return; - local_irq_enable(); -} + /* disable MT so we can configure */ + dvpe(); + dmt(); -void prom_cpus_done(void) -{ -} + /* Put MVPE's into 'configuration state' */ + set_c0_mvpcontrol(MVPCONTROL_VPC); -void core_send_ipi(int cpu, unsigned int action) -{ - int i; - unsigned long flags; - int vpflags; + mvpconf0 = read_c0_mvpconf0(); + ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; - local_irq_save(flags); + nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; + smp_num_siblings = nvpe; - vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */ + /* we'll always have more TC's than VPE's, so loop setting everything + to a sensible state */ + for (tc = 0; tc <= ntc; tc++) { + settc(tc); - switch (action) { - case SMP_CALL_FUNCTION: - i = C_SW1; - break; + smp_tc_init(tc, mvpconf0); + ncpu = smp_vpe_init(tc, mvpconf0, ncpu); + } - case SMP_RESCHEDULE_YOURSELF: - default: - i = C_SW0; - break; + /* Release config state */ + clear_c0_mvpcontrol(MVPCONTROL_VPC); + + /* We'll wait until starting the secondaries before starting MVPE */ + + printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); +} + +static void __init vsmp_prepare_cpus(unsigned int max_cpus) +{ + mips_mt_set_cpuoptions(); + + /* set up ipi interrupts */ + if (cpu_has_vint) { + set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); + set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); } - /* 1:1 mapping of vpe and tc... */ - settc(cpu); - write_vpe_c0_cause(read_vpe_c0_cause() | i); - evpe(vpflags); + cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; + cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; - local_irq_restore(flags); + setup_irq(cpu_ipi_resched_irq, &irq_resched); + setup_irq(cpu_ipi_call_irq, &irq_call); + + set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); + set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); } + +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, +}; diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 335be9bcf0dc..1e5dfc28294a 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -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 ... diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c index 6f3709996172..fe256559c997 100644 --- a/arch/mips/kernel/smtc-proc.c +++ b/arch/mips/kernel/smtc-proc.c @@ -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> diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 9c92d42996cb..85f700e58131 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -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> diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c index 30f1f54cb68b..1695dca5506b 100644 --- a/arch/mips/mips-boards/generic/init.c +++ b/arch/mips/mips-boards/generic/init.c @@ -250,6 +250,8 @@ void __init mips_ejtag_setup(void) flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); } +extern struct plat_smp_ops msmtc_smp_ops; + void __init prom_init(void) { prom_argc = fw_arg0; @@ -416,4 +418,10 @@ void __init prom_init(void) #ifdef CONFIG_SERIAL_8250_CONSOLE console_config(); #endif +#ifdef CONFIG_MIPS_MT_SMP + register_smp_ops(&vsmp_smp_ops); +#endif +#ifdef CONFIG_MIPS_MT_SMTC + register_smp_ops(&msmtc_smp_ops); +#endif } diff --git a/arch/mips/mips-boards/malta/malta_smtc.c b/arch/mips/mips-boards/malta/malta_smtc.c index 5c980f4a48fe..6f051ca243fa 100644 --- a/arch/mips/mips-boards/malta/malta_smtc.c +++ b/arch/mips/mips-boards/malta/malta_smtc.c @@ -15,26 +15,24 @@ * Cause the specified action to be performed on a targeted "CPU" */ -void core_send_ipi(int cpu, unsigned int action) +static void msmtc_send_ipi_single(int cpu, unsigned int action) { /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ smtc_send_ipi(cpu, LINUX_SMP_IPI, action); } -/* - * Platform "CPU" startup hook - */ - -void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) +static void msmtc_send_ipi_mask(cpumask_t mask, unsigned int action) { - smtc_boot_secondary(cpu, idle); + unsigned int i; + + for_each_cpu_mask(i, mask) + msmtc_send_ipi_single(i, action); } /* * Post-config but pre-boot cleanup entry point */ - -void __cpuinit prom_init_secondary(void) +static void __cpuinit msmtc_init_secondary(void) { void smtc_init_secondary(void); int myvpe; @@ -50,45 +48,61 @@ void __cpuinit prom_init_secondary(void) set_c0_status(0x100 << cp0_perfcount_irq); } - smtc_init_secondary(); + smtc_init_secondary(); } /* - * Platform SMP pre-initialization - * - * As noted above, we can assume a single CPU for now - * but it may be multithreaded. + * Platform "CPU" startup hook */ - -void __cpuinit plat_smp_setup(void) +static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle) { - if (read_c0_config3() & (1<<2)) - mipsmt_build_cpu_map(0); + smtc_boot_secondary(cpu, idle); } -void __init plat_prepare_cpus(unsigned int max_cpus) +/* + * SMP initialization finalization entry point + */ +static void __cpuinit msmtc_smp_finish(void) { - if (read_c0_config3() & (1<<2)) - mipsmt_prepare_cpus(); + smtc_smp_finish(); } /* - * SMP initialization finalization entry point + * Hook for after all CPUs are online */ -void __cpuinit prom_smp_finish(void) +static void msmtc_cpus_done(void) { - smtc_smp_finish(); } /* - * Hook for after all CPUs are online + * Platform SMP pre-initialization + * + * As noted above, we can assume a single CPU for now + * but it may be multithreaded. */ -void prom_cpus_done(void) +static void __init msmtc_smp_setup(void) { + mipsmt_build_cpu_map(0); } +static void __init msmtc_prepare_cpus(unsigned int max_cpus) +{ + mipsmt_prepare_cpus(); +} + +struct plat_smp_ops msmtc_smp_ops = { + .send_ipi_single = msmtc_send_ipi_single, + .send_ipi_mask = msmtc_send_ipi_mask, + .init_secondary = msmtc_init_secondary, + .smp_finish = msmtc_smp_finish, + .cpus_done = msmtc_cpus_done, + .boot_secondary = msmtc_boot_secondary, + .smp_setup = msmtc_smp_setup, + .prepare_cpus = msmtc_prepare_cpus, +}; + #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF /* * IRQ affinity hook diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile index 75568b584df4..57f43c1c7882 100644 --- a/arch/mips/mipssim/Makefile +++ b/arch/mips/mipssim/Makefile @@ -21,6 +21,6 @@ obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \ sim_cmdline.o obj-$(CONFIG_EARLY_PRINTK) += sim_console.o -obj-$(CONFIG_SMP) += sim_smp.o +obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o EXTRA_CFLAGS += -Werror diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c index 452c129d02c1..d49fe73426b7 100644 --- a/arch/mips/mipssim/sim_setup.c +++ b/arch/mips/mipssim/sim_setup.c @@ -60,6 +60,8 @@ void __init plat_mem_setup(void) #endif } +extern struct plat_smp_ops ssmtc_smp_ops; + void __init prom_init(void) { set_io_port_base(0xbfd00000); @@ -67,8 +69,20 @@ void __init prom_init(void) pr_info("\nLINUX started...\n"); prom_init_cmdline(); prom_meminit(); -} +#ifdef CONFIG_MIPS_MT_SMP + if (cpu_has_mipsmt) + register_smp_ops(&vsmp_smp_ops); + else + register_smp_ops(&up_smp_ops); +#endif +#ifdef CONFIG_MIPS_MT_SMTC + if (cpu_has_mipsmt) + register_smp_ops(&ssmtc_smp_ops); + else + register_smp_ops(&up_smp_ops); +#endif +} static void __init serial_init(void) { diff --git a/arch/mips/mipssim/sim_smp.c b/arch/mips/mipssim/sim_smtc.c index ccbbccac23ef..d6e4f656ad14 100644 --- a/arch/mips/mipssim/sim_smp.c +++ b/arch/mips/mipssim/sim_smtc.c @@ -16,7 +16,7 @@ * */ /* - * Simulator Platform-specific hooks for SMP operation + * Simulator Platform-specific hooks for SMTC operation */ #include <linux/kernel.h> #include <linux/sched.h> @@ -29,65 +29,72 @@ #include <asm/processor.h> #include <asm/system.h> #include <asm/mmu_context.h> -#ifdef CONFIG_MIPS_MT_SMTC #include <asm/smtc_ipi.h> -#endif /* CONFIG_MIPS_MT_SMTC */ /* VPE/SMP Prototype implements platform interfaces directly */ -#if !defined(CONFIG_MIPS_MT_SMP) /* * Cause the specified action to be performed on a targeted "CPU" */ -void core_send_ipi(int cpu, unsigned int action) +static void ssmtc_send_ipi_single(int cpu, unsigned int action) { -#ifdef CONFIG_MIPS_MT_SMTC smtc_send_ipi(cpu, LINUX_SMP_IPI, action); -#endif /* CONFIG_MIPS_MT_SMTC */ -/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ + /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ +} + +static inline void ssmtc_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; + for_each_cpu_mask(i, mask) + ssmtc_send_ipi_single(i, action); } /* - * Platform "CPU" startup hook + * Post-config but pre-boot cleanup entry point */ - -void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) +static void __cpuinit ssmtc_init_secondary(void) { -#ifdef CONFIG_MIPS_MT_SMTC - smtc_boot_secondary(cpu, idle); -#endif /* CONFIG_MIPS_MT_SMTC */ + void smtc_init_secondary(void); + + smtc_init_secondary(); } /* - * Post-config but pre-boot cleanup entry point + * SMP initialization finalization entry point */ +static void __cpuinit ssmtc_smp_finish(void) +{ + smtc_smp_finish(); +} -void __cpuinit prom_init_secondary(void) +/* + * Hook for after all CPUs are online + */ +static void ssmtc_cpus_done(void) { -#ifdef CONFIG_MIPS_MT_SMTC - void smtc_init_secondary(void); +} - smtc_init_secondary(); -#endif /* CONFIG_MIPS_MT_SMTC */ +/* + * Platform "CPU" startup hook + */ +static void __cpuinit ssmtc_boot_secondary(int cpu, struct task_struct *idle) +{ + smtc_boot_secondary(cpu, idle); } -void plat_smp_setup(void) +static void __init ssmtc_smp_setup(void) { -#ifdef CONFIG_MIPS_MT_SMTC if (read_c0_config3() & (1 << 2)) mipsmt_build_cpu_map(0); -#endif /* CONFIG_MIPS_MT_SMTC */ } /* * Platform SMP pre-initialization */ - -void plat_prepare_cpus(unsigned int max_cpus) +static void ssmtc_prepare_cpus(unsigned int max_cpus) { -#ifdef CONFIG_MIPS_MT_SMTC /* * As noted above, we can assume a single CPU for now * but it may be multithreaded. @@ -96,28 +103,15 @@ void plat_prepare_cpus(unsigned int max_cpus) if (read_c0_config3() & (1 << 2)) { mipsmt_prepare_cpus(); } -#endif /* CONFIG_MIPS_MT_SMTC */ } -/* - * SMP initialization finalization entry point - */ - -void __cpuinit prom_smp_finish(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - smtc_smp_finish(); -#endif /* CONFIG_MIPS_MT_SMTC */ -} - -/* - * Hook for after all CPUs are online - */ - -void prom_cpus_done(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - -#endif /* CONFIG_MIPS_MT_SMTC */ -} -#endif /* CONFIG_MIPS32R2_MT_SMP */ +struct plat_smp_ops ssmtc_smp_ops = { + .send_ipi_single = ssmtc_send_ipi_single, + .send_ipi_mask = ssmtc_send_ipi_mask, + .init_secondary = ssmtc_init_secondary, + .smp_finish = ssmtc_smp_finish, + .cpus_done = ssmtc_cpus_done, + .boot_secondary = ssmtc_boot_secondary, + .smp_setup = ssmtc_smp_setup, + .prepare_cpus = ssmtc_prepare_cpus, +}; diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c index 96d3ff051d3d..35dc435846a6 100644 --- a/arch/mips/pmc-sierra/yosemite/prom.c +++ b/arch/mips/pmc-sierra/yosemite/prom.c @@ -19,6 +19,7 @@ #include <asm/pgtable.h> #include <asm/processor.h> #include <asm/reboot.h> +#include <asm/smp-ops.h> #include <asm/system.h> #include <asm/bootinfo.h> #include <asm/pmon.h> @@ -78,6 +79,8 @@ static void prom_halt(void) __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); } +extern struct plat_smp_ops yos_smp_ops; + /* * Init routine which accepts the variables from PMON */ @@ -127,6 +130,8 @@ void __init prom_init(void) } prom_grab_secondary(); + + register_smp_ops(&yos_smp_ops); } void __init prom_free_prom_memory(void) diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index b0f12cd2968a..653f3ec61cab 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -42,70 +42,6 @@ void __init prom_grab_secondary(void) launchstack + LAUNCHSTACK_SIZE, 0); } -/* - * Detect available CPUs, populate phys_cpu_present_map before smp_init - * - * We don't want to start the secondary CPU yet nor do we have a nice probing - * feature in PMON so we just assume presence of the secondary core. - */ -void __init plat_smp_setup(void) -{ - int i; - - cpus_clear(phys_cpu_present_map); - - for (i = 0; i < 2; i++) { - cpu_set(i, phys_cpu_present_map); - __cpu_number_map[i] = i; - __cpu_logical_map[i] = i; - } -} - -void __init plat_prepare_cpus(unsigned int max_cpus) -{ - /* - * Be paranoid. Enable the IPI only if we're really about to go SMP. - */ - if (cpus_weight(cpu_possible_map)) - set_c0_status(STATUSF_IP5); -} - -/* - * Firmware CPU startup hook - * Complicated by PMON's weird interface which tries to minimic the UNIX fork. - * It launches the next * available CPU and copies some information on the - * stack so the first thing we do is throw away that stuff and load useful - * values into the registers ... - */ -void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) -{ - unsigned long gp = (unsigned long) task_thread_info(idle); - unsigned long sp = __KSTK_TOS(idle); - - secondary_sp = sp; - secondary_gp = gp; - - spin_unlock(&launch_lock); -} - -/* Hook for after all CPUs are online */ -void prom_cpus_done(void) -{ -} - -/* - * After we've done initial boot, this function is called to allow the - * board code to clean up state, if needed - */ -void __cpuinit prom_init_secondary(void) -{ - set_c0_status(ST0_CO | ST0_IE | ST0_IM); -} - -void __cpuinit prom_smp_finish(void) -{ -} - void titan_mailbox_irq(void) { int cpu = smp_processor_id(); @@ -133,7 +69,7 @@ void titan_mailbox_irq(void) /* * Send inter-processor interrupt */ -void core_send_ipi(int cpu, unsigned int action) +static void yos_send_ipi_single(int cpu, unsigned int action) { /* * Generate an INTMSG so that it can be sent over to the @@ -159,3 +95,86 @@ void core_send_ipi(int cpu, unsigned int action) break; } } + +static void yos_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; + + for_each_cpu_mask(i, mask) + yos_send_ipi_single(i, action); +} + +/* + * After we've done initial boot, this function is called to allow the + * board code to clean up state, if needed + */ +static void __cpuinit yos_init_secondary(void) +{ + set_c0_status(ST0_CO | ST0_IE | ST0_IM); +} + +static void __cpuinit yos_smp_finish(void) +{ +} + +/* Hook for after all CPUs are online */ +static void yos_cpus_done(void) +{ +} + +/* + * Firmware CPU startup hook + * Complicated by PMON's weird interface which tries to minimic the UNIX fork. + * It launches the next * available CPU and copies some information on the + * stack so the first thing we do is throw away that stuff and load useful + * values into the registers ... + */ +static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle) +{ + unsigned long gp = (unsigned long) task_thread_info(idle); + unsigned long sp = __KSTK_TOS(idle); + + secondary_sp = sp; + secondary_gp = gp; + + spin_unlock(&launch_lock); +} + +/* + * Detect available CPUs, populate phys_cpu_present_map before smp_init + * + * We don't want to start the secondary CPU yet nor do we have a nice probing + * feature in PMON so we just assume presence of the secondary core. + */ +static void __init yos_smp_setup(void) +{ + int i; + + cpus_clear(phys_cpu_present_map); + + for (i = 0; i < 2; i++) { + cpu_set(i, phys_cpu_present_map); + __cpu_number_map[i] = i; + __cpu_logical_map[i] = i; + } +} + +static void __init yos_prepare_cpus(unsigned int max_cpus) +{ + /* + * Be paranoid. Enable the IPI only if we're really about to go SMP. + */ + if (cpus_weight(cpu_possible_map)) + set_c0_status(STATUSF_IP5); +} + +struct plat_smp_ops yos_smp_ops = { + .send_ipi_single = yos_send_ipi_single, + .send_ipi_mask = yos_send_ipi_mask, + .init_secondary = yos_init_secondary, + .smp_finish = yos_smp_finish, + .cpus_done = yos_cpus_done, + .boot_secondary = yos_boot_secondary, + .smp_setup = yos_smp_setup, + .prepare_cpus = yos_prepare_cpus, +}; diff --git a/arch/mips/qemu/q-smp.c b/arch/mips/qemu/q-smp.c index 4b0178d0df0b..ead6c30eeb14 100644 --- a/arch/mips/qemu/q-smp.c +++ b/arch/mips/qemu/q-smp.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, 07 by Ralf Baechle (ralf@linux-mips.org) * * Symmetric Uniprocessor (TM) Support */ @@ -13,43 +13,55 @@ /* * Send inter-processor interrupt */ -void core_send_ipi(int cpu, unsigned int action) +void up_send_ipi_single(int cpu, unsigned int action) { - panic(KERN_ERR "%s called", __FUNCTION__); + panic(KERN_ERR "%s called", __func__); +} + +static inline void up_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + panic(KERN_ERR "%s called", __func__); } /* * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ -void __cpuinit prom_init_secondary(void) +void __cpuinit up_init_secondary(void) { } -void __cpuinit prom_smp_finish(void) +void __cpuinit up_smp_finish(void) { } /* Hook for after all CPUs are online */ -void prom_cpus_done(void) -{ -} - -void __init prom_prepare_cpus(unsigned int max_cpus) +void up_cpus_done(void) { - cpus_clear(phys_cpu_present_map); } /* * Firmware CPU startup hook */ -void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) +void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle) { } -void __init plat_smp_setup(void) +void __init up_smp_setup(void) { } -void __init plat_prepare_cpus(unsigned int max_cpus) + +void __init up_prepare_cpus(unsigned int max_cpus) { } + +struct plat_smp_ops up_smp_ops = { + .send_ipi_single = up_send_ipi_single, + .send_ipi_mask = up_send_ipi_mask, + .init_secondary = up_init_secondary, + .smp_finish = up_smp_finish, + .cpus_done = up_cpus_done, + .boot_secondary = up_boot_secondary, + .smp_setup = up_smp_setup, + .prepare_cpus = up_prepare_cpus, +}; diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 3305fa9ae66d..a49e7c85f724 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -27,7 +27,6 @@ #include <asm/sn/hub.h> #include <asm/sn/intr.h> #include <asm/current.h> -#include <asm/smp.h> #include <asm/processor.h> #include <asm/mmu_context.h> #include <asm/thread_info.h> diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index f10d9839006d..48932ce1d730 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c @@ -11,7 +11,6 @@ #include <asm/page.h> #include <asm/sections.h> -#include <asm/smp.h> #include <asm/sn/types.h> #include <asm/sn/arch.h> #include <asm/sn/gda.h> diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index a70656d42191..f15fc93d6b35 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -140,30 +140,51 @@ static __init void intr_clear_all(nasid_t nasid) REMOTE_HUB_CLR_INTR(nasid, i); } -void __init plat_smp_setup(void) +static void ip27_send_ipi_single(int destid, unsigned int action) { - cnodeid_t cnode; + int irq; - for_each_online_node(cnode) { - if (cnode == 0) - continue; - intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); + switch (action) { + case SMP_RESCHEDULE_YOURSELF: + irq = CPU_RESCHED_A_IRQ; + break; + case SMP_CALL_FUNCTION: + irq = CPU_CALL_A_IRQ; + break; + default: + panic("sendintr"); } - replicate_kernel_text(); + irq += cputoslice(destid); /* - * Assumption to be fixed: we're always booted on logical / physical - * processor 0. While we're always running on logical processor 0 - * this still means this is physical processor zero; it might for - * example be disabled in the firwware. + * Convert the compact hub number to the NASID to get the correct + * part of the address space. Then set the interrupt bit associated + * with the CPU we want to send the interrupt to. */ - alloc_cpupda(0, 0); + REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq); } -void __init plat_prepare_cpus(unsigned int max_cpus) +static void ip27_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; + + for_each_cpu_mask(i, mask) + ip27_send_ipi_single(i, action); +} + +static void __cpuinit ip27_init_secondary(void) +{ + per_cpu_init(); + local_irq_enable(); +} + +static void __cpuinit ip27_smp_finish(void) +{ +} + +static void __init ip27_cpus_done(void) { - /* We already did everything necessary earlier */ } /* @@ -171,7 +192,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) * set sp to the kernel stack of the newly created idle process, gp to the proc * struct so that current_thread_info() will work. */ -void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) +static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle) { unsigned long gp = (unsigned long)task_thread_info(idle); unsigned long sp = __KSTK_TOS(idle); @@ -181,41 +202,39 @@ void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) 0, (void *) sp, (void *) gp); } -void __cpuinit prom_init_secondary(void) +static void __init ip27_smp_setup(void) { - per_cpu_init(); - local_irq_enable(); -} - -void __init prom_cpus_done(void) -{ -} - -void __cpuinit prom_smp_finish(void) -{ -} - -void core_send_ipi(int destid, unsigned int action) -{ - int irq; + cnodeid_t cnode; - switch (action) { - case SMP_RESCHEDULE_YOURSELF: - irq = CPU_RESCHED_A_IRQ; - break; - case SMP_CALL_FUNCTION: - irq = CPU_CALL_A_IRQ; - break; - default: - panic("sendintr"); + for_each_online_node(cnode) { + if (cnode == 0) + continue; + intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); } - irq += cputoslice(destid); + replicate_kernel_text(); /* - * Convert the compact hub number to the NASID to get the correct - * part of the address space. Then set the interrupt bit associated - * with the CPU we want to send the interrupt to. + * Assumption to be fixed: we're always booted on logical / physical + * processor 0. While we're always running on logical processor 0 + * this still means this is physical processor zero; it might for + * example be disabled in the firwware. */ - REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq); + alloc_cpupda(0, 0); } + +static void __init ip27_prepare_cpus(unsigned int max_cpus) +{ + /* We already did everything necessary earlier */ +} + +struct plat_smp_ops ip27_smp_ops = { + .send_ipi_single = ip27_send_ipi_single, + .send_ipi_mask = ip27_send_ipi_mask, + .init_secondary = ip27_init_secondary, + .smp_finish = ip27_smp_finish, + .cpus_done = ip27_cpus_done, + .boot_secondary = ip27_boot_secondary, + .smp_setup = ip27_smp_setup, + .prepare_cpus = ip27_prepare_cpus, +}; diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 436ba78359ab..183c460b9ca1 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -23,6 +23,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/bcm1480_regs.h> #include <asm/sibyte/bcm1480_int.h> @@ -67,28 +68,114 @@ void __cpuinit bcm1480_smp_init(void) change_c0_status(ST0_IM, imask); } -void __cpuinit bcm1480_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 bcm1480_send_ipi_single(int cpu, unsigned int action) +{ + __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]); +} + +static void bcm1480_send_ipi_mask(cpumask_t mask, unsigned int action) +{ + unsigned int i; + + for_each_cpu_mask(i, mask) + bcm1480_send_ipi_single(i, action); +} + +/* + * Code to run on secondary just after probing the CPU + */ +static void __cpuinit bcm1480_init_secondary(void) +{ + extern void bcm1480_smp_init(void); + + bcm1480_smp_init(); +} + +/* + * Do any tidying up before marking online and running the idle + * loop + */ +static void __cpuinit bcm1480_smp_finish(void) { extern void sb1480_clockevent_init(void); sb1480_clockevent_init(); local_irq_enable(); + bcm1480_smp_finish(); } /* - * These are routines for dealing with the sb1250 smp capabilities - * independent of board/firmware + * Final cleanup after all secondaries booted */ +static void bcm1480_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 bcm1480_boot_secondary(int cpu, struct task_struct *idle) { - __raw_writeq((((u64)action)<< 48), mailbox_0_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 bcm1480_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 bcm1480_prepare_cpus(unsigned int max_cpus) +{ +} + +struct plat_smp_ops bcm1480_smp_ops = { + .send_ipi_single = bcm1480_send_ipi_single, + .send_ipi_mask = bcm1480_send_ipi_mask, + .init_secondary = bcm1480_init_secondary, + .smp_finish = bcm1480_smp_finish, + .cpus_done = bcm1480_cpus_done, + .boot_secondary = bcm1480_boot_secondary, + .smp_setup = bcm1480_smp_setup, + .prepare_cpus = bcm1480_prepare_cpus, +}; + void bcm1480_mailbox_interrupt(void) { int cpu = smp_processor_id(); diff --git a/arch/mips/sibyte/cfe/Makefile b/arch/mips/sibyte/cfe/Makefile index a1214937b705..02b32e142adf 100644 --- a/arch/mips/sibyte/cfe/Makefile +++ b/arch/mips/sibyte/cfe/Makefile @@ -1,3 +1,2 @@ lib-y = setup.o -lib-$(CONFIG_SMP) += smp.o lib-$(CONFIG_SIBYTE_CFE_CONSOLE) += console.o diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c index dbd6e6fdd3f9..50d7c05e15b8 100644 --- a/arch/mips/sibyte/cfe/setup.c +++ b/arch/mips/sibyte/cfe/setup.c @@ -28,6 +28,7 @@ #include <asm/bootinfo.h> #include <asm/reboot.h> #include <asm/sibyte/board.h> +#include <asm/smp-ops.h> #include <asm/fw/cfe/cfe_api.h> #include <asm/fw/cfe/cfe_error.h> @@ -232,6 +233,9 @@ static int __init initrd_setup(char *str) #endif +extern struct plat_smp_ops sb_smp_ops; +extern struct plat_smp_ops bcm1480_smp_ops; + /* * prom_init is called just after the cpu type is determined, from setup_arch() */ @@ -340,6 +344,13 @@ void __init prom_init(void) arcs_cmdline[CL_SIZE-1] = 0; prom_meminit(); + +#if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250) + register_smp_ops(&sb_smp_ops); +#endif +#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) + register_smp_ops(&bcm1480_smp_ops); +#endif } void __init prom_free_prom_memory(void) diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c deleted file mode 100644 index 534a62912f21..000000000000 --- a/arch/mips/sibyte/cfe/smp.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <asm/processor.h> - -#include <asm/fw/cfe/cfe_api.h> -#include <asm/fw/cfe/cfe_error.h> - -/* - * 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 - */ -void __init plat_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); -} - -void __init plat_prepare_cpus(unsigned int max_cpus) -{ -} - -/* - * Setup the PC, SP, and GP of a secondary processor and start it - * running! - */ -void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) -{ - 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); -} - -/* - * Code to run on secondary just after probing the CPU - */ -void __cpuinit prom_init_secondary(void) -{ -#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) - extern void bcm1480_smp_init(void); - bcm1480_smp_init(); -#elif defined(CONFIG_SIBYTE_SB1250) - extern void sb1250_smp_init(void); - sb1250_smp_init(); -#else -#error invalid SMP configuration -#endif -} - -/* - * Do any tidying up before marking online and running the idle - * loop - */ -void __cpuinit prom_smp_finish(void) -{ -#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) - extern void bcm1480_smp_finish(void); - bcm1480_smp_finish(); -#elif defined(CONFIG_SIBYTE_SB1250) - extern void sb1250_smp_finish(void); - sb1250_smp_finish(); -#else -#error invalid SMP configuration -#endif -} - -/* - * Final cleanup after all secondaries booted - */ -void prom_cpus_done(void) -{ -} diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 3f52c95a4eb8..0734b933e969 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(); diff --git a/include/asm-mips/sibyte/sb1250.h b/include/asm-mips/sibyte/sb1250.h index 0dad844a3b5b..80c1a052662a 100644 --- a/include/asm-mips/sibyte/sb1250.h +++ b/include/asm-mips/sibyte/sb1250.h @@ -48,12 +48,10 @@ extern unsigned int zbbus_mhz; extern void sb1250_time_init(void); extern void sb1250_mask_irq(int cpu, int irq); extern void sb1250_unmask_irq(int cpu, int irq); -extern void sb1250_smp_finish(void); extern void bcm1480_time_init(void); extern void bcm1480_mask_irq(int cpu, int irq); extern void bcm1480_unmask_irq(int cpu, int irq); -extern void bcm1480_smp_finish(void); #define AT_spin \ __asm__ __volatile__ ( \ diff --git a/include/asm-mips/smp-ops.h b/include/asm-mips/smp-ops.h new file mode 100644 index 000000000000..b17fdfb5d818 --- /dev/null +++ b/include/asm-mips/smp-ops.h @@ -0,0 +1,56 @@ +/* + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + * Copyright (C) 2000, 2001, 2002 Ralf Baechle + * Copyright (C) 2000, 2001 Broadcom Corporation + */ +#ifndef __ASM_SMP_OPS_H +#define __ASM_SMP_OPS_H + +#ifdef CONFIG_SMP + +#include <linux/cpumask.h> + +struct plat_smp_ops { + void (*send_ipi_single)(int cpu, unsigned int action); + void (*send_ipi_mask)(cpumask_t mask, unsigned int action); + void (*init_secondary)(void); + void (*smp_finish)(void); + void (*cpus_done)(void); + void (*boot_secondary)(int cpu, struct task_struct *idle); + void (*smp_setup)(void); + void (*prepare_cpus)(unsigned int max_cpus); +}; + +extern void register_smp_ops(struct plat_smp_ops *ops); + +static inline void plat_smp_setup(void) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + mp_ops->smp_setup(); +} + +#else /* !CONFIG_SMP */ + +struct plat_smp_ops; + +static inline void plat_smp_setup(void) +{ + /* UP, nothing to do ... */ +} + +static inline void register_smp_ops(struct plat_smp_ops *ops) +{ +} + +#endif /* !CONFIG_SMP */ + +extern struct plat_smp_ops up_smp_ops; +extern struct plat_smp_ops vsmp_smp_ops; + +#endif /* __ASM_SMP_OPS_H */ diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h index 23265879cee9..84fef1aeec0c 100644 --- a/include/asm-mips/smp.h +++ b/include/asm-mips/smp.h @@ -11,14 +11,13 @@ #ifndef __ASM_SMP_H #define __ASM_SMP_H - -#ifdef CONFIG_SMP - #include <linux/bitops.h> #include <linux/linkage.h> #include <linux/threads.h> #include <linux/cpumask.h> + #include <asm/atomic.h> +#include <asm/smp-ops.h> extern int smp_num_siblings; extern cpumask_t cpu_sibling_map[]; @@ -52,56 +51,6 @@ extern struct call_data_struct *call_data; extern cpumask_t phys_cpu_present_map; #define cpu_possible_map phys_cpu_present_map -/* - * These are defined by the board-specific code. - */ - -/* - * Cause the function described by call_data to be executed on the passed - * cpu. When the function has finished, increment the finished field of - * call_data. - */ -extern void core_send_ipi(int cpu, unsigned int action); - -static inline void core_send_ipi_mask(cpumask_t mask, unsigned int action) -{ - unsigned int i; - - for_each_cpu_mask(i, mask) - core_send_ipi(i, action); -} - - -/* - * Firmware CPU startup hook - */ -extern void prom_boot_secondary(int cpu, struct task_struct *idle); - -/* - * After we've done initial boot, this function is called to allow the - * board code to clean up state, if needed - */ -extern void prom_init_secondary(void); - -/* - * Populate cpu_possible_map before smp_init, called from setup_arch. - */ -extern void plat_smp_setup(void); - -/* - * Called in smp_prepare_cpus. - */ -extern void plat_prepare_cpus(unsigned int max_cpus); - -/* - * Last chance for the board code to finish SMP initialization before - * the CPU is "online". - */ -extern void prom_smp_finish(void); - -/* Hook for after all CPUs are online */ -extern void prom_cpus_done(void); - extern void asmlinkage smp_bootstrap(void); /* @@ -111,11 +60,11 @@ extern void asmlinkage smp_bootstrap(void); */ static inline void smp_send_reschedule(int cpu) { - core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF); + extern struct plat_smp_ops *mp_ops; /* private */ + + mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF); } extern asmlinkage void smp_call_function_interrupt(void); -#endif /* CONFIG_SMP */ - #endif /* __ASM_SMP_H */ |