diff options
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index a0d920915b38..c8a4370e2a34 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #include <linux/numa.h> | 26 | #include <linux/numa.h> |
27 | #include <linux/suspend.h> | 27 | #include <linux/suspend.h> |
28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/freezer.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <linux/cpu.h> | ||
32 | #include <linux/console.h> | ||
29 | 33 | ||
30 | #include <asm/page.h> | 34 | #include <asm/page.h> |
31 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -1441,7 +1445,31 @@ int kernel_kexec(void) | |||
1441 | 1445 | ||
1442 | if (kexec_image->preserve_context) { | 1446 | if (kexec_image->preserve_context) { |
1443 | #ifdef CONFIG_KEXEC_JUMP | 1447 | #ifdef CONFIG_KEXEC_JUMP |
1448 | mutex_lock(&pm_mutex); | ||
1449 | pm_prepare_console(); | ||
1450 | error = freeze_processes(); | ||
1451 | if (error) { | ||
1452 | error = -EBUSY; | ||
1453 | goto Restore_console; | ||
1454 | } | ||
1455 | suspend_console(); | ||
1456 | error = device_suspend(PMSG_FREEZE); | ||
1457 | if (error) | ||
1458 | goto Resume_console; | ||
1459 | error = disable_nonboot_cpus(); | ||
1460 | if (error) | ||
1461 | goto Resume_devices; | ||
1444 | local_irq_disable(); | 1462 | local_irq_disable(); |
1463 | /* At this point, device_suspend() has been called, | ||
1464 | * but *not* device_power_down(). We *must* | ||
1465 | * device_power_down() now. Otherwise, drivers for | ||
1466 | * some devices (e.g. interrupt controllers) become | ||
1467 | * desynchronized with the actual state of the | ||
1468 | * hardware at resume time, and evil weirdness ensues. | ||
1469 | */ | ||
1470 | error = device_power_down(PMSG_FREEZE); | ||
1471 | if (error) | ||
1472 | goto Enable_irqs; | ||
1445 | save_processor_state(); | 1473 | save_processor_state(); |
1446 | #endif | 1474 | #endif |
1447 | } else { | 1475 | } else { |
@@ -1459,7 +1487,18 @@ int kernel_kexec(void) | |||
1459 | if (kexec_image->preserve_context) { | 1487 | if (kexec_image->preserve_context) { |
1460 | #ifdef CONFIG_KEXEC_JUMP | 1488 | #ifdef CONFIG_KEXEC_JUMP |
1461 | restore_processor_state(); | 1489 | restore_processor_state(); |
1490 | device_power_up(PMSG_RESTORE); | ||
1491 | Enable_irqs: | ||
1462 | local_irq_enable(); | 1492 | local_irq_enable(); |
1493 | enable_nonboot_cpus(); | ||
1494 | Resume_devices: | ||
1495 | device_resume(PMSG_RESTORE); | ||
1496 | Resume_console: | ||
1497 | resume_console(); | ||
1498 | thaw_processes(); | ||
1499 | Restore_console: | ||
1500 | pm_restore_console(); | ||
1501 | mutex_unlock(&pm_mutex); | ||
1463 | #endif | 1502 | #endif |
1464 | } | 1503 | } |
1465 | 1504 | ||