diff options
author | Axel Lin <axel.lin@ingics.com> | 2014-07-31 10:58:04 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2014-07-31 12:41:46 -0400 |
commit | 99765db299f0b07093318395f789a716ed23fc95 (patch) | |
tree | 0b61ca3e3fed886c05bfe4b0b51e332268e488a2 | |
parent | cf44819c98db11163f58f08b822d626c7a8f5188 (diff) |
hwmon: (lm77) Prevent overflow problem when writing large limits
On platforms with sizeof(int) < sizeof(long), writing a temperature
limit larger than MAXINT will result in unpredictable limit values
written to the chip.
Clamp the input values to the supported limits first to fix the problem.
For set_temp_hyst:
As Guenter pointed out that the temperature is read as unsigned and stored in
an unsigned long. This is wrong; nothing in the datasheet suggests that the
value (the absolute temperature) must be positive.
So change it to signed.
Signed-off-by: Axel Lin <axel.lin@ingics.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/hwmon/lm77.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 5ceb443b938d..69b05cc2f60e 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c | |||
@@ -80,8 +80,7 @@ struct lm77_data { | |||
80 | */ | 80 | */ |
81 | static inline s16 LM77_TEMP_TO_REG(int temp) | 81 | static inline s16 LM77_TEMP_TO_REG(int temp) |
82 | { | 82 | { |
83 | int ntemp = clamp_val(temp, LM77_TEMP_MIN, LM77_TEMP_MAX); | 83 | return (temp / 500) * 8; |
84 | return (ntemp / 500) * 8; | ||
85 | } | 84 | } |
86 | 85 | ||
87 | static inline int LM77_TEMP_FROM_REG(s16 reg) | 86 | static inline int LM77_TEMP_FROM_REG(s16 reg) |
@@ -175,6 +174,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, | |||
175 | if (err) | 174 | if (err) |
176 | return err; | 175 | return err; |
177 | 176 | ||
177 | val = clamp_val(val, LM77_TEMP_MIN, LM77_TEMP_MAX); | ||
178 | mutex_lock(&data->update_lock); | 178 | mutex_lock(&data->update_lock); |
179 | data->temp[nr] = val; | 179 | data->temp[nr] = val; |
180 | lm77_write_value(client, temp_regs[nr], LM77_TEMP_TO_REG(val)); | 180 | lm77_write_value(client, temp_regs[nr], LM77_TEMP_TO_REG(val)); |
@@ -192,15 +192,16 @@ static ssize_t set_temp_hyst(struct device *dev, | |||
192 | { | 192 | { |
193 | struct lm77_data *data = dev_get_drvdata(dev); | 193 | struct lm77_data *data = dev_get_drvdata(dev); |
194 | struct i2c_client *client = data->client; | 194 | struct i2c_client *client = data->client; |
195 | unsigned long val; | 195 | long val; |
196 | int err; | 196 | int err; |
197 | 197 | ||
198 | err = kstrtoul(buf, 10, &val); | 198 | err = kstrtol(buf, 10, &val); |
199 | if (err) | 199 | if (err) |
200 | return err; | 200 | return err; |
201 | 201 | ||
202 | mutex_lock(&data->update_lock); | 202 | mutex_lock(&data->update_lock); |
203 | data->temp[t_hyst] = data->temp[t_crit] - val; | 203 | val = clamp_val(data->temp[t_crit] - val, LM77_TEMP_MIN, LM77_TEMP_MAX); |
204 | data->temp[t_hyst] = val; | ||
204 | lm77_write_value(client, LM77_REG_TEMP_HYST, | 205 | lm77_write_value(client, LM77_REG_TEMP_HYST, |
205 | LM77_TEMP_TO_REG(data->temp[t_hyst])); | 206 | LM77_TEMP_TO_REG(data->temp[t_hyst])); |
206 | mutex_unlock(&data->update_lock); | 207 | mutex_unlock(&data->update_lock); |