From nobody Thu Jul 2 23:42:52 2026 X-Original-To: dev-commits-src-main@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 4grtjS6Zltz6k9Vp for ; Thu, 02 Jul 2026 23:42:52 +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 4grtjS304bz40WS for ; Thu, 02 Jul 2026 23:42:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1783035772; 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=efGKpgUzAxU/BSOwayDioo83NvHrEK6Mj4SLolaHB6yQYKgVPxbhk70TOQiWLPtd2vndYR nN+3iugC2HkoKFIes2b1onNbdwzlMu8pk++JSgYXVfU7yFK5qGL8KYD2+pAoqpwZHhdsTl wKeQW+mDtb4U4fS4G3xqG0+46zJewJFECUaewRsnKkfqru7H+0GWPWMauOCsutv5RFskXm B8euoU4SZQ9ZjrmGSBVWKrPFjomU4jRPRtZmHOdpPe2hEpCPa/jFIphmaL9F1g3g8W9njs asE848rSioEo1d72H32N7tVIXct0Muk5l1L9SqXH9kFhkTmEsNqaHuq6hpGmQw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1783035772; a=rsa-sha256; cv=none; b=WxKDIDoMgaihCL8w+eeQjO4sl256IMH+kcMMX0QI7iyjewGrb+8lpg3cSduhUPTrS2FO1j RC2COjMfNnMSqk0WOmaGZtUMbXZYCv0R0CPMU/UqTuG0waC/dQRRhYC2hdz3287lb26cKv m6rYu2i9daTcRH2glNxBXfFtSS+Ua5N/ocRlf8IimaIng7xCgx3YF7YYgAftlbVGoAW3E0 KWSS9fB2fAkpQMgYXqw32pJzyMocOAhTumUTlKe+s+6Uh2RfdGXVbXl7z+mNvoY7PAQPnS WL8gF1mhnY4J6HCUCFPkpKZevINHzj31/4GgOW6pv27SIr5txMlfM0aSGtCovg== 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=1783035772; 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=Pnk4YTpm51uBGoG7nhUq7Y/jI8u4Yn6iHEGZWEUM3Ly1yZT1z3CR1pmJXiV67YMlruTmos hrlzvh39KW9wOVFr8CTnhOEsvcTjEyzsVDk62//WhfVUQYB4slU92TwhTNjvzscUGovwBK 7eLQapijXSoV9ZYkJTJVUTIGdGeNf9JBrlde6Jc9dLaK5D3Z0+EL0Kq6BJabcUSNCaGETW qR536mo+wh3Vgt3ouhgkwO/G7X7EFoU9bAjYFXOYuugExMoKd+/K54fZ0euh/rpVo5vFHv 5lrvbQPM92Kg66SnnctXqvJ82+WdbpanrU57gy1vzqSZyFyoGrL0zaDlSUJdYg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4grtjS1mddz7ls for ; Thu, 02 Jul 2026 23:42:52 +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 the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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];