aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/mach/arch.h7
-rw-r--r--arch/arm/include/asm/smp.h33
-rw-r--r--arch/arm/kernel/setup.c4
-rw-r--r--arch/arm/kernel/smp.c62
4 files changed, 104 insertions, 2 deletions
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 0b1c94b8c652..917d4fcfd9b4 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -14,6 +14,12 @@ struct tag;
14struct meminfo; 14struct meminfo;
15struct sys_timer; 15struct sys_timer;
16struct pt_regs; 16struct pt_regs;
17struct smp_operations;
18#ifdef CONFIG_SMP
19#define smp_ops(ops) (&(ops))
20#else
21#define smp_ops(ops) (struct smp_operations *)NULL
22#endif
17 23
18struct machine_desc { 24struct machine_desc {
19 unsigned int nr; /* architecture number */ 25 unsigned int nr; /* architecture number */
@@ -35,6 +41,7 @@ struct machine_desc {
35 unsigned char reserve_lp1 :1; /* never has lp1 */ 41 unsigned char reserve_lp1 :1; /* never has lp1 */
36 unsigned char reserve_lp2 :1; /* never has lp2 */ 42 unsigned char reserve_lp2 :1; /* never has lp2 */
37 char restart_mode; /* default restart mode */ 43 char restart_mode; /* default restart mode */
44 struct smp_operations *smp; /* SMP operations */
38 void (*fixup)(struct tag *, char **, 45 void (*fixup)(struct tag *, char **,
39 struct meminfo *); 46 struct meminfo *);
40 void (*reserve)(void);/* reserve mem blocks */ 47 void (*reserve)(void);/* reserve mem blocks */
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index ae29293270a3..f79a9f51e322 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -93,4 +93,37 @@ extern void platform_cpu_enable(unsigned int cpu);
93extern void arch_send_call_function_single_ipi(int cpu); 93extern void arch_send_call_function_single_ipi(int cpu);
94extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); 94extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
95 95
96struct smp_operations {
97#ifdef CONFIG_SMP
98 /*
99 * Setup the set of possible CPUs (via set_cpu_possible)
100 */
101 void (*smp_init_cpus)(void);
102 /*
103 * Initialize cpu_possible map, and enable coherency
104 */
105 void (*smp_prepare_cpus)(unsigned int max_cpus);
106
107 /*
108 * Perform platform specific initialisation of the specified CPU.
109 */
110 void (*smp_secondary_init)(unsigned int cpu);
111 /*
112 * Boot a secondary CPU, and assign it the specified idle task.
113 * This also gives us the initial stack to use for this CPU.
114 */
115 int (*smp_boot_secondary)(unsigned int cpu, struct task_struct *idle);
116#ifdef CONFIG_HOTPLUG_CPU
117 int (*cpu_kill)(unsigned int cpu);
118 void (*cpu_die)(unsigned int cpu);
119 int (*cpu_disable)(unsigned int cpu);
120#endif
121#endif
122};
123
124/*
125 * set platform specific SMP operations
126 */
127extern void smp_set_ops(struct smp_operations *);
128
96#endif /* ifndef __ASM_ARM_SMP_H */ 129#endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index a81dcecc7343..725f9f2a9541 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -977,8 +977,10 @@ void __init setup_arch(char **cmdline_p)
977 unflatten_device_tree(); 977 unflatten_device_tree();
978 978
979#ifdef CONFIG_SMP 979#ifdef CONFIG_SMP
980 if (is_smp()) 980 if (is_smp()) {
981 smp_set_ops(mdesc->smp);
981 smp_init_cpus(); 982 smp_init_cpus();
983 }
982#endif 984#endif
983 reserve_crashkernel(); 985 reserve_crashkernel();
984 986
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ebd8ad274d76..d9241885521b 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -19,7 +19,6 @@
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/cpu.h> 21#include <linux/cpu.h>
22#include <linux/smp.h>
23#include <linux/seq_file.h> 22#include <linux/seq_file.h>
24#include <linux/irq.h> 23#include <linux/irq.h>
25#include <linux/percpu.h> 24#include <linux/percpu.h>
@@ -27,6 +26,7 @@
27#include <linux/completion.h> 26#include <linux/completion.h>
28 27
29#include <linux/atomic.h> 28#include <linux/atomic.h>
29#include <asm/smp.h>
30#include <asm/cacheflush.h> 30#include <asm/cacheflush.h>
31#include <asm/cpu.h> 31#include <asm/cpu.h>
32#include <asm/cputype.h> 32#include <asm/cputype.h>
@@ -42,6 +42,7 @@
42#include <asm/ptrace.h> 42#include <asm/ptrace.h>
43#include <asm/localtimer.h> 43#include <asm/localtimer.h>
44#include <asm/smp_plat.h> 44#include <asm/smp_plat.h>
45#include <asm/mach/arch.h>
45 46
46/* 47/*
47 * as from 2.5, kernels no longer have an init_tasks structure 48 * as from 2.5, kernels no longer have an init_tasks structure
@@ -60,6 +61,14 @@ enum ipi_msg_type {
60 61
61static DECLARE_COMPLETION(cpu_running); 62static DECLARE_COMPLETION(cpu_running);
62 63
64static struct smp_operations smp_ops;
65
66void __init smp_set_ops(struct smp_operations *ops)
67{
68 if (ops)
69 smp_ops = *ops;
70};
71
63int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) 72int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
64{ 73{
65 int ret; 74 int ret;
@@ -100,9 +109,60 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
100 return ret; 109 return ret;
101} 110}
102 111
112/* platform specific SMP operations */
113void __attribute__((weak)) __init smp_init_cpus(void)
114{
115 if (smp_ops.smp_init_cpus)
116 smp_ops.smp_init_cpus();
117}
118
119void __attribute__((weak)) __init platform_smp_prepare_cpus(unsigned int max_cpus)
120{
121 if (smp_ops.smp_prepare_cpus)
122 smp_ops.smp_prepare_cpus(max_cpus);
123}
124
125void __attribute__((weak)) __cpuinit platform_secondary_init(unsigned int cpu)
126{
127 if (smp_ops.smp_secondary_init)
128 smp_ops.smp_secondary_init(cpu);
129}
130
131int __attribute__((weak)) __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
132{
133 if (smp_ops.smp_boot_secondary)
134 return smp_ops.smp_boot_secondary(cpu, idle);
135 return -ENOSYS;
136}
137
103#ifdef CONFIG_HOTPLUG_CPU 138#ifdef CONFIG_HOTPLUG_CPU
104static void percpu_timer_stop(void); 139static void percpu_timer_stop(void);
105 140
141int __attribute__((weak)) platform_cpu_kill(unsigned int cpu)
142{
143 if (smp_ops.cpu_kill)
144 return smp_ops.cpu_kill(cpu);
145 return 1;
146}
147
148void __attribute__((weak)) platform_cpu_die(unsigned int cpu)
149{
150 if (smp_ops.cpu_die)
151 smp_ops.cpu_die(cpu);
152}
153
154int __attribute__((weak)) platform_cpu_disable(unsigned int cpu)
155{
156 if (smp_ops.cpu_disable)
157 return smp_ops.cpu_disable(cpu);
158
159 /*
160 * By default, allow disabling all CPUs except the first one,
161 * since this is special on a lot of platforms, e.g. because
162 * of clock tick interrupts.
163 */
164 return cpu == 0 ? -EPERM : 0;
165}
106/* 166/*
107 * __cpu_disable runs on the processor to be shutdown. 167 * __cpu_disable runs on the processor to be shutdown.
108 */ 168 */