git: 19ab46cc6604 - main - acpi: Parse _S3D in s2idle instead of _S255D
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 08 Apr 2026 12:11:50 UTC
The branch main has been updated by obiwac:
URL: https://cgit.FreeBSD.org/src/commit/?id=19ab46cc66045ea936475f1a1e08763eb2fd663e
commit 19ab46cc66045ea936475f1a1e08763eb2fd663e
Author: Aymeric Wibo <obiwac@FreeBSD.org>
AuthorDate: 2026-03-04 13:09:14 +0000
Commit: Aymeric Wibo <obiwac@FreeBSD.org>
CommitDate: 2026-04-08 12:11:23 +0000
acpi: Parse _S3D in s2idle instead of _S255D
Previously, when entering s2idle, we were parsing the _S255D object to
get the shallowest D-state supported by device, as
acpi_stype_to_sstate() returns -1 for s2idle.
Instead, we should read _S3D.
Relevant document:
https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/07_Power_and_Performance_Mgmt/device-power-management-objects.html#s3d-s3-device-state
Reviewed by: olce
Tested by: emaste, olce
Approved by: olce
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D55118
---
sys/dev/acpica/acpi.c | 84 +++++++++++++++++++++++++++++++--------------------
1 file changed, 52 insertions(+), 32 deletions(-)
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 98578b383f42..bdc197a4fb59 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -2131,44 +2131,64 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname,
}
}
+static int
+acpi_device_pwr_for_sleep_sxd(device_t dev, ACPI_HANDLE handle, int state,
+ int *dstate)
+{
+ ACPI_STATUS status;
+ char sxd[8];
+
+ /* Note illegal _S0D is evaluated because some systems expect this. */
+ snprintf(sxd, sizeof(sxd), "_S%dD", state);
+ status = acpi_GetInteger(handle, sxd, dstate);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ device_printf(dev, "failed to get %s on %s: %s\n", sxd,
+ acpi_name(handle), AcpiFormatException(status));
+ return (ENXIO);
+ }
+ return (0);
+}
+
+/*
+ * Get the D-state we need to set the device to for entry into the sleep type
+ * we are currently entering (sc->acpi_stype is set in acpi_EnterSleepState
+ * before the ACPI bus gets suspended, and thus before this function is called).
+ *
+ * If entering s2idle, we will try to enter whichever D-state we would've been
+ * transitioning to in S3. If we are entering an ACPI S-state, we evaluate the
+ * relevant _SxD state instead (ACPI 7.3.16 - 7.3.19).
+ */
int
acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate)
{
- struct acpi_softc *sc;
- ACPI_HANDLE handle;
- ACPI_STATUS status;
- char sxd[8];
-
- handle = acpi_get_handle(dev);
+ struct acpi_softc *sc = device_get_softc(bus);
+ ACPI_HANDLE handle = acpi_get_handle(dev);
+ int state;
- /*
- * XXX If we find these devices, don't try to power them down.
- * The serial and IRDA ports on my T23 hang the system when
- * set to D3 and it appears that such legacy devices may
- * need special handling in their drivers.
- */
- if (dstate == NULL || handle == NULL ||
- acpi_MatchHid(handle, "PNP0500") ||
- acpi_MatchHid(handle, "PNP0501") ||
- acpi_MatchHid(handle, "PNP0502") ||
- acpi_MatchHid(handle, "PNP0510") ||
- acpi_MatchHid(handle, "PNP0511"))
- return (ENXIO);
+ if (dstate == NULL)
+ return (EINVAL);
- /*
- * Override next state with the value from _SxD, if present.
- * Note illegal _S0D is evaluated because some systems expect this.
- */
- sc = device_get_softc(bus);
- snprintf(sxd, sizeof(sxd), "_S%dD", acpi_stype_to_sstate(sc, sc->acpi_stype));
- status = acpi_GetInteger(handle, sxd, dstate);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- device_printf(dev, "failed to get %s on %s: %s\n", sxd,
- acpi_name(handle), AcpiFormatException(status));
- return (ENXIO);
- }
+ /*
+ * XXX If we find these devices, don't try to power them down.
+ * The serial and IRDA ports on my T23 hang the system when
+ * set to D3 and it appears that such legacy devices may
+ * need special handling in their drivers.
+ */
+ if (handle == NULL ||
+ acpi_MatchHid(handle, "PNP0500") ||
+ acpi_MatchHid(handle, "PNP0501") ||
+ acpi_MatchHid(handle, "PNP0502") ||
+ acpi_MatchHid(handle, "PNP0510") ||
+ acpi_MatchHid(handle, "PNP0511"))
+ return (ENXIO);
- return (0);
+ if (sc->acpi_stype == POWER_STYPE_SUSPEND_TO_IDLE)
+ state = ACPI_STATE_S3;
+ else
+ state = acpi_stype_to_sstate(sc, sc->acpi_stype);
+ if (state == ACPI_STATE_UNKNOWN)
+ return (ENOENT);
+ return (acpi_device_pwr_for_sleep_sxd(bus, handle, state, dstate));
}
/* Callback arg for our implementation of walking the namespace. */