Page MenuHomeFreeBSD

D57712.diff
No OneTemporary

D57712.diff

diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -3747,6 +3747,13 @@
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,36 @@
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 a sleep event (Notify 0x80 instead of the spec-required 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 +4195,8 @@
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 +4225,9 @@
{
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
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -56,6 +56,7 @@
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];

File Metadata

Mime Type
text/plain
Expires
Thu, Jun 25, 4:45 AM (45 m, 14 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34304799
Default Alt Text
D57712.diff (2 KB)

Event Timeline