Convert coretemp(4) to the hardware sensors framework and
make sure to never call sched_bind() for uninitialised CPUs. Submitted by: Constantine A. Murenin <cnst@FreeBSD.org> Sponsored by: Google Summer of Code 2007 (GSoC2007/cnst-sensors) Mentored by: syrinx Tested by: many OKed by: kensmith
This commit is contained in:
parent
989500bf1a
commit
5c6b7871e9
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 23, 2007
|
||||
.Dd September 13, 2007
|
||||
.Dt CORETEMP 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -51,12 +51,20 @@ The
|
||||
driver provides support for the on-die digital thermal sensor present
|
||||
in Intel Core and newer CPUs.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
driver reports each core's temperature through a sysctl node in the
|
||||
corresponding CPU device's sysctl tree, named
|
||||
.Va dev.cpu.%d.temperature .
|
||||
The values are exposed through the
|
||||
.Va HW_SENSORS
|
||||
.Xr sysctl 3
|
||||
tree.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
%sysctl hw.sensors
|
||||
hw.sensors.cpu0.temp0: 28.00 degC
|
||||
hw.sensors.cpu1.temp0: 29.00 degC
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr systat 1 ,
|
||||
.Xr sysctl 3 ,
|
||||
.Xr sensorsd 8 ,
|
||||
.Xr sysctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/module.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sensors.h>
|
||||
#include <sys/proc.h> /* for curthread */
|
||||
#include <sys/sched.h>
|
||||
|
||||
@ -50,10 +50,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
extern int smp_cpus;
|
||||
|
||||
struct coretemp_softc {
|
||||
device_t sc_dev;
|
||||
int sc_tjmax;
|
||||
struct sysctl_oid *sc_oid;
|
||||
struct ksensordev sc_sensordev;
|
||||
struct ksensor sc_sensor;
|
||||
device_t sc_dev;
|
||||
int sc_tjmax;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -65,7 +68,7 @@ static int coretemp_attach(device_t dev);
|
||||
static int coretemp_detach(device_t dev);
|
||||
|
||||
static int coretemp_get_temp(device_t dev);
|
||||
static int coretemp_get_temp_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static void coretemp_refresh(void *arg);
|
||||
|
||||
static device_method_t coretemp_methods[] = {
|
||||
/* Device interface */
|
||||
@ -174,14 +177,17 @@ coretemp_attach(device_t dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the "temperature" MIB to dev.cpu.N.
|
||||
* Add hw.sensors.cpuN.temp0 MIB.
|
||||
*/
|
||||
sc->sc_oid = SYSCTL_ADD_PROC(device_get_sysctl_ctx(pdev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)),
|
||||
OID_AUTO, "temperature",
|
||||
CTLTYPE_INT | CTLFLAG_RD,
|
||||
dev, 0, coretemp_get_temp_sysctl, "I",
|
||||
"Current temperature in degC");
|
||||
strlcpy(sc->sc_sensordev.xname, device_get_nameunit(pdev),
|
||||
sizeof(sc->sc_sensordev.xname));
|
||||
sc->sc_sensor.type = SENSOR_TEMP;
|
||||
sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
|
||||
if (sensor_task_register(sc, coretemp_refresh, 2)) {
|
||||
device_printf(dev, "unable to register update task\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
sensordev_install(&sc->sc_sensordev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -191,7 +197,8 @@ coretemp_detach(device_t dev)
|
||||
{
|
||||
struct coretemp_softc *sc = device_get_softc(dev);
|
||||
|
||||
sysctl_remove_oid(sc->sc_oid, 1, 0);
|
||||
sensordev_deinstall(&sc->sc_sensordev);
|
||||
sensor_task_unregister(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -206,25 +213,21 @@ coretemp_get_temp(device_t dev)
|
||||
struct coretemp_softc *sc = device_get_softc(dev);
|
||||
char stemp[16];
|
||||
|
||||
thread_lock(curthread);
|
||||
sched_bind(curthread, cpu);
|
||||
thread_unlock(curthread);
|
||||
|
||||
/*
|
||||
* The digital temperature reading is located at bit 16
|
||||
* of MSR_THERM_STATUS.
|
||||
*
|
||||
* There is a bit on that MSR that indicates whether the
|
||||
* temperature is valid or not.
|
||||
*
|
||||
* The temperature is computed by subtracting the temperature
|
||||
* reading by Tj(max).
|
||||
* Bind to specific CPU to read the correct temperature.
|
||||
* If not all CPUs are initialised, then only read from
|
||||
* cpu0, returning -1 on all other CPUs.
|
||||
*/
|
||||
msr = rdmsr(MSR_THERM_STATUS);
|
||||
|
||||
thread_lock(curthread);
|
||||
sched_unbind(curthread);
|
||||
thread_unlock(curthread);
|
||||
if (smp_cpus > 1) {
|
||||
thread_lock(curthread);
|
||||
sched_bind(curthread, cpu);
|
||||
msr = rdmsr(MSR_THERM_STATUS);
|
||||
sched_unbind(curthread);
|
||||
thread_unlock(curthread);
|
||||
} else if (cpu != 0)
|
||||
return (-1);
|
||||
else
|
||||
msr = rdmsr(MSR_THERM_STATUS);
|
||||
|
||||
/*
|
||||
* Check for Thermal Status and Thermal Status Log.
|
||||
@ -264,13 +267,21 @@ coretemp_get_temp(device_t dev)
|
||||
return (temp);
|
||||
}
|
||||
|
||||
static int
|
||||
coretemp_get_temp_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
static void
|
||||
coretemp_refresh(void *arg)
|
||||
{
|
||||
device_t dev = (device_t) arg1;
|
||||
struct coretemp_softc *sc = arg;
|
||||
device_t dev = sc->sc_dev;
|
||||
struct ksensor *s = &sc->sc_sensor;
|
||||
int temp;
|
||||
|
||||
temp = coretemp_get_temp(dev);
|
||||
|
||||
return (sysctl_handle_int(oidp, &temp, 0, req));
|
||||
if (temp == -1) {
|
||||
s->flags |= SENSOR_FINVALID;
|
||||
s->value = 0;
|
||||
} else {
|
||||
s->flags &= ~SENSOR_FINVALID;
|
||||
s->value = temp * 1000000 + 273150000;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user