OpenBSD Journal

New two-level sensor API

Contributed by marco on from the measure-me-baby! dept.

Constantine Murenin writes:

OpenBSD 4.0-current has a two-level sensor API starting from 2006-12-23. Theo de Raadt committed my patch that converts sys/sensors.h header file, kern_sensors.c framework implementation, all device drivers, sysctl(3), sysctl(8), as well as sensorsd(8) and ntpd(8), along with all manual pages, to the new API, a prototype of which was originally developed for my final year computing project at De Montfort University, supervised by Dr. Jordan Dimitrov and Prof. Michail Goman.

two-level API from the kernel-space view-point

How it was before

Previously, each driver was adding sensors to a common pile of sensors, which were then accessible via sysctl(3). Although sensors already had a concept of sensor type, sensors were still numbered in a global fashion, where no two sensors on the system could have had the same number.

I.e. if lm0 already had a sensor with number ‘0’ that showed fan speed, then it could not simultaneously have had a sensor with number ‘0’ showing temperature. Moreover, once lm0 would register, say, 15 sensors, which would automatically get numbers from 0 to 14 if lm0 was the first device trying to register sensors, then lm1 sensors would have to live with being numbered 15 and above (and, say, ses0 — 30 and above). I.e. with the way it was, to monitor the first temperature sensor on lm0, you had to call for hw.sensors.10; whereas the first temperature sensor on lm1 would have been hw.sensors.25.

Moreover, as sensor numbering could not have been trusted for anything remotely useful (apart from the count of how many total sensors you might have), it led to the abuse of the sensor description attribute within the drivers using the framework, where a lot of drivers had "Temp1", "Temp2", "Temp3" etc null-terminated strings hardcoded into them, or had a loop creating these null-terminated strings on the fly, which still was an unoptimal solution.

How it is now

Now sensors API has a concept of sensor device, where each driver that supports sensors adds them via sensor_attach(9) to its own sensor device structure (struct sensordev), and then registers its sensor device with sensordev_install(9) within the sysctl(3) framework.

This immediately adds the benefit of having a separate sensor count for each driver instance, i.e. lm0 and lm1 could both have sensors numbered ‘0’! However, we didn't want to stop there, and used an automatically-updated array maxnumt counting the maximum number of sensors of each type a sensor device has — after having this information, we could reset sensor numbering with each type on each sensor device! (Without having such information, you'd have to loop around sysctl a lot in trying to find all possible sensors of all possible types. This array limits such unnecessary looping.)

Not only does this make things simpler from the conceptual understanding of which sensor comes from which device, as well as unifies the information about how many sensors of each type each sensor device has, but because of these improvements, we were able to free most drivers of any types and ordinal numbers in sensor description fields. I.e. "Temp1", "Fan1" and the like were all removed from lm(4), it(4), fintek(4) etc driver definitions, shrinking the kernel by a noticeable amount!

So this two-level sensor API not only improves functionality and rationality, but it also shrinks the kernel without any reduction in functionality!

three-level sensor addressing from the userland prospective

sysctl(8) and sensorsd(8) now use a different naming scheme for specifying sensors. A picture is worth a thousand words, so here is some demonstration of what this framework means to you:

$ sysctl hw.sensors.lm0.{temp{0,1},fan,volt{1,2}}
hw.sensors.lm0.temp0=52.00 degC
hw.sensors.lm0.temp1=44.00 degC
hw.sensors.lm0.fan1=2789 RPM
hw.sensors.lm0.volt1=11.55 V DC (+12V)
hw.sensors.lm0.volt2=3.33 V DC (+3.3V)

Notice that this three-level addressing will provide tremendous simplification for many shell scripts, and will undoubtedly improve their portability!

Future plans?

You can expect more sensorsd(8) improvements soon, as well as some new features and improvements for lm(4)/it(4)/abstm(4)/fcu(4)/fintek(4), so stay tuned for some more mojo. :)

Moreover, feel free to mail me (mureninc@gmail.com) your dmesg, `sysctl hw`, `fgrep sensorsd /var/log/daemon` and /etc/sensorsd.conf as you deem appropriate, before and after the change, inline text/plain format, please. More data about how people use the framework will help me optimise future development.

Credits?

Dr. Jordan Dimitrov and Prof. Michail Goman for supervising my final year project where a prototype of this framework was originally developed; Alexander Yurchenko for initial explanation of the rationale behind the previous framework; David Gwynne for providing some useful feedback on the prototypes; Theo de Raadt for his continued passion towards development of secure and simple operating systems and for his very valuable advices on how operating systems should be developed; and also Marco Peereboom, Leszek Zarzycki, Ray Miller (UKUUG) and Tom Cosgrove.

Happy holidays!

subj. :)

(Comments are closed)


Comments
  1. By Ezekiel Grave (ezekiel) ezekiel@ripmetopieces.net on http://ripmetopieces.net

    Bravo! Much appreciated.

  2. By Mathias (m_mathias) on

    Looks nice! Going to try it on my workstation next week.

  3. By Anonymous Coward (24.113.149.46) on

    Not a huge change on the X40, but nicer than it was:
    hw.sensors.aps0.temp0=40.00 degC
    hw.sensors.aps0.temp1=40.00 degC
    hw.sensors.aps0.raw0=513, (X_ACCEL)
    hw.sensors.aps0.raw1=503, (Y_ACCEL)
    hw.sensors.aps0.raw2=513, (X_VAR)
    hw.sensors.aps0.raw3=503, (Y_VAR)
    hw.sensors.aps0.raw4=1, (Keyboard Active)
    hw.sensors.aps0.raw5=0, (Mouse Active)
    hw.sensors.aps0.raw6=1, (Lid Open)
    hw.sensors.aps0.raw7=7, (unknown)

    Comments
    1. By Constantine A. Murenin (cnst) on http://www.openbsd.org/cgi-bin/cvsweb/src/sys/dev/isa/aps.c?f=h#rev1.12

      
      > Not a huge change on the X40, but nicer than it was:
      > hw.sensors.aps0.temp0=40.00 degC
      > hw.sensors.aps0.temp1=40.00 degC
      > hw.sensors.aps0.raw0=513, (X_ACCEL)
      > hw.sensors.aps0.raw1=503, (Y_ACCEL)
      > hw.sensors.aps0.raw2=513, (X_VAR)
      > hw.sensors.aps0.raw3=503, (Y_VAR)
      > hw.sensors.aps0.raw4=1, (Keyboard Active)
      > hw.sensors.aps0.raw5=0, (Mouse Active)
      > hw.sensors.aps0.raw6=1, (Lid Open)
      > hw.sensors.aps0.raw7=7, (unknown)
      
      

      Today aps(4) was improved a bit further, and it should now have 3 indicators — indicator{0,1,2} — instead of raw{4,5,6}.
      Also, jsg@ removed raw7 as it wasn't of much use.

      Enjoy! :)

  4. By Nate (Nate) Evil on

    But why does it say fan1 instead of fan0 in the example?

    Comments
    1. By Otto Moerbeek (otto) on http://www.drijf.net

      > But why does it say fan1 instead of fan0 in the example?

      Look at the command line asking for the sensors.

      Comments
      1. By Otto Moerbeek (otto) on http://www.drijf.net

        > > But why does it say fan1 instead of fan0 in the example?
        >
        > Look at the command line asking for the sensors.

        Ehh, I looked wrong. Actually I don't know .

        Comments
        1. By Otto Moerbeek (otto) on http://www.drijf.net

          > > > But why does it say fan1 instead of fan0 in the example? > > > > Look at the command line asking for the sensors. > > Ehh, I looked wrong. Actually I don't know . > > Looked a bit more into this. My amd64 shows:
          [otto@lou:3]$ sysctl -a hw.sensors
          hw.sensors.it0.temp0=43.00 degC
          hw.sensors.it0.temp1=30.00 degC
          hw.sensors.it0.temp2=41.00 degC
          hw.sensors.it0.fan0=3183 RPM
          hw.sensors.it0.fan2=5443 RPM
          hw.sensors.it0.volt0=1.36 V DC, (VCORE_A)
          hw.sensors.it0.volt1=0.00 V DC, (VCORE_B)
          hw.sensors.it0.volt2=3.30 V DC, (+3.3V)
          hw.sensors.it0.volt3=4.95 V DC, (+5V)
          hw.sensors.it0.volt4=11.90 V DC, (+12V)
          hw.sensors.it0.volt5=0.67 V DC, (Unused)
          hw.sensors.it0.volt6=-17.00 V DC, (-12V)
          hw.sensors.it0.volt7=4.81 V DC, (+5VSB)
          hw.sensors.it0.volt8=3.06 V DC, (VBAT)
          
          So its seems that fan sensors that are not connected are skipped. The only strange things is the -17 V.

          Comments
          1. By Constantine A. Murenin (cnst) on http://cnst.livejournal.com/tag/openbsd

            > Looked a bit more into this. My amd64 shows:
            >
            > [otto@lou:3]$ sysctl -a hw.sensors
            > hw.sensors.it0.temp0=43.00 degC
            > hw.sensors.it0.temp1=30.00 degC
            > hw.sensors.it0.temp2=41.00 degC
            > hw.sensors.it0.fan0=3183 RPM
            > hw.sensors.it0.fan2=5443 RPM
            > hw.sensors.it0.volt0=1.36 V DC, (VCORE_A)
            > hw.sensors.it0.volt1=0.00 V DC, (VCORE_B)
            > hw.sensors.it0.volt2=3.30 V DC, (+3.3V)
            > hw.sensors.it0.volt3=4.95 V DC, (+5V)
            > hw.sensors.it0.volt4=11.90 V DC, (+12V)
            > hw.sensors.it0.volt5=0.67 V DC, (Unused)
            > hw.sensors.it0.volt6=-17.00 V DC, (-12V)
            > hw.sensors.it0.volt7=4.81 V DC, (+5VSB)
            > hw.sensors.it0.volt8=3.06 V DC, (VBAT)
            >
            > So its seems that fan sensors that are not connected are skipped.
            > The only strange things is the -17 V.


            Yes, this is correct. And please remember, that my patch only fixes the addressing scheme -- it's not supposed to fix other things like negative voltage detection and such. :)

            In fact, a lot of motherboard manufacturers do not wire up some sensors the way sensor chip manufacturers recommend, or some sensor chip manufacturers don't even have any stable recommendations on how to wire up their sensors (i.e. to which VIN on the sensor chip should resistor-converted-12V be connected?), so at times it is impossible to make comprehensive conclusions from readings provided by lm(4), it(4) and the like.

            More details about this are quite beyond this article, BTW. :)

    2. By Constantine A. Murenin (cnst) on http://cnst.livejournal.com/tag/openbsd

      > But why does it say fan1 instead of fan0 in the example?
      
      My lm0 chip from the example is W83627THF.
      It has 3 fan sensors:
      
       * lm0.fan0 — SYSFANIN
       * lm0.fan1 — CPUFANIN
       * lm0.fan2 — AUXFANIN
      
      Apparently, I don't have anything connected to the Auxiliary fan header 
      on the motherboard, and System Fan is a big 90mm or 92mm fan running at 
      low speed due to the decreased voltage that is given to it (I use some 
      voltage-limiting options that W83627THF provides), so its speed cannot 
      be detected. 
      
      I.e. because only CPU fan speed is detectable, and all other fans are 
      marked as invalid by lm(4), you only see lm0.fan1 in my example. For 
      details, see lm78.c::wb_refresh_fanrpm().
      
      In general, as far as lm(4) is concerned, both new and old addressing 
      schemes are deterministic no matter of whether your fans provide valid 
      readings or not. So if you had a gap between sensors in the old scheme, 
      then you are more than likely to have the same gap in the new addressing 
      scheme, and this is obviously a feature, not a bug — you don't want
      you CPU fan reading to jump around different addresses, do you? :)
      

  5. By Frank Denis (82.224.188.215) on http://forum.manucure.info

    It looks like Symon doesn't like it.

    In order to avoid duplicate efforts, has anyone already tried to fix Symon?

    Comments
    1. By cnst (cnst) on

      > It looks like Symon doesn't like it.
      >
      > In order to avoid duplicate efforts, has anyone already tried to fix Symon?

      A few minutes ago I've sent a preliminary patch for adopting symon to the new framework to Willem Dijkstra (symon author), so you can expect to have ports/sysutils/symon up-to-date soon.

      C.

      Comments
      1. By Anonymous Coward (66.65.113.158) on

        > > It looks like Symon doesn't like it.
        > >
        > > In order to avoid duplicate efforts, has anyone already tried to fix Symon?
        >
        > A few minutes ago I've sent a preliminary patch for adopting symon to the new framework to Willem Dijkstra (symon author), so you can expect to have ports/sysutils/symon up-to-date soon.
        >
        > C.

        uhm, have you heard from Willem yet? if not, can you post your update?

        Comments
        1. By cnst (cnst) on

          > uhm, have you heard from Willem yet? if not, can you post your update?
          
          For people still browsing this — I've posted the final version of my 
          symon patch to ports@ on 2007-01-18 so that everyone can have a go at it: 
          
          	http://marc.theaimsgroup.com/?l=openbsd-ports&m=116917726601827&w=2
          
          Willem was CC'ed on that patch, and he told me on 2007-01-20 that he'll 
          try wrap up a new release as soon as he will have some time. :)
          
          C. 
          

          Comments
          1. By cnst (cnst) on

            It is my pleasure to report that the latest version of symon -- 2.75 -- now includes my patch that adds support for the two-level sensor interfacing. It also includes Willem's patch that allows longer module arguments to be transmitted between symon and symux, i.e. the disclaimer in my previous message to ports@ is already taken care of.

            Please note, that symon-2.75, just as my previous patch to ports@, supports BOTH old and new style of sensor addressing, and which style is supported depends on the system where the symon is compiled. I.e. if you compile it on a system that has two-level addressing, then the sensor() module may only be used on a system with two-level addressing, and the same goes for the older one level addressing.

            Cheers,
            Constantine.

Latest Articles

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]