diff options
Diffstat (limited to 'arch/powerpc/platforms/85xx/smp.c')
-rw-r--r-- | arch/powerpc/platforms/85xx/smp.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index a15f582300d8..a6b106557be4 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/kexec.h> | ||
18 | 19 | ||
19 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
20 | #include <asm/pgtable.h> | 21 | #include <asm/pgtable.h> |
@@ -24,6 +25,7 @@ | |||
24 | #include <asm/dbell.h> | 25 | #include <asm/dbell.h> |
25 | 26 | ||
26 | #include <sysdev/fsl_soc.h> | 27 | #include <sysdev/fsl_soc.h> |
28 | #include <sysdev/mpic.h> | ||
27 | 29 | ||
28 | extern void __early_start(void); | 30 | extern void __early_start(void); |
29 | 31 | ||
@@ -99,12 +101,70 @@ static void __init | |||
99 | smp_85xx_setup_cpu(int cpu_nr) | 101 | smp_85xx_setup_cpu(int cpu_nr) |
100 | { | 102 | { |
101 | mpic_setup_this_cpu(); | 103 | mpic_setup_this_cpu(); |
104 | if (cpu_has_feature(CPU_FTR_DBELL)) | ||
105 | doorbell_setup_this_cpu(); | ||
102 | } | 106 | } |
103 | 107 | ||
104 | struct smp_ops_t smp_85xx_ops = { | 108 | struct smp_ops_t smp_85xx_ops = { |
105 | .kick_cpu = smp_85xx_kick_cpu, | 109 | .kick_cpu = smp_85xx_kick_cpu, |
110 | #ifdef CONFIG_KEXEC | ||
111 | .give_timebase = smp_generic_give_timebase, | ||
112 | .take_timebase = smp_generic_take_timebase, | ||
113 | #endif | ||
106 | }; | 114 | }; |
107 | 115 | ||
116 | #ifdef CONFIG_KEXEC | ||
117 | static int kexec_down_cpus = 0; | ||
118 | |||
119 | void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) | ||
120 | { | ||
121 | mpic_teardown_this_cpu(1); | ||
122 | |||
123 | /* When crashing, this gets called on all CPU's we only | ||
124 | * take down the non-boot cpus */ | ||
125 | if (smp_processor_id() != boot_cpuid) | ||
126 | { | ||
127 | local_irq_disable(); | ||
128 | kexec_down_cpus++; | ||
129 | |||
130 | while (1); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void mpc85xx_smp_kexec_down(void *arg) | ||
135 | { | ||
136 | if (ppc_md.kexec_cpu_down) | ||
137 | ppc_md.kexec_cpu_down(0,1); | ||
138 | } | ||
139 | |||
140 | static void mpc85xx_smp_machine_kexec(struct kimage *image) | ||
141 | { | ||
142 | int timeout = 2000; | ||
143 | int i; | ||
144 | |||
145 | set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); | ||
146 | |||
147 | smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); | ||
148 | |||
149 | while ( (kexec_down_cpus != (num_online_cpus() - 1)) && | ||
150 | ( timeout > 0 ) ) | ||
151 | { | ||
152 | timeout--; | ||
153 | } | ||
154 | |||
155 | if ( !timeout ) | ||
156 | printk(KERN_ERR "Unable to bring down secondary cpu(s)"); | ||
157 | |||
158 | for (i = 0; i < num_present_cpus(); i++) | ||
159 | { | ||
160 | if ( i == smp_processor_id() ) continue; | ||
161 | mpic_reset_core(i); | ||
162 | } | ||
163 | |||
164 | default_machine_kexec(image); | ||
165 | } | ||
166 | #endif /* CONFIG_KEXEC */ | ||
167 | |||
108 | void __init mpc85xx_smp_init(void) | 168 | void __init mpc85xx_smp_init(void) |
109 | { | 169 | { |
110 | struct device_node *np; | 170 | struct device_node *np; |
@@ -117,9 +177,14 @@ void __init mpc85xx_smp_init(void) | |||
117 | } | 177 | } |
118 | 178 | ||
119 | if (cpu_has_feature(CPU_FTR_DBELL)) | 179 | if (cpu_has_feature(CPU_FTR_DBELL)) |
120 | smp_85xx_ops.message_pass = smp_dbell_message_pass; | 180 | smp_85xx_ops.message_pass = doorbell_message_pass; |
121 | 181 | ||
122 | BUG_ON(!smp_85xx_ops.message_pass); | 182 | BUG_ON(!smp_85xx_ops.message_pass); |
123 | 183 | ||
124 | smp_ops = &smp_85xx_ops; | 184 | smp_ops = &smp_85xx_ops; |
185 | |||
186 | #ifdef CONFIG_KEXEC | ||
187 | ppc_md.kexec_cpu_down = mpc85xx_smp_kexec_cpu_down; | ||
188 | ppc_md.machine_kexec = mpc85xx_smp_machine_kexec; | ||
189 | #endif | ||
125 | } | 190 | } |