From 5b963089161b8fb244889c972edf553b9d737545 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 5 Aug 2014 10:08:31 +0800 Subject: hwmon: (lm92) 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. The hysteresis temperature range depends on the value of data->temp[attr->index], since val is subtracted from it. Use a wider clamp, [-120000, 220000] should do to cover the possible range. Also add missing TEMP_TO_REG() on writes into cached hysteresis value. Also uses clamp_val to simplify the code a bit. Signed-off-by: Axel Lin [Guenter Roeck: Fixed double TEMP_TO_REG on hysteresis updates] Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/lm92.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index d2060e245ff5..cfaf70b9cba7 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -74,12 +74,9 @@ static inline int TEMP_FROM_REG(s16 reg) return reg / 8 * 625 / 10; } -static inline s16 TEMP_TO_REG(int val) +static inline s16 TEMP_TO_REG(long val) { - if (val <= -60000) - return -60000 * 10 / 625 * 8; - if (val >= 160000) - return 160000 * 10 / 625 * 8; + val = clamp_val(val, -60000, 160000); return val * 10 / 625 * 8; } @@ -206,10 +203,12 @@ static ssize_t set_temp_hyst(struct device *dev, if (err) return err; + val = clamp_val(val, -120000, 220000); mutex_lock(&data->update_lock); - data->temp[t_hyst] = TEMP_FROM_REG(data->temp[attr->index]) - val; + data->temp[t_hyst] = + TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val); i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST, - TEMP_TO_REG(data->temp[t_hyst])); + data->temp[t_hyst]); mutex_unlock(&data->update_lock); return count; } -- cgit v1.2.3 From e981429557cbe10c780fab1c1a237cb832757652 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 5 Aug 2014 09:59:49 +0800 Subject: hwmon: (ads1015) Fix out-of-bounds array access Current code uses data_rate as array index in ads1015_read_adc() and uses pga as array index in ads1015_reg_to_mv, so we must make sure both data_rate and pga settings are in valid value range. Return -EINVAL if the setting is out-of-range. Signed-off-by: Axel Lin Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/ads1015.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 22e0c926989d..126516414c11 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -212,6 +212,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) dev_err(&client->dev, "invalid gain on %s\n", node->full_name); + return -EINVAL; } } @@ -222,6 +223,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) dev_err(&client->dev, "invalid data_rate on %s\n", node->full_name); + return -EINVAL; } } -- cgit v1.2.3 From 539a719f9b90f37b934b90ad52be646b9e74a9f6 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 5 Aug 2014 09:54:04 -0700 Subject: hwmon: (emc6w201) Fix temperature limit range Temperature limit range is [-127, 127], not [-127, 128]. The wrong range caused a bad limit to be written into the chip if the limit was set to a value of 128 degrees C or above. Also use DIV_ROUND_CLOSEST instead of a plain divide operation to reduce the rounding error when writing temperature limits. Signed-off-by: Guenter Roeck Reviewed-by: Jean Delvare --- drivers/hwmon/emc6w201.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index e87da902f3ae..ada90716448d 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c @@ -252,12 +252,12 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, if (err < 0) return err; - val /= 1000; + val = DIV_ROUND_CLOSEST(val, 1000); reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr) : EMC6W201_REG_TEMP_HIGH(nr); mutex_lock(&data->update_lock); - data->temp[sf][nr] = clamp_val(val, -127, 128); + data->temp[sf][nr] = clamp_val(val, -127, 127); err = emc6w201_write8(client, reg, data->temp[sf][nr]); mutex_unlock(&data->update_lock); -- cgit v1.2.3 From d58e47d787c09fe5c61af3c6ce7d784762f29c3d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:02:44 +0800 Subject: 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 [Guenter Roeck: Fix zone temperature cache] Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/dme1737.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/hwmon') 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 { u8 pwm_acz[3]; u8 pwm_freq[6]; u8 pwm_rr[2]; - u8 zone_low[3]; - u8 zone_abs[3]; + s8 zone_low[3]; + s8 zone_abs[3]; u8 zone_hyst[2]; u32 alarms; }; @@ -277,7 +277,7 @@ static inline int IN_FROM_REG(int reg, int nominal, int res) return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2)); } -static inline int IN_TO_REG(int val, int nominal) +static inline int IN_TO_REG(long val, int nominal) { return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255); } @@ -293,7 +293,7 @@ static inline int TEMP_FROM_REG(int reg, int res) return (reg * 1000) >> (res - 8); } -static inline int TEMP_TO_REG(int val) +static inline int TEMP_TO_REG(long val) { return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127); } @@ -308,7 +308,7 @@ static inline int TEMP_RANGE_FROM_REG(int reg) return TEMP_RANGE[(reg >> 4) & 0x0f]; } -static int TEMP_RANGE_TO_REG(int val, int reg) +static int TEMP_RANGE_TO_REG(long val, int reg) { int i; @@ -331,7 +331,7 @@ static inline int TEMP_HYST_FROM_REG(int reg, int ix) return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000; } -static inline int TEMP_HYST_TO_REG(int val, int ix, int reg) +static inline int TEMP_HYST_TO_REG(long val, int ix, int reg) { int hyst = clamp_val((val + 500) / 1000, 0, 15); @@ -347,7 +347,7 @@ static inline int FAN_FROM_REG(int reg, int tpc) return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg; } -static inline int FAN_TO_REG(int val, int tpc) +static inline int FAN_TO_REG(long val, int tpc) { if (tpc) { return clamp_val(val / tpc, 0, 0xffff); @@ -379,7 +379,7 @@ static inline int FAN_TYPE_FROM_REG(int reg) return (edge > 0) ? 1 << (edge - 1) : 0; } -static inline int FAN_TYPE_TO_REG(int val, int reg) +static inline int FAN_TYPE_TO_REG(long val, int reg) { int edge = (val == 4) ? 3 : val; @@ -402,7 +402,7 @@ static int FAN_MAX_FROM_REG(int reg) return 1000 + i * 500; } -static int FAN_MAX_TO_REG(int val) +static int FAN_MAX_TO_REG(long val) { int i; @@ -460,7 +460,7 @@ static inline int PWM_ACZ_FROM_REG(int reg) return acz[(reg >> 5) & 0x07]; } -static inline int PWM_ACZ_TO_REG(int val, int reg) +static inline int PWM_ACZ_TO_REG(long val, int reg) { int acz = (val == 4) ? 2 : val - 1; @@ -476,7 +476,7 @@ static inline int PWM_FREQ_FROM_REG(int reg) return PWM_FREQ[reg & 0x0f]; } -static int PWM_FREQ_TO_REG(int val, int reg) +static int PWM_FREQ_TO_REG(long val, int reg) { int i; @@ -510,7 +510,7 @@ static inline int PWM_RR_FROM_REG(int reg, int ix) return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0; } -static int PWM_RR_TO_REG(int val, int ix, int reg) +static int PWM_RR_TO_REG(long val, int ix, int reg) { int i; @@ -528,7 +528,7 @@ static inline int PWM_RR_EN_FROM_REG(int reg, int ix) return PWM_RR_FROM_REG(reg, ix) ? 1 : 0; } -static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg) +static inline int PWM_RR_EN_TO_REG(long val, int ix, int reg) { int en = (ix == 1) ? 0x80 : 0x08; @@ -1481,13 +1481,16 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct dme1737_data *data = dev_get_drvdata(dev); - long val; + unsigned long val; int err; - err = kstrtol(buf, 10, &val); + err = kstrtoul(buf, 10, &val); if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From eeeafd384f2f1709d48ba00c807e86d4890cf6b5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:06:50 +0800 Subject: hwmon: (hih6130) Fix missing hih6130->write_length setting The hih6130->write_length setting was accidently removed by commit ebc6b9383f3e "hwmon: (hih6130) Convert to devm_hwmon_device_register_with_groups", fix it. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/hih6130.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c index 0e01c4e13e33..7b73d2002d3e 100644 --- a/drivers/hwmon/hih6130.c +++ b/drivers/hwmon/hih6130.c @@ -238,6 +238,9 @@ static int hih6130_probe(struct i2c_client *client, hih6130->client = client; mutex_init(&hih6130->lock); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK)) + hih6130->write_length = 1; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, hih6130, hih6130_groups); -- cgit v1.2.3 From 9c8ae7287a51d0fdc2e3547068afccfc4880e902 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:19:43 +0800 Subject: hwmon: (adm1025) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/adm1025.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index d3d0e8cf27b4..d6c767ace916 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -382,6 +382,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From a4461647f66c6e12676f9e9ce43c1578a2ba02a1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:20:45 +0800 Subject: hwmon: (adm1026) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/adm1026.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index ca8430f92564..e67b9a50ac7c 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -1085,6 +1085,9 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From db59ac434230c2d6c051bb314f320ad977e6841d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:21:49 +0800 Subject: hwmon: (asb100) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/asb100.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index f96063680e58..272fcc837ecc 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -510,6 +510,10 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, err = kstrtoul(buf, 10, &val); if (err) return err; + + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From fa642d9d6e502fbdbd1122a6a247c8ad17063a29 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:24:00 +0800 Subject: hwmon: (lm87) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/lm87.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index ba1d83d48056..a5e295826aea 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -617,6 +617,10 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, err = kstrtoul(buf, 10, &val); if (err) return err; + + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From 5e3b5610f921701b235fc9a1bb17c040224bd76e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:24:54 +0800 Subject: hwmon: (pc87360) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/pc87360.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 988181e4cfcd..145f674c1d87 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -615,6 +615,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From 5c570b9573ecabf3ffc9af7f03daa088f2466d7b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:25:44 +0800 Subject: hwmon: (vt1211) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/vt1211.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 344b22ec2553..3ea57c3504e2 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -879,6 +879,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; -- cgit v1.2.3 From 970255b75d0b54e457091182a7ae3a188ac0c346 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:27:11 +0800 Subject: hwmon: (w83627hf) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/w83627hf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index c1726be3654c..2f55973a8c4c 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -820,6 +820,9 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf err = kstrtoul(buf, 10, &val); if (err) return err; + + if (val > 255) + return -EINVAL; data->vrm = val; return count; -- cgit v1.2.3 From fe04f24b831cf384eda9798e1af642b96ca19d29 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:28:02 +0800 Subject: hwmon: (w83791d) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/w83791d.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index cb3765fec98c..001df856913f 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -1181,6 +1181,9 @@ static ssize_t store_vrm_reg(struct device *dev, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From 2aeee04df8e0ea4d5b91da630687af1a1d93c941 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 6 Aug 2014 08:28:46 +0800 Subject: hwmon: (w83793) Fix vrm write operation vrm is an u8, so the written value needs to be limited to [0, 255]. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/w83793.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 9d63d71214ca..816aa6caf5d5 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -353,6 +353,9 @@ store_vrm(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -- cgit v1.2.3 From 6ddd855c13bcd324a2d9756134e6b57c659cfde6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 10 Aug 2014 17:42:01 +0800 Subject: hwmon: (tmp103) Remove duplicate test for I2C_FUNC_SMBUS_BYTE_DATA functionality Since commit b42261078a91 ("regmap: i2c: fallback to SMBus if the adapter does not support standard I2C"), regmap-i2c will check the I2C_FUNC_SMBUS_[BYTE|WORD]_DATA functionality based on the regmap_config setting if the adapter does not support standard I2C. So remove the I2C_FUNC_SMBUS_BYTE_DATA functionality check in the driver code. Signed-off-by: Axel Lin Signed-off-by: Guenter Roeck --- drivers/hwmon/tmp103.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index c74d2da389d9..e42964f07f67 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -131,13 +131,6 @@ static int tmp103_probe(struct i2c_client *client, struct regmap *regmap; int ret; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, - "adapter doesn't support SMBus byte transactions\n"); - return -ENODEV; - } - regmap = devm_regmap_init_i2c(client, &tmp103_regmap_config); if (IS_ERR(regmap)) { dev_err(dev, "failed to allocate register map\n"); -- cgit v1.2.3