aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAxel Lin <axel.lin@ingics.com>2014-08-05 20:02:44 -0400
committerGuenter Roeck <linux@roeck-us.net>2014-08-05 22:40:15 -0400
commitd58e47d787c09fe5c61af3c6ce7d784762f29c3d (patch)
tree8b33435a10a87f535908ec344b38d25d3e960fdc
parent539a719f9b90f37b934b90ad52be646b9e74a9f6 (diff)
hwmon: (dme1737) 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. Avoid auto-conversion from long to int to fix the problem. Voltage limits, fan minimum speed, pwm frequency, pwm ramp rate, and other attributes have the same problem, fix them as well. Zone temperature limits are signed, but were cached as u8, causing unepected values to be reported for negative temperatures. Cache as s8 to fix the problem. vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin <axel.lin@ingics.com> [Guenter Roeck: Fix zone temperature cache] Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/dme1737.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 4ae3fff13f44..bea0a344fab5 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -247,8 +247,8 @@ struct dme1737_data {
247 u8 pwm_acz[3]; 247 u8 pwm_acz[3];
248 u8 pwm_freq[6]; 248 u8 pwm_freq[6];
249 u8 pwm_rr[2]; 249 u8 pwm_rr[2];
250 u8 zone_low[3]; 250 s8 zone_low[3];
251 u8 zone_abs[3]; 251 s8 zone_abs[3];
252 u8 zone_hyst[2]; 252 u8 zone_hyst[2];
253 u32 alarms; 253 u32 alarms;
254}; 254};
@@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, int nominal, int res)
277 return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2)); 277 return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2));
278} 278}
279 279
280static inline int IN_TO_REG(int val, int nominal) 280static inline int IN_TO_REG(long val, int nominal)
281{ 281{
282 return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255); 282 return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255);
283} 283}
@@ -293,7 +293,7 @@ static inline int TEMP_FROM_REG(int reg, int res)
293 return (reg * 1000) >> (res - 8); 293 return (reg * 1000) >> (res - 8);
294} 294}
295 295
296static inline int TEMP_TO_REG(int val) 296static inline int TEMP_TO_REG(long val)
297{ 297{
298 return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127); 298 return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127);
299} 299}
@@ -308,7 +308,7 @@ static inline int TEMP_RANGE_FROM_REG(int reg)
308 return TEMP_RANGE[(reg >> 4) & 0x0f]; 308 return TEMP_RANGE[(reg >> 4) & 0x0f];
309} 309}
310 310
311static int TEMP_RANGE_TO_REG(int val, int reg) 311static int TEMP_RANGE_TO_REG(long val, int reg)
312{ 312{
313 int i; 313 int i;
314 314
@@ -331,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int reg, int ix)
331 return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000; 331 return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000;
332} 332}
333 333
334static inline int TEMP_HYST_TO_REG(int val, int ix, int reg) 334static inline int TEMP_HYST_TO_REG(long val, int ix, int reg)
335{ 335{
336 int hyst = clamp_val((val + 500) / 1000, 0, 15); 336 int hyst = clamp_val((val + 500) / 1000, 0, 15);
337 337
@@ -347,7 +347,7 @@ static inline int FAN_FROM_REG(int reg, int tpc)
347 return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg; 347 return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg;
348} 348}
349 349
350static inline int FAN_TO_REG(int val, int tpc) 350static inline int FAN_TO_REG(long val, int tpc)
351{ 351{
352 if (tpc) { 352 if (tpc) {
353 return clamp_val(val / tpc, 0, 0xffff); 353 return clamp_val(val / tpc, 0, 0xffff);
@@ -379,7 +379,7 @@ static inline int FAN_TYPE_FROM_REG(int reg)
379 return (edge > 0) ? 1 << (edge - 1) : 0; 379 return (edge > 0) ? 1 << (edge - 1) : 0;
380} 380}
381 381
382static inline int FAN_TYPE_TO_REG(int val, int reg) 382static inline int FAN_TYPE_TO_REG(long val, int reg)
383{ 383{
384 int edge = (val == 4) ? 3 : val; 384 int edge = (val == 4) ? 3 : val;
385 385
@@ -402,7 +402,7 @@ static int FAN_MAX_FROM_REG(int reg)
402 return 1000 + i * 500; 402 return 1000 + i * 500;
403} 403}
404 404
405static int FAN_MAX_TO_REG(int val) 405static int FAN_MAX_TO_REG(long val)
406{ 406{
407 int i; 407 int i;
408 408
@@ -460,7 +460,7 @@ static inline int PWM_ACZ_FROM_REG(int reg)
460 return acz[(reg >> 5) & 0x07]; 460 return acz[(reg >> 5) & 0x07];
461} 461}
462 462
463static inline int PWM_ACZ_TO_REG(int val, int reg) 463static inline int PWM_ACZ_TO_REG(long val, int reg)
464{ 464{
465 int acz = (val == 4) ? 2 : val - 1; 465 int acz = (val == 4) ? 2 : val - 1;
466 466
@@ -476,7 +476,7 @@ static inline int PWM_FREQ_FROM_REG(int reg)
476 return PWM_FREQ[reg & 0x0f]; 476 return PWM_FREQ[reg & 0x0f];
477} 477}
478 478
479static int PWM_FREQ_TO_REG(int val, int reg) 479static int PWM_FREQ_TO_REG(long val, int reg)
480{ 480{
481 int i; 481 int i;
482 482
@@ -510,7 +510,7 @@ static inline int PWM_RR_FROM_REG(int reg, int ix)
510 return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0; 510 return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0;
511} 511}
512 512
513static int PWM_RR_TO_REG(int val, int ix, int reg) 513static int PWM_RR_TO_REG(long val, int ix, int reg)
514{ 514{
515 int i; 515 int i;
516 516
@@ -528,7 +528,7 @@ static inline int PWM_RR_EN_FROM_REG(int reg, int ix)
528 return PWM_RR_FROM_REG(reg, ix) ? 1 : 0; 528 return PWM_RR_FROM_REG(reg, ix) ? 1 : 0;
529} 529}
530 530
531static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg) 531static inline int PWM_RR_EN_TO_REG(long val, int ix, int reg)
532{ 532{
533 int en = (ix == 1) ? 0x80 : 0x08; 533 int en = (ix == 1) ? 0x80 : 0x08;
534 534
@@ -1481,13 +1481,16 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
1481 const char *buf, size_t count) 1481 const char *buf, size_t count)
1482{ 1482{
1483 struct dme1737_data *data = dev_get_drvdata(dev); 1483 struct dme1737_data *data = dev_get_drvdata(dev);
1484 long val; 1484 unsigned long val;
1485 int err; 1485 int err;
1486 1486
1487 err = kstrtol(buf, 10, &val); 1487 err = kstrtoul(buf, 10, &val);
1488 if (err) 1488 if (err)
1489 return err; 1489 return err;
1490 1490
1491 if (val > 255)
1492 return -EINVAL;
1493
1491 data->vrm = val; 1494 data->vrm = val;
1492 return count; 1495 return count;
1493} 1496}