From: Alexey Starikovskiy acpi_gpe_sleep_prepare() does not have counter part at resume time, so changes to GPEs are final. In case someone use S4 and then try S3, he will miss some wakeup devices. So, acpi_gpe_sleep_prepare() is removed, and acpi_enable_wakeup_device() gets its functionality. acpi_disable_wakeup_device() rolls back the changes. there is bug 292300 in bugzilla.novell.com for this issue. Signed-off-by: Alexey Starikovskiy --- drivers/acpi/sleep/main.c | 1 drivers/acpi/sleep/sleep.h | 1 drivers/acpi/sleep/wakeup.c | 117 +++++++++++++++----------------------------- include/acpi/acpi_bus.h | 1 4 files changed, 40 insertions(+), 80 deletions(-) Index: linux-2.6.23-rc8/drivers/acpi/sleep/sleep.h =================================================================== --- linux-2.6.23-rc8.orig/drivers/acpi/sleep/sleep.h +++ linux-2.6.23-rc8/drivers/acpi/sleep/sleep.h @@ -5,6 +5,5 @@ extern int acpi_suspend (u32 state); extern void acpi_enable_wakeup_device_prep(u8 sleep_state); extern void acpi_enable_wakeup_device(u8 sleep_state); extern void acpi_disable_wakeup_device(u8 sleep_state); -extern void acpi_gpe_sleep_prepare(u32 sleep_state); extern int acpi_sleep_prepare(u32 acpi_state); Index: linux-2.6.23-rc8/drivers/acpi/sleep/wakeup.c =================================================================== --- linux-2.6.23-rc8.orig/drivers/acpi/sleep/wakeup.c +++ linux-2.6.23-rc8/drivers/acpi/sleep/wakeup.c @@ -64,36 +64,29 @@ void acpi_enable_wakeup_device(u8 sleep_ ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device"); spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = container_of(node, - struct acpi_device, - wakeup_list); - + struct acpi_device *dev = + container_of(node, struct acpi_device, wakeup_list); + if (!dev->wakeup.flags.valid) + continue; /* If users want to disable run-wake GPE, * we only disable it for wake and leave it for runtime */ - if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { - spin_unlock(&acpi_device_lock); - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_RUNTIME); - /* Re-enable it, since set_gpe_type will disable it */ - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_ISR); - spin_lock(&acpi_device_lock); + if (!dev->wakeup.state.enabled || + sleep_state > (u32) dev->wakeup.sleep_state) { + if (dev->wakeup.flags.run_wake) { + spin_unlock(&acpi_device_lock); + /* set_gpe_type will disable GPE, leave it like that */ + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_RUNTIME); + spin_lock(&acpi_device_lock); + } continue; } - - if (!dev->wakeup.flags.valid || - !dev->wakeup.state.enabled || - (sleep_state > (u32) dev->wakeup.sleep_state)) - continue; - spin_unlock(&acpi_device_lock); - /* run-wake GPE has been enabled */ if (!dev->wakeup.flags.run_wake) acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_ISR); - dev->wakeup.state.active = 1; spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); @@ -112,26 +105,25 @@ void acpi_disable_wakeup_device(u8 sleep spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = container_of(node, - struct acpi_device, - wakeup_list); + struct acpi_device *dev = + container_of(node, struct acpi_device, wakeup_list); - if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { - spin_unlock(&acpi_device_lock); - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE_RUN); - /* Re-enable it, since set_gpe_type will disable it */ - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); - spin_lock(&acpi_device_lock); + if (!dev->wakeup.flags.valid) continue; - } - - if (!dev->wakeup.flags.valid || - !dev->wakeup.state.active || - (sleep_state > (u32) dev->wakeup.sleep_state)) + if (!dev->wakeup.state.enabled || + sleep_state > (u32) dev->wakeup.sleep_state) { + if (dev->wakeup.flags.run_wake) { + spin_unlock(&acpi_device_lock); + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE_RUN); + /* Re-enable it, since set_gpe_type will disable it */ + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, ACPI_NOT_ISR); + spin_lock(&acpi_device_lock); + } continue; + } spin_unlock(&acpi_device_lock); acpi_disable_wakeup_device_power(dev); @@ -142,7 +134,6 @@ void acpi_disable_wakeup_device(u8 sleep acpi_clear_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); } - dev->wakeup.state.active = 0; spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); @@ -160,48 +151,20 @@ static int __init acpi_wakeup_device_ini struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); - /* In case user doesn't load button driver */ - if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { - spin_unlock(&acpi_device_lock); - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_WAKE_RUN); - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); - dev->wakeup.state.enabled = 1; - spin_lock(&acpi_device_lock); - } + if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) + continue; + spin_unlock(&acpi_device_lock); + acpi_set_gpe_type(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, + ACPI_GPE_TYPE_WAKE_RUN); + acpi_enable_gpe(dev->wakeup.gpe_device, + dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.state.enabled = 1; + spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); - return 0; } late_initcall(acpi_wakeup_device_init); - -/* - * Disable all wakeup GPEs before entering requested sleep state. - * @sleep_state: ACPI state - * Since acpi_enter_sleep_state() will disable all - * RUNTIME GPEs, we simply mark all GPES that - * are not enabled for wakeup from requested state as RUNTIME. - */ -void acpi_gpe_sleep_prepare(u32 sleep_state) -{ - struct list_head *node, *next; - - list_for_each_safe(node, next, &acpi_wakeup_device_list) { - struct acpi_device *dev = container_of(node, - struct acpi_device, - wakeup_list); - - /* The GPE can wakeup system from this state, don't touch it */ - if ((u32) dev->wakeup.sleep_state >= sleep_state) - continue; - /* acpi_set_gpe_type will automatically disable GPE */ - acpi_set_gpe_type(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, - ACPI_GPE_TYPE_RUNTIME); - } -} Index: linux-2.6.23-rc8/include/acpi/acpi_bus.h =================================================================== --- linux-2.6.23-rc8.orig/include/acpi/acpi_bus.h +++ linux-2.6.23-rc8/include/acpi/acpi_bus.h @@ -264,7 +264,6 @@ struct acpi_device_wakeup_flags { struct acpi_device_wakeup_state { u8 enabled:1; - u8 active:1; }; struct acpi_device_wakeup { Index: linux-2.6.23-rc8/drivers/acpi/sleep/main.c =================================================================== --- linux-2.6.23-rc8.orig/drivers/acpi/sleep/main.c +++ linux-2.6.23-rc8/drivers/acpi/sleep/main.c @@ -44,7 +44,6 @@ int acpi_sleep_prepare(u32 acpi_state) ACPI_FLUSH_CPU_CACHE(); acpi_enable_wakeup_device_prep(acpi_state); #endif - acpi_gpe_sleep_prepare(acpi_state); acpi_enter_sleep_state_prep(acpi_state); return 0; }