git: a23fa3fe1c0a - main - amdsmu: Diagnose S0i3 entry after resume
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Sep 2026 10:59:27 UTC
The branch main has been updated by obiwac:
URL: https://cgit.FreeBSD.org/src/commit/?id=a23fa3fe1c0aa4e529b26bbec17d17571f8708fd
commit a23fa3fe1c0aa4e529b26bbec17d17571f8708fd
Author: Aymeric Wibo <obiwac@FreeBSD.org>
AuthorDate: 2026-09-18 10:50:22 +0000
Commit: Aymeric Wibo <obiwac@FreeBSD.org>
CommitDate: 2026-09-18 10:59:14 +0000
amdsmu: Diagnose S0i3 entry after resume
Print out diagnostic information after resuming from suspend-to-idle if
we failed to enter S0i3, i.e. the IP blocks that were blocking entry to
S0i3.
Don't give detailed IP block info for other SMUs than for Phoenix, as I
have not had a chance to test these yet and the SMU seems to be very
quirky.
Reviewed by: olce
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D59673
---
sys/dev/amdsmu/amdsmu.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/dev/amdsmu/amdsmu.h | 1 +
2 files changed, 49 insertions(+)
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c
index ffffe0b5219f..5902e5e9af89 100644
--- a/sys/dev/amdsmu/amdsmu.c
+++ b/sys/dev/amdsmu/amdsmu.c
@@ -317,6 +317,51 @@ amdsmu_resume(device_t dev, enum power_stype stype)
amdsmu_fetch_idlemask(dev);
}
+static void
+amdsmu_resume_check(device_t dev, enum power_stype stype)
+{
+ struct amdsmu_softc *sc = device_get_softc(dev);
+ struct amdsmu_metrics *m = &sc->metrics;
+ bool any_blocking = false;
+
+ if (stype != POWER_STYPE_SUSPEND_TO_IDLE)
+ return;
+ if (m->s0i3_last_entry_status != 0)
+ return;
+
+ device_printf(dev,
+ "failed to enter S0i3 during last suspend; "
+ "battery drain will be excessive\n");
+
+ if (sc->product->amdsmu_deviceid != PCI_DEVICEID_AMD_PHOENIX_ROOT) {
+ device_printf(dev, "only limited diagnostic information "
+ "available for %x:%x; check dev.amdsmu.0 sysctl tree\n",
+ sc->product->amdsmu_vendorid,
+ sc->product->amdsmu_deviceid);
+ return;
+ }
+
+ for (size_t i = 0; i < sc->product->ip_block_count; i++) {
+ /*
+ * An IP block only truly blocked S0i3 entry if it was active
+ * for the entire time spent in "SWDRIPS".
+ */
+ if (m->ip_block_last_active_time[i] < m->time_last_in_sw_drips)
+ continue;
+ if (!any_blocking) {
+ device_printf(dev,
+ "IP blocks that blocked S0i3 entry:\n");
+ any_blocking = true;
+ }
+ device_printf(dev, " %s (active for %ju us)\n",
+ sc->product->ip_blocks_names[i],
+ (uintmax_t)m->ip_block_last_active_time[i]);
+ }
+
+ if (!any_blocking)
+ device_printf(dev, "no IP block info available\n");
+}
+
static int
amdsmu_attach(device_t dev)
{
@@ -461,6 +506,8 @@ amdsmu_attach(device_t dev)
amdsmu_suspend, dev, EVENTHANDLER_PRI_LAST);
sc->eh_resume = EVENTHANDLER_REGISTER(acpi_pre_dev_resume,
amdsmu_resume, dev, EVENTHANDLER_PRI_FIRST);
+ sc->eh_resume_check = EVENTHANDLER_REGISTER(power_resume_check,
+ amdsmu_resume_check, dev, EVENTHANDLER_PRI_ANY);
#endif
return (0);
@@ -482,6 +529,7 @@ amdsmu_detach(device_t dev)
#if defined(DEV_ACPI)
EVENTHANDLER_DEREGISTER(acpi_post_dev_suspend, sc->eh_suspend);
EVENTHANDLER_DEREGISTER(acpi_pre_dev_resume, sc->eh_resume);
+ EVENTHANDLER_DEREGISTER(power_resume_check, sc->eh_resume_check);
#endif
bus_space_unmap(sc->bus_tag, sc->smu_space, SMU_MEM_SIZE);
diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h
index 0e7c4df37a43..3b600fab118d 100644
--- a/sys/dev/amdsmu/amdsmu.h
+++ b/sys/dev/amdsmu/amdsmu.h
@@ -123,6 +123,7 @@ struct amdsmu_softc {
struct eventhandler_entry *eh_suspend;
struct eventhandler_entry *eh_resume;
+ struct eventhandler_entry *eh_resume_check;
struct resource *res;
bus_space_tag_t bus_tag;