From 815ab0fd40579ad2aa42058298073503648762b9 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 7 May 2009 22:19:45 -0400 Subject: ACPI: suspend: restore BM_RLD on resume In 2.6.29, 31878dd86b7df9a147f5e6cc6e07092b4308782b "ACPI: remove BM_RLD access from idle entry path" moved BM_RLD initialization to init-time from run time. But we discovered that some BIOS do not restore BM_RLD after suspend, causing device errors on C3 and C4 after resume. So now the kernel restores BM_RLD. http://bugzilla.kernel.org/show_bug.cgi?id=13032 Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/acpi/processor_idle.c') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f7ca8c55956b..c1d59cfdb5fb 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -202,15 +202,38 @@ 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; } -- cgit v1.2.1 From 520daf7217bc1806c02eb4cfa7805447a3da2f66 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 14 May 2009 17:27:38 -0400 Subject: ACPI: idle: fix init-time TSC check regression A previous 2.6.30 patch, a71e4917dc0ebbcb5a0ecb7ca3486643c1c9a6e2, (ACPI: idle: mark_tsc_unstable() at init-time, not run-time) erroneously disabled the TSC on systems that did not actually have valid deep C-states. Move the check after the deep-C-states are validated, via new helper, tsc_check_state(), hich replaces tsc_halts_in_c(). Signed-off-by: Len Brown Acked-by: Venkatesh Pallipadi Acked-by: Thomas Gleixner Tested-by: Frans Pop --- drivers/acpi/processor_idle.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/acpi/processor_idle.c') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f7ca8c55956b..e39a40a2ceae 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -216,7 +216,7 @@ int acpi_processor_resume(struct acpi_device * device) } #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 +226,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) @@ -581,11 +585,6 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; 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 +602,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++; -- cgit v1.2.1 From a0bf284bfedd6dc95bbee7ebf5ccf3b5f753a008 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 15 May 2009 01:29:31 -0400 Subject: ACPI: Idle C-states disabled by max_cstate should not disable the TSC Processor idle power states C2 and C3 stop the TSC on many machines. Linux recognizes this situation and marks the TSC as unstable: Marking TSC unstable due to TSC halts in idle But if those same machines are booted with "processor.max_cstate=1", then there is no need to validate C2 and C3, and no need to disable the TSC, which can be reliably used as a clocksource. Signed-off-by: Len Brown Acked-by: Thomas Gleixner --- drivers/acpi/processor_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi/processor_idle.c') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e39a40a2ceae..e65476fdf40d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -582,7 +582,7 @@ 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]; switch (cx->type) { -- cgit v1.2.1