GIT 0beacae31db0d2e38a9137c3e4958f091690a87d git://lm-sensors.org/kernel/mhoffman/hwmon-2.6.git#testing a56a964d2081c9fc38432034f7d7d47f3d8be3e0 commit a56a964d2081c9fc38432034f7d7d47f3d8be3e0 Author: Mark M. Hoffman Date: Mon Mar 3 23:35:52 2008 -0500 hwmon: fix common race conditions, batch 1 Most hwmon drivers have one or more race conditions that could cause the driver to display incorrect data; in the absolute worst case, these races could allow divide-by-zero/OOPS. The most common of these involves a race between setting a fan divider and displaying the fan data (RPMs). This patch fixes these race conditions by taking the update lock (or equivalent) as necessary. Signed-off-by: Mark M. Hoffman commit d9489e6517209057e92a33cd688bd66ad8c7eb10 Author: Mark M. Hoffman Date: Thu Mar 6 08:41:09 2008 -0500 hwmon: (adt7473) minor cleanup / refactoring Acked-by: Darrick J. Wong Signed-off-by: Mark M. Hoffman commit 9cb893240e7587261999c4f856003f11c7bb3dd4 Author: Mark M. Hoffman Date: Tue Feb 26 08:48:49 2008 -0500 hwmon: (asb100) Remove some dead code Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman commit a617156848e99b93660f0da08fc401661d5cddbf Author: Jean Delvare Date: Tue Feb 19 12:42:58 2008 +0100 hwmon: (lm75) Fix an incorrect comment High-byte first is not opposite to the usual practice - that's what almost all hardware monitoring drivers do. It is opposite to the SMBus standard though. Also delete a duplicate comment. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman commit c8a6f59c321fc921d05de79d13366ec4b902d552 Author: Jean Delvare Date: Tue Feb 12 11:25:07 2008 +0100 hwmon: (w83793) VID and VRM handling cleanups * Rework the device initialization function so as to read the "Multi-Function Pin Control" register (0x58) once instead of twice. I2C transactions aren't cheap so this speeds up the driver loading. * Only create the "vrm" attribute if at least one VID value is available. Signed-off-by: Jean Delvare Cc: Gong Jun Acked-by: Rudolf Marek Signed-off-by: Mark M. Hoffman commit e6c1d870730d7aeb2ea222cbb60c64a7b51558ba Author: Jean Delvare Date: Tue Feb 12 11:17:26 2008 +0100 hwmon: (w83l785ts) Don't ask the user to report failures There's nothing we can do about read errors on the W83L785TS-S, so don't ask the user to report them. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman commit 809307768cb177621b8f45f87fa840993ca4cb60 Author: Craig Kelley Date: Fri Feb 29 10:24:44 2008 -0700 hwmon: (smsc47b397) add a new chip id (0x8c) Added a new ID (0x8c) for the smsc47b397 hardware monitor driver. This ID is used by HP in, at least, their dc7700 line. Signed-off-by: Craig Kelley Signed-off-by: Mark M. Hoffman commit 28162680f2d5c968a2a611e51dc617818e652f53 Author: Jean Delvare Date: Wed Feb 13 08:30:33 2008 -0500 hwmon: Check for ACPI resource conflicts in hwmon drivers Check for ACPI resource conflicts in hwmon drivers. I've included all Super-I/O and PCI drivers. I've voluntarily left out: * Laptop specific and vendor-specific drivers: if they conflicted on any system, this would pretty much mean that they conflict on all systems, and we would know by now. * Legacy ISA drivers (lm78 and w83781d): they only support chips found on old designs were ACPI either wasn't supported or didn't deal with thermal management. * Drivers accessing the I/O resources indirectly (e.g. through SMBus): the check will be added where it belongs, i.e. in the bus drivers. Signed-off-by: Jean Delvare Signed-off-by: Thomas Renninger Cc: Len Brown Signed-off-by: Andrew Morton Signed-off-by: Mark M. Hoffman Documentation/hwmon/w83l785ts | 3 +- drivers/hwmon/adm1026.c | 22 ++++++--- drivers/hwmon/adm1029.c | 30 ++++++++----- drivers/hwmon/adm1031.c | 20 ++++++-- drivers/hwmon/adm9240.c | 20 ++++++--- drivers/hwmon/adt7470.c | 40 ++++++++++------- drivers/hwmon/adt7473.c | 99 ++++++++++++++++++++++------------------ drivers/hwmon/asb100.c | 20 +++++--- drivers/hwmon/dme1737.c | 5 ++ drivers/hwmon/f71805f.c | 5 ++ drivers/hwmon/f71882fg.c | 5 ++ drivers/hwmon/it87.c | 5 ++ drivers/hwmon/lm75.c | 5 +-- drivers/hwmon/pc87360.c | 6 +++ drivers/hwmon/pc87427.c | 5 ++ drivers/hwmon/sis5595.c | 5 ++ drivers/hwmon/smsc47b397.c | 22 ++++++++- drivers/hwmon/smsc47m1.c | 5 ++ drivers/hwmon/via686a.c | 5 ++ drivers/hwmon/vt1211.c | 5 ++ drivers/hwmon/vt8231.c | 5 ++ drivers/hwmon/w83627ehf.c | 6 +++ drivers/hwmon/w83627hf.c | 5 ++ drivers/hwmon/w83793.c | 26 ++++++----- drivers/hwmon/w83l785ts.c | 4 +- 25 files changed, 257 insertions(+), 121 deletions(-) diff --git a/Documentation/hwmon/w83l785ts b/Documentation/hwmon/w83l785ts index 1841ced..bd1fa9d 100644 --- a/Documentation/hwmon/w83l785ts +++ b/Documentation/hwmon/w83l785ts @@ -33,7 +33,8 @@ Known Issues ------------ On some systems (Asus), the BIOS is known to interfere with the driver -and cause read errors. The driver will retry a given number of times +and cause read errors. Or maybe the W83L785TS-S chip is simply unreliable, +we don't really know. The driver will retry a given number of times (5 by default) and then give up, returning the old value (or 0 if there is no old value). It seems to work well enough so that you should not notice anything. Thanks to James Bolt for helping test this feature. diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 904c6ce..ff1fded 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -838,20 +838,26 @@ static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_m static ssize_t show_fan(struct device *dev, struct device_attribute *attr, char *buf) { - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; + int nr = to_sensor_dev_attr(attr)->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - data->fan_div[nr])); + int val; + + mutex_lock(&data->update_lock); + val = FAN_FROM_REG(data->fan[nr], data->fan_div[nr]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, char *buf) { - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; + int nr = to_sensor_dev_attr(attr)->index; struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - data->fan_div[nr])); + int val; + + mutex_lock(&data->update_lock); + val = FAN_FROM_REG(data->fan_min[nr], data->fan_div[nr]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 2c6608d..8cd6c5a 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -165,27 +165,35 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf) static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adm1029_data *data = adm1029_update_device(dev); u16 val; - if (data->fan[attr->index] == 0 || data->fan_div[attr->index] == 0 - || data->fan[attr->index] == 255) { - return sprintf(buf, "0\n"); - } - val = 1880 * 120 / DIV_FROM_REG(data->fan_div[attr->index]) - / data->fan[attr->index]; + mutex_lock(&data->update_lock); + if (data->fan[index] == 0 || data->fan_div[index] == 0 + || data->fan[index] == 255) + val = 0; + else + val = 1880 * 120 / DIV_FROM_REG(data->fan_div[index]) + / data->fan[index]; + mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", val); } static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adm1029_data *data = adm1029_update_device(dev); - if (data->fan_div[attr->index] == 0) - return sprintf(buf, "0\n"); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); + int val; + + mutex_lock(&data->update_lock); + if (data->fan_div[index] == 0) + val = 0; + else + val = DIV_FROM_REG(data->fan_div[index]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t set_fan_div(struct device *dev, diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 2bffcab..c88187a 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -466,8 +466,10 @@ static ssize_t show_fan(struct device *dev, struct adm1031_data *data = adm1031_update_device(dev); int value; + mutex_lock(&data->update_lock); value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; + mutex_unlock(&data->update_lock); return sprintf(buf, "%d\n", value); } @@ -483,9 +485,13 @@ static ssize_t show_fan_min(struct device *dev, { int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - FAN_FROM_REG(data->fan_min[nr], - FAN_DIV_FROM_REG(data->fan_div[nr]))); + int value; + + mutex_lock(&data->update_lock); + value = FAN_FROM_REG(data->fan_min[nr], + FAN_DIV_FROM_REG(data->fan_div[nr])); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); } static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -567,11 +573,15 @@ static ssize_t show_temp(struct device *dev, { int nr = to_sensor_dev_attr(attr)->index; struct adm1031_data *data = adm1031_update_device(dev); - int ext; + int ext, val; + + mutex_lock(&data->update_lock); ext = nr == 0 ? ((data->ext_temp[nr] >> 6) & 0x3) * 2 : (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); - return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); + val = TEMP_FROM_REG_EXT(data->temp[nr], ext); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 149ef25..f43986d 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -290,19 +290,27 @@ vin(5); static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index], - 1 << data->fan_div[attr->index])); + int val; + + mutex_lock(&data->update_lock); + val = FAN_FROM_REG(data->fan[index], 1 << data->fan_div[index]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index], - 1 << data->fan_div[attr->index])); + int val; + + mutex_lock(&data->update_lock); + val = FAN_FROM_REG(data->fan_min[index], 1 << data->fan_div[index]); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_fan_div(struct device *dev, diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 6b5325f..4573855 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -402,14 +402,17 @@ static ssize_t show_fan_max(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adt7470_data *data = adt7470_update_device(dev); + int val; - if (FAN_DATA_VALID(data->fan_max[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan_max[attr->index])); + mutex_lock(&data->lock); + if (FAN_DATA_VALID(data->fan_max[index])) + val = FAN_PERIOD_TO_RPM(data->fan_max[index]); else - return sprintf(buf, "0\n"); + val = 0; + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); } static ssize_t set_fan_max(struct device *dev, @@ -437,14 +440,16 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adt7470_data *data = adt7470_update_device(dev); - - if (FAN_DATA_VALID(data->fan_min[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan_min[attr->index])); + int val; + mutex_lock(&data->lock); + if (FAN_DATA_VALID(data->fan_min[index])) + val = FAN_PERIOD_TO_RPM(data->fan_min[index]); else - return sprintf(buf, "0\n"); + val = 0; + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); } static ssize_t set_fan_min(struct device *dev, @@ -471,14 +476,17 @@ static ssize_t set_fan_min(struct device *dev, static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adt7470_data *data = adt7470_update_device(dev); + int val; - if (FAN_DATA_VALID(data->fan[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan[attr->index])); + mutex_lock(&data->lock); + if (FAN_DATA_VALID(data->fan[index])) + val = FAN_PERIOD_TO_RPM(data->fan[index]); else - return sprintf(buf, "0\n"); + val = 0; + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_force_pwm_max(struct device *dev, diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c index 9587869..28af6cc 100644 --- a/drivers/hwmon/adt7473.c +++ b/drivers/hwmon/adt7473.c @@ -211,6 +211,9 @@ static inline int adt7473_write_word_data(struct i2c_client *client, u8 reg, static void adt7473_init_client(struct i2c_client *client) { + struct adt7473_data *data = i2c_get_clientdata(client); + u8 cfg; + int reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG1); if (!(reg & ADT7473_CFG1_READY)) { @@ -220,6 +223,18 @@ static void adt7473_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, ADT7473_REG_CFG1, reg | ADT7473_CFG1_START); } + + /* Determine temperature encoding */ + cfg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG5); + data->temp_twos_complement = (cfg & ADT7473_CFG5_TEMP_TWOS); + + /* + * What does this do? it implies a variable temperature sensor + * offset, but the datasheet doesn't say anything about this bit + * and other parts of the datasheet imply that "offset64" mode + * means that you shift temp values by -64 if the above bit was set. + */ + data->temp_offset = (cfg & ADT7473_CFG5_TEMP_OFFSET); } static struct adt7473_data *adt7473_update_device(struct device *dev) @@ -227,7 +242,6 @@ static struct adt7473_data *adt7473_update_device(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); unsigned long local_jiffies = jiffies; - u8 cfg; int i; mutex_lock(&data->lock); @@ -240,18 +254,6 @@ static struct adt7473_data *adt7473_update_device(struct device *dev) data->volt[i] = i2c_smbus_read_byte_data(client, ADT7473_REG_VOLT(i)); - /* Determine temperature encoding */ - cfg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG5); - data->temp_twos_complement = (cfg & ADT7473_CFG5_TEMP_TWOS); - - /* - * What does this do? it implies a variable temperature sensor - * offset, but the datasheet doesn't say anything about this bit - * and other parts of the datasheet imply that "offset64" mode - * means that you shift temp values by -64 if the above bit was set. - */ - data->temp_offset = (cfg & ADT7473_CFG5_TEMP_OFFSET); - for (i = 0; i < ADT7473_TEMP_COUNT; i++) data->temp[i] = i2c_smbus_read_byte_data(client, ADT7473_REG_TEMP(i)); @@ -422,18 +424,14 @@ static ssize_t show_volt(struct device *dev, struct device_attribute *devattr, * number in the range -128 to 127, or as an unsigned number that must * be offset by 64. */ -static int decode_temp(struct adt7473_data *data, u8 raw) +static int decode_temp(u8 twos_complement, u8 raw) { - if (data->temp_twos_complement) - return (s8)raw; - return raw - 64; + return twos_complement ? (s8)raw : raw - 64; } -static u8 encode_temp(struct adt7473_data *data, int cooked) +static u8 encode_temp(u8 twos_complement, int cooked) { - if (data->temp_twos_complement) - return (cooked & 0xFF); - return cooked + 64; + return twos_complement ? cooked & 0xFF : cooked + 64; } static ssize_t show_temp_min(struct device *dev, @@ -442,8 +440,9 @@ static ssize_t show_temp_min(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7473_data *data = adt7473_update_device(dev); - return sprintf(buf, "%d\n", - 1000 * decode_temp(data, data->temp_min[attr->index])); + return sprintf(buf, "%d\n", 1000 * decode_temp( + data->temp_twos_complement, + data->temp_min[attr->index])); } static ssize_t set_temp_min(struct device *dev, @@ -455,7 +454,7 @@ static ssize_t set_temp_min(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); int temp = simple_strtol(buf, NULL, 10) / 1000; - temp = encode_temp(data, temp); + temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); data->temp_min[attr->index] = temp; @@ -472,8 +471,9 @@ static ssize_t show_temp_max(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7473_data *data = adt7473_update_device(dev); - return sprintf(buf, "%d\n", - 1000 * decode_temp(data, data->temp_max[attr->index])); + return sprintf(buf, "%d\n", 1000 * decode_temp( + data->temp_twos_complement, + data->temp_max[attr->index])); } static ssize_t set_temp_max(struct device *dev, @@ -485,7 +485,7 @@ static ssize_t set_temp_max(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); int temp = simple_strtol(buf, NULL, 10) / 1000; - temp = encode_temp(data, temp); + temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); data->temp_max[attr->index] = temp; @@ -501,22 +501,26 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7473_data *data = adt7473_update_device(dev); - return sprintf(buf, "%d\n", - 1000 * decode_temp(data, data->temp[attr->index])); + return sprintf(buf, "%d\n", 1000 * decode_temp( + data->temp_twos_complement, + data->temp[attr->index])); } static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adt7473_data *data = adt7473_update_device(dev); + int val; - if (FAN_DATA_VALID(data->fan_min[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan_min[attr->index])); + mutex_lock(&data->lock); + if (FAN_DATA_VALID(data->fan_min[index])) + val = FAN_PERIOD_TO_RPM(data->fan_min[index]); else - return sprintf(buf, "0\n"); + val = 0; + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); } static ssize_t set_fan_min(struct device *dev, @@ -543,14 +547,17 @@ static ssize_t set_fan_min(struct device *dev, static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf) { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = to_sensor_dev_attr(devattr)->index; struct adt7473_data *data = adt7473_update_device(dev); + int val; - if (FAN_DATA_VALID(data->fan[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan[attr->index])); + mutex_lock(&data->lock); + if (FAN_DATA_VALID(data->fan[index])) + val = FAN_PERIOD_TO_RPM(data->fan[index]); else - return sprintf(buf, "0\n"); + val = 0; + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_max_duty_at_crit(struct device *dev, @@ -671,8 +678,9 @@ static ssize_t show_temp_tmax(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7473_data *data = adt7473_update_device(dev); - return sprintf(buf, "%d\n", - 1000 * decode_temp(data, data->temp_tmax[attr->index])); + return sprintf(buf, "%d\n", 1000 * decode_temp( + data->temp_twos_complement, + data->temp_tmax[attr->index])); } static ssize_t set_temp_tmax(struct device *dev, @@ -684,7 +692,7 @@ static ssize_t set_temp_tmax(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); int temp = simple_strtol(buf, NULL, 10) / 1000; - temp = encode_temp(data, temp); + temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); data->temp_tmax[attr->index] = temp; @@ -701,8 +709,9 @@ static ssize_t show_temp_tmin(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct adt7473_data *data = adt7473_update_device(dev); - return sprintf(buf, "%d\n", - 1000 * decode_temp(data, data->temp_tmin[attr->index])); + return sprintf(buf, "%d\n", 1000 * decode_temp( + data->temp_twos_complement, + data->temp_tmin[attr->index])); } static ssize_t set_temp_tmin(struct device *dev, @@ -714,7 +723,7 @@ static ssize_t set_temp_tmin(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); int temp = simple_strtol(buf, NULL, 10) / 1000; - temp = encode_temp(data, temp); + temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); data->temp_tmin[attr->index] = temp; diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 84712a2..2aeac1a 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -276,8 +276,12 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, { int nr = to_sensor_dev_attr(attr)->index; struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); + int val; + + mutex_lock(&data->update_lock); + val = FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr])); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, @@ -285,8 +289,12 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, { int nr = to_sensor_dev_attr(attr)->index; struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); + int val; + + mutex_lock(&data->update_lock); + val = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", val); } static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, @@ -953,12 +961,8 @@ static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) static void asb100_init_client(struct i2c_client *client) { struct asb100_data *data = i2c_get_clientdata(client); - int vid = 0; - vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f; - vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4; data->vrm = vid_which_vrm(); - vid = vid_from_reg(vid, data->vrm); /* Start monitoring */ asb100_write_value(client, ASB100_REG_CONFIG, diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 7673f65..6e1e227 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -34,6 +34,7 @@ #include #include #include +#include #include /* ISA device, if found */ @@ -2238,6 +2239,10 @@ static int __init dme1737_isa_device_add(unsigned short addr) }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + if (!(pdev = platform_device_alloc("dme1737", addr))) { printk(KERN_ERR "dme1737: Failed to allocate device.\n"); err = -ENOMEM; diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 7a14a2d..8998765 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -39,6 +39,7 @@ #include #include #include +#include #include static unsigned short force_id; @@ -1455,6 +1456,10 @@ static int __init f71805f_device_add(unsigned short address, } res.name = pdev->name; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit_device_put; + err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed " diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index cbeb498..eaeeaca 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #define DRVNAME "f71882fg" @@ -898,6 +899,10 @@ static int __init f71882fg_device_add(unsigned short address) return -ENOMEM; res.name = f71882fg_pdev->name; + err = acpi_check_resource_conflict(&res); + if (err) + return err; + err = platform_device_add_resources(f71882fg_pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index e12c132..2db65a4 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #define DRVNAME "it87" @@ -1487,6 +1488,10 @@ static int __init it87_device_add(unsigned short address, }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 115f409..fa76969 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -248,7 +248,7 @@ static int lm75_detach_client(struct i2c_client *client) /* All registers are word-sized, except for the configuration register. LM75 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ + the SMBus standard. */ static int lm75_read_value(struct i2c_client *client, u8 reg) { if (reg == LM75_REG_CONF) @@ -257,9 +257,6 @@ static int lm75_read_value(struct i2c_client *client, u8 reg) return swab16(i2c_smbus_read_word_data(client, reg)); } -/* All registers are word-sized, except for the configuration register. - LM75 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) { if (reg == LM75_REG_CONF) diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 9b462bb..6c8a8b9 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -43,6 +43,7 @@ #include #include #include +#include #include static u8 devid; @@ -1425,6 +1426,11 @@ static int __init pc87360_device_add(unsigned short address) continue; res.start = extra_isa[i]; res.end = extra_isa[i] + PC87360_EXTENT - 1; + + err = acpi_check_resource_conflict(&res); + if (err) + goto exit_device_put; + err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR "pc87360: Device resource[%d] " diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 7265f22..3a8a0f7 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -32,6 +32,7 @@ #include #include #include +#include #include static unsigned short force_id; @@ -524,6 +525,10 @@ static int __init pc87427_device_add(unsigned short address) }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index a276806..aa2e831 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -62,6 +62,7 @@ #include #include #include +#include #include @@ -727,6 +728,10 @@ static int __devinit sis5595_device_add(unsigned short address) }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc("sis5595", address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index f61d8f4..6f6d52b 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -36,6 +36,7 @@ #include #include #include +#include #include static unsigned short force_id; @@ -303,6 +304,10 @@ static int __init smsc47b397_device_add(unsigned short address) }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; @@ -335,11 +340,23 @@ exit: static int __init smsc47b397_find(unsigned short *addr) { u8 id, rev; + char *name; superio_enter(); id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); - if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) { + switch(id) { + case 0x81: + name = "SCH5307-NS"; + break; + case 0x6f: + name = "LPC47B397-NC"; + break; + case 0x85: + case 0x8c: + name = "SCH5317"; + break; + default: superio_exit(); return -ENODEV; } @@ -352,8 +369,7 @@ static int __init smsc47b397_find(unsigned short *addr) printk(KERN_INFO DRVNAME ": found SMSC %s " "(base address 0x%04x, revision %u)\n", - id == 0x81 ? "SCH5307-NS" : id == 0x85 ? "SCH5317" : - "LPC47B397-NC", *addr, rev); + name, *addr, rev); superio_exit(); return 0; diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index d1b4985..a92dbb9 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -37,6 +37,7 @@ #include #include #include +#include #include static unsigned short force_id; @@ -705,6 +706,10 @@ static int __init smsc47m1_device_add(unsigned short address, }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index f1ee5e7..a022aed 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -783,6 +784,10 @@ static int __devinit via686a_device_add(unsigned short address) }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc("via686a", address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 12b4359..b0ce378 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -32,6 +32,7 @@ #include #include #include +#include #include static int uch_config = -1; @@ -1259,6 +1260,10 @@ static int __init vt1211_device_add(unsigned short address) } res.name = pdev->name; + err = acpi_check_resource_conflict(&res); + if (err) + goto EXIT; + err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed " diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 5bc5727..9982b45 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -35,6 +35,7 @@ #include #include #include +#include #include static int force_addr; @@ -894,6 +895,10 @@ static int __devinit vt8231_device_add(unsigned short address) }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc("vt8231", address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 075164d..a3a01dc 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include "lm75.h" @@ -1544,6 +1545,11 @@ static int __init sensors_w83627ehf_init(void) res.start = address + IOREGION_OFFSET; res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; res.flags = IORESOURCE_IO; + + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + err = platform_device_add_resources(pdev, &res, 1); if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed " diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 9564fb0..d26bae9 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include "lm75.h" @@ -1746,6 +1747,10 @@ static int __init w83627hf_device_add(unsigned short address, }; int err; + err = acpi_check_resource_conflict(&res); + if (err) + goto exit; + pdev = platform_device_alloc(DRVNAME, address); if (!pdev) { err = -ENOMEM; diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index ee35af9..ed3c019 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -1024,10 +1024,9 @@ static struct sensor_device_attribute_2 w83793_vid[] = { SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0), SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1), }; +static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm); static struct sensor_device_attribute_2 sda_single_files[] = { - SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm, - NOT_USED, NOT_USED), SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, store_chassis_clear, ALARM_STATUS, 30), SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable, @@ -1080,6 +1079,7 @@ static int w83793_detach_client(struct i2c_client *client) for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) device_remove_file(dev, &w83793_vid[i].dev_attr); + device_remove_file(dev, &dev_attr_vrm); for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) device_remove_file(dev, &w83793_left_fan[i].dev_attr); @@ -1282,7 +1282,6 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) /* Initialize the chip */ w83793_init_client(client); - data->vrm = vid_which_vrm(); /* Only fan 1-5 has their own input pins, Pwm 1-3 has their own pins @@ -1293,7 +1292,9 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) val = w83793_read_value(client, W83793_REG_FANIN_CTRL); /* check the function of pins 49-56 */ - if (!(tmp & 0x80)) { + if (tmp & 0x80) { + data->has_vid |= 0x2; /* has VIDB */ + } else { data->has_pwm |= 0x18; /* pwm 4,5 */ if (val & 0x01) { /* fan 6 */ data->has_fan |= 0x20; @@ -1309,13 +1310,15 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) } } + /* check the function of pins 37-40 */ + if (!(tmp & 0x29)) + data->has_vid |= 0x1; /* has VIDA */ if (0x08 == (tmp & 0x0c)) { if (val & 0x08) /* fan 9 */ data->has_fan |= 0x100; if (val & 0x10) /* fan 10 */ data->has_fan |= 0x200; } - if (0x20 == (tmp & 0x30)) { if (val & 0x20) /* fan 11 */ data->has_fan |= 0x400; @@ -1359,13 +1362,6 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) if (tmp & 0x02) data->has_temp |= 0x20; - /* Detect the VID usage and ignore unused input */ - tmp = w83793_read_value(client, W83793_REG_MFC); - if (!(tmp & 0x29)) - data->has_vid |= 0x1; /* has VIDA */ - if (tmp & 0x80) - data->has_vid |= 0x2; /* has VIDB */ - /* Register sysfs hooks */ for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) { err = device_create_file(dev, @@ -1381,6 +1377,12 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) if (err) goto exit_remove; } + if (data->has_vid) { + data->vrm = vid_which_vrm(); + err = device_create_file(dev, &dev_attr_vrm); + if (err) + goto exit_remove; + } for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { err = device_create_file(dev, &sda_single_files[i].dev_attr); diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index 77f2d48..52e268e 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -301,8 +301,8 @@ static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) msleep(i); } - dev_err(&client->dev, "Couldn't read value from register 0x%02x. " - "Please report.\n", reg); + dev_err(&client->dev, "Couldn't read value from register 0x%02x.\n", + reg); return defval; }