DME1737 review (was Re: http://www.lm-sensors.org/ticket/2188)

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

 



Hans,

First of all, thanks for the review, I really appreciate it. Please
see my comments embedded below.

> General remarks:
> - i2x writes / read status never gets checked anywhere, I dunno if this is done
>    in other lm_sensors drivers similary, but IMHO these things should be
>    checked!

Good point, never thought about it. I checked some of the other hwmon
drivers and none of them checks the return status (not that this is a
good excuse or anything). Checking all reads/writes sounds like an
overkill assuming that Jean is correct and these things hardly ever
fail. The least I can do is spit out a warning if something fails.


> +/* temperature input */
> +static int TEMP_FROM_REG(int reg, int res)
> +{
> +       return (((reg & (1 << (res - 1))) ? reg - (1 << res) : reg) *
> +               1000 / (1 << (res - 8)));
> +}
> +
> +static int TEMP_TO_REG(int val, int res)
> +{
> +       int temp = val * (1 << (res - 8)) / 1000;
> +       return SENSORS_LIMIT((temp < 0) ? temp + (1 << res) : temp,
> +                            0, (1 << res) - 1 );
> +}
>
> Wouldn't it be better readable / clearer when instead of:
> "x * 1000 / (1 << (res - 8))" you write "(x * 1000) >> (res - 8)" ?
> And the same for TEMP_TO_REG, instead of: "val * (1 << (res - 8)) / 1000",
> write: "(val << (res - 8)) / 1000" ?

Yeah, true. And more efficient too. Will fix.


> +static int TEMP_HYST_FROM_REG(int reg, int ix) {
> +       return ((((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000);
> +}
> +
> +static int TEMP_HYST_TO_REG(int val, int ix, int reg)
> +{
> +       int hyst = SENSORS_LIMIT(val, 0, 15);
> +       return ((ix == 1) ? (reg & 0xf0) | hyst : (reg & 0x0f) | (hyst << 4));
> +}
>
> This doesn't seem consistent, when getting a hyst from the reg you multiply it
> by 1000 making it ready for sysfs, but when storing it to the reg, you don't
> divide it by 1000 (which should be done before the limit, or the limit should
> be adjusted)

Good catch! Will fix.


> Actually when using TEMP_HYST_TO_REG here:
> +       case SYS_TEMP_AUTO_POINT1_TEMP_HYST:
> +               data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG(
> +                                       TEMP_FROM_REG(data->zone_low[ix], 8) -
> +                                       val, ix, dme1737_read(client,
> +                                       DME1737_REG_ZONE_HYST(ix == 2)));
> +               dme1737_write(client, DME1737_REG_ZONE_HYST(ix == 2),
> +                             data->zone_hyst[ix == 2]);
> +               break;
>
> You don't divide the temp past to TEMP_HYST_TO_REG by 1000, so its not
> inconsistent its actually a bug (fix please).

Ditto.


> Please add a comment that the pwm_freq registers hold the pwm freq in the lower
> nibble and the temp_range for the speed control in the higher nibble, without
> such a comment, this code looks rather strange:
> +       case SYS_TEMP_AUTO_POINT2_TEMP:
> +               res = TEMP_FROM_REG(data->zone_low[ix], 8) +
> +                     TEMP_RANGE_FROM_REG(data->pwm_freq[ix]);
> +               break;

Will do. I'll also rename the variable/register name to make it clearer.


> +       case SYS_TEMP_AUTO_POINT2_TEMP:
> +               data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val -
> +                                       TEMP_FROM_REG(data->zone_low[ix], 8),
> +                                       dme1737_read(client,
> +                                       DME1737_REG_PWM_FREQ(ix)));
>
> Why do you use the cached temp here, but not the cached pwm_freq reg contents??
> Notice that you do this in several places.

Hmm... I want to make sure that I don't change the pwm_freq bits in
case the cache is out-of-sync with the register value. But if the
cache is stale the temp bits might be bogus and hence my calculated
temp value will be too. I guess you're right, I should read the temp
values from the register rather than using the cached values. Will
fix.


> +#define SYS_PWM                                0
> +#define SYS_PWM_FREQ                   2
> +#define SYS_PWM_ENABLE                 3
> +#define SYS_PWM_RAMP_RATE              4
> +#define SYS_PWM_AUTO_CHANNELS_TEMP     5
> +#define SYS_PWM_AUTO_POINT1_PWM                6
> +#define SYS_PWM_AUTO_POINT2_PWM                7
>
> Why is 1 not used in this "enum" ?

Will fix.


> Wouldn't it be cleaner to instead of:
> +#define SENSOR_ATTR_FAN_1TO4(ix) \
> +       SENSOR_ATTR_2(fan##ix##_type, S_IRUGO | S_IWUSR, \
> +               show_fan, set_fan, SYS_FAN_TYPE, ix-1)
> write:
> +#define SENSOR_ATTR_FAN_1TO4(ix) \
> +       SENSOR_ATTR_FAN(ix) \
> +       SENSOR_ATTR_2(fan##ix##_type, S_IRUGO | S_IWUSR, \
> +               show_fan, set_fan, SYS_FAN_TYPE, ix-1)
>
> And idem for 5to6, and the instead of:
> +       /* fans */
> +       SENSOR_ATTR_FAN(1),
> +       SENSOR_ATTR_FAN(2),
> +       SENSOR_ATTR_FAN(3),
> +       SENSOR_ATTR_FAN(4),
> +       SENSOR_ATTR_FAN(5),
> +       SENSOR_ATTR_FAN(6),
> +       /* fan[1-4] unique attrs */
> +       SENSOR_ATTR_FAN_1TO4(1),
> +       SENSOR_ATTR_FAN_1TO4(2),
> +       SENSOR_ATTR_FAN_1TO4(3),
> +       SENSOR_ATTR_FAN_1TO4(4),
> +       /* fan[5-6] unique attrs */
> +       SENSOR_ATTR_FAN_5TO6(5),
> +       SENSOR_ATTR_FAN_5TO6(6),
>
> write:
> +       /* fans */
> +       SENSOR_ATTR_FAN_1TO4(1),
> +       SENSOR_ATTR_FAN_1TO4(2),
> +       SENSOR_ATTR_FAN_1TO4(3),
> +       SENSOR_ATTR_FAN_1TO4(4),
> +       SENSOR_ATTR_FAN_5TO6(5),
> +       SENSOR_ATTR_FAN_5TO6(6),

Good suggestion. Will fix.


> Well thats it all in all it looks like a clean driver to me.


Thanks. Now on to yours...

Again, thanks a lot for the review. Modified patch coming soon...
...juerg




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

  Powered by Linux