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;
> > }
> 

Reply via email to