xen: use freeze/restore/thaw PM events for suspend/resume/chkpt

Use PM_FREEZE, PM_THAW and PM_RESTORE power events for
suspend/resume/checkpoint functionality, instead of PM_SUSPEND
and PM_RESUME. Use of these pm events fixes the Xen Guest hangup
when taking checkpoints. When a suspend event is cancelled
(while taking checkpoints once/continuously), we use PM_THAW
instead of PM_RESUME. PM_RESTORE is used when suspend is not
cancelled. See Documentation/power/devices.txt and linux/pm.h
for more info about freeze, thaw and restore. The sequence of
pm events in a suspend-resume scenario is shown below.

dpm_suspend_start(PMSG_FREEZE);

dpm_suspend_noirq(PMSG_FREEZE);

sysdev_suspend(PMSG_FREEZE);
cancelled = suspend_hypercall()
sysdev_resume();

dpm_resume_noirq(cancelled ? PMSG_THAW : PMSG_RESTORE);

dpm_resume_end(cancelled ? PMSG_THAW : PMSG_RESTORE);

Acked-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Shriram Rajagopalan <rshriram@cs.ubc.ca>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

authored by Shriram Rajagopalan and committed by Konrad Rzeszutek Wilk b3e96c0c c7853aea

+13 -11
+8 -8
drivers/xen/manage.c
··· 61 xen_mm_unpin_all(); 62 } 63 64 - #ifdef CONFIG_PM_SLEEP 65 static int xen_suspend(void *data) 66 { 67 struct suspend_info *si = data; ··· 69 70 BUG_ON(!irqs_disabled()); 71 72 - err = sysdev_suspend(PMSG_SUSPEND); 73 if (err) { 74 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", 75 err); ··· 118 } 119 #endif 120 121 - err = dpm_suspend_start(PMSG_SUSPEND); 122 if (err) { 123 printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); 124 goto out_thaw; ··· 127 printk(KERN_DEBUG "suspending xenstore...\n"); 128 xs_suspend(); 129 130 - err = dpm_suspend_noirq(PMSG_SUSPEND); 131 if (err) { 132 printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); 133 goto out_resume; ··· 147 148 err = stop_machine(xen_suspend, &si, cpumask_of(0)); 149 150 - dpm_resume_noirq(PMSG_RESUME); 151 152 if (err) { 153 printk(KERN_ERR "failed to start xen_suspend: %d\n", err); ··· 161 } else 162 xs_suspend_cancel(); 163 164 - dpm_resume_end(PMSG_RESUME); 165 166 /* Make sure timer events get retriggered on all CPUs */ 167 clock_was_set(); ··· 173 #endif 174 shutting_down = SHUTDOWN_INVALID; 175 } 176 - #endif /* CONFIG_PM_SLEEP */ 177 178 struct shutdown_handler { 179 const char *command; ··· 202 { "poweroff", do_poweroff }, 203 { "halt", do_poweroff }, 204 { "reboot", do_reboot }, 205 - #ifdef CONFIG_PM_SLEEP 206 { "suspend", do_suspend }, 207 #endif 208 {NULL, NULL},
··· 61 xen_mm_unpin_all(); 62 } 63 64 + #ifdef CONFIG_HIBERNATION 65 static int xen_suspend(void *data) 66 { 67 struct suspend_info *si = data; ··· 69 70 BUG_ON(!irqs_disabled()); 71 72 + err = sysdev_suspend(PMSG_FREEZE); 73 if (err) { 74 printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n", 75 err); ··· 118 } 119 #endif 120 121 + err = dpm_suspend_start(PMSG_FREEZE); 122 if (err) { 123 printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err); 124 goto out_thaw; ··· 127 printk(KERN_DEBUG "suspending xenstore...\n"); 128 xs_suspend(); 129 130 + err = dpm_suspend_noirq(PMSG_FREEZE); 131 if (err) { 132 printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); 133 goto out_resume; ··· 147 148 err = stop_machine(xen_suspend, &si, cpumask_of(0)); 149 150 + dpm_resume_noirq(si.cancelled ? PMSG_THAW : PMSG_RESTORE); 151 152 if (err) { 153 printk(KERN_ERR "failed to start xen_suspend: %d\n", err); ··· 161 } else 162 xs_suspend_cancel(); 163 164 + dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE); 165 166 /* Make sure timer events get retriggered on all CPUs */ 167 clock_was_set(); ··· 173 #endif 174 shutting_down = SHUTDOWN_INVALID; 175 } 176 + #endif /* CONFIG_HIBERNATION */ 177 178 struct shutdown_handler { 179 const char *command; ··· 202 { "poweroff", do_poweroff }, 203 { "halt", do_poweroff }, 204 { "reboot", do_reboot }, 205 + #ifdef CONFIG_HIBERNATION 206 { "suspend", do_suspend }, 207 #endif 208 {NULL, NULL},
+5 -3
drivers/xen/xenbus/xenbus_probe_frontend.c
··· 86 }; 87 88 static const struct dev_pm_ops xenbus_pm_ops = { 89 - .suspend = xenbus_dev_suspend, 90 - .resume = xenbus_dev_resume, 91 - .thaw = xenbus_dev_cancel, 92 }; 93 94 static struct xen_bus_type xenbus_frontend = {
··· 86 }; 87 88 static const struct dev_pm_ops xenbus_pm_ops = { 89 + .suspend = xenbus_dev_suspend, 90 + .resume = xenbus_dev_resume, 91 + .freeze = xenbus_dev_suspend, 92 + .thaw = xenbus_dev_cancel, 93 + .restore = xenbus_dev_resume, 94 }; 95 96 static struct xen_bus_type xenbus_frontend = {