diff options
| author | Aymeric Wibo <obiwac@FreeBSD.org> | 2025-06-14 15:33:24 +0000 |
|---|---|---|
| committer | Aymeric Wibo <obiwac@FreeBSD.org> | 2026-03-04 15:38:57 +0000 |
| commit | 2c60fce365f4398ff02a86b46e2862905f88fa97 (patch) | |
| tree | e0343187b77ff75f9151519a4500b5038c8f9cbf /sys/dev | |
| parent | 40e52e0edd038460a2a2aca017b3ac5a513fe37b (diff) | |
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/amdsmu/amdsmu.c | 48 | ||||
| -rw-r--r-- | sys/dev/amdsmu/amdsmu.h | 11 | ||||
| -rw-r--r-- | sys/dev/amdsmu/amdsmu_reg.h | 1 |
3 files changed, 57 insertions, 3 deletions
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c index 416f875c6176..9a6873b43517 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 <obiwac@freebsd.org> * under sponsorship from the FreeBSD Foundation. @@ -14,6 +14,13 @@ #include <sys/rman.h> #include <sys/sysctl.h> +#include "opt_acpi.h" + +#if defined(DEV_ACPI) +#include <contrib/dev/acpica/include/acpi.h> +#include <dev/acpica/acpivar.h> +#endif + #include <dev/pci/pcivar.h> #include <dev/amdsmu/amdsmu.h> @@ -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 025887f7fe5a..857fa21cba4e 100644 --- a/sys/dev/amdsmu/amdsmu.h +++ b/sys/dev/amdsmu/amdsmu.h @@ -6,11 +6,13 @@ * This software was developed by Aymeric Wibo <obiwac@freebsd.org> * under sponsorship from the FreeBSD Foundation. */ + #ifndef _AMDSMU_H_ #define _AMDSMU_H_ #include <sys/param.h> #include <sys/bus.h> +#include <sys/eventhandler.h> #include <sys/kernel.h> #include <machine/bus.h> #include <x86/cputypes.h> @@ -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 e685b34e6883..d45fa60941d5 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, |
