Page MenuHomeFreeBSD

D48721.id169552.diff
No OneTemporary

D48721.id169552.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
@@ -3436,14 +3436,53 @@
}
enum acpi_sleep_state {
- ACPI_SS_NONE = 0,
- ACPI_SS_GPE_SET = 1 << 0,
- ACPI_SS_DEV_SUSPEND = 1 << 1,
- ACPI_SS_SPMC_ENTER = 1 << 2,
- ACPI_SS_SLP_PREP = 1 << 3,
- ACPI_SS_SLEPT = 1 << 4,
+ ACPI_SS_NONE = 0,
+ ACPI_SS_GPE_SET = 1 << 0,
+ ACPI_SS_DEV_SUSPEND = 1 << 1,
+ ACPI_SS_SPMC_ENTER = 1 << 2,
+ ACPI_SS_AMDSMU_ENTER = 1 << 3,
+ ACPI_SS_SLP_PREP = 1 << 4,
+ ACPI_SS_SLEPT = 1 << 5,
};
+static int
+acpi_amdsmu_get_device(struct acpi_softc *sc, device_t *dev)
+{
+ devclass_t amdsmu_dc = devclass_find("amdsmu");
+
+ MPASS(dev != NULL);
+ if (amdsmu_dc == NULL) {
+ device_printf(sc->acpi_dev, "amdsmu device class not found\n");
+ return (ENXIO);
+ }
+ *dev = devclass_get_device(amdsmu_dc, 0);
+ if (*dev == NULL) {
+ device_printf(sc->acpi_dev, "no amdsmu device found\n");
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static int
+acpi_amdsmu_enter(struct acpi_softc *sc)
+{
+ device_t amdsmu;
+
+ if (acpi_amdsmu_get_device(sc, &amdsmu) != 0)
+ return (ENXIO);
+ return (DEVICE_AMDSMU_ENTER_SLEEP(amdsmu));
+}
+
+static int
+acpi_amdsmu_exit(struct acpi_softc *sc)
+{
+ device_t amdsmu;
+
+ if (acpi_amdsmu_get_device(sc, &amdsmu) != 0)
+ return (ENXIO);
+ return (DEVICE_AMDSMU_EXIT_SLEEP(amdsmu));
+}
+
static void
do_standby(struct acpi_softc *sc, enum acpi_sleep_state *slp_state,
register_t rflags)
@@ -3646,6 +3685,8 @@
else
slp_state |= ACPI_SS_SPMC_ENTER;
}
+ if (acpi_amdsmu_enter(sc) == 0)
+ slp_state |= ACPI_SS_AMDSMU_ENTER;
if (stype != POWER_STYPE_SUSPEND_TO_IDLE) {
status = AcpiEnterSleepStatePrep(acpi_sstate);
@@ -3696,6 +3737,10 @@
sc->acpi_stype = POWER_STYPE_AWAKE;
slp_state &= ~ACPI_SS_GPE_SET;
}
+ if ((slp_state & ACPI_SS_AMDSMU_ENTER) != 0) {
+ acpi_amdsmu_exit(sc);
+ slp_state &= ~ACPI_SS_AMDSMU_ENTER;
+ }
if ((slp_state & ACPI_SS_SPMC_ENTER) != 0) {
MPASS(sc->acpi_spmc_device != NULL);
MPASS(sc->acpi_spmc_exit != NULL);
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c
--- a/sys/dev/amdsmu/amdsmu.c
+++ b/sys/dev/amdsmu/amdsmu.c
@@ -289,6 +289,32 @@
sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK);
}
+static int
+amdsmu_enter(device_t dev)
+{
+ int err;
+
+ err = amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL);
+ if (err != 0) {
+ device_printf(dev, "failed to hint to SMU to enter sleep");
+ return (err);
+ }
+ return (0);
+}
+
+static int
+amdsmu_exit(device_t dev)
+{
+ int err;
+
+ err = amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, false, NULL);
+ if (err != 0) {
+ device_printf(dev, "failed to hint to SMU to exit sleep");
+ return (err);
+ }
+ return (amdsmu_dump_metrics(dev));
+}
+
static int
amdsmu_attach(device_t dev)
{
@@ -450,6 +476,8 @@
DEVMETHOD(device_probe, amdsmu_probe),
DEVMETHOD(device_attach, amdsmu_attach),
DEVMETHOD(device_detach, amdsmu_detach),
+ DEVMETHOD(device_amdsmu_enter_sleep, amdsmu_enter),
+ DEVMETHOD(device_amdsmu_exit_sleep, amdsmu_exit),
DEVMETHOD_END
};
diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h
--- a/sys/dev/amdsmu/amdsmu_reg.h
+++ b/sys/dev/amdsmu/amdsmu_reg.h
@@ -45,6 +45,7 @@
enum amdsmu_msg {
SMU_MSG_GETSMUVERSION = 0x02,
+ SMU_MSG_SLEEP_HINT = 0x03,
SMU_MSG_LOG_GETDRAM_ADDR_HI = 0x04,
SMU_MSG_LOG_GETDRAM_ADDR_LO = 0x05,
SMU_MSG_LOG_START = 0x06,
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -31,7 +31,7 @@
/**
* @defgroup BUS bus - KObj methods for drivers of devices with children
- * @brief A set of methods required device drivers that support
+ * @brief A set of methods required for device drivers that support
* child devices.
* @{
*/
diff --git a/sys/kern/device_if.m b/sys/kern/device_if.m
--- a/sys/kern/device_if.m
+++ b/sys/kern/device_if.m
@@ -358,3 +358,34 @@
METHOD void * register {
device_t dev;
} DEFAULT null_register;
+
+/**
+ * @brief Hint to the AMD SMU that we intend to enter sleep.
+ *
+ * Must be called by the ACPI sleep routine during s2idle before actually
+ * idling the CPU but after calling the SPMC entry function, if one was set on
+ * the ACPI softc.
+ *
+ * @param dev the amdsmu device to hint entry to
+ *
+ * @retval 0 success
+ * @retval ETIMEDOUT timed out trying to send a message to the SMU
+ */
+METHOD int amdsmu_enter_sleep {
+ device_t dev;
+};
+
+/**
+ * @brief Hint to the AMD SMU that we are exiting sleep.
+ *
+ * Must be called by the ACPI sleep routine during s2idle after waking the CPU
+ * but before calling the SPMC exit function, if one was set on the ACPI softc.
+ *
+ * @param dev the amdsmu device to hint exit to
+ *
+ * @retval 0 success
+ * @retval ETIMEDOUT timed out trying to send a message to the SMU
+ */
+METHOD int amdsmu_exit_sleep {
+ device_t dev;
+};

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 12, 7:20 AM (19 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29571542
Default Alt Text
D48721.id169552.diff (4 KB)

Event Timeline