diff options
Diffstat (limited to 'drivers/xen/manage.c')
| -rw-r--r-- | drivers/xen/manage.c | 32 | 
1 files changed, 22 insertions, 10 deletions
| diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 10d03d7931c4..2ac4440e7b08 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | */ | 3 | */ | 
| 4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> | 
| 5 | #include <linux/err.h> | 5 | #include <linux/err.h> | 
| 6 | #include <linux/slab.h> | ||
| 6 | #include <linux/reboot.h> | 7 | #include <linux/reboot.h> | 
| 7 | #include <linux/sysrq.h> | 8 | #include <linux/sysrq.h> | 
| 8 | #include <linux/stop_machine.h> | 9 | #include <linux/stop_machine.h> | 
| @@ -43,7 +44,6 @@ static int xen_suspend(void *data) | |||
| 43 | if (err) { | 44 | if (err) { | 
| 44 | printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", | 45 | printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", | 
| 45 | err); | 46 | err); | 
| 46 | dpm_resume_noirq(PMSG_RESUME); | ||
| 47 | return err; | 47 | return err; | 
| 48 | } | 48 | } | 
| 49 | 49 | ||
| @@ -69,7 +69,6 @@ static int xen_suspend(void *data) | |||
| 69 | } | 69 | } | 
| 70 | 70 | ||
| 71 | sysdev_resume(); | 71 | sysdev_resume(); | 
| 72 | dpm_resume_noirq(PMSG_RESUME); | ||
| 73 | 72 | ||
| 74 | return 0; | 73 | return 0; | 
| 75 | } | 74 | } | 
| @@ -81,6 +80,12 @@ static void do_suspend(void) | |||
| 81 | 80 | ||
| 82 | shutting_down = SHUTDOWN_SUSPEND; | 81 | shutting_down = SHUTDOWN_SUSPEND; | 
| 83 | 82 | ||
| 83 | err = stop_machine_create(); | ||
| 84 | if (err) { | ||
| 85 | printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | |||
| 84 | #ifdef CONFIG_PREEMPT | 89 | #ifdef CONFIG_PREEMPT | 
| 85 | /* If the kernel is preemptible, we need to freeze all the processes | 90 | /* If the kernel is preemptible, we need to freeze all the processes | 
| 86 | to prevent them from being in the middle of a pagetable update | 91 | to prevent them from being in the middle of a pagetable update | 
| @@ -88,14 +93,14 @@ static void do_suspend(void) | |||
| 88 | err = freeze_processes(); | 93 | err = freeze_processes(); | 
| 89 | if (err) { | 94 | if (err) { | 
| 90 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); | 95 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); | 
| 91 | return; | 96 | goto out_destroy_sm; | 
| 92 | } | 97 | } | 
| 93 | #endif | 98 | #endif | 
| 94 | 99 | ||
| 95 | err = dpm_suspend_start(PMSG_SUSPEND); | 100 | err = dpm_suspend_start(PMSG_SUSPEND); | 
| 96 | if (err) { | 101 | if (err) { | 
| 97 | printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); | 102 | printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); | 
| 98 | goto out; | 103 | goto out_thaw; | 
| 99 | } | 104 | } | 
| 100 | 105 | ||
| 101 | printk(KERN_DEBUG "suspending xenstore...\n"); | 106 | printk(KERN_DEBUG "suspending xenstore...\n"); | 
| @@ -104,32 +109,39 @@ static void do_suspend(void) | |||
| 104 | err = dpm_suspend_noirq(PMSG_SUSPEND); | 109 | err = dpm_suspend_noirq(PMSG_SUSPEND); | 
| 105 | if (err) { | 110 | if (err) { | 
| 106 | printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); | 111 | printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); | 
| 107 | goto resume_devices; | 112 | goto out_resume; | 
| 108 | } | 113 | } | 
| 109 | 114 | ||
| 110 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 115 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 
| 116 | |||
| 117 | dpm_resume_noirq(PMSG_RESUME); | ||
| 118 | |||
| 111 | if (err) { | 119 | if (err) { | 
| 112 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); | 120 | printk(KERN_ERR "failed to start xen_suspend: %d\n", err); | 
| 113 | goto out; | 121 | cancelled = 1; | 
| 114 | } | 122 | } | 
| 115 | 123 | ||
| 124 | out_resume: | ||
| 116 | if (!cancelled) { | 125 | if (!cancelled) { | 
| 117 | xen_arch_resume(); | 126 | xen_arch_resume(); | 
| 118 | xs_resume(); | 127 | xs_resume(); | 
| 119 | } else | 128 | } else | 
| 120 | xs_suspend_cancel(); | 129 | xs_suspend_cancel(); | 
| 121 | 130 | ||
| 122 | dpm_resume_noirq(PMSG_RESUME); | ||
| 123 | |||
| 124 | resume_devices: | ||
| 125 | dpm_resume_end(PMSG_RESUME); | 131 | dpm_resume_end(PMSG_RESUME); | 
| 126 | 132 | ||
| 127 | /* Make sure timer events get retriggered on all CPUs */ | 133 | /* Make sure timer events get retriggered on all CPUs */ | 
| 128 | clock_was_set(); | 134 | clock_was_set(); | 
| 129 | out: | 135 | |
| 136 | out_thaw: | ||
| 130 | #ifdef CONFIG_PREEMPT | 137 | #ifdef CONFIG_PREEMPT | 
| 131 | thaw_processes(); | 138 | thaw_processes(); | 
| 139 | |||
| 140 | out_destroy_sm: | ||
| 132 | #endif | 141 | #endif | 
| 142 | stop_machine_destroy(); | ||
| 143 | |||
| 144 | out: | ||
| 133 | shutting_down = SHUTDOWN_INVALID; | 145 | shutting_down = SHUTDOWN_INVALID; | 
| 134 | } | 146 | } | 
| 135 | #endif /* CONFIG_PM_SLEEP */ | 147 | #endif /* CONFIG_PM_SLEEP */ | 
