From b077fbada161479d9a32a7730d2822d5e737b306 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Mon, 11 Feb 2008 15:20:27 -0800 Subject: ACPI: fix suspend regression due to idle update Earlier patch (bc71bec91f9875ef825d12104acf3bf4ca215fa4) broke suspend resume on many laptops. The problem was reported by Carlos R. Mafra and Calvin Walton, who bisected the issue to above patch. The problem was because, C2 and C3 code were calling acpi_idle_enter_c1 directly, with C2 or C3 as state parameter, while suspend/resume was in progress. The patch bc71bec started making use of that state information, assuming that it would always be referring to C1 state. This caused the problem with suspend-resume as we ended up using C2/C3 state indirectly. Fix this by adding acpi_idle_suspend check in enter_c1. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 32003fdc91e8..1f022b0846d4 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1420,6 +1420,14 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, return 0; local_irq_disable(); + + /* Do not access any ACPI IO ports in suspend path */ + if (acpi_idle_suspend) { + acpi_safe_halt(); + local_irq_enable(); + return 0; + } + if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); -- cgit v1.2.3 From 4fcb2fcd4d0678b8ae103d257dcb28074cbfc7fa Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Mon, 11 Feb 2008 17:46:31 -0800 Subject: ACPI, cpuidle: Clarify C-state description in sysfs Add a new sysfs entry under cpuidle states. desc - can be used by driver to communicate to userspace any specific information about the state. This helps in identifying the exact hardware C-states behind the ACPI C-state definition. Idea is to export this through powertop, which will help to map the C-state reported by powertop to actual hardware C-state. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- arch/x86/kernel/acpi/cstate.c | 2 ++ drivers/acpi/processor_idle.c | 11 +++++++++++ drivers/cpuidle/cpuidle.c | 3 ++- drivers/cpuidle/sysfs.c | 14 +++++++++++--- include/acpi/processor.h | 9 ++++++--- include/linux/cpuidle.h | 2 ++ 6 files changed, 34 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index 10b67170b133..8ca3557a6d59 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -126,6 +126,8 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu, printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d " "state\n", cx->type); } + snprintf(cx->desc, ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x", + cx->address); out: set_cpus_allowed(current, saved_mask); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 32003fdc91e8..baa389b908e2 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -945,11 +945,16 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) * Otherwise, ignore this info and continue. */ cx.entry_method = ACPI_CSTATE_HALT; + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); } else { continue; } + } else { + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x", + cx.address); } + obj = &(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) continue; @@ -1643,6 +1648,11 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) return -EINVAL; } + for (i = 0; i < CPUIDLE_STATE_MAX; i++) { + dev->states[i].name[0] = '\0'; + dev->states[i].desc[0] = '\0'; + } + for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = &pr->power.states[i]; state = &dev->states[count]; @@ -1659,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) cpuidle_set_statedata(state, cx); snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); + strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); state->exit_latency = cx->latency; state->target_residency = cx->latency * latency_factor; state->power_usage = cx->power; diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 60f71e6345e3..d73663a52324 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -219,7 +219,8 @@ static void poll_idle_init(struct cpuidle_device *dev) cpuidle_set_statedata(state, NULL); - snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); + snprintf(state->name, CPUIDLE_NAME_LEN, "C0"); + snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); state->exit_latency = 0; state->target_residency = 0; state->power_usage = -1; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 088ea74edd34..69102ca05685 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -218,16 +218,23 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ return sprintf(buf, "%u\n", state->_name);\ } -static ssize_t show_state_name(struct cpuidle_state *state, char *buf) -{ - return sprintf(buf, "%s\n", state->name); +#define define_show_state_str_function(_name) \ +static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ +{ \ + if (state->_name[0] == '\0')\ + return sprintf(buf, "\n");\ + return sprintf(buf, "%s\n", state->_name);\ } define_show_state_function(exit_latency) define_show_state_function(power_usage) define_show_state_function(usage) define_show_state_function(time) +define_show_state_str_function(name) +define_show_state_str_function(desc) + define_one_state_ro(name, show_state_name); +define_one_state_ro(desc, show_state_desc); define_one_state_ro(latency, show_state_exit_latency); define_one_state_ro(power, show_state_power_usage); define_one_state_ro(usage, show_state_usage); @@ -235,6 +242,7 @@ define_one_state_ro(time, show_state_time); static struct attribute *cpuidle_state_default_attrs[] = { &attr_name.attr, + &attr_desc.attr, &attr_latency.attr, &attr_power.attr, &attr_usage.attr, diff --git a/include/acpi/processor.h b/include/acpi/processor.h index cdc8004cfd12..06480bcabfdc 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -32,9 +32,11 @@ #define DOMAIN_COORD_TYPE_SW_ANY 0xfd #define DOMAIN_COORD_TYPE_HW_ALL 0xfe -#define ACPI_CSTATE_SYSTEMIO (0) -#define ACPI_CSTATE_FFH (1) -#define ACPI_CSTATE_HALT (2) +#define ACPI_CSTATE_SYSTEMIO 0 +#define ACPI_CSTATE_FFH 1 +#define ACPI_CSTATE_HALT 2 + +#define ACPI_CX_DESC_LEN 32 /* Power Management */ @@ -74,6 +76,7 @@ struct acpi_processor_cx { u64 time; struct acpi_processor_cx_policy promotion; struct acpi_processor_cx_policy demotion; + char desc[ACPI_CX_DESC_LEN]; }; struct acpi_processor_power { diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 385d45b616db..6b72a4584086 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -19,6 +19,7 @@ #define CPUIDLE_STATE_MAX 8 #define CPUIDLE_NAME_LEN 16 +#define CPUIDLE_DESC_LEN 32 struct cpuidle_device; @@ -29,6 +30,7 @@ struct cpuidle_device; struct cpuidle_state { char name[CPUIDLE_NAME_LEN]; + char desc[CPUIDLE_DESC_LEN]; void *driver_data; unsigned int flags; -- cgit v1.2.3 From 314ccd644cc14b9ebc1996afbabfb4d108004fd0 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 13 Feb 2008 00:32:16 +0100 Subject: ACPI suspend: Execute _WAK with the right argument The _WAK global ACPI control method has to be called with the argument representing the sleep state being exited. Make it happen. Special thanks to Mirco Tischler for reporting the problem and debugging. Reported-by: Mirco Tischler Signed-off-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/hardware/hwsleep.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 058d0be5cbe2..4290e0193097 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -616,6 +616,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) return_ACPI_STATUS(status); } + arg.integer.value = sleep_state; status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); -- cgit v1.2.3 From bfaed45e30f19bb4cee779f3229d2744bc2b2c46 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 13 Feb 2008 23:30:00 +0200 Subject: ACPI: static acpi_no_initrd_override_setup() Signed-off-by: Adrian Bunk Acked-by: Eric Piel Signed-off-by: Len Brown --- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 15e602377655..346f0494dbbb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -419,7 +419,7 @@ acpi_os_table_override(struct acpi_table_header * existing_table, } #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD -int __init acpi_no_initrd_override_setup(char *s) +static int __init acpi_no_initrd_override_setup(char *s) { acpi_no_initrd_override = 1; return 1; -- cgit v1.2.3 From adba2a876c1c971980f9bb3c6c8e20c61490647b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 13 Feb 2008 23:29:58 +0200 Subject: ACPI: static acpi_find_dsdt_initrd() Signed-off-by: Adrian Bunk Signed-off-by: Len Brown --- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 346f0494dbbb..b51954d80ef9 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -325,7 +325,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val, } #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD -struct acpi_table_header *acpi_find_dsdt_initrd(void) +static struct acpi_table_header *acpi_find_dsdt_initrd(void) { struct file *firmware_file; mm_segment_t oldfs; -- cgit v1.2.3 From c8e773fa4f6a999a80d9fa3836f412e259ab6fa1 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 13 Feb 2008 23:29:57 +0200 Subject: ACPI: static acpi_chain_head Signed-off-by: Adrian Bunk Signed-off-by: Len Brown --- drivers/acpi/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 5479dc0eeeec..abec1ca94cf4 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -110,7 +110,7 @@ static const struct file_operations acpi_system_event_ops = { #endif /* CONFIG_ACPI_PROC_EVENT */ /* ACPI notifier chain */ -BLOCKING_NOTIFIER_HEAD(acpi_chain_head); +static BLOCKING_NOTIFIER_HEAD(acpi_chain_head); int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) { -- cgit v1.2.3