Fix a couple of misunderstandings in the monitor code. Passive cooling

is a parallel adjunct to active cooling, not a lesser evil.  The _ACx
levels sort from 0 being hottest, not coolest.

Sanity check the returned temperature values, since we are having
trouble reading them on some systems.

Rearrange sysctl nodes a bit; this is probably close to the final layout.
This commit is contained in:
Mike Smith 2001-07-05 07:19:17 +00:00
parent 6f69255b9f
commit 93962773c5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=79283

View file

@ -32,6 +32,7 @@
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/reboot.h>
#include <sys/sysctl.h>
#include "acpi.h"
@ -71,12 +72,17 @@ struct acpi_tz_softc {
device_t tz_dev;
ACPI_HANDLE tz_handle;
struct callout_handle tz_timeout;
int tz_current;
#define TZ_STATE_NONE 0
#define TZ_STATE_PSV 1
#define TZ_STATE_AC0 2
#define TZ_STATE_HOT (TZ_STATE_AC0 + TZ_NUMLEVELS)
#define TZ_STATE_CRT (TZ_STATE_AC0 + TZ_NUMLEVELS + 1)
int tz_temperature;
int tz_active;
#define TZ_ACTIVE_NONE -1
int tz_flags;
#define TZ_FLAG_NONE 0
#define TZ_FLAG_PSV (1<<0)
#define TZ_FLAG_HOT (1<<2)
#define TZ_FLAG_CRT (1<<3)
struct sysctl_ctx_list tz_sysctl_ctx;
struct sysctl_oid *tz_sysctl_tree;
struct acpi_tz_state tz_state;
};
@ -89,6 +95,7 @@ static void acpi_tz_all_off(struct acpi_tz_softc *sc);
static void acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg);
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 void acpi_tz_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context);
static void acpi_tz_timeout(void *arg);
@ -109,6 +116,9 @@ static driver_t acpi_tz_driver = {
devclass_t acpi_tz_devclass;
DRIVER_MODULE(acpi_tz, acpi, acpi_tz_driver, acpi_tz_devclass, 0, 0);
static struct sysctl_ctx_list acpi_tz_sysctl_ctx;
static struct sysctl_oid *acpi_tz_sysctl_tree;
/*
* Match an ACPI thermal zone.
*/
@ -139,7 +149,10 @@ static int
acpi_tz_attach(device_t dev)
{
struct acpi_tz_softc *sc;
struct acpi_softc *acpi_sc;
int error;
char oidname[8];
int i;
FUNCTION_TRACE(__func__);
@ -162,6 +175,49 @@ acpi_tz_attach(device_t dev)
AcpiInstallNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
acpi_tz_notify_handler, sc);
/*
* Create our sysctl nodes.
*
* XXX we need a mechanism for adding nodes under ACPI.
*/
if (device_get_unit(dev) == 0) {
acpi_sc = acpi_device_get_parent_softc(dev);
sysctl_ctx_init(&acpi_tz_sysctl_ctx);
acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
}
sysctl_ctx_init(&sc->tz_sysctl_ctx);
sprintf(oidname, "tz%d", device_get_unit(dev));
sc->tz_sysctl_tree = SYSCTL_ADD_NODE(&sc->tz_sysctl_ctx,
SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
oidname, CTLFLAG_RD, 0, "");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "temperature", CTLFLAG_RD,
&sc->tz_temperature, 0, "current thermal zone temperature");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "active", CTLFLAG_RD,
&sc->tz_active, 0, "active cooling mode");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "flags", CTLFLAG_RD,
&sc->tz_flags, 0, "thermal zone flags");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "_PSV", CTLFLAG_RD,
&sc->tz_state.psv, 0, "");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "_HOT", CTLFLAG_RD,
&sc->tz_state.hot, 0, "");
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, "_CRT", CTLFLAG_RD,
&sc->tz_state.crt, 0, "");
for (i = 0; i < TZ_NUMLEVELS; i++) {
sprintf(oidname, "_AC%d", i);
SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
OID_AUTO, oidname, CTLFLAG_RD,
&sc->tz_state.ac[i], 0, "");
}
/*
* Don't bother evaluating/printing the temperature at this point;
* on many systems it'll be bogus until the EC is running.
@ -229,17 +285,28 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
acpi_tz_getparam(sc, "_TSP", &sc->tz_state.tsp);
acpi_tz_getparam(sc, "_TZP", &sc->tz_state.tzp);
/*
* Sanity-check the values we've been given.
*
* XXX what do we do about systems that give us the same value for
* more than one of these setpoints?
*/
acpi_tz_sanity(sc, &sc->tz_state.crt, "_CRT");
acpi_tz_sanity(sc, &sc->tz_state.hot, "_HOT");
acpi_tz_sanity(sc, &sc->tz_state.psv, "_PSV");
for (i = 0; i < TZ_NUMLEVELS; i++)
acpi_tz_sanity(sc, &sc->tz_state.ac[i], "_ACx");
/*
* Power off everything that we've just been given.
*/
acpi_tz_all_off(sc);
/*
* Do we need to poll the thermal zone? Ignore the suggested
* rate.
* The timeout routine always needs to run, since it may be involved
* in passive cooling.
*/
if (sc->tz_state.tzp != 0)
sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE);
sc->tz_timeout = timeout(acpi_tz_timeout, sc, 0);
return_VALUE(0);
@ -251,8 +318,9 @@ acpi_tz_establish(struct acpi_tz_softc *sc)
static void
acpi_tz_monitor(struct acpi_tz_softc *sc)
{
int temp, new;
int temp;
int i;
int newactive, newflags;
FUNCTION_TRACE(__func__);
@ -267,62 +335,60 @@ acpi_tz_monitor(struct acpi_tz_softc *sc)
return_VOID;
}
DEBUG_PRINT(TRACE_VALUES, ("got %d.%dC\n", TZ_KELVTOC(temp)));
sc->tz_temperature = temp;
/*
* Work out what we ought to be doing right now.
*
* Note that the _ACx levels sort from hot to cold.
*/
new = TZ_STATE_NONE;
if ((sc->tz_state.psv != -1) && (temp > sc->tz_state.psv))
new = TZ_STATE_PSV;
for (i = 0; i < TZ_NUMLEVELS; i++)
newactive = TZ_ACTIVE_NONE;
for (i = TZ_NUMLEVELS - 1; i >= 0; i--)
if ((sc->tz_state.ac[i] != -1) && (temp > sc->tz_state.ac[i]))
new = TZ_STATE_AC0 + i;
newactive = i;
newflags = TZ_FLAG_NONE;
if ((sc->tz_state.psv != -1) && (temp > sc->tz_state.psv))
newflags |= TZ_FLAG_PSV;
if ((sc->tz_state.hot != -1) && (temp > sc->tz_state.hot))
new = TZ_STATE_HOT;
newflags |= TZ_FLAG_HOT;
if ((sc->tz_state.crt != -1) && (temp > sc->tz_state.crt))
new = TZ_STATE_CRT;
newflags |= TZ_FLAG_CRT;
/*
* If our state has not changed, do nothing.
* If the active cooling state has changed, we have to switch things.
*/
if (new == sc->tz_current)
return_VOID;
/*
* XXX if we're in a passive-cooling mode, revert to full-speed operation.
*/
if (sc->tz_current == TZ_STATE_PSV) {
/* XXX implement */
if (newactive != sc->tz_active) {
/* turn off the cooling devices that are on, if any are */
if (sc->tz_active != TZ_ACTIVE_NONE)
acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[sc->tz_active].Pointer,
acpi_tz_switch_cooler_off, sc);
/* turn on cooling devices that are required, if any are */
if (newactive != TZ_ACTIVE_NONE)
acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[newactive].Pointer,
acpi_tz_switch_cooler_on, sc);
sc->tz_active = newactive;
}
/*
* If we're in an active-cooling mode, turn off the current cooler(s).
*/
if ((sc->tz_current >= TZ_STATE_AC0) && (sc->tz_current < (TZ_STATE_AC0 + TZ_NUMLEVELS)))
acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[sc->tz_current - TZ_STATE_AC0].Pointer,
acpi_tz_switch_cooler_off, sc);
/*
* XXX If the new mode is passive-cooling, make appropriate adjustments.
* XXX (de)activate any passive cooling that may be required.
*/
/*
* If the new mode is an active-cooling mode, turn on the new cooler(s).
* If we have just become _HOT or _CRT, warn the user.
*
* We should actually shut down at this point, but it's not clear
* that some systems don't actually map _CRT to the same value as _AC0.
*/
if ((new >= TZ_STATE_AC0) && (new < (TZ_STATE_AC0 + TZ_NUMLEVELS)))
acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[new - TZ_STATE_AC0].Pointer,
acpi_tz_switch_cooler_on, sc);
/*
* If we're _HOT or _CRT, shut down now!
*/
if ((new == TZ_STATE_HOT) || (new == TZ_STATE_CRT)) {
device_printf(sc->tz_dev, "WARNING - emergency thermal shutdown in progress.\n");
shutdown_nice(RB_POWEROFF);
if ((newflags & (TZ_FLAG_HOT | TZ_FLAG_CRT)) &&
!(sc->tz_flags & (TZ_FLAG_HOT | TZ_FLAG_CRT))) {
device_printf(sc->tz_dev, "WARNING - current temperature (%d.%dC) exceeds system limits\n",
TZ_KELVTOC(sc->tz_temperature), sc->tz_temperature);
/* shutdown_nice(RB_POWEROFF);*/
}
/* gone to new state */
sc->tz_current = new;
sc->tz_flags = newflags;
return_VOID;
}
@ -353,7 +419,8 @@ acpi_tz_all_off(struct acpi_tz_softc *sc)
* XXX revert any passive-cooling options.
*/
sc->tz_current = TZ_STATE_NONE;
sc->tz_active = TZ_ACTIVE_NONE;
sc->tz_flags = TZ_FLAG_NONE;
return_VOID;
}
@ -452,6 +519,20 @@ acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
}
return_VOID;
}
/*
* Sanity-check a temperature value. Assume that setpoints
* should be between 0C and 150C.
*/
static void
acpi_tz_sanity(struct acpi_tz_softc *sc, int *val, char *what)
{
if ((*val != -1) && ((*val < TZ_ZEROC) || (*val > (TZ_ZEROC + 1500)))) {
device_printf(sc->tz_dev, "%s value is absurd, ignored (%d.%dC)\n",
what, TZ_KELVTOC(*val));
*val = -1;
}
}
/*
* Respond to a Notify event sent to the zone.