|
@@ -211,6 +211,13 @@ void __cpuinit __cpu_die(unsigned int cpu)
|
|
|
}
|
|
|
printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
|
|
|
|
|
|
+ /*
|
|
|
+ * platform_cpu_kill() is generally expected to do the powering off
|
|
|
+ * and/or cutting of clocks to the dying CPU. Optionally, this may
|
|
|
+ * be done by the CPU which is dying in preference to supporting
|
|
|
+ * this call, but that means there is _no_ synchronisation between
|
|
|
+ * the requesting CPU and the dying CPU actually losing power.
|
|
|
+ */
|
|
|
if (!platform_cpu_kill(cpu))
|
|
|
printk("CPU%u: unable to kill\n", cpu);
|
|
|
}
|
|
@@ -230,14 +237,41 @@ void __ref cpu_die(void)
|
|
|
idle_task_exit();
|
|
|
|
|
|
local_irq_disable();
|
|
|
- mb();
|
|
|
|
|
|
- /* Tell __cpu_die() that this CPU is now safe to dispose of */
|
|
|
+ /*
|
|
|
+ * Flush the data out of the L1 cache for this CPU. This must be
|
|
|
+ * before the completion to ensure that data is safely written out
|
|
|
+ * before platform_cpu_kill() gets called - which may disable
|
|
|
+ * *this* CPU and power down its cache.
|
|
|
+ */
|
|
|
+ flush_cache_louis();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Tell __cpu_die() that this CPU is now safe to dispose of. Once
|
|
|
+ * this returns, power and/or clocks can be removed at any point
|
|
|
+ * from this CPU and its cache by platform_cpu_kill().
|
|
|
+ */
|
|
|
RCU_NONIDLE(complete(&cpu_died));
|
|
|
|
|
|
/*
|
|
|
- * actual CPU shutdown procedure is at least platform (if not
|
|
|
- * CPU) specific.
|
|
|
+ * Ensure that the cache lines associated with that completion are
|
|
|
+ * written out. This covers the case where _this_ CPU is doing the
|
|
|
+ * powering down, to ensure that the completion is visible to the
|
|
|
+ * CPU waiting for this one.
|
|
|
+ */
|
|
|
+ flush_cache_louis();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The actual CPU shutdown procedure is at least platform (if not
|
|
|
+ * CPU) specific. This may remove power, or it may simply spin.
|
|
|
+ *
|
|
|
+ * Platforms are generally expected *NOT* to return from this call,
|
|
|
+ * although there are some which do because they have no way to
|
|
|
+ * power down the CPU. These platforms are the _only_ reason we
|
|
|
+ * have a return path which uses the fragment of assembly below.
|
|
|
+ *
|
|
|
+ * The return path should not be used for platforms which can
|
|
|
+ * power off the CPU.
|
|
|
*/
|
|
|
if (smp_ops.cpu_die)
|
|
|
smp_ops.cpu_die(cpu);
|