summaryrefslogtreecommitdiffstats
path: root/sys/dev/coretemp
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2007-10-14 10:59:44 +0000
committernetchild <netchild@FreeBSD.org>2007-10-14 10:59:44 +0000
commitf372c9fc9b4256b53b40d0c220aa194b415ef499 (patch)
tree5d33cf636bb125bf5a72f9c9da969da3daa5d34e /sys/dev/coretemp
parent8423df3d9411c6e4e79b3a3b06ea1c3c6aaaa81f (diff)
downloadFreeBSD-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/dev/coretemp')
-rw-r--r--sys/dev/coretemp/coretemp.c79
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;
+ }
}
OpenPOWER on IntegriCloud