Skip to content

Commit a39a1d6

Browse files
committed
ACPI: sleep: Avoid breaking S3 wakeup due to might_sleep()
jira LE-1907 Rebuild_History Non-Buildable kernel-5.14.0-284.30.1.el9_2 commit-author Rafael J. Wysocki <rafael.j.wysocki@intel.com> commit 22db063 The addition of might_sleep() to down_timeout() caused the latter to enable interrupts unconditionally in some cases, which in turn broke the ACPI S3 wakeup path in acpi_suspend_enter(), where down_timeout() is called by acpi_disable_all_gpes() via acpi_ut_acquire_mutex(). Namely, if CONFIG_DEBUG_ATOMIC_SLEEP is set, might_sleep() causes might_resched() to be used and if CONFIG_PREEMPT_VOLUNTARY is set, this triggers __cond_resched() which may call preempt_schedule_common(), so __schedule() gets invoked and it ends up with enabled interrupts (in the prev == next case). Now, enabling interrupts early in the S3 wakeup path causes the kernel to crash. Address this by modifying acpi_suspend_enter() to disable GPEs without attempting to acquire the sleeping lock which is not needed in that code path anyway. Fixes: 99409b9 ("locking/semaphore: Add might_sleep() to down_*() family") Reported-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: 5.15+ <stable@vger.kernel.org> # 5.15+ (cherry picked from commit 22db063) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent 37136bb commit a39a1d6

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

drivers/acpi/acpica/achware.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ acpi_status
101101
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
102102
acpi_event_status *event_status);
103103

104-
acpi_status acpi_hw_disable_all_gpes(void);
105-
106104
acpi_status acpi_hw_enable_all_runtime_gpes(void);
107105

108106
acpi_status acpi_hw_enable_all_wakeup_gpes(void);

drivers/acpi/sleep.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,11 +632,19 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
632632
}
633633

634634
/*
635-
* Disable and clear GPE status before interrupt is enabled. Some GPEs
636-
* (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
637-
* acpi_leave_sleep_state will reenable specific GPEs later
635+
* Disable all GPE and clear their status bits before interrupts are
636+
* enabled. Some GPEs (like wakeup GPEs) have no handlers and this can
637+
* prevent them from producing spurious interrups.
638+
*
639+
* acpi_leave_sleep_state() will reenable specific GPEs later.
640+
*
641+
* Because this code runs on one CPU with disabled interrupts (all of
642+
* the other CPUs are offline at this time), it need not acquire any
643+
* sleeping locks which may trigger an implicit preemption point even
644+
* if there is no contention, so avoid doing that by using a low-level
645+
* library routine here.
638646
*/
639-
acpi_disable_all_gpes();
647+
acpi_hw_disable_all_gpes();
640648
/* Allow EC transactions to happen. */
641649
acpi_ec_unblock_transactions();
642650

include/acpi/acpixf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
751751
acpi_event_status
752752
*event_status))
753753
ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number))
754+
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_hw_disable_all_gpes(void))
754755
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
755756
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
756757
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))

0 commit comments

Comments
 (0)