| From c41e5e6a7c2aec0a905a513aded7b7c1581b9052 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 4 Feb 2022 18:31:02 +0100 |
| Subject: ACPI: PM: s2idle: Cancel wakeup before dispatching EC GPE |
| |
| From: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| |
| [ Upstream commit dc0075ba7f387fe4c48a8c674b11ab6f374a6acc ] |
| |
| Commit 4a9af6cac050 ("ACPI: EC: Rework flushing of EC work while |
| suspended to idle") made acpi_ec_dispatch_gpe() check |
| pm_wakeup_pending(), but that is before canceling the SCI wakeup, |
| so pm_wakeup_pending() is always true. This causes the loop in |
| acpi_ec_dispatch_gpe() to always terminate after one iteration which |
| may not be correct. |
| |
| Address this issue by canceling the SCI wakeup earlier, from |
| acpi_ec_dispatch_gpe() itself. |
| |
| Fixes: 4a9af6cac050 ("ACPI: EC: Rework flushing of EC work while suspended to idle") |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/acpi/ec.c | 10 ++++++++++ |
| drivers/acpi/sleep.c | 14 ++++---------- |
| 2 files changed, 14 insertions(+), 10 deletions(-) |
| |
| diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c |
| index 9b859ff976e89..98d1782275440 100644 |
| --- a/drivers/acpi/ec.c |
| +++ b/drivers/acpi/ec.c |
| @@ -2051,6 +2051,16 @@ bool acpi_ec_dispatch_gpe(void) |
| if (acpi_any_gpe_status_set(first_ec->gpe)) |
| return true; |
| |
| + /* |
| + * Cancel the SCI wakeup and process all pending events in case there |
| + * are any wakeup ones in there. |
| + * |
| + * Note that if any non-EC GPEs are active at this point, the SCI will |
| + * retrigger after the rearming in acpi_s2idle_wake(), so no events |
| + * should be missed by canceling the wakeup here. |
| + */ |
| + pm_system_cancel_wakeup(); |
| + |
| /* |
| * Dispatch the EC GPE in-band, but do not report wakeup in any case |
| * to allow the caller to process events properly after that. |
| diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c |
| index 7ae09e4b45927..245a0fa979cbb 100644 |
| --- a/drivers/acpi/sleep.c |
| +++ b/drivers/acpi/sleep.c |
| @@ -739,21 +739,15 @@ bool acpi_s2idle_wake(void) |
| return true; |
| } |
| |
| - /* Check non-EC GPE wakeups and dispatch the EC GPE. */ |
| + /* |
| + * Check non-EC GPE wakeups and if there are none, cancel the |
| + * SCI-related wakeup and dispatch the EC GPE. |
| + */ |
| if (acpi_ec_dispatch_gpe()) { |
| pm_pr_dbg("ACPI non-EC GPE wakeup\n"); |
| return true; |
| } |
| |
| - /* |
| - * Cancel the SCI wakeup and process all pending events in case |
| - * there are any wakeup ones in there. |
| - * |
| - * Note that if any non-EC GPEs are active at this point, the |
| - * SCI will retrigger after the rearming below, so no events |
| - * should be missed by canceling the wakeup here. |
| - */ |
| - pm_system_cancel_wakeup(); |
| acpi_os_wait_events_complete(); |
| |
| /* |
| -- |
| 2.34.1 |
| |