diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r-- | drivers/acpi/processor_idle.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f7ca8c55956..72069ba5f1e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -202,21 +202,44 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, * Suspend / resume control */ static int acpi_idle_suspend; +static u32 saved_bm_rld; + +static void acpi_idle_bm_rld_save(void) +{ + acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld); +} +static void acpi_idle_bm_rld_restore(void) +{ + u32 resumed_bm_rld; + + acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld); + + if (resumed_bm_rld != saved_bm_rld) + acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld); +} int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) { + if (acpi_idle_suspend == 1) + return 0; + + acpi_idle_bm_rld_save(); acpi_idle_suspend = 1; return 0; } int acpi_processor_resume(struct acpi_device * device) { + if (acpi_idle_suspend == 0) + return 0; + + acpi_idle_bm_rld_restore(); acpi_idle_suspend = 0; return 0; } #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) -static int tsc_halts_in_c(int state) +static void tsc_check_state(int state) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: @@ -226,13 +249,17 @@ static int tsc_halts_in_c(int state) * C/P/S0/S1 states when this bit is set. */ if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) - return 0; + return; /*FALL THROUGH*/ default: - return state > ACPI_STATE_C1; + /* TSC could halt in idle, so notify users */ + if (state > ACPI_STATE_C1) + mark_tsc_unstable("TSC halts in idle"); } } +#else +static void tsc_check_state(int state) { return; } #endif static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) @@ -578,14 +605,9 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) pr->power.timer_broadcast_on_state = INT_MAX; - for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { + for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { struct acpi_processor_cx *cx = &pr->power.states[i]; -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) - /* TSC could halt in idle, so notify users */ - if (tsc_halts_in_c(cx->type)) - mark_tsc_unstable("TSC halts in idle");; -#endif switch (cx->type) { case ACPI_STATE_C1: cx->valid = 1; @@ -603,6 +625,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) acpi_timer_check_state(i, pr, cx); break; } + if (cx->valid) + tsc_check_state(cx->type); if (cx->valid) working++; |