Hi,

I have encounter problem with acpitz: basically with acpitz enable, 
a fan keep running at max speed (with lot of noise).

I have traced the problem (see
http://marc.info/?l=openbsd-bugs&m=140517557620686&w=2 for reference).

As I haven't received any indications, I go to the ACPI spec in order to
understand what happens. Currently, I'm not sure to understand all the
terms, so please correct my if I am wrong: that would help me !

The host is an HP compaq nc6400 (see dmesg from previous reference if need).

>From what I understand, the host use notify 0x81 when temperature pass
an active point. The spec say it is ok: "The following are the primary
uses for this type of thermal notification:
 - ...
 - ...
 - After the crossing of an active or passive trip point is signaled to
   implement hysteresis."

The current code in acpitz.c for 0x81 notify is to reread TRIP points
(passive: _PSV and actives: _ACx), and for active points, to reinitiate
sc_ac_stat (which seems to keep the current state of fan:
-1=uninitialized / 0=OFF / 1=ON). 

sc_ac_stat is taken from _STA: "Returns the current ON or OFF status for
the power resource." (0=OFF / 1=ON)

The problem is the code set sc_ac_stat to -1, whereas fan could be ON.

>From dev/acpi/acpitz.c:

>        /* active cooling */
>        for (i = 0; i < ACPITZ_MAX_AC; i++) {
>                if (sc->sc_ac[i] != -1 && sc->sc_ac[i] <= sc->sc_tmp) {
>                        /* turn on fan i */
>                        if (sc->sc_ac_stat[i] <= 0)
>                                acpitz_setfan(sc, i, "_ON_");
>                } else if (sc->sc_ac[i] != -1) {
>                        /* turn off fan i */
>                        if (sc->sc_ac_stat[i] > 0)
>                                acpitz_setfan(sc, i, "_OFF");
>                }
>        }

The active cooling code could set the fan ON if sc_ac_stat is -1, but
couldn't set the fan OFF...

So when a notify 0x81 occurs and the fan is ON, sc_ac_stat is set to -1,
and as the temperature will keep low, the active cooling will not do
anything... keeping the fan running.


So I have change the round-trip reinitialization to not bindly set -1 to
sc_ac_stat, but reread the corresponding _STA instead of.

The following patch acheive this by:
 - change acpitz_setfan function to allow a NULL method (instead of
   "_ON_" or "_OFF" values only).

   The purpose is to reuse the codepath that read _STA, but without set
   the fan ON or OFF.

 - call acpitz_setfan with NULL during acpitz_init, when reading trip
   points. It always set sc_ac_stat=-1, but if no error in acpitz_setfan
   occurs, the call will set sc_ac_stat= _STA.


Another possibility (not tested) should be to change active cooling code
to permit call acpitz_setfan(OFF) when sc_ac_stat == -1.


Thanks to comment.
-- 
Sébastien Marie


Index: src-sys-current/dev/acpi/acpitz.c
===================================================================
--- src-sys-current.orig/dev/acpi/acpitz.c
+++ src-sys-current/dev/acpi/acpitz.c
@@ -141,6 +141,7 @@ acpitz_init(struct acpitz_softc *sc, int
                        snprintf(name, sizeof(name), "_AC%d", i);
                        sc->sc_ac[i] = acpitz_getreading(sc, name);
                        sc->sc_ac_stat[i] = -1;
+                       acpitz_setfan(sc, i, NULL);
                }
        }
 
@@ -317,8 +318,8 @@ acpitz_setfan(struct acpitz_softc *sc, i
                                    DEVNAME(sc), name, x, y);
                                continue;
                        }
-                       if (aml_evalname(sc->sc_acpi, ref->node, method, 0,
-                           NULL, NULL))
+                       if (method != NULL && aml_evalname(sc->sc_acpi, 
ref->node,
+                           method, 0, NULL, NULL))
                                printf("%s: %s[%d.%d] %s fails\n",
                                    DEVNAME(sc), name, x, y, method);
 

Reply via email to