[RFC] Asus ATK0110 ACPI hwmon driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

As discussed before I've been reviewing the ATK0110 driver. Over all I like it 
(a lot even), but I have serious concerns about mixing ACPI sensor IC access 
with native IC driver access, see my separate mail about this. I've also 
proposed a solution for this in that mail. If we solve things this way, then I 
believe that this driver is good to go in in general. I still have some remarks 
for making it even better:

1) You write:

#ifdef DEBUG

static void atk_print_sensor(struct atk_data *data, union acpi_object *obj)
{
    /* lots of code */
}

#else

static void atk_print_sensor(struct atk_data *data, union acpi_object *obj)
{
}

#endif

Why not just write ? :

static void atk_print_sensor(struct atk_data *data, union acpi_object *obj)
{
#ifdef DEBUG
    /* lots of code */
#endif
}


2) The 3 atk_*_label_show functions are all 3 the same, just create one
    atk_label_show function and use that

3) atk_volt_min_show and atk_fan_min_show are identical, make one function
    for the both of them, same for the max_show variants

4) Following the above line of reasoning actually all in/fan/temp show
    functions are very much alike. If you add a type member to the
    atk_sensor_data struct and store the HWMON_TYPE_XXXX needed for
    atk_read_value_old, there. And then conditionally multiply the read
    value by 100 if s->type == HWMON_TYPE_TEMP, then you can use one set of
    4 show functions instead of 3 sets. I admit the show functions aren't all
    that big, still I advocate this approach because the 3 atk_add_voltage() /
    atk_add_temp() / atk_add_temp() functions are also very similar and
    become even more similar when there is only one set of show functions:

5) Once 2), 3) and 4) above are done, then the atk_add_*() methods are
    almost identical. There are 4 differences left:
    a) attribute names are inX_foo vs tempX_foo vs fanX_foo, this can be solved
       by passing in an additional argument which is "in", "temp", or "fan".
    b) atk_sensor_data.type needs to be set to HWMON_TYPE_XXXX, simply pass
       this in as an argument
    c) limit1 / 2 are min / max for in and fan and high / crit for temp, special
       case this on atk_sensor_data.type == HWMON_TYPE_TEMP. I don't like
       special cases like this but I believe the removal of code duplication is
       well worth it.
    d) The list to which the sensor gets added is different, this looking at how
       you use these lists, you always do the same operations on all 3 of them,
       so you simply make this 1 list, this will also simplify code in other
       places

6) The 3th argument to atk_init_attribute() is always 0444, and the 5th always
    is NULL, I think things would be better readable if you hardcode these 2
    inside atk_init_attribute()


So all in other, other then some opportunities to remove some code 
duplications, so far I see no problems. Please consider all of the above as 
things which IMHO you should fix, but these are not items which I consider must 
fix things. In other words if you have strong disagreeing opinions feel free to 
not follow some or all of the above ideas for improvements.

Unfortunately there also is one bigger problem, each time an app reads an input 
value, and ACPI call gets made, so doing something like:
while true; do cat /sys/class/hwmon/hwmon0/fan1_input; done

Leads to 100% *system* load on one CPU on my dual core, iow one core is 
spending 100% of its time inside the kernel. This is not strange as each the 
underlying acpi code needs to do slow IO to the super-IO IC, or even slower smbus.

So I think you should add an input or value member to the atk_sensor_data 
struct and a last_updated timestamp to the atk_data struct and have an 
update_device function which gets called in show_input, which checks the time 
since the last update and for example max twice a second or maybe even once 
every 2 seconds, walks the list and calls atk_read_value_old/new for all 
sensors updating the value member of the atk_sensor_data struct and then have 
show_input use the cached value inside the atk_sensor_data struct. This is how 
all other hwmon drivers "solve" the IO starvation problem which can be caused 
by abusive programs other wise. Just take a look at any other hwmon driver to 
see how this is implemented, search for a function called update_device, the 
update function isalmost always called update_device().

So summarizing:
1) I like it :)
2) I see some opportunities for removing duplicate code /
    simplifying (only one list).
3) Blocker: must protect against userspace abuse causing lots of IO /
    an ACPI call storm
4) Blocker: we must make sure we do not have ACPI and native IC drivers
    banging IO's of the same IC

Regards,

Hans





[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux