diff options
| author | Justin T. Gibbs <gibbs@FreeBSD.org> | 2011-09-20 23:44:34 +0000 |
|---|---|---|
| committer | Justin T. Gibbs <gibbs@FreeBSD.org> | 2011-09-20 23:44:34 +0000 |
| commit | 2ca7463bc7ac8a1c0ece154ee21aeab4cb394eec (patch) | |
| tree | 6b8fcd349b3da3727d19a4671541e3c2563ca2d8 /sys/dev/xen/control | |
| parent | b296414c6222eecb519ad4e784e6ff7ca7821452 (diff) | |
Notes
Diffstat (limited to 'sys/dev/xen/control')
| -rw-r--r-- | sys/dev/xen/control/control.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c index 301d4e827c6e..63ece1ef05f4 100644 --- a/sys/dev/xen/control/control.c +++ b/sys/dev/xen/control/control.c @@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/reboot.h> #include <sys/rman.h> +#include <sys/sched.h> #include <sys/taskqueue.h> #include <sys/types.h> #include <sys/vnode.h> @@ -201,6 +202,8 @@ xctrl_suspend() int i, j, k, fpp; unsigned long max_pfn, start_info_mfn; + EVENTHANDLER_INVOKE(power_suspend); + #ifdef SMP struct thread *td; cpuset_t map; @@ -221,7 +224,13 @@ xctrl_suspend() stop_cpus(map); #endif + /* + * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE + * drivers need this. + */ + mtx_lock(&Giant); if (DEVICE_SUSPEND(root_bus) != 0) { + mtx_unlock(&Giant); printf("xen_suspend: device_suspend failed\n"); #ifdef SMP if (!CPU_EMPTY(&map)) @@ -229,6 +238,7 @@ xctrl_suspend() #endif return; } + mtx_unlock(&Giant); local_irq_disable(); @@ -283,11 +293,14 @@ xctrl_suspend() vcpu_prepare(i); #endif + /* * Only resume xenbus /after/ we've prepared our VCPUs; otherwise * the VCPU hotplug callback can race with our vcpu_prepare */ + mtx_lock(&Giant); DEVICE_RESUME(root_bus); + mtx_unlock(&Giant); #ifdef SMP thread_lock(curthread); @@ -296,6 +309,7 @@ xctrl_suspend() if (!CPU_EMPTY(&map)) restart_cpus(map); #endif + EVENTHANDLER_INVOKE(power_resume); } static void @@ -322,39 +336,47 @@ xctrl_suspend() { int suspend_cancelled; + EVENTHANDLER_INVOKE(power_suspend); + + /* + * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE + * drivers need this. + */ + mtx_lock(&Giant); if (DEVICE_SUSPEND(root_bus)) { + mtx_unlock(&Giant); printf("xen_suspend: device_suspend failed\n"); return; } - - /* - * Make sure we don't change cpus or switch to some other - * thread. for the duration. - */ - critical_enter(); + mtx_unlock(&Giant); /* * Prevent any races with evtchn_interrupt() handler. */ - irq_suspend(); disable_intr(); + irq_suspend(); suspend_cancelled = HYPERVISOR_suspend(0); - if (!suspend_cancelled) + if (suspend_cancelled) + irq_resume(); + else xenpci_resume(); /* * Re-enable interrupts and put the scheduler back to normal. */ enable_intr(); - critical_exit(); /* * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or * similar. */ + mtx_lock(&Giant); if (!suspend_cancelled) DEVICE_RESUME(root_bus); + mtx_unlock(&Giant); + + EVENTHANDLER_INVOKE(power_resume); } #endif |
