diff options
Diffstat (limited to 'drivers/xen/manage.c')
| -rw-r--r-- | drivers/xen/manage.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 07e857b0de13..1799bd890315 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/stop_machine.h> | 9 | #include <linux/stop_machine.h> |
| 10 | #include <linux/freezer.h> | 10 | #include <linux/freezer.h> |
| 11 | 11 | ||
| 12 | #include <xen/xen.h> | ||
| 12 | #include <xen/xenbus.h> | 13 | #include <xen/xenbus.h> |
| 13 | #include <xen/grant_table.h> | 14 | #include <xen/grant_table.h> |
| 14 | #include <xen/events.h> | 15 | #include <xen/events.h> |
| @@ -17,6 +18,7 @@ | |||
| 17 | 18 | ||
| 18 | #include <asm/xen/hypercall.h> | 19 | #include <asm/xen/hypercall.h> |
| 19 | #include <asm/xen/page.h> | 20 | #include <asm/xen/page.h> |
| 21 | #include <asm/xen/hypervisor.h> | ||
| 20 | 22 | ||
| 21 | enum shutdown_state { | 23 | enum shutdown_state { |
| 22 | SHUTDOWN_INVALID = -1, | 24 | SHUTDOWN_INVALID = -1, |
| @@ -33,10 +35,30 @@ enum shutdown_state { | |||
| 33 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; | 35 | static enum shutdown_state shutting_down = SHUTDOWN_INVALID; |
| 34 | 36 | ||
| 35 | #ifdef CONFIG_PM_SLEEP | 37 | #ifdef CONFIG_PM_SLEEP |
| 36 | static int xen_suspend(void *data) | 38 | static int xen_hvm_suspend(void *data) |
| 37 | { | 39 | { |
| 40 | struct sched_shutdown r = { .reason = SHUTDOWN_suspend }; | ||
| 38 | int *cancelled = data; | 41 | int *cancelled = data; |
| 42 | |||
| 43 | BUG_ON(!irqs_disabled()); | ||
| 44 | |||
| 45 | *cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r); | ||
| 46 | |||
| 47 | xen_hvm_post_suspend(*cancelled); | ||
| 48 | gnttab_resume(); | ||
| 49 | |||
| 50 | if (!*cancelled) { | ||
| 51 | xen_irq_resume(); | ||
| 52 | xen_timer_resume(); | ||
| 53 | } | ||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int xen_suspend(void *data) | ||
| 59 | { | ||
| 39 | int err; | 60 | int err; |
| 61 | int *cancelled = data; | ||
| 40 | 62 | ||
| 41 | BUG_ON(!irqs_disabled()); | 63 | BUG_ON(!irqs_disabled()); |
| 42 | 64 | ||
| @@ -106,7 +128,10 @@ static void do_suspend(void) | |||
| 106 | goto out_resume; | 128 | goto out_resume; |
| 107 | } | 129 | } |
| 108 | 130 | ||
| 109 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | 131 | if (xen_hvm_domain()) |
| 132 | err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0)); | ||
| 133 | else | ||
| 134 | err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); | ||
| 110 | 135 | ||
| 111 | dpm_resume_noirq(PMSG_RESUME); | 136 | dpm_resume_noirq(PMSG_RESUME); |
| 112 | 137 | ||
| @@ -255,7 +280,19 @@ static int shutdown_event(struct notifier_block *notifier, | |||
| 255 | return NOTIFY_DONE; | 280 | return NOTIFY_DONE; |
| 256 | } | 281 | } |
| 257 | 282 | ||
| 258 | static int __init setup_shutdown_event(void) | 283 | static int __init __setup_shutdown_event(void) |
| 284 | { | ||
| 285 | /* Delay initialization in the PV on HVM case */ | ||
| 286 | if (xen_hvm_domain()) | ||
| 287 | return 0; | ||
| 288 | |||
| 289 | if (!xen_pv_domain()) | ||
| 290 | return -ENODEV; | ||
| 291 | |||
| 292 | return xen_setup_shutdown_event(); | ||
| 293 | } | ||
| 294 | |||
| 295 | int xen_setup_shutdown_event(void) | ||
| 259 | { | 296 | { |
| 260 | static struct notifier_block xenstore_notifier = { | 297 | static struct notifier_block xenstore_notifier = { |
| 261 | .notifier_call = shutdown_event | 298 | .notifier_call = shutdown_event |
| @@ -264,5 +301,6 @@ static int __init setup_shutdown_event(void) | |||
| 264 | 301 | ||
| 265 | return 0; | 302 | return 0; |
| 266 | } | 303 | } |
| 304 | EXPORT_SYMBOL_GPL(xen_setup_shutdown_event); | ||
| 267 | 305 | ||
| 268 | subsys_initcall(setup_shutdown_event); | 306 | subsys_initcall(__setup_shutdown_event); |
