adm9240.c review

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

 



Hi Michiel,

Here are my comments about your Linux 2.6 port of the adm9420.c driver.

>     Copyright (c) 1999  Frodo Looijaard <frodol at dds.nl>
>     and Philip Edelbrock <phil at netroedge.com>
> 
>     Copyright (c) 2003 Michiel Rook <michiel at grendelproject.nl>    

Copyright is (C), not (c).

> /* Supports ADM9240, DS1780, and LM81. See doc/chips/adm9240 for details */

Drop the second part of the comment, since the mentioned file is not
part of the Linux kernel.

> #include <linux/module.h>
> #include <linux/slab.h>
> #include <linux/proc_fs.h>
> #include <linux/ioport.h>
> #include <linux/sysctl.h>
> #include <linux/types.h>
> #include <linux/i2c.h>
> #include <linux/i2c-sensor.h>
> #include <linux/init.h>
> #include <asm/errno.h>
> #include <asm/io.h>

These are too many headers, you most certainly don't need all of them.
The follwing should be OK:
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>

> MODULE_LICENSE("GPL");

Please move this down to the bottom of the file (after the MODULE_AUTHOR
line).

> /* Many ADM9240 constants specified below */
> 
> #define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2)
> #define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2)
> #define ADM9240_REG_IN(nr) (0x20 + (nr))
> #define ADM9240_REG_FAN_MIN(nr) (ADM9240_REG_FAN1_MIN + nr)
> (...)

Please align all these defines using tabs.

> /* Scales for each voltage */
> int scales[6] = { 250, 270, 330, 500, 1200, 270 };
>    
> #define IN_TO_REG(val,nr) (SENSORS_LIMIT(((val) & 0xff),0,255))

This macro is broken. The "& ff" should be discarded.

> #define IN_FROM_REG(val,nr) (val * scales[nr] / 192)

Missing braces around "val".

> #define TEMP_FROM_REG(temp) \
>    ((temp)<256?((((temp)&0x1fe) >> 1) * 10)      + ((temp) & 1) * 5:  \
>                ((((temp)&0x1fe) >> 1) -255) * 10 - ((temp) & 1) * 5)  \

Could be simplified. "(A >> 1) * 10 + (A & 1) * 5" is nothing different
from "A * 5" as far as I can see.

> #define TEMP_LIMIT_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)

Shouldn't it be ">=0x80"?

> #define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
>                                                       ((val)+5)/10), \
>                                              0,255)

That one looks bogus. You cannot possibly set a negative limit, while
the test suggests it should be possible.

> /* Initial limits */
> #define ADM9240_INIT_IN_0 190
> #define ADM9240_INIT_IN_1 190
> #define ADM9240_INIT_IN_2 190
> #define ADM9240_INIT_IN_3 190
> #define ADM9240_INIT_IN_4 190
> #define ADM9240_INIT_IN_5 190
> (...)

Discard all of these constants, they aren't used anymore.

> static int adm9240_read_value(struct i2c_client *client, u8 register);
> static int adm9240_write_value(struct i2c_client *client, u8 register,
> 			       u8 value);

Rename "register" to "reg". "register" is a reserved keyword in C.

> static DEVICE_ATTR(temp1_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst, set_temp_os_hyst);

According to the sysfs interface standard, this file should be named
temp1_max_hyst.

> 	/* Make sure we aren't probing the ISA bus!! This is just a safety check
> 	   at this moment; i2c_detect really won't call us. */
> #ifdef DEBUG
> 	if (i2c_is_isa_adapter(adapter)) {
> 		printk
> 		    ("adm9240.o: adm9240_detect called for an ISA bus adapter?!?\n");
> 		return 0;
> 	}
> #endif

You can discard this entirely, as it is redundant with the check right
below.

>       ERROR3:
>       ERROR1:
> 	kfree(new_client);
>       ERROR0:
> 	return err;

Drop label "ERROR3", since it is not used. Align other labels to the
left.

> static int adm9240_read_value(struct i2c_client *client, u8 reg)
> {
> 	return 0xFF & i2c_smbus_read_byte_data(client, reg);
> }

Discard that "0xFF &", it's dangerous.

> /* Called when we have found a new ADM9240. Sets limits, etc. */

Discard the second part of the comment, since we don't set limits
anymore.

> static void adm9240_init_client(struct i2c_client *client)
> {
> 	/* Reset */
> 	adm9240_write_value(client, ADM9240_REG_CONFIG, 0x80);
> 	
> 	/* Reset chassis intrusion pin */
> 	adm9240_write_value(client, ADM9240_REG_CONFIG, 0x40);
> 	
> 	/* Start monitoring */
> 	adm9240_write_value(client, ADM9240_REG_CONFIG, 0x01);
> }

These writes are kind of agressive. You don't want to unconditionally
reset the chip. I would remove the write. If you think it should be
kept, please make it a module parameter (named reset or init).
You should use read-modify-writes for the other ones, since you really
only want to change one bit each time. I also suspect that the last two
calls could be merged.

Additional comments:

1* The magnitudes for temperatures and voltages are not correct. As I
read your code, voltages are exported with 0.01V/bit, and temperatures
with 0.1dC/bit. Should be 0.001 for both (magnitude 3).

2* The vid value should be in a file named... well in1_ref or cpu0_vid,
we're discussing it at the moment. But not vid, for sure. The library
has "in1_ref" at the moment but it will most certainly be changed to
"cpu0_vid" in the few next days.

The rest looks acceptable to me at a quick glance. There are some things
that should be updated but the decision to change them occured after you
started your initial work, so I cannot blame you for not doing them, and
will take care of submitting a corrective patch at a later time.

Please submit a modified version of your ported driver taking all my
comments into account. The prefered form would be a patch against a
recent 2.6 kernel tree (2.6.8-rc4 would be fine), including changes to
drivers/i2c/chips/Makefile and drivers/i2c/chips/Kconfig.

What we really need you (Michiel and Bert) for is testing the new
driver. As I don't have any compatible chip for testing, I rely on you
to confirm that things work well. I'll rely on you too for my later
changes. Please test corner cases as well if possible (such as setting
unreasonable limits).

Phil, do you still have an ADM9240 chip available for testing?

There are a number of strange comments in both the driver and docs which
would need reviewing (such as fan clock divider presumably not working,
or voltage readings being broken).

Thanks.

-- 
Jean "Khali" Delvare
http://khali.linux-fr.org/



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

  Powered by Linux