Skip site navigation (1)Skip section navigation (2)
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>