On Fri, Jul 17, 2015 at 08:54:26PM +0200, Mark Kettenis wrote:
> Tobias Ulmer schreef op 2015-07-15 02:33:
> >As we all know, some Thinkpads have problems with their EC fan control.
> >EC is not spinning up the fans to maximum speed, let alone blast mode.
> >They also do not offer ACPI methods to spin the fan up.
> >
> >Previous diffs doing manual fan control were always rejected because
> >hooking into the sensors framework with fixed temp limits is crude and
> >there are concerns with slowing the fan down and frying the hardware.
> >
> >This is an attempt to solve the problem slightly differently.
> >- Hook into acpitz and only speed the fan up when it is requesting active
> > cooling
> >- Never set the fan to a mode that would endanger the hardware should we
> > crash
> >
> >PS: It would be nice if there was a function to add cooling methods to
> >acpitz eg: acpitz_add(void (*fn)(struct acpitz_softc *, void *), void
> >*arg)
> >I tried but getting struct acpitz_softc into a header is a bit messy.
>
> Does the AML define any active cooling trip points (_AC0, _AC1, etc)?
No, not in my machines.
Aside from not checking for interference with ACPI, this diff can't
handle multiple thermal zones in a sensible manner.
There's also the problem of not throttling the CPU fast enough for the
little thermal mass in some machines. And I suspect acpitz_refresh()
is not running frequent enough to regulate properly.
I need to play with this some more, not feeling good about it just yet..
>
> >Index: acpithinkpad.c
> >===================================================================
> >RCS file: /home/vcs/cvs/openbsd/src/sys/dev/acpi/acpithinkpad.c,v
> >retrieving revision 1.44
> >diff -u -p -r1.44 acpithinkpad.c
> >--- acpithinkpad.c 24 Apr 2015 14:44:17 -0000 1.44
> >+++ acpithinkpad.c 14 Jul 2015 23:52:14 -0000
> >@@ -104,6 +104,11 @@
> > #define THINKPAD_ECOFFSET_FANLO 0x84
> > #define THINKPAD_ECOFFSET_FANHI 0x85
> >
> >+#define THINKPAD_ECOFFSET_FANLEVEL 0x2f
> >+#define THINKPAD_ECFANLEVEL_MAX 7
> >+#define THINKPAD_ECFANLEVEL_BLAST (1<<6)
> >+#define THINKPAD_ECFANLEVEL_AUTO (1<<7)
> >+
> > #define THINKPAD_ADAPTIVE_MODE_HOME 1
> > #define THINKPAD_ADAPTIVE_MODE_FUNCTION 3
> >
> >@@ -119,6 +124,7 @@ struct acpithinkpad_softc {
> > };
> >
> > extern void acpiec_read(struct acpiec_softc *, u_int8_t, int, u_int8_t
> >*);
> >+extern void (*acpitz_activecool)(int, int);
> >
> > int thinkpad_match(struct device *, void *, void *);
> > void thinkpad_attach(struct device *, struct device *, void *);
> >@@ -134,6 +140,7 @@ int thinkpad_brightness_up(struct acpith
> > int thinkpad_brightness_down(struct acpithinkpad_softc *);
> > int thinkpad_adaptive_change(struct acpithinkpad_softc *);
> > int thinkpad_activate(struct device *, int);
> >+void thinkpad_activecool(int, int);
> >
> > void thinkpad_sensor_attach(struct acpithinkpad_softc *sc);
> > void thinkpad_sensor_refresh(void *);
> >@@ -228,6 +235,7 @@ thinkpad_attach(struct device *parent, s
> > {
> > struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self;
> > struct acpi_attach_args *aa = aux;
> >+ u_int8_t level;
> >
> > sc->sc_acpi = (struct acpi_softc *)parent;
> > sc->sc_devnode = aa->aaa_node;
> >@@ -241,6 +249,11 @@ thinkpad_attach(struct device *parent, s
> > /* Run thinkpad_hotkey on button presses */
> > aml_register_notify(sc->sc_devnode, aa->aaa_dev,
> > thinkpad_hotkey, sc, ACPIDEV_POLL);
> >+
> >+ /* Make sure fan is in auto mode, otherwise we're not sure of support */
> >+ acpiec_read(acpi_softc->sc_ec, THINKPAD_ECOFFSET_FANLEVEL, 1, &level);
> >+ if (level == THINKPAD_ECFANLEVEL_AUTO)
> >+ acpitz_activecool = thinkpad_activecool;
> > }
> >
> > int
> >@@ -546,4 +559,30 @@ thinkpad_activate(struct device *self, i
> > break;
> > }
> > return (0);
> >+}
> >+
> >+void
> >+thinkpad_activecool(int tmp, int psv)
> >+{
> >+ static uint8_t level = THINKPAD_ECFANLEVEL_AUTO;
> >+ uint8_t nlevel;
> >+
> >+ if (tmp < 0 || psv < 0)
> >+ return;
> >+
> >+ if (tmp > psv)
> >+ nlevel = THINKPAD_ECFANLEVEL_BLAST;
> >+ else if (tmp > psv-50)
> >+ /* EC firmware fan control is too slow in some models. When
> >+ * we're getting within 5C of active cooling mode, turn the
> >+ * fan to MAX. Helps with oscillation between blast and auto */
> >+ nlevel = THINKPAD_ECFANLEVEL_MAX;
> >+ else
> >+ nlevel = THINKPAD_ECFANLEVEL_AUTO;
> >+
> >+ if (nlevel != level) {
> >+ acpiec_write(acpi_softc->sc_ec, THINKPAD_ECOFFSET_FANLEVEL, 1,
> >+ &nlevel);
> >+ level = nlevel;
> >+ }
> > }
> >Index: acpitz.c
> >===================================================================
> >RCS file: /home/vcs/cvs/openbsd/src/sys/dev/acpi/acpitz.c,v
> >retrieving revision 1.49
> >diff -u -p -r1.49 acpitz.c
> >--- acpitz.c 6 May 2015 01:41:55 -0000 1.49
> >+++ acpitz.c 14 Jul 2015 23:52:14 -0000
> >@@ -86,6 +86,7 @@ int acpitz_setfan(struct acpitz_softc *,
> > void acpitz_init(struct acpitz_softc *, int);
> >
> > void (*acpitz_cpu_setperf)(int);
> >+void (*acpitz_activecool)(int, int) = NULL;
> > int acpitz_perflevel = -1;
> > extern void (*cpu_setperf)(int);
> > extern int perflevel;
> >@@ -427,6 +428,11 @@ acpitz_refresh(void *arg)
> > acpitz_setfan(sc, i, "_OFF");
> > }
> > }
> >+
> >+ /* active cooling hook */
> >+ if (acpitz_activecool)
> >+ acpitz_activecool(sc->sc_tmp, sc->sc_psv);
> >+
> > sc->sc_sens.value = sc->sc_tmp * 100000 - 50000;
> > }
>