From f372c9fc9b4256b53b40d0c220aa194b415ef499 Mon Sep 17 00:00:00 2001 From: netchild Date: Sun, 14 Oct 2007 10:59:44 +0000 Subject: Convert coretemp(4) to the hardware sensors framework and make sure to never call sched_bind() for uninitialised CPUs. Submitted by: Constantine A. Murenin Sponsored by: Google Summer of Code 2007 (GSoC2007/cnst-sensors) Mentored by: syrinx Tested by: many OKed by: kensmith --- sys/dev/coretemp/coretemp.c | 79 ++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) (limited to 'sys/dev/coretemp') 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 #include #include -#include +#include #include /* for curthread */ #include @@ -50,10 +50,13 @@ __FBSDID("$FreeBSD$"); #include #include +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; + } } -- cgit v1.1