Commit d5406284 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPI: PM: s2idle: Refine active GPEs check

The check for any active GPEs added by commit fdde0ff8 ("ACPI:
PM: s2idle: Prevent spurious SCIs from waking up the system") turns
out to be insufficiently precise to prevent some systems from
resuming prematurely due to a spurious EC wakeup, so refine it
by first checking if any GPEs other than the EC GPE are active
and skipping all of the SCIs coming from the EC that do not produce
any genuine wakeup events after processing.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=206629
Fixes: fdde0ff8 ("ACPI: PM: s2idle: Prevent spurious SCIs from waking up the system")
Reported-by: default avatarOndřej Caletka <ondrej@caletka.cz>
Tested-by: default avatarOndřej Caletka <ondrej@caletka.cz>
Cc: 5.4+ <stable@vger.kernel.org> # 5.4+
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 0ce792d6
...@@ -2037,6 +2037,11 @@ void acpi_ec_set_gpe_wake_mask(u8 action) ...@@ -2037,6 +2037,11 @@ void acpi_ec_set_gpe_wake_mask(u8 action)
acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action); acpi_set_gpe_wake_mask(NULL, first_ec->gpe, action);
} }
bool acpi_ec_other_gpes_active(void)
{
return acpi_any_gpe_status_set(first_ec ? first_ec->gpe : U32_MAX);
}
bool acpi_ec_dispatch_gpe(void) bool acpi_ec_dispatch_gpe(void)
{ {
u32 ret; u32 ret;
......
...@@ -202,6 +202,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); ...@@ -202,6 +202,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
void acpi_ec_flush_work(void); void acpi_ec_flush_work(void);
bool acpi_ec_other_gpes_active(void);
bool acpi_ec_dispatch_gpe(void); bool acpi_ec_dispatch_gpe(void);
#endif #endif
......
...@@ -1010,18 +1010,19 @@ static bool acpi_s2idle_wake(void) ...@@ -1010,18 +1010,19 @@ static bool acpi_s2idle_wake(void)
return true; return true;
/* /*
* If there are no EC events to process and at least one of the * If the status bit is set for any enabled GPE other than the
* other enabled GPEs is active, the wakeup is regarded as a * EC one, the wakeup is regarded as a genuine one.
* genuine one.
*
* Note that the checks below must be carried out in this order
* to avoid returning prematurely due to a change of the EC GPE
* status bit from unset to set between the checks with the
* status bits of all the other GPEs unset.
*/ */
if (acpi_any_gpe_status_set(U32_MAX) && !acpi_ec_dispatch_gpe()) if (acpi_ec_other_gpes_active())
return true; return true;
/*
* If the EC GPE status bit has not been set, the wakeup is
* regarded as a spurious one.
*/
if (!acpi_ec_dispatch_gpe())
return false;
/* /*
* Cancel the wakeup and process all pending events in case * Cancel the wakeup and process all pending events in case
* there are any wakeup ones in there. * there are any wakeup ones in there.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment