acpid: wire lid-open to exit_s2idle (symmetric with lid-closed)

Round 2 follow-up to lid-closed → enter_s2idle wiring. Without
the symmetric lid-open → exit_s2idle call, the system stays in
'wake devices armed' state after the lid opens (until the kernel
kstop reason=2 path fires, which only happens if MWAIT actually
engaged).

Lid-open now runs the AML wake sequence (_SST(2) → _WAK(0) →
_SST(1) + wake-device disarming). The kernel-side MWAIT-return
path also calls exit_s2idle(); the double-call is safe because
AML _WAK/_SST methods are spec-required to be idempotent in the
working state (ACPI 6.5 §3.5.3).

External-display detection (Linux's HandleLidSwitchDocked=ignore)
is still not wired — every lid-close triggers s2idle. Documented
as a follow-up in the LG Gram assessment doc.
This commit is contained in:
Red Bear OS
2026-07-26 17:25:50 +09:00
parent 1331b8c017
commit 887718da49
+34
View File
@@ -295,6 +295,40 @@ fn daemon(daemon: daemon::Daemon) -> ! {
}
power_events::PowerEvent::LidChanged(open) => {
log::info!("acpid: lid {}", if open { "opened" } else { "closed" });
// Symmetric lid-switch → s2idle wiring. Mirrors
// Linux logind's `HandleLidSwitch=suspend` default
// for laptops.
//
// Lid-closed runs `enter_s2idle()` — the AML
// preparation sequence (_TTS/_PTS/_SST + wake-device
// arming via _DSW/_PSW) so the system is in the
// correct state when the kernel MWAIT loop (Phase
// 9.1, not yet landed) actually idles the CPU.
//
// Lid-open runs `exit_s2idle()` — the AML wake
// sequence (_SST(2) → _WAK(0) → _SST(1) + wake-device
// disarming). This is the userspace-driven wake path
// for the case where the kernel MWAIT loop hasn't
// engaged yet (e.g. a brief lid-close/open during
// active workload). When MWAIT IS engaged, the
// kernel-side MWAIT-return path fires kstop
// reason=2 which ALSO calls exit_s2idle() — the
// double-call is safe because the AML _WAK/_SST
// methods are spec-required to be idempotent in
// the working state (ACPI 6.5 §3.5.3).
//
// External-display detection (Linux's
// HandleLidSwitchDocked=ignore) is not wired yet —
// every lid-close triggers s2idle. Documented as a
// follow-up in local/docs/evidence/lg-gram/
// ASSESSMENT-2026-07-26.md.
if open {
log::info!("acpid: lid opened — running s2idle wake sequence");
acpi_context.exit_s2idle();
} else {
log::info!("acpid: lid closed — entering s2idle preparation");
acpi_context.enter_s2idle();
}
}
power_events::PowerEvent::Notify { device, value } => {
log::debug!("acpid: device notification {} = {:#x}", device, value);