On 14 May 2011 c. 01:09:03 Christopher Zimmermann wrote:
> On 05/13/11 20:56, Alexander Polakov wrote:
> > * Marco Peereboom<sl...@peereboom.us>  [110512 17:59]:
> >> On Thu, May 12, 2011 at 03:32:56PM +0200, Christopher Zimmermann wrote:
> >>> On 05/12/11 14:37, Vadim Zhukov wrote:
> >>>> Hello all.
> >>>>
> >>>> Here is a patch that allows for me to work on other things. :)
> >>>> Basically, it makes OS choose fan mode instead of firmware. Main
> >>>> feature here is enabling of "disengadged" mode when temperature
> >>>> goes critical, picking 80C as a "red line". Now I can fully load
> >>>> CPU on my X201i - say, "make -j 4" - and it still works instead
> >>>> of being powering off by acpitz(4).
> >>
> >> User space will not be allowed to play.  I don't have a stinkpad so
> >> I can't test this but I do encourage people to play with this diff
> >> and report to the list.
> >
> > My thinkpad is AMD-powered, so 60 degrees is *normal* for it. With
> > this diff the fan is always running at max speed, generating lots of
> > noise.
>
> I think the THINKPAD_FANMODE_MAX part could be left out. The normal
> automatic should be able to set maximum speed at a model specific
> appropriate temperature. The important part is the disengaged mode,
> because the automatic regulation of the firmware is not able to set
> this mode.

Received your letter just before rebooting new kernel. :)
New version acts as you say: place fan in disengadged mode on
critical overheat, and return to automatical firmware management
when temperature goes back to (more or less) normal.

I also made temperature and fan mode sensors fill sensor status.
If anyone objects, I'll make this a separate diff, of course.

--
  Best wishes,
    Vadim Zhukov

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?


Index: acpithinkpad.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v
retrieving revision 1.26
diff -u -p -r1.26 acpithinkpad.c
--- acpithinkpad.c      27 Apr 2011 20:55:42 -0000      1.26
+++ acpithinkpad.c      13 May 2011 21:36:43 -0000
@@ -71,11 +71,21 @@
 #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
+
+#define THINKPAD_FANMODE_AUTO          0x80
+#define THINKPAD_FANMODE_DISENGADGED   0x40
+
+/* critical temperature mark, in Celsius */
+#define THINKPAD_TEMP_OUCH             80

 struct acpithinkpad_softc {
        struct device            sc_dev;
@@ -103,7 +113,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 *);

 struct cfattach acpithinkpad_ca = {
@@ -156,8 +166,12 @@ 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]);

        sensordev_install(&sc->sc_sensdev);
 }
@@ -166,9 +180,11 @@ void
 thinkpad_sensor_refresh(void *arg)
 {
        struct acpithinkpad_softc *sc = arg;
-       u_int8_t lo, hi, i;
-       int64_t tmp;
+       u_int8_t lo, hi, i, mode;
+       int64_t tmp, maxtmp = -127;    /* minimal correct value, see below */
+       enum sensor_status ss;
        char sname[5];
+       const char *desc;

        /* Refresh sensor readings */
        for (i=0; i<THINKPAD_NTEMPSENSORS; i++) {
@@ -176,14 +192,41 @@ 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)
+                       sc->sc_sens[i].status = SENSOR_S_CRIT;
+               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 (maxtmp > THINKPAD_TEMP_OUCH) {
+               mode = THINKPAD_FANMODE_DISENGADGED;
+               desc = "disengadged";
+               ss = SENSOR_S_CRIT;
+       } else {
+               mode = THINKPAD_FANMODE_AUTO;
+               desc = "auto";
+               ss = SENSOR_S_OK;
+       }
+       acpiec_write(sc->sc_ec, THINKPAD_ECOFFSET_FANMODE, 1, &mode);
+       sc->sc_sens[THINKPAD_SENSOR_FANMODE].value = mode;
+       sc->sc_sens[THINKPAD_SENSOR_FANMODE].status = ss;
+       snprintf(sc->sc_sens[THINKPAD_SENSOR_FANMODE].desc,
+           sizeof(sc->sc_sens[THINKPAD_SENSOR_FANMODE]),
+           "fan mode: %s", desc);
 }

 void

Reply via email to