From 531566e66397de31692200b6ce1f7ba09d924593 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Imre=20Vad=C3=A1sz?= Date: Sat, 16 May 2015 19:49:39 +0200 Subject: [PATCH] kernel/acpi_thermal: Improve hw.acpi.thermal.polling_rate sysctl behaviour * 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 | 9 ++++++++- sys/dev/acpica/acpi_thermal.c | 36 ++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/share/man/man4/acpi_thermal.4 b/share/man/man4/acpi_thermal.4 index 00787540d8..f0fdfc89a2 100644 --- a/share/man/man4/acpi_thermal.4 +++ b/share/man/man4/acpi_thermal.4 @@ -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 diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c index b0efde8fef..201597e15f 100644 --- a/sys/dev/acpica/acpi_thermal.c +++ b/sys/dev/acpica/acpi_thermal.c @@ -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); } -- 2.41.0