From nobody Sun Sep 14 21:52:48 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cQ22m3Nzxz67XGy; Sun, 14 Sep 2025 21:52:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cQ22m2LJ9z3G9y; Sun, 14 Sep 2025 21:52:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1757886768; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tyWVOeN61sJs4ESKnEKKbkUI8GRbskAjvOB+lWQ1jvM=; b=GcXXv3s5gx9NMA6qiWNmsXnKgVRR+W9OHRNSN31IQUfBA7QTlBRjyZTf7kHLNIc0VSJr4P 1Y42jBHEvg6RzH+yHJQlH345Yinjj0GBsFqsJJ5mF6ux3DtZVdVySYyOUyoetc96aM+XAx tWO+xA1ff4W8E2XbY3b1TtaibgWPVjV09yd8IOc8E4Tk1SqI/fObsycbcUWUON2Io5hwuw diWFMYt86dFdxwxmIqUbYs34X978jYHKxq9iXNlgvziBafiB9OjwZC6S6XfxvpDzELX+xI SL8K1mZ8CihLDPQnvQkNMbzmw1o344sLDcJ0gyQZ4uW+OyJxK6sJNLX5wlwl2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1757886768; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tyWVOeN61sJs4ESKnEKKbkUI8GRbskAjvOB+lWQ1jvM=; b=s92qHw2Ay0deJHWZKIq5ksvQHItqqpsnLZRs797ySb6ZKmN4m03XIkpfxLRFcvL+LpFTL5 k9z0SIvp2WGLSqyHN+oizf+nYi/0NM2la56Hn1hOinnLbpXd8FmVrmCjKoTNBk8sGzu7Qo J4fVjkdTXdtbg+10R0oax8vd6X3TLcuWp0jyh496aJrd+wYK2heMkgpSFEz3cuSHOjiG+/ 6cICo/kYkK4Zortsn4sukwW8t/TcpiPCVS5itIALz3lkmyk+k1iOh3R7nIHc7I1cYMmJQd wvMaHRovHScZ9wDdLcAu8+dppGN5qxpYRY3YPyWfUo9QQOZc3jlkTrt2VYdm4Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1757886768; a=rsa-sha256; cv=none; b=O0YKRqXuu8OXMhdYEQ1iZvV6oo4stn3bKX1jvqmsUlNWm1cao1dd+2JIG8lyiMpvkGzmOu /Pyd0jdrH8xgjNriL785exUlUVJ5Ki3H0gF0FX6jls+olrPi4OgxcaEoHDEoA4Jk0fXrgb a6ARRqGvVgphPsMnzPDMLB8Pg5moVW/BOiw7aRlojYHbVHe1Y4wePmZxDhbckqWfE99zhf CruHndrcrx/sETK3iFyLJDooyKZVYJ69g8tGpP7yeh1cdFQIP3UGUJE2EQOOn6jV39dZgG D08pM+qW6Shs9WWqSDrLcA3/y5YIZI+HSbS3rBl4Pi1rSxrEkyXcJmHxjeKRzg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cQ22m1xdxzBd7; Sun, 14 Sep 2025 21:52:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 58ELqmI9052551; Sun, 14 Sep 2025 21:52:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 58ELqm78052548; Sun, 14 Sep 2025 21:52:48 GMT (envelope-from git) Date: Sun, 14 Sep 2025 21:52:48 GMT Message-Id: <202509142152.58ELqm78052548@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Aymeric Wibo Subject: git: c43473dc9b83 - main - sys/power: Generic sleep types List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: obiwac X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c43473dc9b8349103f78107300457ca35e437882 Auto-Submitted: auto-generated The branch main has been updated by obiwac: URL: https://cgit.FreeBSD.org/src/commit/?id=c43473dc9b8349103f78107300457ca35e437882 commit c43473dc9b8349103f78107300457ca35e437882 Author: Aymeric Wibo AuthorDate: 2025-09-14 21:33:33 +0000 Commit: Aymeric Wibo CommitDate: 2025-09-14 21:48:46 +0000 sys/power: Generic sleep types Pull out the sleep types (stype) from ACPI, as was previously being done in D48732, and pass this sleep type to `power_pm_fn` instead of passing the existing sleep state. This is a little awkward because we already kinda have generic sleep states (`POWER_SLEEP_STATE_*`), but these are not precise enough to build upon. This revision also adds generic equivalents to `hw.acpi.suspend_state` etc sysctls, e.g. `kern.power.suspend`. Reviewed by: markj, mckusick (mentor) Approved by: markj, mckusick (mentor) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D52036 --- sys/dev/acpica/acpi.c | 58 ++++++++++++++++-------------- sys/dev/acpica/acpivar.h | 1 + sys/kern/subr_power.c | 92 ++++++++++++++++++++++++++++++++++++++++++++---- sys/sys/power.h | 52 +++++++++++++++++++++++++-- 4 files changed, 168 insertions(+), 35 deletions(-) diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index a2159b12876f..574d3aacbcde 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -4,6 +4,10 @@ * Copyright (c) 2000, 2001 Michael Smith * Copyright (c) 2000 BSDi * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -181,7 +185,8 @@ static const char *acpi_sstate2sname(int sstate); static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_debug_objects_sysctl(SYSCTL_HANDLER_ARGS); -static int acpi_pm_func(u_long cmd, void *arg, ...); +static int acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype); +static int acpi_pm_func(u_long cmd, void *arg, enum power_stype stype); static void acpi_enable_pcie(void); static void acpi_reset_interfaces(device_t dev); @@ -741,6 +746,28 @@ acpi_attach(device_t dev) return_VALUE (error); } +static int +acpi_stype_to_sstate(struct acpi_softc *sc, enum power_stype stype) +{ + switch (stype) { + case POWER_STYPE_AWAKE: + return (ACPI_STATE_S0); + case POWER_STYPE_STANDBY: + return (sc->acpi_standby_sx); + case POWER_STYPE_SUSPEND_TO_MEM: + return (ACPI_STATE_S3); + case POWER_STYPE_HIBERNATE: + return (ACPI_STATE_S4); + case POWER_STYPE_POWEROFF: + return (ACPI_STATE_S5); + case POWER_STYPE_SUSPEND_TO_IDLE: + case POWER_STYPE_COUNT: + case POWER_STYPE_UNKNOWN: + return (ACPI_STATE_UNKNOWN); + } + return (ACPI_STATE_UNKNOWN); +} + static void acpi_set_power_children(device_t dev, int state) { @@ -4621,12 +4648,10 @@ acpi_reset_interfaces(device_t dev) } static int -acpi_pm_func(u_long cmd, void *arg, ...) +acpi_pm_func(u_long cmd, void *arg, enum power_stype stype) { - int state, acpi_state; - int error; + int error, sstate; struct acpi_softc *sc; - va_list ap; error = 0; switch (cmd) { @@ -4636,27 +4661,8 @@ acpi_pm_func(u_long cmd, void *arg, ...) error = EINVAL; goto out; } - - va_start(ap, arg); - state = va_arg(ap, int); - va_end(ap); - - switch (state) { - case POWER_SLEEP_STATE_STANDBY: - acpi_state = sc->acpi_standby_sx; - break; - case POWER_SLEEP_STATE_SUSPEND: - acpi_state = sc->acpi_suspend_sx; - break; - case POWER_SLEEP_STATE_HIBERNATE: - acpi_state = ACPI_STATE_S4; - break; - default: - error = EINVAL; - goto out; - } - - if (ACPI_FAILURE(acpi_EnterSleepState(sc, acpi_state))) + sstate = acpi_stype_to_sstate(sc, stype); + if (ACPI_FAILURE(acpi_EnterSleepState(sc, sstate))) error = ENXIO; break; default: diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 7495a010432b..fac32d832598 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/kern/subr_power.c b/sys/kern/subr_power.c index db0e7bf5b0e3..eb5bd03f5018 100644 --- a/sys/kern/subr_power.c +++ b/sys/kern/subr_power.c @@ -3,6 +3,10 @@ * * Copyright (c) 2001 Mitsuru IWASAKI * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,20 +34,83 @@ #include #include #include +#include +#include #include #include +enum power_stype power_standby_stype = POWER_STYPE_STANDBY; +enum power_stype power_suspend_stype = POWER_STYPE_SUSPEND_TO_IDLE; +enum power_stype power_hibernate_stype = POWER_STYPE_HIBERNATE; + static u_int power_pm_type = POWER_PM_TYPE_NONE; static power_pm_fn_t power_pm_fn = NULL; static void *power_pm_arg = NULL; static struct task power_pm_task; +enum power_stype +power_name_to_stype(const char *name) +{ + enum power_stype stype; + + for (stype = 0; stype < POWER_STYPE_COUNT; stype++) { + if (strcasecmp(name, power_stype_names[stype]) == 0) + return (stype); + } + return (POWER_STYPE_UNKNOWN); +} + +const char * +power_stype_to_name(enum power_stype stype) +{ + if (stype == POWER_STYPE_UNKNOWN) + return ("NONE"); + if (stype < POWER_STYPE_AWAKE || stype >= POWER_STYPE_COUNT) + return (NULL); + return (power_stype_names[stype]); +} + +static int +power_sysctl_stype(SYSCTL_HANDLER_ARGS) +{ + char name[10]; + int err; + enum power_stype new_stype, old_stype; + + old_stype = *(enum power_stype *)oidp->oid_arg1; + strlcpy(name, power_stype_to_name(old_stype), sizeof(name)); + err = sysctl_handle_string(oidp, name, sizeof(name), req); + if (err != 0 || req->newptr == NULL) + return (err); + + new_stype = power_name_to_stype(name); + if (new_stype == POWER_STYPE_UNKNOWN) + return (EINVAL); + /* TODO Check to see if the new stype is supported. */ + if (new_stype != old_stype) + *(enum power_stype *)oidp->oid_arg1 = new_stype; + return (0); +} + +static SYSCTL_NODE(_kern, OID_AUTO, power, CTLFLAG_RW, 0, + "Generic power management related sysctls"); + +SYSCTL_PROC(_kern_power, OID_AUTO, standby, CTLTYPE_STRING | CTLFLAG_RW, + &power_standby_stype, 0, power_sysctl_stype, "A", + "Sleep type to enter on standby"); +SYSCTL_PROC(_kern_power, OID_AUTO, suspend, CTLTYPE_STRING | CTLFLAG_RW, + &power_suspend_stype, 0, power_sysctl_stype, "A", + "Sleep type to enter on suspend"); +SYSCTL_PROC(_kern_power, OID_AUTO, hibernate, CTLTYPE_STRING | CTLFLAG_RW, + &power_hibernate_stype, 0, power_sysctl_stype, "A", + "Sleep type to enter on hibernate"); + static void power_pm_deferred_fn(void *arg, int pending) { - int state = (intptr_t)arg; + enum power_stype stype = (intptr_t)arg; - power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state); + power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, stype); } int @@ -75,14 +142,27 @@ power_pm_get_type(void) void power_pm_suspend(int state) { + enum power_stype stype; + if (power_pm_fn == NULL) return; - if (state != POWER_SLEEP_STATE_STANDBY && - state != POWER_SLEEP_STATE_SUSPEND && - state != POWER_SLEEP_STATE_HIBERNATE) + switch (state) { + case POWER_SLEEP_STATE_STANDBY: + stype = power_standby_stype; + break; + case POWER_SLEEP_STATE_SUSPEND: + stype = power_suspend_stype; + break; + case POWER_SLEEP_STATE_HIBERNATE: + stype = power_hibernate_stype; + break; + default: + printf("%s: unknown sleep state %d\n", __func__, state); return; - power_pm_task.ta_context = (void *)(intptr_t)state; + } + + power_pm_task.ta_context = (void *)(intptr_t)stype; taskqueue_enqueue(taskqueue_thread, &power_pm_task); } diff --git a/sys/sys/power.h b/sys/sys/power.h index 3ee021b0e587..44d7fc354423 100644 --- a/sys/sys/power.h +++ b/sys/sys/power.h @@ -3,6 +3,10 @@ * * Copyright (c) 2001 Mitsuru IWASAKI * All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Aymeric Wibo + * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +35,7 @@ #ifdef _KERNEL #include +#include /* Power management system type */ #define POWER_PM_TYPE_ACPI 0x01 @@ -39,13 +44,54 @@ /* Commands for Power management function */ #define POWER_CMD_SUSPEND 0x00 -/* Sleep state */ +/* + * Sleep state. + * + * These are high-level sleep states that the system can enter. They map to + * a specific generic sleep type (enum power_stype). + */ #define POWER_SLEEP_STATE_STANDBY 0x00 #define POWER_SLEEP_STATE_SUSPEND 0x01 #define POWER_SLEEP_STATE_HIBERNATE 0x02 -typedef int (*power_pm_fn_t)(u_long, void*, ...); -extern int power_pm_register(u_int, power_pm_fn_t, void *); +/* + * Sleep type. + * + * These are the specific generic methods of entering a sleep state. E.g. + * POWER_SLEEP_STATE_SUSPEND could be set to enter either suspend-to-RAM (which + * is S3 on ACPI systems), or suspend-to-idle (S0ix on ACPI systems). This + * would be done through the kern.power.suspend sysctl. + */ +enum power_stype { + POWER_STYPE_AWAKE, + POWER_STYPE_STANDBY, + POWER_STYPE_SUSPEND_TO_MEM, + POWER_STYPE_SUSPEND_TO_IDLE, + POWER_STYPE_HIBERNATE, + POWER_STYPE_POWEROFF, + POWER_STYPE_COUNT, + POWER_STYPE_UNKNOWN, +}; + +static const char * const power_stype_names[POWER_STYPE_COUNT] = { + [POWER_STYPE_AWAKE] = "awake", + [POWER_STYPE_STANDBY] = "standby", + [POWER_STYPE_SUSPEND_TO_MEM] = "s2mem", + [POWER_STYPE_SUSPEND_TO_IDLE] = "s2idle", + [POWER_STYPE_HIBERNATE] = "hibernate", + [POWER_STYPE_POWEROFF] = "poweroff", +}; + +extern enum power_stype power_standby_stype; +extern enum power_stype power_suspend_stype; +extern enum power_stype power_hibernate_stype; + +extern enum power_stype power_name_to_stype(const char *_name); +extern const char *power_stype_to_name(enum power_stype _stype); + +typedef int (*power_pm_fn_t)(u_long _cmd, void* _arg, enum power_stype _stype); +extern int power_pm_register(u_int _pm_type, power_pm_fn_t _pm_fn, + void *_pm_arg); extern u_int power_pm_get_type(void); extern void power_pm_suspend(int);