diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c index 416f875c617..9a6873b4351 100644 --- a/sys/dev/amdsmu/amdsmu.c +++ b/sys/dev/amdsmu/amdsmu.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025-2026 The FreeBSD Foundation * * This software was developed by Aymeric Wibo * under sponsorship from the FreeBSD Foundation. @@ -14,6 +14,13 @@ #include #include +#include "opt_acpi.h" + +#if defined(DEV_ACPI) +#include +#include +#endif + #include #include @@ -289,6 +296,27 @@ amdsmu_fetch_idlemask(device_t dev) sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK); } +static void +amdsmu_suspend(device_t dev, enum power_stype stype) +{ + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) + return; + if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL) != 0) + device_printf(dev, "failed to hint to SMU to enter sleep"); +} + +static void +amdsmu_resume(device_t dev, enum power_stype stype) +{ + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) + return; + if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, false, NULL) != 0) + device_printf(dev, "failed to hint to SMU to exit sleep"); + /* Update metrics after resume. */ + amdsmu_dump_metrics(dev); + amdsmu_fetch_idlemask(dev); +} + static int amdsmu_attach(device_t dev) { @@ -422,6 +450,19 @@ amdsmu_attach(device_t dev) "value is not documented - only used to help AMD internally debug " "issues"); +#if defined(DEV_ACPI) + /* + * Register post device suspend/pre device resume eventhandlers. We use + * a lower priority for the suspend event as we want this to be called + * after the SPMC suspend hook, and a higher priority for the resume + * event as we want this to be called before the SPMC hook. + */ + sc->eh_suspend = EVENTHANDLER_REGISTER(acpi_post_dev_suspend, + amdsmu_suspend, dev, -10); + sc->eh_resume = EVENTHANDLER_REGISTER(acpi_pre_dev_resume, + amdsmu_resume, dev, 10); +#endif + return (0); err_dump: bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE); @@ -438,6 +479,11 @@ amdsmu_detach(device_t dev) struct amdsmu_softc *sc = device_get_softc(dev); int rid = 0; +#if defined(DEV_ACPI) + EVENTHANDLER_DEREGISTER(acpi_post_dev_suspend, sc->eh_suspend); + EVENTHANDLER_DEREGISTER(acpi_pre_dev_resume, sc->eh_resume); +#endif + bus_space_unmap(sc->bus_tag, sc->smu_space, SMU_MEM_SIZE); bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE); diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h index 025887f7fe5..857fa21cba4 100644 --- a/sys/dev/amdsmu/amdsmu.h +++ b/sys/dev/amdsmu/amdsmu.h @@ -6,11 +6,13 @@ * This software was developed by Aymeric Wibo * under sponsorship from the FreeBSD Foundation. */ + #ifndef _AMDSMU_H_ #define _AMDSMU_H_ #include #include +#include #include #include #include @@ -60,6 +62,9 @@ struct amdsmu_softc { struct sysctl_ctx_list *sysctlctx; struct sysctl_oid *sysctlnode; + struct eventhandler_entry *eh_suspend; + struct eventhandler_entry *eh_resume; + struct resource *res; bus_space_tag_t bus_tag; @@ -72,8 +77,10 @@ struct amdsmu_softc { uint32_t active_ip_blocks; struct sysctl_oid *ip_blocks_sysctlnode; size_t ip_block_count; - struct sysctl_oid *ip_block_sysctlnodes[nitems(amdsmu_ip_blocks_names)]; - bool ip_blocks_active[nitems(amdsmu_ip_blocks_names)]; + struct sysctl_oid *ip_block_sysctlnodes[ + nitems(amdsmu_ip_blocks_names)]; + bool ip_blocks_active[ + nitems(amdsmu_ip_blocks_names)]; bus_space_handle_t metrics_space; struct amdsmu_metrics metrics; diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h index e685b34e688..d45fa60941d 100644 --- a/sys/dev/amdsmu/amdsmu_reg.h +++ b/sys/dev/amdsmu/amdsmu_reg.h @@ -45,6 +45,7 @@ enum amdsmu_res { 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/modules/amdsmu/Makefile b/sys/modules/amdsmu/Makefile index 752f57173d6..faeb1b13606 100644 --- a/sys/modules/amdsmu/Makefile +++ b/sys/modules/amdsmu/Makefile @@ -9,6 +9,7 @@ KMOD= amdsmu SRCS= amdsmu.c -SRCS+= bus_if.h device_if.h pci_if.h +SRCS+= bus_if.h device_if.h pci_if.h \ + opt_acpi.h .include