[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] acpi sleep: Rearrange code for entering system sleep states.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1271327780 -3600 # Node ID 11423ce78ee0ff314351c10842dcac9af6e11d1e # Parent 85ab727868ea68bef59947f676f03a1669a83fae acpi sleep: Rearrange code for entering system sleep states. We cannot freeze_domains in hypercall-continuation context any more, since that is a softirq context which can interrupt an arbitrary vcpu. Hence sleeping all vcpus in that context can easily deadlock (against the vcpu we interrupted). So rearrange the code to freeze_domains before calling continue_hypercall_on_cpu(). Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/acpi/power.c | 38 +++++++++++++++++++++++++------------- 1 files changed, 25 insertions(+), 13 deletions(-) diff -r 85ab727868ea -r 11423ce78ee0 xen/arch/x86/acpi/power.c --- a/xen/arch/x86/acpi/power.c Thu Apr 15 11:33:39 2010 +0100 +++ b/xen/arch/x86/acpi/power.c Thu Apr 15 11:36:20 2010 +0100 @@ -149,15 +149,7 @@ static int enter_state(u32 state) int error; unsigned long cr4; - if ( (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) ) - return -EINVAL; - - if ( !spin_trylock(&pm_lock) ) - return -EBUSY; - - printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state); - - freeze_domains(); + BUG_ON(!spin_is_locked(&pm_lock)); disable_nonboot_cpus(); if ( num_online_cpus() != 1 ) @@ -246,6 +238,9 @@ static long enter_state_helper(void *dat */ int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep) { + int rc; + u32 state; + if ( !IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt_blk.address ) return -EPERM; @@ -258,14 +253,31 @@ int acpi_enter_sleep(struct xenpf_enter_ return -EINVAL; } - if ( sleep->flags ) + state = sleep->sleep_state; + if ( sleep->flags || + (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) ) return -EINVAL; + + if ( !spin_trylock(&pm_lock) ) + return -EBUSY; acpi_sinfo.pm1a_cnt_val = sleep->pm1a_cnt_val; acpi_sinfo.pm1b_cnt_val = sleep->pm1b_cnt_val; - acpi_sinfo.sleep_state = sleep->sleep_state; - - return continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo); + acpi_sinfo.sleep_state = state; + + printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state); + + freeze_domains(); + + rc = continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo); + if ( rc ) + { + /* Continuation will not execute: undo our own work so far. */ + thaw_domains(); + spin_unlock(&pm_lock); + } + + return rc; } static int acpi_get_wake_status(void) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |