aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/power/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/power/cpu.c')
-rw-r--r--arch/x86/power/cpu.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 218cdb16163c..120cee1c3f8d 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -21,6 +21,7 @@
21#include <asm/suspend.h> 21#include <asm/suspend.h>
22#include <asm/debugreg.h> 22#include <asm/debugreg.h>
23#include <asm/fpu-internal.h> /* pcntxt_mask */ 23#include <asm/fpu-internal.h> /* pcntxt_mask */
24#include <asm/cpu.h>
24 25
25#ifdef CONFIG_X86_32 26#ifdef CONFIG_X86_32
26static struct saved_context saved_context; 27static struct saved_context saved_context;
@@ -237,3 +238,84 @@ void restore_processor_state(void)
237#ifdef CONFIG_X86_32 238#ifdef CONFIG_X86_32
238EXPORT_SYMBOL(restore_processor_state); 239EXPORT_SYMBOL(restore_processor_state);
239#endif 240#endif
241
242/*
243 * When bsp_check() is called in hibernate and suspend, cpu hotplug
244 * is disabled already. So it's unnessary to handle race condition between
245 * cpumask query and cpu hotplug.
246 */
247static int bsp_check(void)
248{
249 if (cpumask_first(cpu_online_mask) != 0) {
250 pr_warn("CPU0 is offline.\n");
251 return -ENODEV;
252 }
253
254 return 0;
255}
256
257static int bsp_pm_callback(struct notifier_block *nb, unsigned long action,
258 void *ptr)
259{
260 int ret = 0;
261
262 switch (action) {
263 case PM_SUSPEND_PREPARE:
264 case PM_HIBERNATION_PREPARE:
265 ret = bsp_check();
266 break;
267#ifdef CONFIG_DEBUG_HOTPLUG_CPU0
268 case PM_RESTORE_PREPARE:
269 /*
270 * When system resumes from hibernation, online CPU0 because
271 * 1. it's required for resume and
272 * 2. the CPU was online before hibernation
273 */
274 if (!cpu_online(0))
275 _debug_hotplug_cpu(0, 1);
276 break;
277 case PM_POST_RESTORE:
278 /*
279 * When a resume really happens, this code won't be called.
280 *
281 * This code is called only when user space hibernation software
282 * prepares for snapshot device during boot time. So we just
283 * call _debug_hotplug_cpu() to restore to CPU0's state prior to
284 * preparing the snapshot device.
285 *
286 * This works for normal boot case in our CPU0 hotplug debug
287 * mode, i.e. CPU0 is offline and user mode hibernation
288 * software initializes during boot time.
289 *
290 * If CPU0 is online and user application accesses snapshot
291 * device after boot time, this will offline CPU0 and user may
292 * see different CPU0 state before and after accessing
293 * the snapshot device. But hopefully this is not a case when
294 * user debugging CPU0 hotplug. Even if users hit this case,
295 * they can easily online CPU0 back.
296 *
297 * To simplify this debug code, we only consider normal boot
298 * case. Otherwise we need to remember CPU0's state and restore
299 * to that state and resolve racy conditions etc.
300 */
301 _debug_hotplug_cpu(0, 0);
302 break;
303#endif
304 default:
305 break;
306 }
307 return notifier_from_errno(ret);
308}
309
310static int __init bsp_pm_check_init(void)
311{
312 /*
313 * Set this bsp_pm_callback as lower priority than
314 * cpu_hotplug_pm_callback. So cpu_hotplug_pm_callback will be called
315 * earlier to disable cpu hotplug before bsp online check.
316 */
317 pm_notifier(bsp_pm_callback, -INT_MAX);
318 return 0;
319}
320
321core_initcall(bsp_pm_check_init);