From: r.marek@sh.cvut.cz (Rudolf Marek)
To: lm-sensors@vger.kernel.org
Subject: [lm-sensors] [PATCH] W83627EHF driver update
Date: Wed, 14 Jun 2006 12:48:56 +0000 [thread overview]
Message-ID: <449005B8.6090908@sh.cvut.cz> (raw)
In-Reply-To: <4485CB7A.9050209@sh.cvut.cz>
Hi all,
>
> The name is not very well chosen, these registers can hold both a target
> temperature or a target fan speed depending on the control mode (even
> if we don't support the latter at the moment.) What about just
> W83627EHF_REG_TARGET?
I think this is in the plan for future driver upgrade.
>
>> +static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
>> +
>> +
>> +/* Advanced Fan control */
>> +static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
>> +static const u8 W83627EHF_REG_FAN_MAX_OUTPUT[] = { 0x67, 0x69 };
>> +static const u8 W83627EHF_REG_FAN_STEP[] = { 0x68, 0x6A };
>> +static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 };
>> +static const u8 W83627EHF_REG_FAN_STEP_TIME[] = { 0x0E, 0x0F };
>> +
>
> For arrays with four values it's quite clear that there's one value for
> each fan, but for the arrays with only two values, it's not so clear.
> Some comments would be welcome.
OK
>
>> /*
>> * Conversions
>> */
>>
>> +/* 0 is PWM mode, output in ms */
>> +static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
>> +{
>> + return mode ? 100 * reg : 400 * reg;
>> +}
>
> Comment is wrong, PWM mode is 1 not 0.
Good catch.
>
>> +
>> +static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
>> +{
>> + return mode ? (msec + 50) / 100 : (msec + 200) / 400;
>> +}
>> +
>
> Missing check for overflow!
When it is bigger than 255... Will fix...
=>
> Initialization not needed.
OK
>
>>
>> mutex_lock(&data->update_lock);
>>
>> @@ -416,6 +471,43 @@ static struct w83627ehf_data *w83627ehf_
>> }
>> }
>>
>> + for (i = 0; i < 4; i++) {
>> + if (i != 1)
>> + tmp = w83627ehf_read_value(client,
>> + W83627EHF_REG_PWM_ENABLE[i]);
>> + data->pwm_mode[i] >> + ((tmp >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
>> + ? 0 : 1;
>> + if (data->pwm_enable[i] != 0 ||
>> + ((tmp >> W83627EHF_PWM_ENABLE_SHIFT[i]) & 3) != 0)
>> + data->pwm_enable[i] =
>> + ((tmp >> W83627EHF_PWM_ENABLE_SHIFT[i])
>> + & 3) + 1;
>
> I don't understand this test, can you please explain?
Well this is for that MODE 0 emulation. I think we agreed we can ignore the mode.
>
>> + data->pwm[i] = w83627ehf_read_value(client,
>> + W83627EHF_REG_PWM[i]);
>> + data->fan_min_output[i] = w83627ehf_read_value(client,
>> + W83627EHF_REG_FAN_MIN_OUTPUT[i]);
>> + data->fan_stop_time[i] = w83627ehf_read_value(client,
>> + W83627EHF_REG_FAN_STOP_TIME[i]);
>> + data->target_temp[i] >> + w83627ehf_read_value(client,
>> + W83627EHF_REG_TARGET_TEMP[i]) &
>> + (data->pwm_mode[i] = 1 ? 0x7f : 0xff);
>> + data->tolerance[i] >> + (w83627ehf_read_value(client,
>> + W83627EHF_REG_TOLERANCE[i]) >>
>> + (i = 1 ? 4 : 0)) & 0x0f;
>> + }
>
> Register 0x07 is read twice, this could be avoided with the same trick
> you use for register 0x04. I would also suggest that you make the
> temporary variable(s) local as you only use it (them) here. What about
> the following?
>
> for (i = 0; i < 4; i++) {
> int pwmcfg, tolerance;
>
> if (i != 1) {
> pwmcfg = w83627ehf_read_value(client,
> W83627EHF_REG_PWM_ENABLE[i]);
> tolerance = w83627ehf_read_value(client,
> W83627EHF_REG_TOLERANCE[i]);
> }
>
Ok looks good.
> data->pwm_mode[i] > ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
> ? 0 : 1;
>
> (... other register reads ...)
>
> data->tolerance[i] = (tolerance >> (i = 1 ? 4 : 0)) & 0x0f;
> }
>
>> +
>> + for (i = 0; i < 2; i++) {
>> + data->fan_max_output[i] = w83627ehf_read_value(client,
>> + W83627EHF_REG_FAN_MAX_OUTPUT[i]);
>> + data->fan_step[i] = w83627ehf_read_value(client,
>> + W83627EHF_REG_FAN_STEP[i]);
>> + data->fan_step_time[i] = w83627ehf_read_value(client,
>> + W83627EHF_REG_FAN_STEP_TIME[i]);
>> + }
>> +
>> /* Measured temperatures and limits */
>> data->temp1 = w83627ehf_read_value(client,
>> W83627EHF_REG_TEMP1);
>> @@ -777,6 +869,321 @@ static struct sensor_device_attribute sd
>> SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
>> };
>>
>> +#define show_pwm_reg(reg) \
>> +static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
>> + char *buf) \
>> +{ \
>> + struct w83627ehf_data *data = w83627ehf_update_device(dev); \
>> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);\
>> + int nr = sensor_attr->index;\
>> + return sprintf(buf,"%d\n", data->reg[nr]); \
>
> Missing space after comma. Your spaces before backslashes are also
> inconsistent.
Ok I will try to unify this. There are three authors of this patch so sometimes
it is quite hard to get all stuff right.
>
>> +}
>> +
>> +show_pwm_reg(pwm_mode)
>> +show_pwm_reg(pwm_enable)
>> +show_pwm_reg(pwm)
>> +
>> +static ssize_t
>> +store_pwm_mode(struct device *dev, struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct w83627ehf_data *data = w83627ehf_update_device(dev);
>
> No, you don't need to call update_device in a "store" sysfs callback.
Yes good catch.
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
>> + int nr = sensor_attr->index;
>> + u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 1);
>
> Using SENSOR_LIMIT here doesn't make sense, as we're not dealing with a
> range. Better return -EINVAL if value is neither 0 nor 1.
Well yes why not, maybe we should write a note to a docs?
>
>> + u16 reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
>> +
>> + if (data->pwm_mode[nr] != val) {
>> + mutex_lock(&data->update_lock);
>> + data->pwm_mode[nr] = val;
>> + reg = (reg & ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]));
>
> reg &= ..., or at least drop the extra pair of parentheses.
oOK
>
>> + if (!val)
>> + reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
>> + w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr],
>> + reg);
>> + mutex_unlock(&data->update_lock);
>> + }
>> + return count;
>> +}
>
> Locking is broken. You're doing a read-modify-write cycle, you must
> hold the lock before the read.
> You also must hold the lock when testing
> data->pwm_mode[nr] - even though I don't think you should test it at
> all, I see no reason to make the register write conditional.
The register writes are just time "savers" I think it Yuan did it also for the
new driver...
>
> Same comments apply to all your store callback functions, it seems.
I'm not a author of this code, I just did not catch it ...
>> +
>> +static ssize_t
>> +store_pwm(struct device *dev, struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct w83627ehf_data *data = w83627ehf_update_device(dev);
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
>> + int nr = sensor_attr->index;
>> + u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
>> +
>> + if (data->pwm_enable[nr] != 0 && data->pwm[nr] != val) {
>> + mutex_lock(&data->update_lock);
>> + data->pwm[nr] = val;
>> + w83627ehf_write_value(client, W83627EHF_REG_PWM[nr],
>> + val);
>> + mutex_unlock(&data->update_lock);
>> + }
>> + return count;
>> +}
>> +
>> +static ssize_t
>> +store_pwm_enable(struct device *dev, struct device_attribute *attr,
>> + const char *buf, size_t count)
>> +{
>> + struct w83627ehf_data *data = w83627ehf_update_device(dev);
>> + struct i2c_client *client = to_i2c_client(dev);
>> + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
>> + int nr = sensor_attr->index;
>> + u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 3);
>> + u16 reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
>> +
>> + if (data->pwm_enable[nr] != val) {
>> + if (!val) {
>> + store_pwm(dev, attr, "255", 3);
>> + mutex_lock(&data->update_lock);
>> + data->pwm_enable[nr] = val;
>> + }
>> + else {
>> + mutex_lock(&data->update_lock);
>> + data->pwm_enable[nr] = val;
>> + val--;
>> + }
>> + reg = (reg & ~(11 << W83627EHF_PWM_ENABLE_SHIFT[nr]));
>
> What is this "11" falling from the sky?
>
>> + reg |= val << W83627EHF_PWM_ENABLE_SHIFT[nr];
>> + w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr],
>> + reg);
>> + mutex_unlock(&data->update_lock);
>> + }
>> + return count;
>> +}
>
> I just realized that you are emulating pwm_enable = 0. I guess the chip
> doesn't support it? Then you don't want to implement it in the driver.
> This emulation makes your code much more complex with no gain at all.
> Drivers must implement what the chip support, they must NOT emulate
> features.
On the other hand we want consistent interface... I thought that either the file
could be present or not, but if present it MUST support 0 and 1 at least.
I think you told me that that -EINVAL should do it and I can revert the
emulation stuff back. But I think we should FIX this in docs so it cannot be a
matter of interpretation.
I will fix the minor stuff too.
> * use of w83627ehf_update_device
> * use of SENSORS_LIMIT
> * locking
> * conditional register writes
As for the conditional register writes. You just told me to save one read and
you dont want the conditional writes? hmmm?
> all around the place, then test the patch again, and then I'll review
> it again.
OK
Many thanks for the review. As I already told you we need some kind of wiki page
describing all those pitfalls so I can easily check the stuff and dont forget
about anything..
Anyone will help me?
Regards
Rudolf
next prev parent reply other threads:[~2006-06-14 12:48 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-06-06 18:37 [lm-sensors] [PATCH] W83627EHF driver update Rudolf Marek
2006-06-06 21:02 ` David Hubbard
2006-06-07 10:29 ` Jim Cromie
2006-06-07 20:51 ` David Hubbard
2006-06-07 21:00 ` Rudolf Marek
2006-06-07 21:06 ` Rudolf Marek
2006-06-07 22:13 ` Sylvain Jeaugey
2006-06-08 1:01 ` David Hubbard
2006-06-08 7:51 ` Sylvain Jeaugey
2006-06-12 16:30 ` Jean Delvare
2006-06-12 23:12 ` David Hubbard
2006-06-13 8:53 ` Jean Delvare
2006-06-13 16:03 ` David Hubbard
2006-06-14 12:48 ` Rudolf Marek [this message]
2006-06-14 15:06 ` Jean Delvare
2006-06-14 15:14 ` Rudolf Marek
2006-06-14 15:50 ` Jean Delvare
2006-06-14 21:29 ` Rudolf Marek
2006-06-15 14:55 ` David Hubbard
2006-06-15 15:20 ` Sylvain Jeaugey
2006-06-16 4:29 ` David Hubbard
2006-06-16 21:33 ` Rudolf Marek
2006-06-19 15:53 ` David Hubbard
2006-06-20 12:41 ` Jean Delvare
2006-06-21 15:10 ` David Hubbard
2006-06-24 16:42 ` Rudolf Marek
2006-06-25 14:04 ` Jean Delvare
2006-06-25 16:00 ` Rudolf Marek
2006-06-26 19:33 ` Jean Delvare
2006-06-26 20:34 ` Rudolf Marek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=449005B8.6090908@sh.cvut.cz \
--to=r.marek@sh.cvut.cz \
--cc=lm-sensors@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.