diff options
author | netchild <netchild@FreeBSD.org> | 2007-10-14 10:59:44 +0000 |
---|---|---|
committer | netchild <netchild@FreeBSD.org> | 2007-10-14 10:59:44 +0000 |
commit | f372c9fc9b4256b53b40d0c220aa194b415ef499 (patch) | |
tree | 5d33cf636bb125bf5a72f9c9da969da3daa5d34e /sys | |
parent | 8423df3d9411c6e4e79b3a3b06ea1c3c6aaaa81f (diff) | |
download | FreeBSD-src-f372c9fc9b4256b53b40d0c220aa194b415ef499.zip FreeBSD-src-f372c9fc9b4256b53b40d0c220aa194b415ef499.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/coretemp/coretemp.c | 79 |
1 files changed, 45 insertions, 34 deletions
diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c index 61e4606..fcc0005 100644 --- a/sys/dev/coretemp/coretemp.c +++ b/sys/dev/coretemp/coretemp.c @@ -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; + } } |