Thanks to everybody who helped with the design and discussion of this.

-------- Forwarded Message --------
Subject: svn commit: r288446 - in head: sbin/init sys/dev/acpica sys/kern 
sys/sys
Date: Thu, 1 Oct 2015 10:52:27 +0000 (UTC)
From: Colin Percival <cperc...@freebsd.org>
To: src-committ...@freebsd.org, svn-src-...@freebsd.org, 
svn-src-h...@freebsd.org

Author: cperciva
Date: Thu Oct  1 10:52:26 2015
New Revision: 288446
URL: https://svnweb.freebsd.org/changeset/base/288446

Log:
  Disable suspend when we're shutting down.  This solves the "tell FreeBSD
  to shut down; close laptop lid" scenario which otherwise tended to end
  with a laptop overheating or the battery dying.

  The implementation uses a new sysctl, kern.suspend_blocked; init(8) sets
  this while rc.suspend runs, and the ACPI sleep code ignores requests while
  the sysctl is set.

  Discussed on: freebsd-acpi (35 emails)
  MFC after:    1 week

Modified:
  head/sbin/init/init.c
  head/sys/dev/acpica/acpi.c
  head/sys/kern/kern_shutdown.c
  head/sys/sys/systm.h

Modified: head/sbin/init/init.c
==============================================================================
--- head/sbin/init/init.c       Thu Oct  1 10:43:40 2015        (r288445)
+++ head/sbin/init/init.c       Thu Oct  1 10:52:26 2015        (r288446)
@@ -1487,6 +1487,15 @@ static state_func_t
 death(void)
 {
        session_t *sp;
+       int block, blocked;
+       size_t len;
+
+       /* Temporarily block suspend. */
+       len = sizeof(blocked);
+       block = 1;
+       if (sysctlbyname("kern.suspend_blocked", &blocked, &len,
+           &block, sizeof(block)) == -1)
+               blocked = 0;

        /*
         * Also revoke the TTY here.  Because runshutdown() may reopen
@@ -1503,6 +1512,11 @@ death(void)
        /* Try to run the rc.shutdown script within a period of time */
        runshutdown();

+       /* Unblock suspend if we blocked it. */
+       if (!blocked)
+               sysctlbyname("kern.suspend_blocked", NULL, NULL,
+                   &blocked, sizeof(blocked));
+
        return (state_func_t) death_single;
 }


Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c  Thu Oct  1 10:43:40 2015        (r288445)
+++ head/sys/dev/acpica/acpi.c  Thu Oct  1 10:52:26 2015        (r288446)
@@ -2574,8 +2574,11 @@ acpi_ReqSleepState(struct acpi_softc *sc
     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 blocked due to an upcoming shutdown, just return.
+     */
+    if (rebooting || sc->acpi_next_sstate != 0 || suspend_blocked) {
        return (0);
     }


Modified: head/sys/kern/kern_shutdown.c
==============================================================================
--- head/sys/kern/kern_shutdown.c       Thu Oct  1 10:43:40 2015        
(r288445)
+++ head/sys/kern/kern_shutdown.c       Thu Oct  1 10:52:26 2015        
(r288446)
@@ -137,6 +137,10 @@ static int show_busybufs = 1;
 SYSCTL_INT(_kern_shutdown, OID_AUTO, show_busybufs, CTLFLAG_RW,
        &show_busybufs, 0, "");

+int suspend_blocked = 0;
+SYSCTL_INT(_kern, OID_AUTO, suspend_blocked, CTLFLAG_RW,
+       &suspend_blocked, 0, "Block suspend due to a pending shutdown");
+
 /*
  * Variable panicstr contains argument to first call to panic; used as flag
  * to indicate that the kernel has already called panic.

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h        Thu Oct  1 10:43:40 2015        (r288445)
+++ head/sys/sys/systm.h        Thu Oct  1 10:52:26 2015        (r288446)
@@ -46,6 +46,7 @@
 #include <sys/stdint.h>                /* for people using printf mainly */

 extern int cold;               /* nonzero if we are doing a cold boot */
+extern int suspend_blocked;    /* block suspend due to pending shutdown */
 extern int rebooting;          /* kern_reboot() has been called. */
 extern const char *panicstr;   /* panic message */
 extern char version[];         /* system version */





_______________________________________________
freebsd-acpi@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-acpi
To unsubscribe, send any mail to "freebsd-acpi-unsubscr...@freebsd.org"

Reply via email to