From nobody Thu Jul 2 23:42:52 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4grtjY4N9yz6k9DG for ; Thu, 02 Jul 2026 23:42:57 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4grtjY3MzCz40TX for ; Thu, 02 Jul 2026 23:42:57 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783035777; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Gux1jGTMNCXkac+yRpjgp+AI69ER1yIMoqp6CyqwvS8=; b=w4ZbCMYX6/BeUu2SBluXG/nkzgFL44q27zCHARz+oejajkBj0nLWQoLSppCbVVxBbbxYma XscV4kBUG68p14Oro11khA8bFsGoiC9tPPwcycg2fcHN0KT5HYtP4hFtDq2wKGQvVSCkRb PDrDyCemzm+ttYwCAlOmEXLhgaCbr+TqVMpBjSI+mKj10AlaDBFsVvUzqtaBE6TKB19FFU GHMYDXKxbdT/+gCmNBrA3QSMMWBOCOyVW/Vp3PVWGO/jLOFplyYwDe4s1Oh+5ZliAEXm/d msjiXpResTTh75N25hsEdqRsaa9Ma5Lk1R8zwJCaTsmWG4H6n6tQQIIl0AYfng== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1783035777; a=rsa-sha256; cv=none; b=XYM+FbtqH7aWPUsVMuC/eSraW/t87583oMSDldFrtt4XYm62quV3HtdRa5rM8/3L+i3apN Ymdjh+ebCQZ/bdZZY6DzafO+PpolLydZ4IB0EYi9e1AKUIEsVAZItVU3ZYc6HbHDnSZ7Lq DWnw2WwHu8ObBmY3DYI3MCI45Hl49F0CnTsgbGuDuIJZiRHVNqUeptYyJBNN31ENHzurhA Z6x06JfO6gWGmVNBWTzNmOGNB5QnqyZ2A0HHhKr6n1oYnFkXcdG5HH7qWjJ5YvCMfpppdb IWWyTACfWHTwLwiVcaH2VDNLpWDK42QalRPXyiRa3cB8MOnOWMfZ18W6DnMrUA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783035777; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Gux1jGTMNCXkac+yRpjgp+AI69ER1yIMoqp6CyqwvS8=; b=r4WHRxM7SsbsfgGXUq0jLyVsQofakZCticbZXlbKLCRcxjhVWSlChTQFL3lMzcmYJcJoX3 T6G5v9rHRxH38l7mSKTLsDx1NnoP0VQsvVduBjaMC3Ax8NASXAx64IMpDxxpp/7G40A6Zw jrdeNYyA4gYlZOXt6g7lezl8c0Bew8+E3zZ9wr9DiLRKJMXFQCH0oRDULZ5e1g0zNbYPE1 +txUdZo0Z23+VpAwrfAzZl0QHHSP5lcOoUZR/6+QSJmO93E87dU7Kp0j04EyWdYqrmXAK4 c1yT/RrLHPyIF7r4K4E3PAMqGqqLecCNmgFgUcstdE8XHcjOPMq3X3YZYUhsbg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4grtjY1trFz7ZS for ; Thu, 02 Jul 2026 23:42:57 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 203c6 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 02 Jul 2026 23:42:52 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Devin Teske Subject: git: d1b62492f97f - main - acpi: ignore wake button press replayed by firmware on resume List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dteske X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d1b62492f97f5044b498fa4624e3a007a43efa6f Auto-Submitted: auto-generated Date: Thu, 02 Jul 2026 23:42:52 +0000 Message-Id: <6a46f77c.203c6.1c8a53af@gitrepo.freebsd.org> The branch main has been updated by dteske: URL: https://cgit.FreeBSD.org/src/commit/?id=d1b62492f97f5044b498fa4624e3a007a43efa6f commit d1b62492f97f5044b498fa4624e3a007a43efa6f Author: Devin Teske AuthorDate: 2026-06-20 16:17:40 +0000 Commit: Devin Teske CommitDate: 2026-07-02 23:39:13 +0000 acpi: ignore wake button press replayed by firmware on resume Some firmware delivers the power or sleep button press that woke the system as an ordinary button press (Notify 0x80) shortly after resume, rather than as the wakeup notification (Notify 0x02) the ACPI specification requires for a button that is also a wake source. On affected machines (e.g. the Framework Laptop 12, Intel Raptor Lake-P) the power button is a control-method device behind the embedded controller. The EC latches the key press that woke the system across the sleep transition and flushes it through its normal _Qxx query path as soon as it is reinitialized on resume. The replayed press is indistinguishable from a genuine one, so the kernel honors it as a fresh suspend request and the machine suspends again immediately after waking; it cannot be kept awake with the button. The event cannot be filtered at its source: it arrives over the same EC query path that also carries legitimate events (lid, AC, thermal, battery), so suppressing the drain would lose real notifications. Instead, record the time of resume and ignore a button-initiated suspend that arrives within a short grace window of it. The timestamp is taken before DEVICE_RESUME() re-initializes the EC, so it is set before the replay can be processed on the ACPICA notify taskqueue; otherwise the replay can be evaluated before the timestamp is written and slip through. Measured from that point, the replay lands at ~600 ms across many cycles on a Framework Laptop 12, whereas a deliberate press cannot occur that quickly -- it happens well after the display is back -- so a one-second window separates the two without ignoring real presses for any perceptible time. Spec-compliant firmware reports the wake as Notify 0x02, which is handled on a different path and never reaches this check, so there is no change in behavior on such systems. The replay window is a fixed compile-time constant rather than a tunable on purpose: it tracks a hardware characteristic -- the EC's post-resume replay latency -- not a user policy, so there is no value a user would meaningfully choose. PR: 296243 Reviewed by: adrian, imp (earlier revision), olce MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D57712 --- sys/dev/acpica/acpi.c | 43 +++++++++++++++++++++++++++++++++++++++++++ sys/dev/acpica/acpivar.h | 1 + 2 files changed, 44 insertions(+) diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 0033ba734dc1..93451667a2b2 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -3747,6 +3747,13 @@ backout: slp_state &= ~ACPI_SS_GPE_SET; } if ((slp_state & ACPI_SS_DEV_SUSPEND) != 0) { + /* + * Record the resume time so a spurious power/sleep button press can be + * ignored for a grace period afterward (see the comment before + * ACPI_BUTTON_REPLAY_WINDOW). This must be taken before + * DEVICE_RESUME(), which re-initializes the EC that replays the press. + */ + sc->acpi_resume_sbt = getsbinuptime(); EVENTHANDLER_INVOKE(acpi_pre_dev_resume, stype); DEVICE_RESUME(root_bus); slp_state &= ~ACPI_SS_DEV_SUSPEND; @@ -4137,6 +4144,37 @@ acpi_system_eventhandler_wakeup(struct acpi_softc *const sc, return_VOID; } +/* + * Grace window after wakeup during which a power/sleep button press for suspend + * is ignored. Some firmware wrongly reports the depress that caused the wakeup + * as an "S0 Power/Sleep Button Pressed" notify (value 0x80) instead of the + * spec-required "Device Wake" notify (0x02); honoring it re-enters sleep + * immediately after resume. On the Framework Laptop 12 the replayed event + * arrives within ~620 ms of the recorded resume time, so a one-second window + * was chosen. See https://bugs.freebsd.org/296243 for the traces, timing + * data, and analysis. + */ +#define ACPI_BUTTON_REPLAY_WINDOW SBT_1S + +static bool +acpi_button_resume_replay(struct acpi_softc *sc, const char *which) +{ + sbintime_t elapsed; + + if (sc->acpi_resume_sbt == 0) + return (false); + elapsed = getsbinuptime() - sc->acpi_resume_sbt; + if (elapsed < 0 || elapsed >= ACPI_BUTTON_REPLAY_WINDOW) + return (false); + if (bootverbose) { + device_printf(sc->acpi_dev, + "ignoring %s button press %jd us after resume " + "(firmware replayed the wake event)\n", + which, (intmax_t)(elapsed / SBT_1US)); + } + return (true); +} + /* * ACPICA Event Handlers (FixedEvent, also called from button notify handler) */ @@ -4158,6 +4196,8 @@ acpi_event_power_button_sleep(struct acpi_softc *sc) ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); #if defined(__amd64__) || defined(__i386__) + if (acpi_button_resume_replay(sc, "power")) + return_VALUE (ACPI_INTERRUPT_HANDLED); if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER, (ACPI_OSD_EXEC_CALLBACK)acpi_invoke_sleep_eventhandler, &sc->acpi_power_button_stype))) @@ -4186,6 +4226,9 @@ acpi_event_sleep_button_sleep(struct acpi_softc *sc) { ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + if (acpi_button_resume_replay(sc, "sleep")) + return_VALUE (ACPI_INTERRUPT_HANDLED); + if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER, (ACPI_OSD_EXEC_CALLBACK)acpi_invoke_sleep_eventhandler, &sc->acpi_sleep_button_stype))) diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 9facbaea595a..27300a00b8d1 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -56,6 +56,7 @@ struct acpi_softc { int acpi_enabled; enum power_stype acpi_stype; int acpi_sleep_disabled; + sbintime_t acpi_resume_sbt; /* Uptime at last resume. */ /* Supported sleep states and types. */ bool acpi_supported_stypes[POWER_STYPE_COUNT];