Date: Tue, 22 Sep 2015 13:35:01 -0400 From: Jung-uk Kim <jkim@FreeBSD.org> To: Colin Percival <cperciva@freebsd.org>, Anthony Jenkins <Scoobi_doo@yahoo.com>, "freebsd-acpi@freebsd.org" <freebsd-acpi@freebsd.org> Subject: Re: disabling sleep when shutting down Message-ID: <56019145.2070903@FreeBSD.org> In-Reply-To: <55FE5D54.1030806@freebsd.org> References: <55FA3848.7090802@freebsd.org> <55FB233D.2080000@FreeBSD.org> <55FB48E3.20401@freebsd.org> <55FC4F13.3090603@FreeBSD.org> <55FC57F9.3050702@yahoo.com> <55FE5D54.1030806@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------070003050204040408020807 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 09/20/2015 03:16, Colin Percival wrote: > On 09/18/15 11:29, Anthony Jenkins wrote: >> Is it possible for /etc/rc.shutdown to complete, but shutdown >> not occur? If so, there should be a mechanism to restore the >> ability to suspend. Other than that, I like it. > > Hmm... well, rc.shutdown runs before the system drops into > single-user mode. Which makes me think that maybe we should be > making the kernel call from inside init instead of from > rc.shutdown. I didn't want to pollute init with arch-dependent hacks. Anyway, the attached patch should do what you want (not tested). Jung-uk Kim -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAEBCAAGBQJWAZFAAAoJEHyflib82/FGtJEIAIEd52nb4OaB51G4A/ygOvnR 71wooCMDS/6MJBGGptdOl3YEjVpN5rfuTTr+kxZrrvONjyTdxm15/Qp3usvuNpQQ 7dMYckAc8ZjT9tXGfHQIyG8gwhRgaE/jpPY25xKrExG8NfyEXvMzSjIlJprHZgtX JcqBLXjGKPhrbJbIBYs+7CeFKhKpPKBeiT2hAPtvHh1OfNi/J/3u5sDeEBeHkx05 dFNZ+sjGIAi/2GeEwrT0IFAfkE6+ecvVZUvYcTreYcMjsLAqwGHOG5GCX/RW50xn yU9Cu2EWM4Rj3Zet9rXsRajnco0s/tX5wc4oMuWVRakjDupkG17oih+PkpIAIKs= =q9E6 -----END PGP SIGNATURE----- --------------070003050204040408020807 Content-Type: text/x-patch; name="acpi.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="acpi.diff" Index: sbin/init/init.c =================================================================== --- sbin/init/init.c (revision 288120) +++ sbin/init/init.c (working copy) @@ -52,6 +52,10 @@ static const char rcsid[] = #include <sys/stat.h> #include <sys/uio.h> +#if defined(__amd64__) || defined(__i386__) +#include <dev/acpica/acpiio.h> +#endif + #include <db.h> #include <errno.h> #include <fcntl.h> @@ -1480,6 +1484,20 @@ alrm_handler(int sig) clang = 1; } +static void +block_sleep(int block) +{ +#if defined(__amd64__) || defined(__i386__) + int fd; + + fd = open("/dev/acpi", O_RDWR); + if (fd != -1) { + ioctl(fd, ACPIIO_BLKSLPSTATE, &block); + close(fd); + } +#endif +} + /* * Bring the system down to single user. */ @@ -1488,6 +1506,9 @@ death(void) { session_t *sp; + /* Temporarily block any suspend requests. */ + block_sleep(1); + /* * Also revoke the TTY here. Because runshutdown() may reopen * the TTY whose getty we're killing here, there is no guarantee @@ -1503,6 +1524,9 @@ death(void) /* Try to run the rc.shutdown script within a period of time */ runshutdown(); + /* Unblock suspend requests. */ + block_sleep(0); + return (state_func_t) death_single; } Index: sys/dev/acpica/acpi.c =================================================================== --- sys/dev/acpica/acpi.c (revision 288120) +++ sys/dev/acpica/acpi.c (working copy) @@ -98,6 +98,9 @@ struct callout acpi_sleep_timer; /* Bitmap of device quirks. */ int acpi_quirks; +/* Block suspend requests. */ +static int acpi_sleep_blocked; + /* Supported sleep states. */ static BOOLEAN acpi_sleep_states[ACPI_S_STATE_COUNT]; @@ -2574,10 +2577,12 @@ acpi_ReqSleepState(struct acpi_softc *sc, int stat if (!acpi_sleep_states[state]) return (EOPNOTSUPP); - /* If a suspend request is already in progress, just return. */ - if (sc->acpi_next_sstate != 0) { + /* + * If a reboot/shutdown/suspend request is already in progress + * or suspend is explicitly disabled, just return. + */ + if (rebooting || sc->acpi_next_sstate != 0 || acpi_sleep_blocked) return (0); - } /* Wait until sleep is enabled. */ while (sc->acpi_sleep_disabled) { @@ -3568,6 +3573,9 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t ad error = *(int *)addr; error = acpi_AckSleepState(sc->acpi_clone, error); break; + case ACPIIO_BLKSLPSTATE: + acpi_sleep_blocked = *(int *)addr; + break; case ACPIIO_SETSLPSTATE: /* DEPRECATED */ state = *(int *)addr; if (state < ACPI_STATE_S0 || state > ACPI_S_STATES_MAX) Index: sys/dev/acpica/acpiio.h =================================================================== --- sys/dev/acpica/acpiio.h (revision 288120) +++ sys/dev/acpica/acpiio.h (working copy) @@ -41,6 +41,9 @@ /* Allow suspend to continue (0) or abort it (errno). */ #define ACPIIO_ACKSLPSTATE _IOW('P', 5, int) +/* Allow suspend request (0) or block it. */ +#define ACPIIO_BLKSLPSTATE _IOW('P', 6, int) + struct acpi_battinfo { int cap; /* percent */ int min; /* remaining time (in minutes) */ Index: usr.sbin/acpi/acpiconf/acpiconf.8 =================================================================== --- usr.sbin/acpi/acpiconf/acpiconf.8 (revision 288120) +++ usr.sbin/acpi/acpiconf/acpiconf.8 (working copy) @@ -35,6 +35,7 @@ .Nd control ACPI power management .Sh SYNOPSIS .Nm +.Op Fl b Ar block .Op Fl h .Op Fl i Ar batt .Op Fl k Ar ack @@ -45,7 +46,10 @@ The utility allows the user control of the ACPI power management functions. The following command-line options are recognized: -.Bl -tag -width ".Fl s Ar type" +.Bl -tag -width ".Fl b Ar block" +.It Fl b Ar block +Block or unblock suspend requests using the argument provided. +.Sy Most users should not use this option directly. .It Fl h Displays a summary of available options. .It Fl i Ar batt Index: usr.sbin/acpi/acpiconf/acpiconf.c =================================================================== --- usr.sbin/acpi/acpiconf/acpiconf.c (revision 288120) +++ usr.sbin/acpi/acpiconf/acpiconf.c (working copy) @@ -77,6 +77,17 @@ acpi_sleep_ack(int err_val) err(EX_IOERR, "ack sleep type failed"); } +/* Block or unblock suspend requests. */ +static void +acpi_sleep_block(int block) +{ + int ret; + + ret = ioctl(acpifd, ACPIIO_BLKSLPSTATE, &block); + if (ret != 0) + err(EX_IOERR, "%sblock sleep failed", block ? "" : "un"); +} + /* should be a acpi define, but doesn't appear to be */ #define UNKNOWN_CAP 0xffffffff #define UNKNOWN_VOLTAGE 0xffffffff @@ -213,8 +224,11 @@ main(int argc, char *argv[]) sleep_type = -1; acpi_init(); - while ((c = getopt(argc, argv, "hi:k:s:")) != -1) { + while ((c = getopt(argc, argv, "b:hi:k:s:")) != -1) { switch (c) { + case 'b': + acpi_sleep_block(atoi(optarg)); + break; case 'i': acpi_battinfo(atoi(optarg)); break; --------------070003050204040408020807--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?56019145.2070903>