kernel/acpi_thermal: Improve hw.acpi.thermal.polling_rate sysctl behaviour
authorImre Vadász <imre@vdsz.com>
Sat, 16 May 2015 17:49:39 +0000 (19:49 +0200)
committerImre Vadasz <imre@vdsz.com>
Sat, 16 May 2015 20:17:15 +0000 (22:17 +0200)
* No longer allow setting hw.acpi.thermal.polling_rate to negative or to
  meaninglessly large values of more than 3600s.

* Wake up the acpi_tz_thread after changing hw.acpi.thermal.polling_rate,
  to wake it up when hw.acpi.thermal.polling_rate was set to 0 (i.e.
  disabled polling) or a very large value before.

share/man/man4/acpi_thermal.4
sys/dev/acpica/acpi_thermal.c

index 0078754..f0fdfc8 100644 (file)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: head/share/man/man4/acpi_thermal.4 167670 2007-03-18 00:57:07Z njl $
 .\"
-.Dd February 10, 2010
+.Dd May 16, 2015
 .Dt ACPI_THERMAL 4
 .Os
 .Sh NAME
@@ -60,6 +60,13 @@ Number of seconds to continue active cooling once started.
 A new active cooling level will not be selected until this interval expires.
 .It Va hw.acpi.thermal.polling_rate
 Number of seconds between polling the current temperature.
+If set to 0, temperature polling is deactivated.
+Use with care, strange hardware-specific issues can occur when a wrong
+value is set.
+Some systems will always report the same temperature when the polling
+period is too low.
+Also ACPI based fan control can stop working when the wrong value is
+set here.
 .It Va hw.acpi.thermal.user_override
 If set to 1, allow user override of various setpoints (below).
 The original values for these settings are obtained from the BIOS and
index b0efde8..201597e 100644 (file)
@@ -126,7 +126,8 @@ struct acpi_tz_softc {
 };
 
 /* silence errors after X seconds, try again after Y seconds */
-#define TZ_SILENCE_ERROR       (acpi_tz_polling_rate * 2 + 1)
+#define TZ_SILENCE_ERROR                                               \
+    ((acpi_tz_polling_rate <= 0 ? TZ_POLLRATE : acpi_tz_polling_rate) * 2 + 1)
 #define TZ_RETRY_ERROR         7200
 
 #define        TZ_ACTIVE_LEVEL(act)    ((act) >= 0 ? (act) : TZ_NUMLEVELS)
@@ -142,6 +143,7 @@ static void acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg);
 static void    acpi_tz_getparam(struct acpi_tz_softc *sc, char *node,
                                 int *data);
 static void    acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what);
+static int     acpi_tz_polling_sysctl(SYSCTL_HANDLER_ARGS);
 static int     acpi_tz_active_sysctl(SYSCTL_HANDLER_ARGS);
 static int     acpi_tz_cooling_sysctl(SYSCTL_HANDLER_ARGS);
 static int     acpi_tz_temp_sysctl(SYSCTL_HANDLER_ARGS);
@@ -256,10 +258,11 @@ acpi_tz_attach(device_t dev)
                       OID_AUTO, "min_runtime", CTLFLAG_RW,
                       &acpi_tz_min_runtime, 0,
                       "minimum cooling run time in sec");
-       SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
+       SYSCTL_ADD_PROC(&acpi_tz_sysctl_ctx,
                       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
-                      OID_AUTO, "polling_rate", CTLFLAG_RW,
-                      &acpi_tz_polling_rate, 0, "monitor polling interval in seconds");
+                      OID_AUTO, "polling_rate", CTLTYPE_INT | CTLFLAG_RW,
+                      &acpi_tz_polling_rate, 0, acpi_tz_polling_sysctl,
+                      "I", "monitor polling interval in seconds");
        SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
                       SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
                       "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
@@ -728,6 +731,28 @@ acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
     return_VOID;
 }
 
+/*
+ * Handle sysctl for reading and changing the termal-zone polling rate.
+ */
+static int
+acpi_tz_polling_sysctl(SYSCTL_HANDLER_ARGS)
+{
+    int val, error;
+
+    val = acpi_tz_polling_rate;
+    error = sysctl_handle_int(oidp, &val, 0, req);
+
+    /* Error or no new value */
+    if (error != 0 || req->newptr == NULL)
+       return (error);
+    if (val < 0 || val > 3600)
+       return (EINVAL);
+
+    acpi_tz_polling_rate = val;
+    wakeup(&acpi_tz_td);
+    return (error);
+}
+
 /*
  * Sanity-check a temperature value.  Assume that setpoints
  * should be between 0C and 200C.
@@ -1029,7 +1054,8 @@ acpi_tz_thread(void *arg)
        if (i == devcount) {
            tsleep_interlock(&acpi_tz_td, 0);
            ACPI_UNLOCK(thermal);
-           tsleep(&acpi_tz_td, 0, "tzpoll", hz * acpi_tz_polling_rate);
+           tsleep(&acpi_tz_td, 0, "tzpoll",
+               (acpi_tz_polling_rate <= 0 ? 0 : hz * acpi_tz_polling_rate));
        } else {
            ACPI_UNLOCK(thermal);
        }