Hello all. This is a bit improved version of the patch showed up on tech@ in... er-r-r... don't mind. This makes my ThinkPad usable under high load for more than a year, and should not cause problems mentioned before (spinning higher and lower constantly) by using two temperature marks instead of one.
I also found that disengaged mode should be enabled separately off other modes, so now Alexander Polyakov's X100e should behave correctly. Any ThinkPad users willing to test? -- WBR, Vadim Zhukov Index: sys/dev/acpi/acpithinkpad.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v retrieving revision 1.28 diff -u -p -r1.28 acpithinkpad.c --- sys/dev/acpi/acpithinkpad.c 6 Jun 2011 06:13:46 -0000 1.28 +++ sys/dev/acpi/acpithinkpad.c 9 Dec 2012 19:55:43 -0000 @@ -76,11 +76,25 @@ #define THINKPAD_POWER_CHANGED 0x6030 #define THINKPAD_SWITCH_WIRELESS 0x7000 -#define THINKPAD_NSENSORS 9 -#define THINKPAD_NTEMPSENSORS 8 +#define THINKPAD_NSENSORS 10 +#define THINKPAD_NTEMPSENSORS 8 + +#define THINKPAD_SENSOR_FANRPM (THINKPAD_NTEMPSENSORS + 0) +#define THINKPAD_SENSOR_FANMODE (THINKPAD_NTEMPSENSORS + 1) #define THINKPAD_ECOFFSET_FANLO 0x84 #define THINKPAD_ECOFFSET_FANHI 0x85 +#define THINKPAD_ECOFFSET_FANMODE 0x2f + +/* not used: #define THINKPAD_FANMODE_MIN 0x00 */ +#define THINKPAD_FANMODE_MAX 0x07 +#define THINKPAD_FANMODE_AUTO 0x80 +#define THINKPAD_FANMODE_DISENGAGED 0x40 +#define THINKPAD_FANMODE_FORCEMAX (THINKPAD_FANMODE_MAX | THINKPAD_FANMODE_DISENGAGED) + +/* critical temperature marks, in Celsius */ +#define THINKPAD_TEMP_OUCH_HMARK 80 +#define THINKPAD_TEMP_OUCH_LMARK 70 struct acpithinkpad_softc { struct device sc_dev; @@ -90,7 +104,10 @@ struct acpithinkpad_softc { struct aml_node *sc_devnode; struct ksensor sc_sens[THINKPAD_NSENSORS]; +#define sc_sensfanmode sc_sens[THINKPAD_SENSOR_FANMODE] struct ksensordev sc_sensdev; + + u_int8_t sc_fanmodeinit; }; extern void acpiec_read(struct acpiec_softc *, u_int8_t, int, u_int8_t *); @@ -108,7 +125,7 @@ int thinkpad_volume_mute(struct acpithin int thinkpad_brightness_up(struct acpithinkpad_softc *); int thinkpad_brightness_down(struct acpithinkpad_softc *); -void thinkpad_sensor_attach(struct acpithinkpad_softc *sc); +void thinkpad_sensor_attach(struct acpithinkpad_softc *); void thinkpad_sensor_refresh(void *); #if NAUDIO > 0 && NWSKBD > 0 @@ -165,8 +182,14 @@ thinkpad_sensor_attach(struct acpithinkp } /* Add fan probe */ - sc->sc_sens[i].type = SENSOR_FANRPM; - sensor_attach(&sc->sc_sensdev, &sc->sc_sens[i]); + sc->sc_sens[THINKPAD_SENSOR_FANRPM].type = SENSOR_FANRPM; + sensor_attach(&sc->sc_sensdev, &sc->sc_sens[THINKPAD_SENSOR_FANRPM]); + + /* Add fan mode indicator */ + sc->sc_sens[THINKPAD_SENSOR_FANMODE].type = SENSOR_INTEGER; + sensor_attach(&sc->sc_sensdev, &sc->sc_sens[THINKPAD_SENSOR_FANMODE]); + acpiec_read(sc->sc_ec, THINKPAD_ECOFFSET_FANMODE, 1, + &sc->sc_fanmodeinit); sensordev_install(&sc->sc_sensdev); } @@ -176,8 +199,10 @@ thinkpad_sensor_refresh(void *arg) { struct acpithinkpad_softc *sc = arg; u_int8_t lo, hi, i; - int64_t tmp; + int64_t tmp, maxtmp = -127; /* minimal correct value, see below */ + int updatemode = 0; /* should we bother BIOS? */ char sname[5]; + const char *desc; /* Refresh sensor readings */ for (i=0; i<THINKPAD_NTEMPSENSORS; i++) { @@ -185,14 +210,59 @@ thinkpad_sensor_refresh(void *arg) aml_evalinteger(sc->sc_acpi, sc->sc_ec->sc_devnode, sname, 0, 0, &tmp); sc->sc_sens[i].value = (tmp * 1000000) + 273150000; - if (tmp > 127 || tmp < -127) + if (tmp > 127 || tmp < -127) { sc->sc_sens[i].flags = SENSOR_FINVALID; + sc->sc_sens[i].status = SENSOR_S_UNKNOWN; + } + if ((sc->sc_sens[i].flags & SENSOR_FINVALID) == SENSOR_FINVALID) + continue; + if (tmp > maxtmp) + maxtmp = tmp; + if (tmp > THINKPAD_TEMP_OUCH_HMARK) + sc->sc_sens[i].status = SENSOR_S_CRIT; + else if (tmp > THINKPAD_TEMP_OUCH_LMARK) + sc->sc_sens[i].status = SENSOR_S_WARN; + else + sc->sc_sens[i].status = SENSOR_S_OK; } /* Read fan RPM */ acpiec_read(sc->sc_ec, THINKPAD_ECOFFSET_FANLO, 1, &lo); acpiec_read(sc->sc_ec, THINKPAD_ECOFFSET_FANHI, 1, &hi); - sc->sc_sens[i].value = ((hi << 8L) + lo); + sc->sc_sens[THINKPAD_SENSOR_FANRPM].value = ((hi << 8L) + lo); + + /* + * Update fan mode based on max temperature seen. + * If temperature is between THINKPAD_TEMP_OUCH_LMARK and + * THINKPAD_TEMP_OUCH_HMARK, we try to avoid setting fan mode + * to avoid extra spinning. + */ + + if (maxtmp > THINKPAD_TEMP_OUCH_HMARK) { + sc->sc_sensfanmode.value = THINKPAD_FANMODE_FORCEMAX; + sc->sc_sensfanmode.status = SENSOR_S_CRIT; + desc = "disengaged"; + updatemode = 1; + } else if (maxtmp <= THINKPAD_TEMP_OUCH_LMARK) { + sc->sc_sensfanmode.value = sc->sc_fanmodeinit; + sc->sc_sensfanmode.status = SENSOR_S_OK; + desc = "auto"; + updatemode = 1; + } else { + if (sc->sc_sensfanmode.status == SENSOR_S_UNSPEC) { + /* Better safe than sorry */ + sc->sc_sensfanmode.value = THINKPAD_FANMODE_FORCEMAX; + desc = "disengaged"; + updatemode = 1; + } + sc->sc_sensfanmode.status = SENSOR_S_WARN; + } + snprintf(sc->sc_sensfanmode.desc, sizeof(sc->sc_sensfanmode.desc), + "fan mode: %s", desc); + + if (updatemode) + acpiec_write(sc->sc_ec, THINKPAD_ECOFFSET_FANMODE, 1, + (u_int8_t*)&sc->sc_sensfanmode.value); } void Index: share/man/man4/acpithinkpad.4 =================================================================== RCS file: /cvs/src/share/man/man4/acpithinkpad.4,v retrieving revision 1.2 diff -u -p -r1.2 acpithinkpad.4 --- share/man/man4/acpithinkpad.4 31 May 2008 22:02:03 -0000 1.2 +++ share/man/man4/acpithinkpad.4 9 Dec 2012 19:55:43 -0000 @@ -28,6 +28,17 @@ The driver provides ACPI support for IBM/Lenovo ThinkPad laptops. It responds to various hotkey button presses such as the brightness adjustment and wireless toggle keys. +.Pp +Also +.Nm +monitors temperature and when it goes too high (current limit is set +to 80C), fan mode is changed to so called +.Dq disengaged +mode. +When temperature goes back under 70C, fan mode control is returned +to firmware. +This prevents laptops like X201, with hot CPUs, from being shooted down by +.Xr acpitz 4 . .Sh SEE ALSO .Xr acpi 4 , .Xr intro 4