diff options
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r-- | arch/arm/kernel/smp.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 4619177bcfe6..47ab90563bf4 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -211,6 +211,13 @@ void __cpuinit __cpu_die(unsigned int cpu) | |||
211 | } | 211 | } |
212 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); | 212 | printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); |
213 | 213 | ||
214 | /* | ||
215 | * platform_cpu_kill() is generally expected to do the powering off | ||
216 | * and/or cutting of clocks to the dying CPU. Optionally, this may | ||
217 | * be done by the CPU which is dying in preference to supporting | ||
218 | * this call, but that means there is _no_ synchronisation between | ||
219 | * the requesting CPU and the dying CPU actually losing power. | ||
220 | */ | ||
214 | if (!platform_cpu_kill(cpu)) | 221 | if (!platform_cpu_kill(cpu)) |
215 | printk("CPU%u: unable to kill\n", cpu); | 222 | printk("CPU%u: unable to kill\n", cpu); |
216 | } | 223 | } |
@@ -230,14 +237,41 @@ void __ref cpu_die(void) | |||
230 | idle_task_exit(); | 237 | idle_task_exit(); |
231 | 238 | ||
232 | local_irq_disable(); | 239 | local_irq_disable(); |
233 | mb(); | ||
234 | 240 | ||
235 | /* Tell __cpu_die() that this CPU is now safe to dispose of */ | 241 | /* |
242 | * Flush the data out of the L1 cache for this CPU. This must be | ||
243 | * before the completion to ensure that data is safely written out | ||
244 | * before platform_cpu_kill() gets called - which may disable | ||
245 | * *this* CPU and power down its cache. | ||
246 | */ | ||
247 | flush_cache_louis(); | ||
248 | |||
249 | /* | ||
250 | * Tell __cpu_die() that this CPU is now safe to dispose of. Once | ||
251 | * this returns, power and/or clocks can be removed at any point | ||
252 | * from this CPU and its cache by platform_cpu_kill(). | ||
253 | */ | ||
236 | RCU_NONIDLE(complete(&cpu_died)); | 254 | RCU_NONIDLE(complete(&cpu_died)); |
237 | 255 | ||
238 | /* | 256 | /* |
239 | * actual CPU shutdown procedure is at least platform (if not | 257 | * Ensure that the cache lines associated with that completion are |
240 | * CPU) specific. | 258 | * written out. This covers the case where _this_ CPU is doing the |
259 | * powering down, to ensure that the completion is visible to the | ||
260 | * CPU waiting for this one. | ||
261 | */ | ||
262 | flush_cache_louis(); | ||
263 | |||
264 | /* | ||
265 | * The actual CPU shutdown procedure is at least platform (if not | ||
266 | * CPU) specific. This may remove power, or it may simply spin. | ||
267 | * | ||
268 | * Platforms are generally expected *NOT* to return from this call, | ||
269 | * although there are some which do because they have no way to | ||
270 | * power down the CPU. These platforms are the _only_ reason we | ||
271 | * have a return path which uses the fragment of assembly below. | ||
272 | * | ||
273 | * The return path should not be used for platforms which can | ||
274 | * power off the CPU. | ||
241 | */ | 275 | */ |
242 | if (smp_ops.cpu_die) | 276 | if (smp_ops.cpu_die) |
243 | smp_ops.cpu_die(cpu); | 277 | smp_ops.cpu_die(cpu); |