diff options
author | Rod Whitby <rod@whitby.id.au> | 2006-04-14 06:39:54 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2006-04-14 06:39:54 +0000 |
commit | c9cadd074271be3812dfc501d98ae93df22d7bd0 (patch) | |
tree | 5817ca1378e5e20cae845cfe0dfe48764529e6c5 /packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch | |
parent | 5c26c1237a294e04c6a8542d11d15a4200f70a8a (diff) |
ixp4xx-kernel: Removed obsolete patches, and refreshed patchset from the nslu2-linux kernel CVS repo.
Diffstat (limited to 'packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch')
-rw-r--r-- | packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch | 13671 |
1 files changed, 13671 insertions, 0 deletions
diff --git a/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch b/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch new file mode 100644 index 0000000000..86c88c3746 --- /dev/null +++ b/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch @@ -0,0 +1,13671 @@ +--- linux-2.6.16.orig/include/linux/hwmon-sysfs.h 2006-03-22 17:06:11.000000000 +0100 ++++ linux-2.6.16/include/linux/hwmon-sysfs.h 2006-03-22 17:06:15.000000000 +0100 +@@ -27,11 +27,13 @@ + #define to_sensor_dev_attr(_dev_attr) \ + container_of(_dev_attr, struct sensor_device_attribute, dev_attr) + +-#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \ +-struct sensor_device_attribute sensor_dev_attr_##_name = { \ +- .dev_attr = __ATTR(_name,_mode,_show,_store), \ +- .index = _index, \ +-} ++#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \ ++ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ ++ .index = _index } ++ ++#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \ ++struct sensor_device_attribute sensor_dev_attr_##_name \ ++ = SENSOR_ATTR(_name, _mode, _show, _store, _index) + + struct sensor_device_attribute_2 { + struct device_attribute dev_attr; +@@ -41,11 +43,13 @@ + #define to_sensor_dev_attr_2(_dev_attr) \ + container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr) + ++#define SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) \ ++ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ ++ .index = _index, \ ++ .nr = _nr } ++ + #define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index) \ +-struct sensor_device_attribute_2 sensor_dev_attr_##_name = { \ +- .dev_attr = __ATTR(_name,_mode,_show,_store), \ +- .index = _index, \ +- .nr = _nr, \ +-} ++struct sensor_device_attribute_2 sensor_dev_attr_##_name \ ++ = SENSOR_ATTR_2(_name, _mode, _show, _store, _nr, _index) + + #endif /* _LINUX_HWMON_SYSFS_H */ +--- linux-2.6.16.orig/drivers/hwmon/pc87360.c 2006-03-22 17:06:11.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/pc87360.c 2006-03-22 17:06:15.000000000 +0100 +@@ -43,6 +43,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + static u8 devid; +@@ -183,8 +184,8 @@ + struct pc87360_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; +- struct semaphore update_lock; ++ struct mutex lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -283,7 +284,7 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long fan_min = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index])); + + /* If it wouldn't fit, change clock divisor */ +@@ -300,23 +301,31 @@ + /* Write new divider, preserve alarm bits */ + pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index), + data->fan_status[attr->index] & 0xF9); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } + +-#define show_and_set_fan(offset) \ +-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ +- show_fan_input, NULL, offset-1); \ +-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \ +- show_fan_min, set_fan_min, offset-1); \ +-static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ +- show_fan_div, NULL, offset-1); \ +-static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \ +- show_fan_status, NULL, offset-1); +-show_and_set_fan(1) +-show_and_set_fan(2) +-show_and_set_fan(3) ++static struct sensor_device_attribute fan_input[] = { ++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0), ++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1), ++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2), ++}; ++static struct sensor_device_attribute fan_status[] = { ++ SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0), ++ SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1), ++ SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2), ++}; ++static struct sensor_device_attribute fan_div[] = { ++ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), ++ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), ++ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), ++}; ++static struct sensor_device_attribute fan_min[] = { ++ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), ++ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), ++ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), ++}; + + static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) + { +@@ -335,21 +344,20 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm[attr->index] = PWM_TO_REG(val, + FAN_CONFIG_INVERT(data->fan_conf, attr->index)); + pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index), + data->pwm[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +-#define show_and_set_pwm(offset) \ +-static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \ +- show_pwm, set_pwm, offset-1); +-show_and_set_pwm(1) +-show_and_set_pwm(2) +-show_and_set_pwm(3) ++static struct sensor_device_attribute pwm[] = { ++ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0), ++ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1), ++ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), ++}; + + static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) + { +@@ -386,11 +394,11 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); + pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN, + data->in_min[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf, +@@ -401,35 +409,67 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[attr->index] = IN_TO_REG(val, + data->in_vref); + pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX, + data->in_max[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +-#define show_and_set_in(offset) \ +-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ +- show_in_input, NULL, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ +- show_in_min, set_in_min, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ +- show_in_max, set_in_max, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \ +- show_in_status, NULL, offset); +-show_and_set_in(0) +-show_and_set_in(1) +-show_and_set_in(2) +-show_and_set_in(3) +-show_and_set_in(4) +-show_and_set_in(5) +-show_and_set_in(6) +-show_and_set_in(7) +-show_and_set_in(8) +-show_and_set_in(9) +-show_and_set_in(10) ++static struct sensor_device_attribute in_input[] = { ++ SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0), ++ SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1), ++ SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2), ++ SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3), ++ SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4), ++ SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5), ++ SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6), ++ SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7), ++ SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8), ++ SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9), ++ SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10), ++}; ++static struct sensor_device_attribute in_status[] = { ++ SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0), ++ SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1), ++ SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2), ++ SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3), ++ SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4), ++ SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5), ++ SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6), ++ SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7), ++ SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8), ++ SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9), ++ SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10), ++}; ++static struct sensor_device_attribute in_min[] = { ++ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0), ++ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1), ++ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2), ++ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3), ++ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4), ++ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5), ++ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6), ++ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7), ++ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8), ++ SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9), ++ SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10), ++}; ++static struct sensor_device_attribute in_max[] = { ++ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0), ++ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1), ++ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2), ++ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3), ++ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4), ++ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5), ++ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6), ++ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7), ++ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8), ++ SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9), ++ SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), ++}; + + static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) + { +@@ -473,11 +513,11 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); + pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN, + data->in_min[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf, +@@ -488,11 +528,11 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); + pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX, + data->in_max[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf, +@@ -503,28 +543,51 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); + pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT, + data->in_crit[attr->index-11]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +-#define show_and_set_therm(offset) \ +-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ +- show_therm_input, NULL, 11+offset-4); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ +- show_therm_min, set_therm_min, 11+offset-4); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ +- show_therm_max, set_therm_max, 11+offset-4); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ +- show_therm_crit, set_therm_crit, 11+offset-4); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ +- show_therm_status, NULL, 11+offset-4); +-show_and_set_therm(4) +-show_and_set_therm(5) +-show_and_set_therm(6) ++/* the +11 term below reflects the fact that VLM units 11,12,13 are ++ used in the chip to measure voltage across the thermistors ++*/ ++static struct sensor_device_attribute therm_input[] = { ++ SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11), ++ SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11), ++ SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11), ++}; ++static struct sensor_device_attribute therm_status[] = { ++ SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11), ++ SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11), ++ SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11), ++}; ++static struct sensor_device_attribute therm_min[] = { ++ SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, ++ show_therm_min, set_therm_min, 0+11), ++ SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, ++ show_therm_min, set_therm_min, 1+11), ++ SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, ++ show_therm_min, set_therm_min, 2+11), ++}; ++static struct sensor_device_attribute therm_max[] = { ++ SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, ++ show_therm_max, set_therm_max, 0+11), ++ SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, ++ show_therm_max, set_therm_max, 1+11), ++ SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, ++ show_therm_max, set_therm_max, 2+11), ++}; ++static struct sensor_device_attribute therm_crit[] = { ++ SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, ++ show_therm_crit, set_therm_crit, 0+11), ++ SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, ++ show_therm_crit, set_therm_crit, 1+11), ++ SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, ++ show_therm_crit, set_therm_crit, 2+11), ++}; + + static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) + { +@@ -592,11 +655,11 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_min[attr->index] = TEMP_TO_REG(val); + pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN, + data->temp_min[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf, +@@ -607,11 +670,11 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[attr->index] = TEMP_TO_REG(val); + pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX, + data->temp_max[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf, +@@ -622,28 +685,48 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_crit[attr->index] = TEMP_TO_REG(val); + pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT, + data->temp_crit[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +-#define show_and_set_temp(offset) \ +-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ +- show_temp_input, NULL, offset-1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ +- show_temp_min, set_temp_min, offset-1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ +- show_temp_max, set_temp_max, offset-1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \ +- show_temp_crit, set_temp_crit, offset-1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \ +- show_temp_status, NULL, offset-1); +-show_and_set_temp(1) +-show_and_set_temp(2) +-show_and_set_temp(3) ++static struct sensor_device_attribute temp_input[] = { ++ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0), ++ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1), ++ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2), ++}; ++static struct sensor_device_attribute temp_status[] = { ++ SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0), ++ SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1), ++ SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2), ++}; ++static struct sensor_device_attribute temp_min[] = { ++ SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR, ++ show_temp_min, set_temp_min, 0), ++ SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR, ++ show_temp_min, set_temp_min, 1), ++ SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR, ++ show_temp_min, set_temp_min, 2), ++}; ++static struct sensor_device_attribute temp_max[] = { ++ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, ++ show_temp_max, set_temp_max, 0), ++ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, ++ show_temp_max, set_temp_max, 1), ++ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, ++ show_temp_max, set_temp_max, 2), ++}; ++static struct sensor_device_attribute temp_crit[] = { ++ SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR, ++ show_temp_crit, set_temp_crit, 0), ++ SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR, ++ show_temp_crit, set_temp_crit, 1), ++ SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR, ++ show_temp_crit, set_temp_crit, 2), ++}; + + static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf) + { +@@ -749,22 +832,24 @@ + static int pc87360_detect(struct i2c_adapter *adapter) + { + int i; +- struct i2c_client *new_client; ++ struct i2c_client *client; + struct pc87360_data *data; + int err = 0; + const char *name = "pc87360"; + int use_thermistors = 0; ++ struct device *dev; + + if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) + return -ENOMEM; + +- new_client = &data->client; +- i2c_set_clientdata(new_client, data); +- new_client->addr = address; +- init_MUTEX(&data->lock); +- new_client->adapter = adapter; +- new_client->driver = &pc87360_driver; +- new_client->flags = 0; ++ client = &data->client; ++ dev = &client->dev; ++ i2c_set_clientdata(client, data); ++ client->addr = address; ++ mutex_init(&data->lock); ++ client->adapter = adapter; ++ client->driver = &pc87360_driver; ++ client->flags = 0; + + data->fannr = 2; + data->innr = 0; +@@ -792,15 +877,15 @@ + break; + } + +- strcpy(new_client->name, name); ++ strlcpy(client->name, name, sizeof(client->name)); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + for (i = 0; i < 3; i++) { + if (((data->address[i] = extra_isa[i])) + && !request_region(extra_isa[i], PC87360_EXTENT, + pc87360_driver.driver.name)) { +- dev_err(&new_client->dev, "Region 0x%x-0x%x already " ++ dev_err(&client->dev, "Region 0x%x-0x%x already " + "in use!\n", extra_isa[i], + extra_isa[i]+PC87360_EXTENT-1); + for (i--; i >= 0; i--) +@@ -814,7 +899,7 @@ + if (data->fannr) + data->fan_conf = confreg[0] | (confreg[1] << 8); + +- if ((err = i2c_attach_client(new_client))) ++ if ((err = i2c_attach_client(client))) + goto ERROR2; + + /* Use the correct reference voltage +@@ -828,7 +913,7 @@ + PC87365_REG_TEMP_CONFIG); + } + data->in_vref = (i&0x02) ? 3025 : 2966; +- dev_dbg(&new_client->dev, "Using %s reference voltage\n", ++ dev_dbg(&client->dev, "Using %s reference voltage\n", + (i&0x02) ? "external" : "internal"); + + data->vid_conf = confreg[3]; +@@ -847,154 +932,64 @@ + if (devid == 0xe9 && data->address[1]) /* PC87366 */ + use_thermistors = confreg[2] & 0x40; + +- pc87360_init_client(new_client, use_thermistors); ++ pc87360_init_client(client, use_thermistors); + } + + /* Register sysfs hooks */ +- data->class_dev = hwmon_device_register(&new_client->dev); ++ data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto ERROR3; + } + + if (data->innr) { +- device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr); +- +- device_create_file(&new_client->dev, &dev_attr_cpu0_vid); +- device_create_file(&new_client->dev, &dev_attr_vrm); +- device_create_file(&new_client->dev, &dev_attr_alarms_in); ++ for (i = 0; i < 11; i++) { ++ device_create_file(dev, &in_input[i].dev_attr); ++ device_create_file(dev, &in_min[i].dev_attr); ++ device_create_file(dev, &in_max[i].dev_attr); ++ device_create_file(dev, &in_status[i].dev_attr); ++ } ++ device_create_file(dev, &dev_attr_cpu0_vid); ++ device_create_file(dev, &dev_attr_vrm); ++ device_create_file(dev, &dev_attr_alarms_in); + } + + if (data->tempnr) { +- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr); +- +- device_create_file(&new_client->dev, &dev_attr_alarms_temp); +- } +- if (data->tempnr == 3) { +- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr); ++ for (i = 0; i < data->tempnr; i++) { ++ device_create_file(dev, &temp_input[i].dev_attr); ++ device_create_file(dev, &temp_min[i].dev_attr); ++ device_create_file(dev, &temp_max[i].dev_attr); ++ device_create_file(dev, &temp_crit[i].dev_attr); ++ device_create_file(dev, &temp_status[i].dev_attr); ++ } ++ device_create_file(dev, &dev_attr_alarms_temp); + } ++ + if (data->innr == 14) { +- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr); +- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr); +- } +- +- if (data->fannr) { +- if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) { +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan1_input.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan1_min.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan1_div.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan1_status.dev_attr); +- } +- +- if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) { +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan2_input.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan2_min.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan2_div.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan2_status.dev_attr); +- } +- +- if (FAN_CONFIG_CONTROL(data->fan_conf, 0)) +- device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr); +- if (FAN_CONFIG_CONTROL(data->fan_conf, 1)) +- device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr); +- } +- if (data->fannr == 3) { +- if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) { +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan3_input.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan3_min.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan3_div.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_fan3_status.dev_attr); ++ for (i = 0; i < 3; i++) { ++ device_create_file(dev, &therm_input[i].dev_attr); ++ device_create_file(dev, &therm_min[i].dev_attr); ++ device_create_file(dev, &therm_max[i].dev_attr); ++ device_create_file(dev, &therm_crit[i].dev_attr); ++ device_create_file(dev, &therm_status[i].dev_attr); + } ++ } + +- if (FAN_CONFIG_CONTROL(data->fan_conf, 2)) +- device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); ++ for (i = 0; i < data->fannr; i++) { ++ if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { ++ device_create_file(dev, &fan_input[i].dev_attr); ++ device_create_file(dev, &fan_min[i].dev_attr); ++ device_create_file(dev, &fan_div[i].dev_attr); ++ device_create_file(dev, &fan_status[i].dev_attr); ++ } ++ if (FAN_CONFIG_CONTROL(data->fan_conf, i)) ++ device_create_file(dev, &pwm[i].dev_attr); + } + + return 0; + + ERROR3: +- i2c_detach_client(new_client); ++ i2c_detach_client(client); + ERROR2: + for (i = 0; i < 3; i++) { + if (data->address[i]) { +@@ -1033,11 +1028,11 @@ + { + int res; + +- down(&(data->lock)); ++ mutex_lock(&(data->lock)); + if (bank != NO_BANK) + outb_p(bank, data->address[ldi] + PC87365_REG_BANK); + res = inb_p(data->address[ldi] + reg); +- up(&(data->lock)); ++ mutex_unlock(&(data->lock)); + + return res; + } +@@ -1045,11 +1040,11 @@ + static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, + u8 reg, u8 value) + { +- down(&(data->lock)); ++ mutex_lock(&(data->lock)); + if (bank != NO_BANK) + outb_p(bank, data->address[ldi] + PC87365_REG_BANK); + outb_p(value, data->address[ldi] + reg); +- up(&(data->lock)); ++ mutex_unlock(&(data->lock)); + } + + static void pc87360_init_client(struct i2c_client *client, int use_thermistors) +@@ -1071,7 +1066,7 @@ + } + + nr = data->innr < 11 ? data->innr : 11; +- for (i=0; i<nr; i++) { ++ for (i = 0; i < nr; i++) { + if (init >= init_in[i]) { + /* Forcibly enable voltage channel */ + reg = pc87360_read_value(data, LD_IN, i, +@@ -1088,14 +1083,14 @@ + + /* We can't blindly trust the Super-I/O space configuration bit, + most BIOS won't set it properly */ +- for (i=11; i<data->innr; i++) { ++ for (i = 11; i < data->innr; i++) { + reg = pc87360_read_value(data, LD_IN, i, + PC87365_REG_TEMP_STATUS); + use_thermistors = use_thermistors || (reg & 0x01); + } + + i = use_thermistors ? 2 : 0; +- for (; i<data->tempnr; i++) { ++ for (; i < data->tempnr; i++) { + if (init >= init_temp[i]) { + /* Forcibly enable temperature channel */ + reg = pc87360_read_value(data, LD_TEMP, i, +@@ -1111,7 +1106,7 @@ + } + + if (use_thermistors) { +- for (i=11; i<data->innr; i++) { ++ for (i = 11; i < data->innr; i++) { + if (init >= init_in[i]) { + /* The pin may already be used by thermal + diodes */ +@@ -1221,7 +1216,7 @@ + struct pc87360_data *data = i2c_get_clientdata(client); + u8 i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { + dev_dbg(&client->dev, "Data update\n"); +@@ -1321,7 +1316,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/f71805f.c 2006-03-22 17:06:11.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/f71805f.c 2006-03-22 17:06:16.000000000 +0100 +@@ -30,6 +30,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-sysfs.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + static struct platform_device *pdev; +@@ -98,10 +99,6 @@ + #define ADDR_REG_OFFSET 0 + #define DATA_REG_OFFSET 1 + +-static struct resource f71805f_resource __initdata = { +- .flags = IORESOURCE_IO, +-}; +- + /* + * Registers + */ +@@ -131,10 +128,10 @@ + struct f71805f_data { + unsigned short addr; + const char *name; +- struct semaphore lock; ++ struct mutex lock; + struct class_device *class_dev; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long last_limits; /* In jiffies */ +@@ -150,7 +147,7 @@ + u8 temp_high[3]; + u8 temp_hyst[3]; + u8 temp_mode; +- u8 alarms[3]; ++ unsigned long alarms; + }; + + static inline long in_from_reg(u8 reg) +@@ -224,20 +221,20 @@ + { + u8 val; + +- down(&data->lock); ++ mutex_lock(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + val = inb(data->addr + DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + + return val; + } + + static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) + { +- down(&data->lock); ++ mutex_lock(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + outb(val, data->addr + DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + } + + /* It is important to read the MSB first, because doing so latches the +@@ -246,24 +243,24 @@ + { + u16 val; + +- down(&data->lock); ++ mutex_lock(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + val = inb(data->addr + DATA_REG_OFFSET) << 8; + outb(++reg, data->addr + ADDR_REG_OFFSET); + val |= inb(data->addr + DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + + return val; + } + + static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) + { +- down(&data->lock); ++ mutex_lock(&data->lock); + outb(reg, data->addr + ADDR_REG_OFFSET); + outb(val >> 8, data->addr + DATA_REG_OFFSET); + outb(++reg, data->addr + ADDR_REG_OFFSET); + outb(val & 0xff, data->addr + DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + } + + static struct f71805f_data *f71805f_update_device(struct device *dev) +@@ -271,7 +268,7 @@ + struct f71805f_data *data = dev_get_drvdata(dev); + int nr; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + /* Limit registers cache is refreshed after 60 seconds */ + if (time_after(jiffies, data->last_updated + 60 * HZ) +@@ -314,16 +311,15 @@ + data->temp[nr] = f71805f_read8(data, + F71805F_REG_TEMP(nr)); + } +- for (nr = 0; nr < 3; nr++) { +- data->alarms[nr] = f71805f_read8(data, +- F71805F_REG_STATUS(nr)); +- } ++ data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0)) ++ + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8) ++ + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16); + + data->last_updated = jiffies; + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +@@ -362,10 +358,10 @@ + struct f71805f_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_high[0] = in0_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -376,18 +372,14 @@ + struct f71805f_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_low[0] = in0_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } + +-static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL); +-static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max); +-static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min); +- + static ssize_t show_in(struct device *dev, struct device_attribute *devattr, + char *buf) + { +@@ -426,10 +418,10 @@ + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_high[nr] = in_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -442,31 +434,14 @@ + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_low[nr] = in_to_reg(val); + f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } + +-#define sysfs_in(offset) \ +-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ +- show_in, NULL, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ +- show_in_max, set_in_max, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ +- show_in_min, set_in_min, offset) +- +-sysfs_in(1); +-sysfs_in(2); +-sysfs_in(3); +-sysfs_in(4); +-sysfs_in(5); +-sysfs_in(6); +-sysfs_in(7); +-sysfs_in(8); +- + static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) + { +@@ -495,24 +470,14 @@ + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_low[nr] = fan_to_reg(val); + f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } + +-#define sysfs_fan(offset) \ +-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ +- show_fan, NULL, offset - 1); \ +-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ +- show_fan_min, set_fan_min, offset - 1) +- +-sysfs_fan(1); +-sysfs_fan(2); +-sysfs_fan(3); +- + static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, + char *buf) + { +@@ -562,10 +527,10 @@ + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_high[nr] = temp_to_reg(val); + f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -578,35 +543,20 @@ + int nr = attr->index; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_hyst[nr] = temp_to_reg(val); + f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } + +-#define sysfs_temp(offset) \ +-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ +- show_temp, NULL, offset - 1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ +- show_temp_max, set_temp_max, offset - 1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ +- show_temp_hyst, set_temp_hyst, offset - 1); \ +-static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \ +- show_temp_type, NULL, offset - 1) +- +-sysfs_temp(1); +-sysfs_temp(2); +-sysfs_temp(3); +- + static ssize_t show_alarms_in(struct device *dev, struct device_attribute + *devattr, char *buf) + { + struct f71805f_data *data = f71805f_update_device(dev); + +- return sprintf(buf, "%d\n", data->alarms[0] | +- ((data->alarms[1] & 0x01) << 8)); ++ return sprintf(buf, "%lu\n", data->alarms & 0x1ff); + } + + static ssize_t show_alarms_fan(struct device *dev, struct device_attribute +@@ -614,7 +564,7 @@ + { + struct f71805f_data *data = f71805f_update_device(dev); + +- return sprintf(buf, "%d\n", data->alarms[2] & 0x07); ++ return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07); + } + + static ssize_t show_alarms_temp(struct device *dev, struct device_attribute +@@ -622,12 +572,18 @@ + { + struct f71805f_data *data = f71805f_update_device(dev); + +- return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); ++ return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07); + } + +-static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); +-static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); +-static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); ++static ssize_t show_alarm(struct device *dev, struct device_attribute ++ *devattr, char *buf) ++{ ++ struct f71805f_data *data = f71805f_update_device(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ int nr = attr->index; ++ ++ return sprintf(buf, "%lu\n", (data->alarms >> nr) & 1); ++} + + static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +@@ -637,7 +593,104 @@ + return sprintf(buf, "%s\n", data->name); + } + +-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); ++static struct device_attribute f71805f_dev_attr[] = { ++ __ATTR(in0_input, S_IRUGO, show_in0, NULL), ++ __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max), ++ __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min), ++ __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL), ++ __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL), ++ __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL), ++ __ATTR(name, S_IRUGO, show_name, NULL), ++}; ++ ++static struct sensor_device_attribute f71805f_sensor_attr[] = { ++ SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), ++ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), ++ SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 1), ++ SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 1), ++ SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), ++ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), ++ SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 2), ++ SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 2), ++ SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), ++ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), ++ SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 3), ++ SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 3), ++ SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), ++ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), ++ SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 4), ++ SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 4), ++ SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4), ++ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), ++ SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 5), ++ SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 5), ++ SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5), ++ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), ++ SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 6), ++ SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 6), ++ SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6), ++ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), ++ SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 7), ++ SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 7), ++ SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7), ++ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), ++ SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR, ++ show_in_max, set_in_max, 8), ++ SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR, ++ show_in_min, set_in_min, 8), ++ SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8), ++ ++ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), ++ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, ++ show_temp_max, set_temp_max, 0), ++ SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, ++ show_temp_hyst, set_temp_hyst, 0), ++ SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), ++ SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11), ++ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), ++ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, ++ show_temp_max, set_temp_max, 1), ++ SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, ++ show_temp_hyst, set_temp_hyst, 1), ++ SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), ++ SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12), ++ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), ++ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, ++ show_temp_max, set_temp_max, 2), ++ SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, ++ show_temp_hyst, set_temp_hyst, 2), ++ SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), ++ SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), ++}; ++ ++static struct sensor_device_attribute f71805f_fan_attr[] = { ++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), ++ SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR, ++ show_fan_min, set_fan_min, 0), ++ SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16), ++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), ++ SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR, ++ show_fan_min, set_fan_min, 1), ++ SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17), ++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), ++ SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR, ++ show_fan_min, set_fan_min, 2), ++ SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18), ++}; + + /* + * Device registration and initialization +@@ -668,7 +721,7 @@ + { + struct f71805f_data *data; + struct resource *res; +- int err; ++ int i, err; + + if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) { + err = -ENOMEM; +@@ -678,9 +731,9 @@ + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + data->addr = res->start; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + data->name = "f71805f"; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + platform_set_drvdata(pdev, data); + +@@ -695,76 +748,31 @@ + f71805f_init_device(data); + + /* Register sysfs interface files */ +- device_create_file(&pdev->dev, &dev_attr_in0_input); +- device_create_file(&pdev->dev, &dev_attr_in0_max); +- device_create_file(&pdev->dev, &dev_attr_in0_min); +- device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr); +- if (data->fan_enabled & (1 << 0)) { +- device_create_file(&pdev->dev, +- &sensor_dev_attr_fan1_input.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_fan1_min.dev_attr); +- } +- if (data->fan_enabled & (1 << 1)) { +- device_create_file(&pdev->dev, +- &sensor_dev_attr_fan2_input.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_fan2_min.dev_attr); +- } +- if (data->fan_enabled & (1 << 2)) { +- device_create_file(&pdev->dev, +- &sensor_dev_attr_fan3_input.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_fan3_min.dev_attr); +- } +- device_create_file(&pdev->dev, +- &sensor_dev_attr_temp1_input.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_temp2_input.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_temp3_input.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_temp1_max_hyst.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_temp2_max_hyst.dev_attr); +- device_create_file(&pdev->dev, +- &sensor_dev_attr_temp3_max_hyst.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr); +- device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr); +- device_create_file(&pdev->dev, &dev_attr_alarms_in); +- device_create_file(&pdev->dev, &dev_attr_alarms_fan); +- device_create_file(&pdev->dev, &dev_attr_alarms_temp); +- device_create_file(&pdev->dev, &dev_attr_name); ++ for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) { ++ err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]); ++ if (err) ++ goto exit_class; ++ } ++ for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) { ++ err = device_create_file(&pdev->dev, ++ &f71805f_sensor_attr[i].dev_attr); ++ if (err) ++ goto exit_class; ++ } ++ for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) { ++ if (!(data->fan_enabled & (1 << (i / 3)))) ++ continue; ++ err = device_create_file(&pdev->dev, ++ &f71805f_fan_attr[i].dev_attr); ++ if (err) ++ goto exit_class; ++ } + + return 0; + ++exit_class: ++ dev_err(&pdev->dev, "Sysfs interface creation failed\n"); ++ hwmon_device_unregister(data->class_dev); + exit_free: + kfree(data); + exit: +@@ -793,6 +801,11 @@ + + static int __init f71805f_device_add(unsigned short address) + { ++ struct resource res = { ++ .start = address, ++ .end = address + REGION_LENGTH - 1, ++ .flags = IORESOURCE_IO, ++ }; + int err; + + pdev = platform_device_alloc(DRVNAME, address); +@@ -802,10 +815,8 @@ + goto exit; + } + +- f71805f_resource.start = address; +- f71805f_resource.end = address + REGION_LENGTH - 1; +- f71805f_resource.name = pdev->name; +- err = platform_device_add_resources(pdev, &f71805f_resource, 1); ++ res.name = pdev->name; ++ err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR DRVNAME ": Device resource addition failed " + "(%d)\n", err); +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ali1535.c 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ali1535.c 2006-03-22 17:06:16.000000000 +0100 +@@ -63,7 +63,6 @@ + #include <linux/i2c.h> + #include <linux/init.h> + #include <asm/io.h> +-#include <asm/semaphore.h> + + + /* ALI1535 SMBus address offsets */ +@@ -136,7 +135,6 @@ + + static struct pci_driver ali1535_driver; + static unsigned short ali1535_smba; +-static DECLARE_MUTEX(i2c_ali1535_sem); + + /* Detect whether a ALI1535 can be found, and initialize it, where necessary. + Note the differences between kernels with the old PCI BIOS interface and +@@ -345,7 +343,6 @@ + int timeout; + s32 result = 0; + +- down(&i2c_ali1535_sem); + /* make sure SMBus is idle */ + temp = inb_p(SMBHSTSTS); + for (timeout = 0; +@@ -460,7 +457,6 @@ + break; + } + EXIT: +- up(&i2c_ali1535_sem); + return result; + } + +@@ -479,7 +475,7 @@ + + static struct i2c_adapter ali1535_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/chips/ds1374.c 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/ds1374.c 2006-03-22 17:06:14.000000000 +0100 +@@ -26,6 +26,7 @@ + #include <linux/i2c.h> + #include <linux/rtc.h> + #include <linux/bcd.h> ++#include <linux/mutex.h> + + #define DS1374_REG_TOD0 0x00 + #define DS1374_REG_TOD1 0x01 +@@ -41,7 +42,7 @@ + + #define DS1374_DRV_NAME "ds1374" + +-static DECLARE_MUTEX(ds1374_mutex); ++static DEFINE_MUTEX(ds1374_mutex); + + static struct i2c_driver ds1374_driver; + static struct i2c_client *save_client; +@@ -114,7 +115,7 @@ + ulong t1, t2; + int limit = 10; /* arbitrary retry limit */ + +- down(&ds1374_mutex); ++ mutex_lock(&ds1374_mutex); + + /* + * Since the reads are being performed one byte at a time using +@@ -127,7 +128,7 @@ + t2 = ds1374_read_rtc(); + } while (t1 != t2 && limit--); + +- up(&ds1374_mutex); ++ mutex_unlock(&ds1374_mutex); + + if (t1 != t2) { + dev_warn(&save_client->dev, +@@ -145,7 +146,7 @@ + + t1 = *(ulong *) arg; + +- down(&ds1374_mutex); ++ mutex_lock(&ds1374_mutex); + + /* + * Since the writes are being performed one byte at a time using +@@ -158,7 +159,7 @@ + t2 = ds1374_read_rtc(); + } while (t1 != t2 && limit--); + +- up(&ds1374_mutex); ++ mutex_unlock(&ds1374_mutex); + + if (t1 != t2) + dev_warn(&save_client->dev, +--- linux-2.6.16.orig/drivers/i2c/chips/m41t00.c 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/m41t00.c 2006-03-22 17:06:14.000000000 +0100 +@@ -24,13 +24,14 @@ + #include <linux/i2c.h> + #include <linux/rtc.h> + #include <linux/bcd.h> ++#include <linux/mutex.h> + + #include <asm/time.h> + #include <asm/rtc.h> + + #define M41T00_DRV_NAME "m41t00" + +-static DECLARE_MUTEX(m41t00_mutex); ++static DEFINE_MUTEX(m41t00_mutex); + + static struct i2c_driver m41t00_driver; + static struct i2c_client *save_client; +@@ -54,7 +55,7 @@ + sec = min = hour = day = mon = year = 0; + sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; + +- down(&m41t00_mutex); ++ mutex_lock(&m41t00_mutex); + do { + if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) + && ((min = i2c_smbus_read_byte_data(save_client, 1)) +@@ -80,7 +81,7 @@ + mon1 = mon; + year1 = year; + } while (--limit > 0); +- up(&m41t00_mutex); ++ mutex_unlock(&m41t00_mutex); + + if (limit == 0) { + dev_warn(&save_client->dev, +@@ -125,7 +126,7 @@ + BIN_TO_BCD(tm.tm_mday); + BIN_TO_BCD(tm.tm_year); + +- down(&m41t00_mutex); ++ mutex_lock(&m41t00_mutex); + if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) + || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) + < 0) +@@ -140,7 +141,7 @@ + + dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); + +- up(&m41t00_mutex); ++ mutex_unlock(&m41t00_mutex); + return; + } + +--- linux-2.6.16.orig/drivers/i2c/i2c-core.c 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/i2c-core.c 2006-03-22 17:06:21.000000000 +0100 +@@ -31,14 +31,17 @@ + #include <linux/idr.h> + #include <linux/seq_file.h> + #include <linux/platform_device.h> ++#include <linux/mutex.h> + #include <asm/uaccess.h> + + + static LIST_HEAD(adapters); + static LIST_HEAD(drivers); +-static DECLARE_MUTEX(core_lists); ++static DEFINE_MUTEX(core_lists); + static DEFINE_IDR(i2c_adapter_idr); + ++static void i2c_notify(struct i2c_adapter *adap, struct i2c_driver *driver); ++ + /* match always succeeds, as we want the probe() to tell if we really accept this match */ + static int i2c_device_match(struct device *dev, struct device_driver *drv) + { +@@ -153,7 +156,7 @@ + struct list_head *item; + struct i2c_driver *driver; + +- down(&core_lists); ++ mutex_lock(&core_lists); + + if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { + res = -ENOMEM; +@@ -168,8 +171,8 @@ + } + + adap->nr = id & MAX_ID_MASK; +- init_MUTEX(&adap->bus_lock); +- init_MUTEX(&adap->clist_lock); ++ mutex_init(&adap->bus_lock); ++ mutex_init(&adap->clist_lock); + list_add_tail(&adap->list,&adapters); + INIT_LIST_HEAD(&adap->clients); + +@@ -197,13 +200,11 @@ + /* inform drivers of new adapters */ + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); +- if (driver->attach_adapter) +- /* We ignore the return code; if it fails, too bad */ +- driver->attach_adapter(adap); ++ i2c_notify(adap, driver); + } + + out_unlock: +- up(&core_lists); ++ mutex_unlock(&core_lists); + return res; + } + +@@ -216,7 +217,7 @@ + struct i2c_client *client; + int res = 0; + +- down(&core_lists); ++ mutex_lock(&core_lists); + + /* First make sure that this adapter was ever added */ + list_for_each_entry(adap_from_list, &adapters, list) { +@@ -272,7 +273,7 @@ + dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); + + out_unlock: +- up(&core_lists); ++ mutex_unlock(&core_lists); + return res; + } + +@@ -287,9 +288,7 @@ + { + struct list_head *item; + struct i2c_adapter *adapter; +- int res = 0; +- +- down(&core_lists); ++ int res; + + /* add the driver to the list of i2c drivers in the driver core */ + driver->driver.owner = owner; +@@ -297,22 +296,21 @@ + + res = driver_register(&driver->driver); + if (res) +- goto out_unlock; ++ return res; + ++ mutex_lock(&core_lists); ++ + list_add_tail(&driver->list,&drivers); + pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); + + /* now look for instances of driver on our adapters */ +- if (driver->attach_adapter) { +- list_for_each(item,&adapters) { +- adapter = list_entry(item, struct i2c_adapter, list); +- driver->attach_adapter(adapter); +- } ++ list_for_each(item, &adapters) { ++ adapter = list_entry(item, struct i2c_adapter, list); ++ i2c_notify(adapter, driver); + } + +- out_unlock: +- up(&core_lists); +- return res; ++ mutex_unlock(&core_lists); ++ return 0; + } + EXPORT_SYMBOL(i2c_register_driver); + +@@ -324,7 +322,7 @@ + + int res = 0; + +- down(&core_lists); ++ mutex_lock(&core_lists); + + /* Have a look at each adapter, if clients of this driver are still + * attached. If so, detach them to be able to kill the driver +@@ -363,7 +361,7 @@ + pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); + + out_unlock: +- up(&core_lists); ++ mutex_unlock(&core_lists); + return 0; + } + +@@ -384,9 +382,9 @@ + { + int rval; + +- down(&adapter->clist_lock); ++ mutex_lock(&adapter->clist_lock); + rval = __i2c_check_addr(adapter, addr); +- up(&adapter->clist_lock); ++ mutex_unlock(&adapter->clist_lock); + + return rval; + } +@@ -395,13 +393,13 @@ + { + struct i2c_adapter *adapter = client->adapter; + +- down(&adapter->clist_lock); ++ mutex_lock(&adapter->clist_lock); + if (__i2c_check_addr(client->adapter, client->addr)) { +- up(&adapter->clist_lock); ++ mutex_unlock(&adapter->clist_lock); + return -EBUSY; + } + list_add_tail(&client->list,&adapter->clients); +- up(&adapter->clist_lock); ++ mutex_unlock(&adapter->clist_lock); + + if (adapter->client_register) { + if (adapter->client_register(client)) { +@@ -450,12 +448,12 @@ + } + } + +- down(&adapter->clist_lock); ++ mutex_lock(&adapter->clist_lock); + list_del(&client->list); + init_completion(&client->released); + device_remove_file(&client->dev, &dev_attr_client_name); + device_unregister(&client->dev); +- up(&adapter->clist_lock); ++ mutex_unlock(&adapter->clist_lock); + wait_for_completion(&client->released); + + out: +@@ -513,19 +511,19 @@ + struct list_head *item; + struct i2c_client *client; + +- down(&adap->clist_lock); ++ mutex_lock(&adap->clist_lock); + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + if (!try_module_get(client->driver->driver.owner)) + continue; + if (NULL != client->driver->command) { +- up(&adap->clist_lock); ++ mutex_unlock(&adap->clist_lock); + client->driver->command(client,cmd,arg); +- down(&adap->clist_lock); ++ mutex_lock(&adap->clist_lock); + } + module_put(client->driver->driver.owner); + } +- up(&adap->clist_lock); ++ mutex_unlock(&adap->clist_lock); + } + + static int __init i2c_init(void) +@@ -569,9 +567,9 @@ + } + #endif + +- down(&adap->bus_lock); ++ mutex_lock(&adap->bus_lock); + ret = adap->algo->master_xfer(adap,msgs,num); +- up(&adap->bus_lock); ++ mutex_unlock(&adap->bus_lock); + + return ret; + } else { +@@ -775,16 +773,53 @@ + return 0; + } + ++/* For explicitely attaching a driver to a given device */ ++int i2c_probe_device(struct i2c_adapter *adapter, int driver_id, ++ int addr, int kind) ++{ ++ struct list_head *item; ++ struct i2c_driver *driver = NULL; ++ ++ /* There's no way to probe addresses on this adapter... */ ++ if (kind < 0 && !i2c_check_functionality(adapter, ++ I2C_FUNC_SMBUS_QUICK)) ++ return -EINVAL; ++ ++ mutex_lock(&core_lists); ++ list_for_each(item, &drivers) { ++ driver = list_entry(item, struct i2c_driver, list); ++ if (driver->id == driver_id) ++ break; ++ } ++ mutex_unlock(&core_lists); ++ if (!item) ++ return -ENOENT; ++ ++ return i2c_probe_address(adapter, addr, kind, driver->detect_client); ++} ++ ++static void i2c_notify(struct i2c_adapter *adap, struct i2c_driver *driver) ++{ ++ if (driver->attach_adapter) ++ driver->attach_adapter(adap); ++ ++ /* Probe devices if the driver provided the necessary information ++ (detect_client and address_data) */ ++ if (driver->detect_client && driver->address_data && ++ (driver->class & adap->class)) ++ i2c_probe(adap, driver->address_data, driver->detect_client); ++} ++ + struct i2c_adapter* i2c_get_adapter(int id) + { + struct i2c_adapter *adapter; + +- down(&core_lists); ++ mutex_lock(&core_lists); + adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id); + if (adapter && !try_module_get(adapter->owner)) + adapter = NULL; + +- up(&core_lists); ++ mutex_unlock(&core_lists); + return adapter; + } + +@@ -919,12 +954,11 @@ + u8 length, u8 *values) + { + union i2c_smbus_data data; +- int i; ++ + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; +- for (i = 1; i <= length; i++) +- data.block[i] = values[i-1]; + data.block[0] = length; ++ memcpy(&data.block[1], values, length); + return i2c_smbus_xfer(client->adapter,client->addr,client->flags, + I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_DATA,&data); +@@ -934,16 +968,14 @@ + s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) + { + union i2c_smbus_data data; +- int i; ++ + if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, + I2C_SMBUS_READ,command, + I2C_SMBUS_I2C_BLOCK_DATA,&data)) + return -1; +- else { +- for (i = 1; i <= data.block[0]; i++) +- values[i-1] = data.block[i]; +- return data.block[0]; +- } ++ ++ memcpy(values, &data.block[1], data.block[0]); ++ return data.block[0]; + } + + s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, +@@ -1118,10 +1150,10 @@ + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + if (adapter->algo->smbus_xfer) { +- down(&adapter->bus_lock); ++ mutex_lock(&adapter->bus_lock); + res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, + command,size,data); +- up(&adapter->bus_lock); ++ mutex_unlock(&adapter->bus_lock); + } else + res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, + command,size,data); +@@ -1153,6 +1185,7 @@ + EXPORT_SYMBOL(i2c_get_adapter); + EXPORT_SYMBOL(i2c_put_adapter); + EXPORT_SYMBOL(i2c_probe); ++EXPORT_SYMBOL(i2c_probe_device); + + EXPORT_SYMBOL(i2c_smbus_xfer); + EXPORT_SYMBOL(i2c_smbus_write_quick); +--- linux-2.6.16.orig/drivers/i2c/busses/scx200_acb.c 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/scx200_acb.c 2006-03-22 17:06:16.000000000 +0100 +@@ -1,27 +1,26 @@ +-/* linux/drivers/i2c/scx200_acb.c +- ++/* + Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> + + National Semiconductor SCx200 ACCESS.bus support +- ++ Also supports the AMD CS5535 and AMD CS5536 ++ + Based on i2c-keywest.c which is: + Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> + Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> +- ++ + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. +- ++ + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. +- ++ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +- + */ + + #include <linux/module.h> +@@ -32,7 +31,9 @@ + #include <linux/smp_lock.h> + #include <linux/pci.h> + #include <linux/delay.h> ++#include <linux/mutex.h> + #include <asm/io.h> ++#include <asm/msr.h> + + #include <linux/scx200.h> + +@@ -47,16 +48,7 @@ + module_param_array(base, int, NULL, 0); + MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); + +-#ifdef DEBUG +-#define DBG(x...) printk(KERN_DEBUG NAME ": " x) +-#else +-#define DBG(x...) +-#endif +- +-/* The hardware supports interrupt driven mode too, but I haven't +- implemented that. */ +-#define POLLED_MODE 1 +-#define POLL_TIMEOUT (HZ) ++#define POLL_TIMEOUT (HZ/5) + + enum scx200_acb_state { + state_idle, +@@ -79,12 +71,11 @@ + }; + + /* Physical interface */ +-struct scx200_acb_iface +-{ ++struct scx200_acb_iface { + struct scx200_acb_iface *next; + struct i2c_adapter adapter; + unsigned base; +- struct semaphore sem; ++ struct mutex mutex; + + /* State machine data */ + enum scx200_acb_state state; +@@ -100,7 +91,7 @@ + #define ACBSDA (iface->base + 0) + #define ACBST (iface->base + 1) + #define ACBST_SDAST 0x40 /* SDA Status */ +-#define ACBST_BER 0x20 ++#define ACBST_BER 0x20 + #define ACBST_NEGACK 0x10 /* Negative Acknowledge */ + #define ACBST_STASTR 0x08 /* Stall After Start */ + #define ACBST_MASTER 0x02 +@@ -109,9 +100,9 @@ + #define ACBCTL1 (iface->base + 3) + #define ACBCTL1_STASTRE 0x80 + #define ACBCTL1_NMINTE 0x40 +-#define ACBCTL1_ACK 0x10 +-#define ACBCTL1_STOP 0x02 +-#define ACBCTL1_START 0x01 ++#define ACBCTL1_ACK 0x10 ++#define ACBCTL1_STOP 0x02 ++#define ACBCTL1_START 0x01 + #define ACBADDR (iface->base + 4) + #define ACBCTL2 (iface->base + 5) + #define ACBCTL2_ENABLE 0x01 +@@ -122,8 +113,8 @@ + { + const char *errmsg; + +- DBG("state %s, status = 0x%02x\n", +- scx200_acb_state_name[iface->state], status); ++ dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n", ++ scx200_acb_state_name[iface->state], status); + + if (status & ACBST_BER) { + errmsg = "bus error"; +@@ -133,8 +124,17 @@ + errmsg = "not master"; + goto error; + } +- if (status & ACBST_NEGACK) +- goto negack; ++ if (status & ACBST_NEGACK) { ++ dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", ++ scx200_acb_state_name[iface->state]); ++ ++ iface->state = state_idle; ++ iface->result = -ENXIO; ++ ++ outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); ++ outb(ACBST_STASTR | ACBST_NEGACK, ACBST); ++ return; ++ } + + switch (iface->state) { + case state_idle: +@@ -160,10 +160,10 @@ + case state_repeat_start: + outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); + /* fallthrough */ +- ++ + case state_quick: + if (iface->address_byte & 1) { +- if (iface->len == 1) ++ if (iface->len == 1) + outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); + else + outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); +@@ -202,26 +202,15 @@ + outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); + break; + } +- ++ + outb(*iface->ptr++, ACBSDA); + --iface->len; +- ++ + break; + } + + return; + +- negack: +- DBG("negative acknowledge in state %s\n", +- scx200_acb_state_name[iface->state]); +- +- iface->state = state_idle; +- iface->result = -ENXIO; +- +- outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); +- outb(ACBST_STASTR | ACBST_NEGACK, ACBST); +- return; +- + error: + dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, + scx200_acb_state_name[iface->state]); +@@ -231,20 +220,9 @@ + iface->needs_reset = 1; + } + +-static void scx200_acb_timeout(struct scx200_acb_iface *iface) +-{ +- dev_err(&iface->adapter.dev, "timeout in state %s\n", +- scx200_acb_state_name[iface->state]); +- +- iface->state = state_idle; +- iface->result = -EIO; +- iface->needs_reset = 1; +-} +- +-#ifdef POLLED_MODE + static void scx200_acb_poll(struct scx200_acb_iface *iface) + { +- u8 status = 0; ++ u8 status; + unsigned long timeout; + + timeout = jiffies + POLL_TIMEOUT; +@@ -254,17 +232,21 @@ + scx200_acb_machine(iface, status); + return; + } +- msleep(10); ++ yield(); + } + +- scx200_acb_timeout(iface); ++ dev_err(&iface->adapter.dev, "timeout in state %s\n", ++ scx200_acb_state_name[iface->state]); ++ ++ iface->state = state_idle; ++ iface->result = -EIO; ++ iface->needs_reset = 1; + } +-#endif /* POLLED_MODE */ + + static void scx200_acb_reset(struct scx200_acb_iface *iface) + { + /* Disable the ACCESS.bus device and Configure the SCL +- frequency: 16 clock cycles */ ++ frequency: 16 clock cycles */ + outb(0x70, ACBCTL2); + /* Polling mode */ + outb(0, ACBCTL1); +@@ -283,9 +265,9 @@ + } + + static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, +- u16 address, unsigned short flags, +- char rw, u8 command, int size, +- union i2c_smbus_data *data) ++ u16 address, unsigned short flags, ++ char rw, u8 command, int size, ++ union i2c_smbus_data *data) + { + struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); + int len; +@@ -295,53 +277,47 @@ + + switch (size) { + case I2C_SMBUS_QUICK: +- len = 0; +- buffer = NULL; +- break; ++ len = 0; ++ buffer = NULL; ++ break; ++ + case I2C_SMBUS_BYTE: +- if (rw == I2C_SMBUS_READ) { +- len = 1; +- buffer = &data->byte; +- } else { +- len = 1; +- buffer = &command; +- } +- break; ++ len = 1; ++ buffer = rw ? &data->byte : &command; ++ break; ++ + case I2C_SMBUS_BYTE_DATA: +- len = 1; +- buffer = &data->byte; +- break; ++ len = 1; ++ buffer = &data->byte; ++ break; ++ + case I2C_SMBUS_WORD_DATA: + len = 2; +- cur_word = cpu_to_le16(data->word); +- buffer = (u8 *)&cur_word; ++ cur_word = cpu_to_le16(data->word); ++ buffer = (u8 *)&cur_word; + break; ++ + case I2C_SMBUS_BLOCK_DATA: +- len = data->block[0]; +- buffer = &data->block[1]; ++ len = data->block[0]; ++ buffer = &data->block[1]; + break; ++ + default: +- return -EINVAL; ++ return -EINVAL; + } + +- DBG("size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", +- size, address, command, len, rw == I2C_SMBUS_READ); ++ dev_dbg(&adapter->dev, ++ "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", ++ size, address, command, len, rw); + + if (!len && rw == I2C_SMBUS_READ) { +- dev_warn(&adapter->dev, "zero length read\n"); ++ dev_dbg(&adapter->dev, "zero length read\n"); + return -EINVAL; + } + +- if (len && !buffer) { +- dev_warn(&adapter->dev, "nonzero length but no buffer\n"); +- return -EFAULT; +- } +- +- down(&iface->sem); ++ mutex_lock(&iface->mutex); + +- iface->address_byte = address<<1; +- if (rw == I2C_SMBUS_READ) +- iface->address_byte |= 1; ++ iface->address_byte = (address << 1) | rw; + iface->command = command; + iface->ptr = buffer; + iface->len = len; +@@ -355,25 +331,21 @@ + else + iface->state = state_address; + +-#ifdef POLLED_MODE + while (iface->state != state_idle) + scx200_acb_poll(iface); +-#else /* POLLED_MODE */ +-#error Interrupt driven mode not implemented +-#endif /* POLLED_MODE */ + + if (iface->needs_reset) + scx200_acb_reset(iface); + + rc = iface->result; + +- up(&iface->sem); ++ mutex_unlock(&iface->mutex); + + if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) +- data->word = le16_to_cpu(cur_word); ++ data->word = le16_to_cpu(cur_word); + + #ifdef DEBUG +- DBG(": transfer done, result: %d", rc); ++ dev_dbg(&adapter->dev, "transfer done, result: %d", rc); + if (buffer) { + int i; + printk(" data:"); +@@ -400,17 +372,18 @@ + }; + + static struct scx200_acb_iface *scx200_acb_list; ++static DECLARE_MUTEX(scx200_acb_list_mutex); + + static int scx200_acb_probe(struct scx200_acb_iface *iface) + { + u8 val; + + /* Disable the ACCESS.bus device and Configure the SCL +- frequency: 16 clock cycles */ ++ frequency: 16 clock cycles */ + outb(0x70, ACBCTL2); + + if (inb(ACBCTL2) != 0x70) { +- DBG("ACBCTL2 readback failed\n"); ++ pr_debug(NAME ": ACBCTL2 readback failed\n"); + return -ENXIO; + } + +@@ -418,7 +391,8 @@ + + val = inb(ACBCTL1); + if (val) { +- DBG("disabled, but ACBCTL1=0x%02x\n", val); ++ pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n", ++ val); + return -ENXIO; + } + +@@ -428,18 +402,19 @@ + + val = inb(ACBCTL1); + if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { +- DBG("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n", val); ++ pr_debug(NAME ": enabled, but NMINTE won't be set, " ++ "ACBCTL1=0x%02x\n", val); + return -ENXIO; + } + + return 0; + } + +-static int __init scx200_acb_create(int base, int index) ++static int __init scx200_acb_create(const char *text, int base, int index) + { + struct scx200_acb_iface *iface; + struct i2c_adapter *adapter; +- int rc = 0; ++ int rc; + char description[64]; + + iface = kzalloc(sizeof(*iface), GFP_KERNEL); +@@ -451,50 +426,51 @@ + + adapter = &iface->adapter; + i2c_set_adapdata(adapter, iface); +- snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index); ++ snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); + adapter->owner = THIS_MODULE; + adapter->id = I2C_HW_SMBUS_SCX200; + adapter->algo = &scx200_acb_algorithm; +- adapter->class = I2C_CLASS_HWMON; ++ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_DATA; ++ ++ mutex_init(&iface->mutex); + +- init_MUTEX(&iface->sem); ++ snprintf(description, sizeof(description), "%s ACCESS.bus [%s]", ++ text, adapter->name); + +- snprintf(description, sizeof(description), "NatSemi SCx200 ACCESS.bus [%s]", adapter->name); + if (request_region(base, 8, description) == 0) { +- dev_err(&adapter->dev, "can't allocate io 0x%x-0x%x\n", ++ printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n", + base, base + 8-1); + rc = -EBUSY; +- goto errout; ++ goto errout_free; + } + iface->base = base; + + rc = scx200_acb_probe(iface); + if (rc) { +- dev_warn(&adapter->dev, "probe failed\n"); +- goto errout; ++ printk(KERN_WARNING NAME ": probe failed\n"); ++ goto errout_release; + } + + scx200_acb_reset(iface); + + if (i2c_add_adapter(adapter) < 0) { +- dev_err(&adapter->dev, "failed to register\n"); ++ printk(KERN_ERR NAME ": failed to register\n"); + rc = -ENODEV; +- goto errout; ++ goto errout_release; + } + +- lock_kernel(); ++ down(&scx200_acb_list_mutex); + iface->next = scx200_acb_list; + scx200_acb_list = iface; +- unlock_kernel(); ++ up(&scx200_acb_list_mutex); + + return 0; + ++ errout_release: ++ release_region(iface->base, 8); ++ errout_free: ++ kfree(iface); + errout: +- if (iface) { +- if (iface->base) +- release_region(iface->base, 8); +- kfree(iface); +- } + return rc; + } + +@@ -504,50 +480,69 @@ + { }, + }; + ++static struct pci_device_id divil_pci[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, ++ { } /* NULL entry */ ++}; ++ ++#define MSR_LBAR_SMB 0x5140000B ++ ++static int scx200_add_cs553x(void) ++{ ++ u32 low, hi; ++ u32 smb_base; ++ ++ /* Grab & reserve the SMB I/O range */ ++ rdmsr(MSR_LBAR_SMB, low, hi); ++ ++ /* Check the IO mask and whether SMB is enabled */ ++ if (hi != 0x0000F001) { ++ printk(KERN_WARNING NAME ": SMBus not enabled\n"); ++ return -ENODEV; ++ } ++ ++ /* SMBus IO size is 8 bytes */ ++ smb_base = low & 0x0000FFF8; ++ ++ return scx200_acb_create("CS5535", smb_base, 0); ++} ++ + static int __init scx200_acb_init(void) + { + int i; +- int rc; ++ int rc = -ENODEV; + + pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); + + /* Verify that this really is a SCx200 processor */ +- if (pci_dev_present(scx200) == 0) +- return -ENODEV; ++ if (pci_dev_present(scx200)) { ++ for (i = 0; i < MAX_DEVICES; ++i) { ++ if (base[i] > 0) ++ rc = scx200_acb_create("SCx200", base[i], i); ++ } ++ } else if (pci_dev_present(divil_pci)) ++ rc = scx200_add_cs553x(); + +- rc = -ENXIO; +- for (i = 0; i < MAX_DEVICES; ++i) { +- if (base[i] > 0) +- rc = scx200_acb_create(base[i], i); +- } +- if (scx200_acb_list) +- return 0; + return rc; + } + + static void __exit scx200_acb_cleanup(void) + { + struct scx200_acb_iface *iface; +- lock_kernel(); ++ ++ down(&scx200_acb_list_mutex); + while ((iface = scx200_acb_list) != NULL) { + scx200_acb_list = iface->next; +- unlock_kernel(); ++ up(&scx200_acb_list_mutex); + + i2c_del_adapter(&iface->adapter); + release_region(iface->base, 8); + kfree(iface); +- lock_kernel(); ++ down(&scx200_acb_list_mutex); + } +- unlock_kernel(); ++ up(&scx200_acb_list_mutex); + } + + module_init(scx200_acb_init); + module_exit(scx200_acb_cleanup); +- +-/* +- Local variables: +- compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" +- c-basic-offset: 8 +- End: +-*/ +- +--- linux-2.6.16.orig/Documentation/i2c/busses/scx200_acb 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/Documentation/i2c/busses/scx200_acb 2006-03-22 17:06:15.000000000 +0100 +@@ -6,9 +6,10 @@ + ----------------- + + * base: int +- Base addresses for the ACCESS.bus controllers ++ Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices + + Description + ----------- + +-Enable the use of the ACCESS.bus controllers of a SCx200 processor. ++Enable the use of the ACCESS.bus controller on the Geode SCx200 and ++SC1100 processors and the CS5535 and CS5536 Geode companion devices. +--- linux-2.6.16.orig/drivers/i2c/busses/Kconfig 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/Kconfig 2006-03-22 17:06:16.000000000 +0100 +@@ -163,17 +163,22 @@ + I2C bus. + + config I2C_PIIX4 +- tristate "Intel PIIX4" ++ tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" + depends on I2C && PCI + help + If you say yes to this option, support will be included for the Intel + PIIX4 family of mainboard I2C interfaces. Specifically, the following +- versions of the chipset are supported: ++ versions of the chipset are supported (note that Serverworks is part ++ of Broadcom): + Intel PIIX4 + Intel 440MX ++ ATI IXP200 ++ ATI IXP300 ++ ATI IXP400 + Serverworks OSB4 + Serverworks CSB5 + Serverworks CSB6 ++ Serverworks HT-1000 + SMSC Victory66 + + This driver can also be built as a module. If so, the module +@@ -284,7 +289,10 @@ + This driver is a replacement for (and was inspired by) an older + driver named i2c-philips-par. The new driver supports more devices, + and makes it easier to add support for new devices. +- ++ ++ An adapter type parameter is now mandatory. Please read the file ++ Documentation/i2c/busses/i2c-parport for details. ++ + Another driver exists, named i2c-parport-light, which doesn't depend + on the parport driver. This is meant for embedded systems. Don't say + Y here if you intend to say Y or M there. +@@ -389,10 +397,11 @@ + also be specified with a module parameter. + + config SCx200_ACB +- tristate "NatSemi SCx200 ACCESS.bus" +- depends on I2C && PCI ++ tristate "Geode ACCESS.bus support" ++ depends on X86_32 && I2C && PCI + help +- Enable the use of the ACCESS.bus controllers of a SCx200 processor. ++ Enable the use of the ACCESS.bus controllers on the Geode SCx200 and ++ SC1100 processors and the CS5535 and CS5536 Geode companion devices. + + If you don't know what to do here, say N. + +--- linux-2.6.16.orig/drivers/hwmon/w83792d.c 2006-03-22 17:06:10.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/w83792d.c 2006-03-22 17:06:16.000000000 +0100 +@@ -43,6 +43,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-sysfs.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; +@@ -271,7 +272,7 @@ + struct class_device *class_dev; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -300,7 +301,6 @@ + u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ + }; + +-static int w83792d_attach_adapter(struct i2c_adapter *adapter); + static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind); + static int w83792d_detach_client(struct i2c_client *client); + static struct w83792d_data *w83792d_update_device(struct device *dev); +@@ -315,7 +315,9 @@ + .driver = { + .name = "w83792d", + }, +- .attach_adapter = w83792d_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = w83792d_detect, + .detach_client = w83792d_detach_client, + }; + +@@ -382,30 +384,40 @@ + store_in_reg(MIN, min); + store_in_reg(MAX, max); + +-#define sysfs_in_reg(offset) \ +-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ +- NULL, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ +- show_in_min, store_in_min, offset); \ +-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ +- show_in_max, store_in_max, offset); +- +-sysfs_in_reg(0); +-sysfs_in_reg(1); +-sysfs_in_reg(2); +-sysfs_in_reg(3); +-sysfs_in_reg(4); +-sysfs_in_reg(5); +-sysfs_in_reg(6); +-sysfs_in_reg(7); +-sysfs_in_reg(8); +- +-#define device_create_file_in(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \ +-} while (0) ++static struct sensor_device_attribute sda_in_input[] = { ++ SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), ++ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), ++ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), ++ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), ++ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), ++ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), ++ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), ++ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), ++ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), ++}; ++static struct sensor_device_attribute sda_in_min[] = { ++ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), ++ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), ++ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), ++ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), ++ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), ++ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), ++ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), ++ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), ++ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), ++}; ++static struct sensor_device_attribute sda_in_max[] = { ++ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), ++ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), ++ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), ++ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), ++ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), ++ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), ++ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), ++ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), ++ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), ++}; ++ + + #define show_fan_reg(reg) \ + static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ +@@ -486,28 +498,33 @@ + return count; + } + +-#define sysfs_fan(offset) \ +-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ +- offset); \ +-static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ +- show_fan_div, store_fan_div, offset); \ +-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ +- show_fan_min, store_fan_min, offset); +- +-sysfs_fan(1); +-sysfs_fan(2); +-sysfs_fan(3); +-sysfs_fan(4); +-sysfs_fan(5); +-sysfs_fan(6); +-sysfs_fan(7); +- +-#define device_create_file_fan(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \ +-} while (0) ++static struct sensor_device_attribute sda_fan_input[] = { ++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1), ++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2), ++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3), ++ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4), ++ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5), ++ SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6), ++ SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7), ++}; ++static struct sensor_device_attribute sda_fan_min[] = { ++ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1), ++ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2), ++ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3), ++ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4), ++ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5), ++ SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6), ++ SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7), ++}; ++static struct sensor_device_attribute sda_fan_div[] = { ++ SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1), ++ SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2), ++ SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3), ++ SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4), ++ SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5), ++ SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6), ++ SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7), ++}; + + + /* read/write the temperature1, includes measured value and limits */ +@@ -539,21 +556,6 @@ + return count; + } + +- +-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0); +-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1, +- store_temp1, 1); +-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, +- store_temp1, 2); +- +-#define device_create_file_temp1(client) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \ +-} while (0) +- +- + /* read/write the temperature2-3, includes measured value and limits */ + + static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, +@@ -590,25 +592,23 @@ + return count; + } + +-#define sysfs_temp23(name,idx) \ +-static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \ +- idx, 0); \ +-static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \ +- show_temp23, store_temp23, idx, 2); \ +-static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \ +- show_temp23, store_temp23, idx, 4); +- +-sysfs_temp23(temp2,0) +-sysfs_temp23(temp3,1) +- +-#define device_create_file_temp_add(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \ +-device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \ +-device_create_file(&client->dev, \ +-&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \ +-} while (0) ++static struct sensor_device_attribute_2 sda_temp_input[] = { ++ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), ++ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), ++ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), ++}; ++ ++static struct sensor_device_attribute_2 sda_temp_max[] = { ++ SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1), ++ SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2), ++ SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2), ++}; + ++static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { ++ SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2), ++ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4), ++ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4), ++}; + + /* get reatime status of all sensors items: voltage, temp, fan */ + static ssize_t +@@ -620,10 +620,6 @@ + + static + DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +-#define device_create_file_alarms(client) \ +-device_create_file(&client->dev, &dev_attr_alarms); +- +- + + static ssize_t + show_pwm(struct device *dev, struct device_attribute *attr, +@@ -711,26 +707,19 @@ + return count; + } + +-#define sysfs_pwm(offset) \ +-static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ +- show_pwm, store_pwm, offset); \ +-static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ +- show_pwmenable, store_pwmenable, offset); \ +- +-sysfs_pwm(1); +-sysfs_pwm(2); +-sysfs_pwm(3); +- +- +-#define device_create_file_pwm(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \ +-} while (0) +- +-#define device_create_file_pwmenable(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \ +-} while (0) ++static struct sensor_device_attribute sda_pwm[] = { ++ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), ++ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), ++ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), ++}; ++static struct sensor_device_attribute sda_pwm_enable[] = { ++ SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, ++ show_pwmenable, store_pwmenable, 1), ++ SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, ++ show_pwmenable, store_pwmenable, 2), ++ SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, ++ show_pwmenable, store_pwmenable, 3), ++}; + + + static ssize_t +@@ -764,18 +753,14 @@ + return count; + } + +-#define sysfs_pwm_mode(offset) \ +-static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \ +- show_pwm_mode, store_pwm_mode, offset); +- +-sysfs_pwm_mode(1); +-sysfs_pwm_mode(2); +-sysfs_pwm_mode(3); +- +-#define device_create_file_pwm_mode(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \ +-} while (0) ++static struct sensor_device_attribute sda_pwm_mode[] = { ++ SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, ++ show_pwm_mode, store_pwm_mode, 1), ++ SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, ++ show_pwm_mode, store_pwm_mode, 2), ++ SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, ++ show_pwm_mode, store_pwm_mode, 3), ++}; + + + static ssize_t +@@ -788,12 +773,6 @@ + + static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); + +-#define device_create_file_chassis(client) \ +-do { \ +-device_create_file(&client->dev, &dev_attr_chassis); \ +-} while (0) +- +- + static ssize_t + show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) + { +@@ -824,13 +803,6 @@ + static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, + show_chassis_clear, store_chassis_clear); + +-#define device_create_file_chassis_clear(client) \ +-do { \ +-device_create_file(&client->dev, &dev_attr_chassis_clear); \ +-} while (0) +- +- +- + /* For Smart Fan I / Thermal Cruise */ + static ssize_t + show_thermal_cruise(struct device *dev, struct device_attribute *attr, +@@ -864,20 +836,14 @@ + return count; + } + +-#define sysfs_thermal_cruise(offset) \ +-static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \ +- show_thermal_cruise, store_thermal_cruise, offset); +- +-sysfs_thermal_cruise(1); +-sysfs_thermal_cruise(2); +-sysfs_thermal_cruise(3); +- +-#define device_create_file_thermal_cruise(client, offset) \ +-do { \ +-device_create_file(&client->dev, \ +-&sensor_dev_attr_thermal_cruise##offset.dev_attr); \ +-} while (0) +- ++static struct sensor_device_attribute sda_thermal_cruise[] = { ++ SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, ++ show_thermal_cruise, store_thermal_cruise, 1), ++ SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, ++ show_thermal_cruise, store_thermal_cruise, 2), ++ SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, ++ show_thermal_cruise, store_thermal_cruise, 3), ++}; + + /* For Smart Fan I/Thermal Cruise and Smart Fan II */ + static ssize_t +@@ -916,19 +882,14 @@ + return count; + } + +-#define sysfs_tolerance(offset) \ +-static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \ +- show_tolerance, store_tolerance, offset); +- +-sysfs_tolerance(1); +-sysfs_tolerance(2); +-sysfs_tolerance(3); +- +-#define device_create_file_tolerance(client, offset) \ +-do { \ +-device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \ +-} while (0) +- ++static struct sensor_device_attribute sda_tolerance[] = { ++ SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO, ++ show_tolerance, store_tolerance, 1), ++ SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO, ++ show_tolerance, store_tolerance, 2), ++ SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO, ++ show_tolerance, store_tolerance, 3), ++}; + + /* For Smart Fan II */ + static ssize_t +@@ -964,28 +925,34 @@ + return count; + } + +-#define sysfs_sf2_point(offset, index) \ +-static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \ +- show_sf2_point, store_sf2_point, offset, index); +- +-sysfs_sf2_point(1, 1); /* Fan1 */ +-sysfs_sf2_point(2, 1); /* Fan1 */ +-sysfs_sf2_point(3, 1); /* Fan1 */ +-sysfs_sf2_point(4, 1); /* Fan1 */ +-sysfs_sf2_point(1, 2); /* Fan2 */ +-sysfs_sf2_point(2, 2); /* Fan2 */ +-sysfs_sf2_point(3, 2); /* Fan2 */ +-sysfs_sf2_point(4, 2); /* Fan2 */ +-sysfs_sf2_point(1, 3); /* Fan3 */ +-sysfs_sf2_point(2, 3); /* Fan3 */ +-sysfs_sf2_point(3, 3); /* Fan3 */ +-sysfs_sf2_point(4, 3); /* Fan3 */ +- +-#define device_create_file_sf2_point(client, offset, index) \ +-do { \ +-device_create_file(&client->dev, \ +-&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \ +-} while (0) ++static struct sensor_device_attribute_2 sda_sf2_point[] = { ++ SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 1, 1), ++ SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 2, 1), ++ SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 3, 1), ++ SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 4, 1), ++ ++ SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 1, 2), ++ SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 2, 2), ++ SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 3, 2), ++ SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 4, 2), ++ ++ SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 1, 3), ++ SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 2, 3), ++ SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 3, 3), ++ SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_point, store_sf2_point, 4, 3), ++}; + + + static ssize_t +@@ -1026,39 +993,28 @@ + return count; + } + +-#define sysfs_sf2_level(offset, index) \ +-static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \ +- show_sf2_level, store_sf2_level, offset, index); +- +-sysfs_sf2_level(1, 1); /* Fan1 */ +-sysfs_sf2_level(2, 1); /* Fan1 */ +-sysfs_sf2_level(3, 1); /* Fan1 */ +-sysfs_sf2_level(1, 2); /* Fan2 */ +-sysfs_sf2_level(2, 2); /* Fan2 */ +-sysfs_sf2_level(3, 2); /* Fan2 */ +-sysfs_sf2_level(1, 3); /* Fan3 */ +-sysfs_sf2_level(2, 3); /* Fan3 */ +-sysfs_sf2_level(3, 3); /* Fan3 */ +- +-#define device_create_file_sf2_level(client, offset, index) \ +-do { \ +-device_create_file(&client->dev, \ +-&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \ +-} while (0) +- +- +-/* This function is called when: +- * w83792d_driver is inserted (when this module is loaded), for each +- available adapter +- * when a new adapter is inserted (and w83792d_driver is still present) */ +-static int +-w83792d_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, w83792d_detect); +-} +- ++static struct sensor_device_attribute_2 sda_sf2_level[] = { ++ SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 1, 1), ++ SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 2, 1), ++ SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 3, 1), ++ ++ SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 1, 2), ++ SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 2, 2), ++ SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 3, 2), ++ ++ SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 1, 3), ++ SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 2, 3), ++ SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, ++ show_sf2_level, store_sf2_level, 3, 3), ++}; + + static int + w83792d_create_subclient(struct i2c_adapter *adapter, +@@ -1147,12 +1103,19 @@ + return err; + } + ++static void device_create_file_fan(struct device *dev, int i) ++{ ++ device_create_file(dev, &sda_fan_input[i].dev_attr); ++ device_create_file(dev, &sda_fan_div[i].dev_attr); ++ device_create_file(dev, &sda_fan_min[i].dev_attr); ++} + + static int + w83792d_detect(struct i2c_adapter *adapter, int address, int kind) + { + int i = 0, val1 = 0, val2; +- struct i2c_client *new_client; ++ struct i2c_client *client; ++ struct device *dev; + struct w83792d_data *data; + int err = 0; + const char *client_name = ""; +@@ -1170,12 +1133,13 @@ + goto ERROR0; + } + +- new_client = &data->client; +- i2c_set_clientdata(new_client, data); +- new_client->addr = address; +- new_client->adapter = adapter; +- new_client->driver = &w83792d_driver; +- new_client->flags = 0; ++ client = &data->client; ++ dev = &client->dev; ++ i2c_set_clientdata(client, data); ++ client->addr = address; ++ client->adapter = adapter; ++ client->driver = &w83792d_driver; ++ client->flags = 0; + + /* Now, we do the remaining detection. */ + +@@ -1184,50 +1148,49 @@ + force_*=... parameter, and the Winbond will be reset to the right + bank. */ + if (kind < 0) { +- if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) { +- dev_warn(&new_client->dev, "Detection failed at step " +- "3\n"); ++ if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) { ++ dev_dbg(dev, "Detection failed at step 1\n"); + goto ERROR1; + } +- val1 = w83792d_read_value(new_client, W83792D_REG_BANK); +- val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); ++ val1 = w83792d_read_value(client, W83792D_REG_BANK); ++ val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); + /* Check for Winbond ID if in bank 0 */ + if (!(val1 & 0x07)) { /* is Bank0 */ + if (((!(val1 & 0x80)) && (val2 != 0xa3)) || + ((val1 & 0x80) && (val2 != 0x5c))) { ++ dev_dbg(dev, "Detection failed at step 2\n"); + goto ERROR1; + } + } + /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR + should match */ +- if (w83792d_read_value(new_client, ++ if (w83792d_read_value(client, + W83792D_REG_I2C_ADDR) != address) { +- dev_warn(&new_client->dev, "Detection failed " +- "at step 5\n"); ++ dev_dbg(dev, "Detection failed at step 3\n"); + goto ERROR1; + } + } + + /* We have either had a force parameter, or we have already detected the + Winbond. Put it now into bank 0 and Vendor ID High Byte */ +- w83792d_write_value(new_client, ++ w83792d_write_value(client, + W83792D_REG_BANK, +- (w83792d_read_value(new_client, ++ (w83792d_read_value(client, + W83792D_REG_BANK) & 0x78) | 0x80); + + /* Determine the chip type. */ + if (kind <= 0) { + /* get vendor ID */ +- val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN); ++ val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); + if (val2 != 0x5c) { /* the vendor is NOT Winbond */ + goto ERROR1; + } +- val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID); ++ val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); + if (val1 == 0x7a) { + kind = w83792d; + } else { + if (kind == 0) +- dev_warn(&new_client->dev, ++ dev_warn(dev, + "w83792d: Ignoring 'force' parameter for" + " unknown chip at adapter %d, address" + " 0x%02x\n", i2c_adapter_id(adapter), +@@ -1239,120 +1202,86 @@ + if (kind == w83792d) { + client_name = "w83792d"; + } else { +- dev_err(&new_client->dev, "w83792d: Internal error: unknown" ++ dev_err(dev, "w83792d: Internal error: unknown" + " kind (%d)?!?", kind); + goto ERROR1; + } + + /* Fill in the remaining client fields and put into the global list */ +- strlcpy(new_client->name, client_name, I2C_NAME_SIZE); ++ strlcpy(client->name, client_name, I2C_NAME_SIZE); + data->type = kind; + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ +- if ((err = i2c_attach_client(new_client))) ++ if ((err = i2c_attach_client(client))) + goto ERROR1; + + if ((err = w83792d_detect_subclients(adapter, address, +- kind, new_client))) ++ kind, client))) + goto ERROR2; + + /* Initialize the chip */ +- w83792d_init_client(new_client); ++ w83792d_init_client(client); + + /* A few vars need to be filled upon startup */ + for (i = 0; i < 7; i++) { +- data->fan_min[i] = w83792d_read_value(new_client, ++ data->fan_min[i] = w83792d_read_value(client, + W83792D_REG_FAN_MIN[i]); + } + + /* Register sysfs hooks */ +- data->class_dev = hwmon_device_register(&new_client->dev); ++ data->class_dev = hwmon_device_register(dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto ERROR3; + } +- device_create_file_in(new_client, 0); +- device_create_file_in(new_client, 1); +- device_create_file_in(new_client, 2); +- device_create_file_in(new_client, 3); +- device_create_file_in(new_client, 4); +- device_create_file_in(new_client, 5); +- device_create_file_in(new_client, 6); +- device_create_file_in(new_client, 7); +- device_create_file_in(new_client, 8); +- +- device_create_file_fan(new_client, 1); +- device_create_file_fan(new_client, 2); +- device_create_file_fan(new_client, 3); ++ for (i = 0; i < 9; i++) { ++ device_create_file(dev, &sda_in_input[i].dev_attr); ++ device_create_file(dev, &sda_in_max[i].dev_attr); ++ device_create_file(dev, &sda_in_min[i].dev_attr); ++ } ++ for (i = 0; i < 3; i++) ++ device_create_file_fan(dev, i); + + /* Read GPIO enable register to check if pins for fan 4,5 are used as + GPIO */ +- val1 = w83792d_read_value(new_client, W83792D_REG_GPIO_EN); ++ val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); + if (!(val1 & 0x40)) +- device_create_file_fan(new_client, 4); ++ device_create_file_fan(dev, 3); + if (!(val1 & 0x20)) +- device_create_file_fan(new_client, 5); ++ device_create_file_fan(dev, 4); + +- val1 = w83792d_read_value(new_client, W83792D_REG_PIN); ++ val1 = w83792d_read_value(client, W83792D_REG_PIN); + if (val1 & 0x40) +- device_create_file_fan(new_client, 6); ++ device_create_file_fan(dev, 5); + if (val1 & 0x04) +- device_create_file_fan(new_client, 7); ++ device_create_file_fan(dev, 6); ++ ++ for (i = 0; i < 3; i++) { ++ device_create_file(dev, &sda_temp_input[i].dev_attr); ++ device_create_file(dev, &sda_temp_max[i].dev_attr); ++ device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); ++ device_create_file(dev, &sda_thermal_cruise[i].dev_attr); ++ device_create_file(dev, &sda_tolerance[i].dev_attr); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) { ++ device_create_file(dev, &sda_pwm[i].dev_attr); ++ device_create_file(dev, &sda_pwm_enable[i].dev_attr); ++ device_create_file(dev, &sda_pwm_mode[i].dev_attr); ++ } ++ ++ device_create_file(dev, &dev_attr_alarms); ++ device_create_file(dev, &dev_attr_chassis); ++ device_create_file(dev, &dev_attr_chassis_clear); ++ ++ for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++) ++ device_create_file(dev, &sda_sf2_point[i].dev_attr); + +- device_create_file_temp1(new_client); /* Temp1 */ +- device_create_file_temp_add(new_client, 2); /* Temp2 */ +- device_create_file_temp_add(new_client, 3); /* Temp3 */ +- +- device_create_file_alarms(new_client); +- +- device_create_file_pwm(new_client, 1); +- device_create_file_pwm(new_client, 2); +- device_create_file_pwm(new_client, 3); +- +- device_create_file_pwmenable(new_client, 1); +- device_create_file_pwmenable(new_client, 2); +- device_create_file_pwmenable(new_client, 3); +- +- device_create_file_pwm_mode(new_client, 1); +- device_create_file_pwm_mode(new_client, 2); +- device_create_file_pwm_mode(new_client, 3); +- +- device_create_file_chassis(new_client); +- device_create_file_chassis_clear(new_client); +- +- device_create_file_thermal_cruise(new_client, 1); +- device_create_file_thermal_cruise(new_client, 2); +- device_create_file_thermal_cruise(new_client, 3); +- +- device_create_file_tolerance(new_client, 1); +- device_create_file_tolerance(new_client, 2); +- device_create_file_tolerance(new_client, 3); +- +- device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */ +- device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */ +- device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */ +- device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */ +- device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */ +- device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */ +- device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */ +- device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */ +- device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */ +- device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */ +- device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */ +- device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */ +- +- device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */ +- device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */ +- device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */ +- device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */ +- device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */ +- device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */ +- device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */ +- device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */ +- device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */ ++ for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++) ++ device_create_file(dev, &sda_sf2_level[i].dev_attr); + + return 0; + +@@ -1366,7 +1295,7 @@ + kfree(data->lm75[1]); + } + ERROR2: +- i2c_detach_client(new_client); ++ i2c_detach_client(client); + ERROR1: + kfree(data); + ERROR0: +@@ -1434,7 +1363,7 @@ + int i, j; + u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after + (jiffies - data->last_updated, (unsigned long) (HZ * 3)) +@@ -1545,7 +1474,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + #ifdef DEBUG + w83792d_print_debug(data, dev); +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-amd756-s4882.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-amd756-s4882.c 2006-03-22 17:06:15.000000000 +0100 +@@ -38,6 +38,7 @@ + #include <linux/slab.h> + #include <linux/init.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + extern struct i2c_adapter amd756_smbus; + +@@ -45,7 +46,7 @@ + static struct i2c_algorithm *s4882_algo; + + /* Wrapper access functions for multiplexed SMBus */ +-static struct semaphore amd756_lock; ++static DEFINE_MUTEX(amd756_lock); + + static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, +@@ -59,12 +60,12 @@ + || addr == 0x18) + return -1; + +- down(&amd756_lock); ++ mutex_lock(&amd756_lock); + + error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, + command, size, data); + +- up(&amd756_lock); ++ mutex_unlock(&amd756_lock); + + return error; + } +@@ -87,7 +88,7 @@ + if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) + return -1; + +- down(&amd756_lock); ++ mutex_lock(&amd756_lock); + + if (last_channels != channels) { + union i2c_smbus_data mplxdata; +@@ -105,7 +106,7 @@ + command, size, data); + + UNLOCK: +- up(&amd756_lock); ++ mutex_unlock(&amd756_lock); + return error; + } + +@@ -166,8 +167,6 @@ + } + + printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); +- init_MUTEX(&amd756_lock); +- + /* Define the 5 virtual adapters and algorithms structures */ + if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), + GFP_KERNEL))) { +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-isa.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-isa.c 2006-03-22 17:06:15.000000000 +0100 +@@ -125,7 +125,7 @@ + + static int __init i2c_isa_init(void) + { +- init_MUTEX(&isa_adapter.clist_lock); ++ mutex_init(&isa_adapter.clist_lock); + INIT_LIST_HEAD(&isa_adapter.clients); + + isa_adapter.nr = ANY_I2C_ISA_BUS; +--- linux-2.6.16.orig/drivers/i2c/chips/eeprom.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/eeprom.c 2006-03-22 17:06:16.000000000 +0100 +@@ -33,6 +33,7 @@ + #include <linux/sched.h> + #include <linux/jiffies.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, +@@ -54,7 +55,7 @@ + /* Each client has this additional data */ + struct eeprom_data { + struct i2c_client client; +- struct semaphore update_lock; ++ struct mutex update_lock; + u8 valid; /* bitfield, bit!=0 if slice is valid */ + unsigned long last_updated[8]; /* In jiffies, 8 slices */ + u8 data[EEPROM_SIZE]; /* Register values */ +@@ -62,7 +63,6 @@ + }; + + +-static int eeprom_attach_adapter(struct i2c_adapter *adapter); + static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); + static int eeprom_detach_client(struct i2c_client *client); + +@@ -72,7 +72,9 @@ + .name = "eeprom", + }, + .id = I2C_DRIVERID_EEPROM, +- .attach_adapter = eeprom_attach_adapter, ++ .class = I2C_CLASS_DATA, ++ .address_data = &addr_data, ++ .detect_client = eeprom_detect, + .detach_client = eeprom_detach_client, + }; + +@@ -81,7 +83,7 @@ + struct eeprom_data *data = i2c_get_clientdata(client); + int i, j; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (!(data->valid & (1 << slice)) || + time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { +@@ -107,7 +109,7 @@ + data->valid |= (1 << slice); + } + exit: +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +@@ -149,11 +151,6 @@ + .read = eeprom_read, + }; + +-static int eeprom_attach_adapter(struct i2c_adapter *adapter) +-{ +- return i2c_probe(adapter, &addr_data, eeprom_detect); +-} +- + /* This function is called by i2c_probe */ + static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) + { +@@ -187,7 +184,7 @@ + /* Fill in the remaining client fields */ + strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + data->nature = UNKNOWN; + + /* Tell the I2C layer a new client has arrived */ +--- linux-2.6.16.orig/drivers/i2c/chips/max6875.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/max6875.c 2006-03-22 17:06:15.000000000 +0100 +@@ -31,7 +31,7 @@ + #include <linux/module.h> + #include <linux/slab.h> + #include <linux/i2c.h> +-#include <asm/semaphore.h> ++#include <linux/mutex.h> + + /* Do not scan - the MAX6875 access method will write to some EEPROM chips */ + static unsigned short normal_i2c[] = {I2C_CLIENT_END}; +@@ -54,7 +54,7 @@ + /* Each client has this additional data */ + struct max6875_data { + struct i2c_client client; +- struct semaphore update_lock; ++ struct mutex update_lock; + + u32 valid; + u8 data[USER_EEPROM_SIZE]; +@@ -83,7 +83,7 @@ + if (slice >= USER_EEPROM_SLICES) + return; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + buf = &data->data[slice << SLICE_BITS]; + +@@ -122,7 +122,7 @@ + data->valid |= (1 << slice); + } + exit_up: +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, +@@ -196,7 +196,7 @@ + real_client->driver = &max6875_driver; + real_client->flags = 0; + strlcpy(real_client->name, "max6875", I2C_NAME_SIZE); +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Init fake client data */ + /* set the client data to the i2c_client so that it will get freed */ +--- linux-2.6.16.orig/drivers/i2c/chips/pcf8591.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/pcf8591.c 2006-03-22 17:06:15.000000000 +0100 +@@ -24,6 +24,7 @@ + #include <linux/init.h> + #include <linux/slab.h> + #include <linux/i2c.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, +@@ -74,7 +75,7 @@ + + struct pcf8591_data { + struct i2c_client client; +- struct semaphore update_lock; ++ struct mutex update_lock; + + u8 control; + u8 aout; +@@ -144,13 +145,13 @@ + struct pcf8591_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if (val) + data->control |= PCF8591_CONTROL_AOEF; + else + data->control &= ~PCF8591_CONTROL_AOEF; + i2c_smbus_write_byte(client, data->control); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -200,7 +201,7 @@ + /* Fill in the remaining client fields and put it into the global + list */ + strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE); +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -265,7 +266,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct pcf8591_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { + data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) +@@ -278,7 +279,7 @@ + } + value = i2c_smbus_read_byte(client); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + if ((channel == 2 && input_mode == 2) || + (channel != 3 && (input_mode == 1 || input_mode == 3))) +--- linux-2.6.16.orig/drivers/i2c/chips/tps65010.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/tps65010.c 2006-03-22 17:06:15.000000000 +0100 +@@ -32,6 +32,7 @@ + #include <linux/suspend.h> + #include <linux/debugfs.h> + #include <linux/seq_file.h> ++#include <linux/mutex.h> + + #include <asm/irq.h> + #include <asm/mach-types.h> +@@ -81,7 +82,7 @@ + + struct tps65010 { + struct i2c_client client; +- struct semaphore lock; ++ struct mutex lock; + int irq; + struct work_struct work; + struct dentry *file; +@@ -218,7 +219,7 @@ + seq_printf(s, "driver %s\nversion %s\nchip %s\n\n", + DRIVER_NAME, DRIVER_VERSION, chip); + +- down(&tps->lock); ++ mutex_lock(&tps->lock); + + /* FIXME how can we tell whether a battery is present? + * likely involves a charge gauging chip (like BQ26501). +@@ -300,7 +301,7 @@ + (v2 & (1 << (4 + i))) ? "rising" : "falling"); + } + +- up(&tps->lock); ++ mutex_unlock(&tps->lock); + return 0; + } + +@@ -416,7 +417,7 @@ + { + struct tps65010 *tps = _tps; + +- down(&tps->lock); ++ mutex_lock(&tps->lock); + + tps65010_interrupt(tps); + +@@ -444,7 +445,7 @@ + if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags)) + enable_irq(tps->irq); + +- up(&tps->lock); ++ mutex_unlock(&tps->lock); + } + + static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs) +@@ -505,7 +506,7 @@ + if (!tps) + return 0; + +- init_MUTEX(&tps->lock); ++ mutex_init(&tps->lock); + INIT_WORK(&tps->work, tps65010_work, tps); + tps->irq = -1; + tps->client.addr = address; +@@ -695,7 +696,7 @@ + if ((gpio < GPIO1) || (gpio > GPIO4)) + return -EINVAL; + +- down(&the_tps->lock); ++ mutex_lock(&the_tps->lock); + + defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO); + +@@ -720,7 +721,7 @@ + gpio, value ? "high" : "low", + i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO)); + +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + return status; + } + EXPORT_SYMBOL(tps65010_set_gpio_out_value); +@@ -745,7 +746,7 @@ + led = LED2; + } + +- down(&the_tps->lock); ++ mutex_lock(&the_tps->lock); + + pr_debug("%s: led%i_on 0x%02x\n", DRIVER_NAME, led, + i2c_smbus_read_byte_data(&the_tps->client, +@@ -771,7 +772,7 @@ + default: + printk(KERN_ERR "%s: Wrong mode parameter for set_led()\n", + DRIVER_NAME); +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + return -EINVAL; + } + +@@ -781,7 +782,7 @@ + if (status != 0) { + printk(KERN_ERR "%s: Failed to write led%i_on register\n", + DRIVER_NAME, led); +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + return status; + } + +@@ -794,7 +795,7 @@ + if (status != 0) { + printk(KERN_ERR "%s: Failed to write led%i_per register\n", + DRIVER_NAME, led); +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + return status; + } + +@@ -802,7 +803,7 @@ + i2c_smbus_read_byte_data(&the_tps->client, + TPS_LED1_PER + offs)); + +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + + return status; + } +@@ -820,7 +821,7 @@ + if (!the_tps) + return -ENODEV; + +- down(&the_tps->lock); ++ mutex_lock(&the_tps->lock); + + vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2); + vdcdc2 &= ~(1 << 1); +@@ -831,7 +832,7 @@ + + pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off"); + +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + return status; + } + EXPORT_SYMBOL(tps65010_set_vib); +@@ -848,7 +849,7 @@ + if (!the_tps) + return -ENODEV; + +- down(&the_tps->lock); ++ mutex_lock(&the_tps->lock); + + pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME, + mode ? "enable" : "disable", +@@ -876,7 +877,7 @@ + pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, + i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); + +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + + return status; + } +@@ -894,7 +895,7 @@ + if (!the_tps) + return -ENODEV; + +- down(&the_tps->lock); ++ mutex_lock(&the_tps->lock); + + pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, + i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); +@@ -909,7 +910,7 @@ + pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME, + i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1)); + +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + + return status; + } +@@ -931,7 +932,7 @@ + if (!the_tps || the_tps->por) + return -ENODEV; + +- down(&the_tps->lock); ++ mutex_lock(&the_tps->lock); + + pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n", + DRIVER_NAME, +@@ -959,7 +960,7 @@ + if (status != 0) { + printk(KERN_ERR "%s: Failed to write chconfig register\n", + DRIVER_NAME); +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + return status; + } + +@@ -977,7 +978,7 @@ + pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME, + i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1)); + +- up(&the_tps->lock); ++ mutex_unlock(&the_tps->lock); + + return status; + } +--- linux-2.6.16.orig/include/linux/i2c.h 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/include/linux/i2c.h 2006-03-22 17:06:21.000000000 +0100 +@@ -32,7 +32,7 @@ + #include <linux/mod_devicetable.h> + #include <linux/device.h> /* for struct device */ + #include <linux/sched.h> /* for completion */ +-#include <asm/semaphore.h> ++#include <linux/mutex.h> + + /* --- For i2c-isa ---------------------------------------------------- */ + +@@ -48,6 +48,7 @@ + struct i2c_adapter; + struct i2c_client; + struct i2c_driver; ++struct i2c_client_address_data; + union i2c_smbus_data; + + /* +@@ -116,6 +117,7 @@ + struct i2c_driver { + int id; + unsigned int class; ++ struct i2c_client_address_data *address_data; + + /* Notifies the driver that a new bus has appeared. This routine + * can be used by the driver to test if the bus meets its conditions +@@ -133,6 +135,15 @@ + */ + int (*detach_client)(struct i2c_client *); + ++ /* Requests that the driver validate an address on a bus and attach a ++ * new client. If this routine is supplied, it will be called for ++ * each device on new buses that appear, provided the bus class ++ * matches the class field and devices exist at the addresses listed ++ * in the address_data field. For most drivers, this mechanism can ++ * be used instead of an attach_adapter routine. ++ */ ++ int (*detect_client)(struct i2c_adapter *, int addr, int kind); ++ + /* a ioctl like command that can be used to perform specific functions + * with the device. + */ +@@ -225,8 +236,8 @@ + int (*client_unregister)(struct i2c_client *); + + /* data fields that are valid for all devices */ +- struct semaphore bus_lock; +- struct semaphore clist_lock; ++ struct mutex bus_lock; ++ struct mutex clist_lock; + + int timeout; + int retries; +@@ -262,7 +273,7 @@ + #define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */ + #define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */ + #define I2C_CLASS_TV_DIGITAL (1<<2) /* dvb cards */ +-#define I2C_CLASS_DDC (1<<3) /* i2c-matroxfb ? */ ++#define I2C_CLASS_DATA (1<<3) /* data storage */ + #define I2C_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */ + #define I2C_CLASS_CAM_DIGITAL (1<<5) /* most webcams */ + #define I2C_CLASS_SOUND (1<<6) /* sound devices */ +@@ -329,6 +340,10 @@ + struct i2c_client_address_data *address_data, + int (*found_proc) (struct i2c_adapter *, int, int)); + ++/* Direct chip probing function to create clients by address */ ++extern int i2c_probe_device(struct i2c_adapter *adapter, int driver_id, ++ int addr, int kind); ++ + /* An ioctl like call to set div. parameters of the adapter. + */ + extern int i2c_control(struct i2c_client *,unsigned int, unsigned long); +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-pxa.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-pxa.c 2006-03-22 17:06:15.000000000 +0100 +@@ -647,7 +647,7 @@ + } + + /* +- * We are protected by the adapter bus semaphore. ++ * We are protected by the adapter bus mutex. + */ + static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) + { +--- linux-2.6.16.orig/drivers/hwmon/adm1021.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/adm1021.c 2006-03-22 17:06:16.000000000 +0100 +@@ -26,6 +26,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + + /* Addresses to scan */ +@@ -92,7 +93,7 @@ + struct class_device *class_dev; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -111,7 +112,6 @@ + u8 remote_temp_offset_prec; + }; + +-static int adm1021_attach_adapter(struct i2c_adapter *adapter); + static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind); + static void adm1021_init_client(struct i2c_client *client); + static int adm1021_detach_client(struct i2c_client *client); +@@ -130,7 +130,9 @@ + .name = "adm1021", + }, + .id = I2C_DRIVERID_ADM1021, +- .attach_adapter = adm1021_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = adm1021_detect, + .detach_client = adm1021_detach_client, + }; + +@@ -162,10 +164,10 @@ + struct adm1021_data *data = i2c_get_clientdata(client); \ + int temp = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = TEMP_TO_REG(temp); \ + adm1021_write_value(client, reg, data->value); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + set(temp_max, ADM1021_REG_TOS_W); +@@ -182,13 +184,6 @@ + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + + +-static int adm1021_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, adm1021_detect); +-} +- + static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) + { + int i; +@@ -275,7 +270,7 @@ + strlcpy(new_client->name, type_name, I2C_NAME_SIZE); + data->type = kind; + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -351,7 +346,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct adm1021_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -375,7 +370,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/adm1025.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/adm1025.c 2006-03-22 17:06:16.000000000 +0100 +@@ -53,6 +53,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -107,7 +108,6 @@ + * Functions declaration + */ + +-static int adm1025_attach_adapter(struct i2c_adapter *adapter); + static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind); + static void adm1025_init_client(struct i2c_client *client); + static int adm1025_detach_client(struct i2c_client *client); +@@ -122,7 +122,9 @@ + .name = "adm1025", + }, + .id = I2C_DRIVERID_ADM1025, +- .attach_adapter = adm1025_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = adm1025_detect, + .detach_client = adm1025_detach_client, + }; + +@@ -133,7 +135,7 @@ + struct adm1025_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -207,11 +209,11 @@ + struct adm1025_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->in_min[offset] = IN_TO_REG(val, in_scale[offset]); \ + i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(offset), \ + data->in_min[offset]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } \ + static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ +@@ -221,11 +223,11 @@ + struct adm1025_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->in_max[offset] = IN_TO_REG(val, in_scale[offset]); \ + i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(offset), \ + data->in_max[offset]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } \ + static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ +@@ -247,11 +249,11 @@ + struct adm1025_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->temp_min[offset-1] = TEMP_TO_REG(val); \ + i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(offset-1), \ + data->temp_min[offset-1]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } \ + static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \ +@@ -261,11 +263,11 @@ + struct adm1025_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->temp_max[offset-1] = TEMP_TO_REG(val); \ + i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(offset-1), \ + data->temp_max[offset-1]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } \ + static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ +@@ -307,13 +309,6 @@ + * Real code + */ + +-static int adm1025_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, adm1025_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -404,7 +399,7 @@ + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -523,7 +518,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct adm1025_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { + int i; +@@ -558,7 +553,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/adm1026.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/adm1026.c 2006-03-22 17:06:21.000000000 +0100 +@@ -32,6 +32,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; +@@ -260,10 +261,10 @@ + struct adm1026_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + int valid; /* !=0 if following fields are valid */ + unsigned long last_reading; /* In jiffies */ + unsigned long last_config; /* In jiffies */ +@@ -294,13 +295,11 @@ + u8 config3; /* Register value */ + }; + +-static int adm1026_attach_adapter(struct i2c_adapter *adapter); + static int adm1026_detect(struct i2c_adapter *adapter, int address, + int kind); + static int adm1026_detach_client(struct i2c_client *client); +-static int adm1026_read_value(struct i2c_client *client, u8 register); +-static int adm1026_write_value(struct i2c_client *client, u8 register, +- int value); ++static int adm1026_read_value(struct i2c_client *client, u8 reg); ++static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); + static void adm1026_print_gpio(struct i2c_client *client); + static void adm1026_fixup_gpio(struct i2c_client *client); + static struct adm1026_data *adm1026_update_device(struct device *dev); +@@ -311,18 +310,12 @@ + .driver = { + .name = "adm1026", + }, +- .attach_adapter = adm1026_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = adm1026_detect, + .detach_client = adm1026_detach_client, + }; + +-static int adm1026_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) { +- return 0; +- } +- return i2c_probe(adapter, &addr_data, adm1026_detect); +-} +- + static int adm1026_detach_client(struct i2c_client *client) + { + struct adm1026_data *data = i2c_get_clientdata(client); +@@ -575,7 +568,7 @@ + int i; + long value, alarms, gpio; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if (!data->valid + || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) { + /* Things that change quickly */ +@@ -710,7 +703,7 @@ + dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n"); + data->vid = (data->gpio >> 11) & 0x1f; + data->valid = 1; +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return data; + } + +@@ -739,10 +732,10 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = INS_TO_REG(nr, val); + adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, +@@ -762,10 +755,10 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = INS_TO_REG(nr, val); + adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -813,10 +806,10 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); + adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf) +@@ -831,10 +824,10 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); + adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -874,11 +867,11 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); + adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), + data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -939,7 +932,7 @@ + if (new_div == 0) { + return -EINVAL; + } +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + orig_div = data->fan_div[nr]; + data->fan_div[nr] = DIV_FROM_REG(new_div); + +@@ -958,7 +951,7 @@ + if (data->fan_div[nr] != orig_div) { + fixup_fan_min(dev,nr,orig_div); + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1001,11 +994,11 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_min[nr] = TEMP_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], + data->temp_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, +@@ -1025,11 +1018,11 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[nr] = TEMP_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], + data->temp_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1064,11 +1057,11 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_offset[nr] = TEMP_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], + data->temp_offset[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1115,11 +1108,11 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_tmin[nr] = TEMP_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], + data->temp_tmin[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1150,11 +1143,11 @@ + int val = simple_strtol(buf, NULL, 10); + + if ((val == 1) || (val==0)) { +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); + adm1026_write_value(client, ADM1026_REG_CONFIG1, + data->config1); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + return count; + } +@@ -1184,11 +1177,11 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_crit[nr] = TEMP_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], + data->temp_crit[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1212,10 +1205,10 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->analog_out = DAC_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1267,7 +1260,7 @@ + int val = simple_strtol(buf, NULL, 10); + unsigned long mask; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->alarm_mask = val & 0x7fffffff; + mask = data->alarm_mask + | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); +@@ -1282,7 +1275,7 @@ + mask >>= 8; + adm1026_write_value(client, ADM1026_REG_MASK4, + mask & 0xff); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1303,7 +1296,7 @@ + int val = simple_strtol(buf, NULL, 10); + long gpio; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->gpio = val & 0x1ffff; + gpio = data->gpio; + adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7,gpio & 0xff); +@@ -1311,7 +1304,7 @@ + adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15,gpio & 0xff); + gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); + adm1026_write_value(client, ADM1026_REG_STATUS4,gpio & 0xff); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1331,7 +1324,7 @@ + int val = simple_strtol(buf, NULL, 10); + long mask; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->gpio_mask = val & 0x1ffff; + mask = data->gpio_mask; + adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7,mask & 0xff); +@@ -1339,7 +1332,7 @@ + adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15,mask & 0xff); + mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); + adm1026_write_value(client, ADM1026_REG_MASK1,mask & 0xff); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -1359,10 +1352,10 @@ + if (data->pwm1.enable == 1) { + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm1.pwm = PWM_TO_REG(val); + adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + return count; + } +@@ -1378,14 +1371,14 @@ + struct adm1026_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); + if (data->pwm1.enable == 2) { /* apply immediately */ + data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | + PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); + adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf) +@@ -1406,7 +1399,7 @@ + int old_enable; + + if ((val >= 0) && (val < 3)) { +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + old_enable = data->pwm1.enable; + data->pwm1.enable = val; + data->config1 = (data->config1 & ~CFG1_PWM_AFC) +@@ -1424,7 +1417,7 @@ + adm1026_write_value(client, ADM1026_REG_PWM, + data->pwm1.pwm); + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + return count; + } +@@ -1541,7 +1534,7 @@ + /* Fill in the remaining client fields */ + data->type = kind; + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +--- linux-2.6.16.orig/drivers/hwmon/adm1031.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/adm1031.c 2006-03-22 17:06:16.000000000 +0100 +@@ -28,6 +28,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Following macros takes channel parameter starting from 0 to 2 */ + #define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) +@@ -70,7 +71,7 @@ + struct adm1031_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + int chip_type; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ +@@ -97,7 +98,6 @@ + s8 temp_crit[3]; + }; + +-static int adm1031_attach_adapter(struct i2c_adapter *adapter); + static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind); + static void adm1031_init_client(struct i2c_client *client); + static int adm1031_detach_client(struct i2c_client *client); +@@ -108,7 +108,9 @@ + .driver = { + .name = "adm1031", + }, +- .attach_adapter = adm1031_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = adm1031_detect, + .detach_client = adm1031_detach_client, + }; + +@@ -262,10 +264,10 @@ + + old_fan_mode = data->conf1; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®))) { +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return ret; + } + if (((data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1)) & ADM1031_CONF1_AUTO_MODE) ^ +@@ -288,7 +290,7 @@ + } + data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); + adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -329,11 +331,11 @@ + struct adm1031_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); + adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), + data->auto_temp[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr) +@@ -349,11 +351,11 @@ + struct adm1031_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]); + adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), + data->temp_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -405,11 +407,11 @@ + int val = simple_strtol(buf, NULL, 10); + int reg; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && + (((val>>4) & 0xf) != 5)) { + /* In automatic mode, the only PWM accepted is 33% */ +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + data->pwm[nr] = PWM_TO_REG(val); +@@ -417,7 +419,7 @@ + adm1031_write_value(client, ADM1031_REG_PWM, + nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) + : (data->pwm[nr] & 0xf) | (reg & 0xf0)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -511,7 +513,7 @@ + struct adm1031_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if (val) { + data->fan_min[nr] = + FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); +@@ -519,7 +521,7 @@ + data->fan_min[nr] = 0xff; + } + adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t +@@ -540,7 +542,7 @@ + if (tmp == 0xff) + return -EINVAL; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); + data->fan_div[nr] = (tmp & 0xC0) | (0x3f & data->fan_div[nr]); + new_min = data->fan_min[nr] * old_div / +@@ -553,7 +555,7 @@ + data->fan_div[nr]); + adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), + data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -627,11 +629,11 @@ + + val = simple_strtol(buf, NULL, 10); + val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_min[nr] = TEMP_TO_REG(val); + adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), + data->temp_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t +@@ -643,11 +645,11 @@ + + val = simple_strtol(buf, NULL, 10); + val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[nr] = TEMP_TO_REG(val); + adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), + data->temp_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t +@@ -659,11 +661,11 @@ + + val = simple_strtol(buf, NULL, 10); + val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_crit[nr] = TEMP_TO_REG(val); + adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), + data->temp_crit[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -722,13 +724,6 @@ + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + + +-static int adm1031_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, adm1031_detect); +-} +- + /* This function is called by i2c_probe */ + static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) + { +@@ -778,7 +773,7 @@ + + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -891,7 +886,7 @@ + struct adm1031_data *data = i2c_get_clientdata(client); + int chan; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -965,7 +960,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/adm9240.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/adm9240.c 2006-03-22 17:06:16.000000000 +0100 +@@ -49,6 +49,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, +@@ -129,7 +130,6 @@ + return SCALE(reg, 1250, 255); + } + +-static int adm9240_attach_adapter(struct i2c_adapter *adapter); + static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind); + static void adm9240_init_client(struct i2c_client *client); + static int adm9240_detach_client(struct i2c_client *client); +@@ -141,7 +141,9 @@ + .name = "adm9240", + }, + .id = I2C_DRIVERID_ADM9240, +- .attach_adapter = adm9240_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = adm9240_detect, + .detach_client = adm9240_detach_client, + }; + +@@ -150,7 +152,7 @@ + enum chips type; + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; + unsigned long last_updated_measure; + unsigned long last_updated_config; +@@ -195,11 +197,11 @@ + struct adm9240_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[attr->index] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index), + data->temp_max[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -246,11 +248,11 @@ + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[attr->index] = IN_TO_REG(val, attr->index); + i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index), + data->in_min[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -263,11 +265,11 @@ + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[attr->index] = IN_TO_REG(val, attr->index); + i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index), + data->in_max[attr->index]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -350,7 +352,7 @@ + int nr = attr->index; + u8 new_div; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (!val) { + data->fan_min[nr] = 255; +@@ -390,7 +392,7 @@ + i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr), + data->fan_min[nr]); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -439,10 +441,10 @@ + struct adm9240_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->aout = AOUT_TO_REG(val); + i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); +@@ -539,7 +541,7 @@ + /* fill in the remaining client fields and attach */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->type = kind; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + if ((err = i2c_attach_client(new_client))) + goto exit_free; +@@ -621,13 +623,6 @@ + return err; + } + +-static int adm9240_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, adm9240_detect); +-} +- + static int adm9240_detach_client(struct i2c_client *client) + { + struct adm9240_data *data = i2c_get_clientdata(client); +@@ -691,7 +686,7 @@ + struct adm9240_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + /* minimum measurement cycle: 1.75 seconds */ + if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) +@@ -771,7 +766,7 @@ + data->last_updated_config = jiffies; + data->valid = 1; + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return data; + } + +--- linux-2.6.16.orig/drivers/hwmon/asb100.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/asb100.c 2006-03-22 17:06:16.000000000 +0100 +@@ -44,6 +44,7 @@ + #include <linux/err.h> + #include <linux/init.h> + #include <linux/jiffies.h> ++#include <linux/mutex.h> + #include "lm75.h" + + /* +@@ -182,10 +183,10 @@ + struct asb100_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + unsigned long last_updated; /* In jiffies */ + + /* array of 2 pointers to subclients */ +@@ -210,7 +211,6 @@ + static int asb100_read_value(struct i2c_client *client, u16 reg); + static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); + +-static int asb100_attach_adapter(struct i2c_adapter *adapter); + static int asb100_detect(struct i2c_adapter *adapter, int address, int kind); + static int asb100_detach_client(struct i2c_client *client); + static struct asb100_data *asb100_update_device(struct device *dev); +@@ -221,7 +221,9 @@ + .name = "asb100", + }, + .id = I2C_DRIVERID_ASB100, +- .attach_adapter = asb100_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = asb100_detect, + .detach_client = asb100_detach_client, + }; + +@@ -245,11 +247,11 @@ + struct asb100_data *data = i2c_get_clientdata(client); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ + data->in_##reg[nr]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -331,10 +333,10 @@ + struct asb100_data *data = i2c_get_clientdata(client); + u32 val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -351,7 +353,7 @@ + unsigned long val = simple_strtoul(buf, NULL, 10); + int reg; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + min = FAN_FROM_REG(data->fan_min[nr], + DIV_FROM_REG(data->fan_div[nr])); +@@ -381,7 +383,7 @@ + FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -461,7 +463,7 @@ + struct asb100_data *data = i2c_get_clientdata(client); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + switch (nr) { \ + case 1: case 2: \ + data->reg[nr] = LM75_TEMP_TO_REG(val); \ +@@ -472,7 +474,7 @@ + } \ + asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ + data->reg[nr]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -574,11 +576,11 @@ + struct asb100_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm &= 0x80; /* keep the enable bit */ + data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); + asb100_write_value(client, ASB100_REG_PWM1, data->pwm); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -595,11 +597,11 @@ + struct asb100_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm &= 0x0f; /* keep the duty cycle bits */ + data->pwm |= (val ? 0x80 : 0x00); + asb100_write_value(client, ASB100_REG_PWM1, data->pwm); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -611,18 +613,6 @@ + device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \ + } while (0) + +-/* This function is called when: +- asb100_driver is inserted (when this module is loaded), for each +- available adapter +- when a new adapter is inserted (and asb100_driver is still present) +- */ +-static int asb100_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, asb100_detect); +-} +- + static int asb100_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *new_client) + { +@@ -729,7 +719,7 @@ + } + + new_client = &data->client; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; +@@ -789,7 +779,7 @@ + data->type = kind; + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -885,7 +875,7 @@ + struct i2c_client *cl; + int res, bank; + +- down(&data->lock); ++ mutex_lock(&data->lock); + + bank = (reg >> 8) & 0x0f; + if (bank > 2) +@@ -919,7 +909,7 @@ + if (bank > 2) + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); + +- up(&data->lock); ++ mutex_unlock(&data->lock); + + return res; + } +@@ -930,7 +920,7 @@ + struct i2c_client *cl; + int bank; + +- down(&data->lock); ++ mutex_lock(&data->lock); + + bank = (reg >> 8) & 0x0f; + if (bank > 2) +@@ -960,7 +950,7 @@ + if (bank > 2) + i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); + +- up(&data->lock); ++ mutex_unlock(&data->lock); + } + + static void asb100_init_client(struct i2c_client *client) +@@ -984,7 +974,7 @@ + struct asb100_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -1042,7 +1032,7 @@ + dev_dbg(&client->dev, "... device update complete\n"); + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/atxp1.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/atxp1.c 2006-03-22 17:06:16.000000000 +0100 +@@ -26,6 +26,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); +@@ -44,7 +45,6 @@ + + I2C_CLIENT_INSMOD_1(atxp1); + +-static int atxp1_attach_adapter(struct i2c_adapter * adapter); + static int atxp1_detach_client(struct i2c_client * client); + static struct atxp1_data * atxp1_update_device(struct device *dev); + static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind); +@@ -53,14 +53,16 @@ + .driver = { + .name = "atxp1", + }, +- .attach_adapter = atxp1_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = atxp1_detect, + .detach_client = atxp1_detach_client, + }; + + struct atxp1_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + unsigned long last_updated; + u8 valid; + struct { +@@ -80,7 +82,7 @@ + client = to_i2c_client(dev); + data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + +@@ -93,7 +95,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return(data); + } +@@ -251,13 +253,6 @@ + static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); + + +-static int atxp1_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, &atxp1_detect); +-}; +- + static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) + { + struct i2c_client * new_client; +@@ -309,7 +304,7 @@ + + data->valid = 0; + +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + err = i2c_attach_client(new_client); + +--- linux-2.6.16.orig/drivers/hwmon/ds1621.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/ds1621.c 2006-03-22 17:06:16.000000000 +0100 +@@ -28,6 +28,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include "lm75.h" + + /* Addresses to scan */ +@@ -72,7 +73,7 @@ + struct ds1621_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -80,7 +81,6 @@ + u8 conf; /* Register encoding, combined */ + }; + +-static int ds1621_attach_adapter(struct i2c_adapter *adapter); + static int ds1621_detect(struct i2c_adapter *adapter, int address, + int kind); + static void ds1621_init_client(struct i2c_client *client); +@@ -93,7 +93,9 @@ + .name = "ds1621", + }, + .id = I2C_DRIVERID_DS1621, +- .attach_adapter = ds1621_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = ds1621_detect, + .detach_client = ds1621_detach_client, + }; + +@@ -156,10 +158,10 @@ + struct ds1621_data *data = ds1621_update_client(dev); \ + u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = val; \ + ds1621_write_value(client, reg, data->value); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -178,13 +180,6 @@ + static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); + + +-static int ds1621_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, ds1621_detect); +-} +- + /* This function is called by i2c_probe */ + static int ds1621_detect(struct i2c_adapter *adapter, int address, + int kind) +@@ -242,7 +237,7 @@ + /* Fill in remaining client fields and put it into the global list */ + strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -297,7 +292,7 @@ + struct ds1621_data *data = i2c_get_clientdata(client); + u8 new_conf; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -327,7 +322,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/fscher.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/fscher.c 2006-03-22 17:06:16.000000000 +0100 +@@ -33,6 +33,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -104,7 +105,6 @@ + * Functions declaration + */ + +-static int fscher_attach_adapter(struct i2c_adapter *adapter); + static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); + static int fscher_detach_client(struct i2c_client *client); + static struct fscher_data *fscher_update_device(struct device *dev); +@@ -122,7 +122,9 @@ + .name = "fscher", + }, + .id = I2C_DRIVERID_FSCHER, +- .attach_adapter = fscher_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = fscher_detect, + .detach_client = fscher_detach_client, + }; + +@@ -133,7 +135,7 @@ + struct fscher_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -284,13 +286,6 @@ + * Real code + */ + +-static int fscher_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, fscher_detect); +-} +- + static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) + { + struct i2c_client *new_client; +@@ -332,7 +327,7 @@ + * global list */ + strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -417,7 +412,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct fscher_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + +@@ -457,7 +452,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +@@ -472,10 +467,10 @@ + /* bits 0..1, 3..7 reserved => mask with 0x04 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; + fscher_write_value(client, reg, v); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -490,10 +485,10 @@ + { + unsigned long v = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; + fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -518,14 +513,14 @@ + return -EINVAL; + } + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + /* bits 2..7 reserved => mask with 0x03 */ + data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; + data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; + + fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -552,10 +547,10 @@ + /* bits 2..7 reserved, 0 read only => mask with 0x02 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; + fscher_write_value(client, reg, v); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -609,10 +604,10 @@ + /* bits 1..7 reserved => mask with 0x01 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->global_control &= ~v; + fscher_write_value(client, reg, v); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -631,11 +626,11 @@ + /* bits 0..3 reserved => mask with 0xf0 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->watchdog[2] &= ~0xf0; + data->watchdog[2] |= v; + fscher_write_value(client, reg, data->watchdog[2]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -651,10 +646,10 @@ + /* bits 0, 2..7 reserved => mask with 0x02 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->watchdog[1] &= ~v; + fscher_write_value(client, reg, v); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -669,10 +664,10 @@ + { + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->watchdog[0] = v; + fscher_write_value(client, reg, data->watchdog[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +--- linux-2.6.16.orig/drivers/hwmon/fscpos.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/fscpos.c 2006-03-22 17:06:16.000000000 +0100 +@@ -37,6 +37,7 @@ + #include <linux/init.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -85,12 +86,11 @@ + /* + * Functions declaration + */ +-static int fscpos_attach_adapter(struct i2c_adapter *adapter); + static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind); + static int fscpos_detach_client(struct i2c_client *client); + +-static int fscpos_read_value(struct i2c_client *client, u8 register); +-static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value); ++static int fscpos_read_value(struct i2c_client *client, u8 reg); ++static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value); + static struct fscpos_data *fscpos_update_device(struct device *dev); + static void fscpos_init_client(struct i2c_client *client); + +@@ -104,7 +104,9 @@ + .name = "fscpos", + }, + .id = I2C_DRIVERID_FSCPOS, +- .attach_adapter = fscpos_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = fscpos_detect, + .detach_client = fscpos_detach_client, + }; + +@@ -114,7 +116,7 @@ + struct fscpos_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* 0 until following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -208,13 +210,13 @@ + return -EINVAL; + } + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + /* bits 2..7 reserved => mask with 0x03 */ + data->fan_ripple[nr - 1] &= ~0x03; + data->fan_ripple[nr - 1] |= v; + + fscpos_write_value(client, reg, data->fan_ripple[nr - 1]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -232,10 +234,10 @@ + if (v < 0) v = 0; + if (v > 255) v = 255; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm[nr - 1] = v; + fscpos_write_value(client, reg, data->pwm[nr - 1]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -278,11 +280,11 @@ + /* bits 0..3 reserved => mask with 0xf0 */ + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->wdog_control &= ~0xf0; + data->wdog_control |= v; + fscpos_write_value(client, reg, data->wdog_control); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -304,10 +306,10 @@ + return -EINVAL; + } + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->wdog_state &= ~v; + fscpos_write_value(client, reg, v); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -321,10 +323,10 @@ + { + unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->wdog_preset = v; + fscpos_write_value(client, reg, data->wdog_preset); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -431,13 +433,6 @@ + static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL); + static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL); + +-static int fscpos_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, fscpos_detect); +-} +- + static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) + { + struct i2c_client *new_client; +@@ -483,7 +478,7 @@ + strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE); + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -579,7 +574,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct fscpos_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + int i; +@@ -625,7 +620,7 @@ + data->last_updated = jiffies; + data->valid = 1; + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return data; + } + +--- linux-2.6.16.orig/drivers/hwmon/gl518sm.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/gl518sm.c 2006-03-22 17:06:16.000000000 +0100 +@@ -43,6 +43,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; +@@ -120,7 +121,7 @@ + struct class_device *class_dev; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -141,7 +142,6 @@ + u8 beep_enable; /* Boolean */ + }; + +-static int gl518_attach_adapter(struct i2c_adapter *adapter); + static int gl518_detect(struct i2c_adapter *adapter, int address, int kind); + static void gl518_init_client(struct i2c_client *client); + static int gl518_detach_client(struct i2c_client *client); +@@ -155,7 +155,9 @@ + .name = "gl518sm", + }, + .id = I2C_DRIVERID_GL518, +- .attach_adapter = gl518_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = gl518_detect, + .detach_client = gl518_detach_client, + }; + +@@ -212,10 +214,10 @@ + struct gl518_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = type##_TO_REG(val); \ + gl518_write_value(client, reg, data->value); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -228,12 +230,12 @@ + int regvalue; \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + regvalue = gl518_read_value(client, reg); \ + data->value = type##_TO_REG(val); \ + regvalue = (regvalue & ~mask) | (data->value << shift); \ + gl518_write_value(client, reg, regvalue); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -265,7 +267,7 @@ + int regvalue; + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); + data->fan_min[0] = FAN_TO_REG(val, + DIV_FROM_REG(data->fan_div[0])); +@@ -280,7 +282,7 @@ + data->beep_mask &= data->alarm_mask; + gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -291,7 +293,7 @@ + int regvalue; + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); + data->fan_min[1] = FAN_TO_REG(val, + DIV_FROM_REG(data->fan_div[1])); +@@ -306,7 +308,7 @@ + data->beep_mask &= data->alarm_mask; + gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -343,13 +345,6 @@ + * Real code + */ + +-static int gl518_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, gl518_detect); +-} +- + static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) + { + int i; +@@ -407,7 +402,7 @@ + strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE); + data->type = kind; + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -525,7 +520,7 @@ + struct gl518_data *data = i2c_get_clientdata(client); + int val; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -586,7 +581,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/gl520sm.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/gl520sm.c 2006-03-22 17:06:16.000000000 +0100 +@@ -29,6 +29,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Type of the extra sensor */ + static unsigned short extra_sensor_type; +@@ -99,7 +100,6 @@ + * Function declarations + */ + +-static int gl520_attach_adapter(struct i2c_adapter *adapter); + static int gl520_detect(struct i2c_adapter *adapter, int address, int kind); + static void gl520_init_client(struct i2c_client *client); + static int gl520_detach_client(struct i2c_client *client); +@@ -113,7 +113,9 @@ + .name = "gl520sm", + }, + .id = I2C_DRIVERID_GL520, +- .attach_adapter = gl520_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = gl520_detect, + .detach_client = gl520_detach_client, + }; + +@@ -121,7 +123,7 @@ + struct gl520_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until the following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -303,7 +305,7 @@ + long v = simple_strtol(buf, NULL, 10); + u8 r; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (n == 0) + r = VDD_TO_REG(v); +@@ -317,7 +319,7 @@ + else + gl520_write_value(client, reg, r); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -331,7 +333,7 @@ + else + r = IN_TO_REG(v); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + data->in_max[n] = r; + +@@ -340,7 +342,7 @@ + else + gl520_write_value(client, reg, r); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -373,7 +375,7 @@ + unsigned long v = simple_strtoul(buf, NULL, 10); + u8 r; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + r = FAN_TO_REG(v, data->fan_div[n - 1]); + data->fan_min[n - 1] = r; + +@@ -390,7 +392,7 @@ + data->beep_mask &= data->alarm_mask; + gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -409,7 +411,7 @@ + return -EINVAL; + } + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_div[n - 1] = r; + + if (n == 1) +@@ -417,7 +419,7 @@ + else + gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4)); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -425,10 +427,10 @@ + { + u8 r = simple_strtoul(buf, NULL, 10)?1:0; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_off = r; + gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -454,10 +456,10 @@ + { + long v = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[n - 1] = TEMP_TO_REG(v);; + gl520_write_value(client, reg, data->temp_max[n - 1]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -465,10 +467,10 @@ + { + long v = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max_hyst[n - 1] = TEMP_TO_REG(v); + gl520_write_value(client, reg, data->temp_max_hyst[n - 1]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -491,10 +493,10 @@ + { + u8 r = simple_strtoul(buf, NULL, 10)?0:1; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->beep_enable = !r; + gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -502,11 +504,11 @@ + { + u8 r = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + r &= data->alarm_mask; + data->beep_mask = r; + gl520_write_value(client, reg, r); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -515,13 +517,6 @@ + * Real code + */ + +-static int gl520_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, gl520_detect); +-} +- + static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) + { + struct i2c_client *new_client; +@@ -561,7 +556,7 @@ + /* Fill in the remaining client fields */ + strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -685,7 +680,7 @@ + struct gl520_data *data = i2c_get_clientdata(client); + int val; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + +@@ -750,7 +745,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/hdaps.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/hdaps.c 2006-03-22 17:06:15.000000000 +0100 +@@ -33,6 +33,7 @@ + #include <linux/module.h> + #include <linux/timer.h> + #include <linux/dmi.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ +@@ -70,10 +71,10 @@ + static int rest_x; + static int rest_y; + +-static DECLARE_MUTEX(hdaps_sem); ++static DEFINE_MUTEX(hdaps_mutex); + + /* +- * __get_latch - Get the value from a given port. Callers must hold hdaps_sem. ++ * __get_latch - Get the value from a given port. Callers must hold hdaps_mutex. + */ + static inline u8 __get_latch(u16 port) + { +@@ -82,7 +83,7 @@ + + /* + * __check_latch - Check a port latch for a given value. Returns zero if the +- * port contains the given value. Callers must hold hdaps_sem. ++ * port contains the given value. Callers must hold hdaps_mutex. + */ + static inline int __check_latch(u16 port, u8 val) + { +@@ -93,7 +94,7 @@ + + /* + * __wait_latch - Wait up to 100us for a port latch to get a certain value, +- * returning zero if the value is obtained. Callers must hold hdaps_sem. ++ * returning zero if the value is obtained. Callers must hold hdaps_mutex. + */ + static int __wait_latch(u16 port, u8 val) + { +@@ -110,7 +111,7 @@ + + /* + * __device_refresh - request a refresh from the accelerometer. Does not wait +- * for refresh to complete. Callers must hold hdaps_sem. ++ * for refresh to complete. Callers must hold hdaps_mutex. + */ + static void __device_refresh(void) + { +@@ -124,7 +125,7 @@ + /* + * __device_refresh_sync - request a synchronous refresh from the + * accelerometer. We wait for the refresh to complete. Returns zero if +- * successful and nonzero on error. Callers must hold hdaps_sem. ++ * successful and nonzero on error. Callers must hold hdaps_mutex. + */ + static int __device_refresh_sync(void) + { +@@ -134,7 +135,7 @@ + + /* + * __device_complete - indicate to the accelerometer that we are done reading +- * data, and then initiate an async refresh. Callers must hold hdaps_sem. ++ * data, and then initiate an async refresh. Callers must hold hdaps_mutex. + */ + static inline void __device_complete(void) + { +@@ -152,7 +153,7 @@ + { + int ret; + +- down(&hdaps_sem); ++ mutex_lock(&hdaps_mutex); + + /* do a sync refresh -- we need to be sure that we read fresh data */ + ret = __device_refresh_sync(); +@@ -163,7 +164,7 @@ + __device_complete(); + + out: +- up(&hdaps_sem); ++ mutex_unlock(&hdaps_mutex); + return ret; + } + +@@ -198,9 +199,9 @@ + { + int ret; + +- down(&hdaps_sem); ++ mutex_lock(&hdaps_mutex); + ret = __hdaps_read_pair(port1, port2, val1, val2); +- up(&hdaps_sem); ++ mutex_unlock(&hdaps_mutex); + + return ret; + } +@@ -213,7 +214,7 @@ + { + int total, ret = -ENXIO; + +- down(&hdaps_sem); ++ mutex_lock(&hdaps_mutex); + + outb(0x13, 0x1610); + outb(0x01, 0x161f); +@@ -279,7 +280,7 @@ + } + + out: +- up(&hdaps_sem); ++ mutex_unlock(&hdaps_mutex); + return ret; + } + +@@ -313,7 +314,7 @@ + }; + + /* +- * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. ++ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_mutex. + */ + static void hdaps_calibrate(void) + { +@@ -325,7 +326,7 @@ + int x, y; + + /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ +- if (down_trylock(&hdaps_sem)) { ++ if (!mutex_trylock(&hdaps_mutex)) { + mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); + return; + } +@@ -340,7 +341,7 @@ + mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); + + out: +- up(&hdaps_sem); ++ mutex_unlock(&hdaps_mutex); + } + + +@@ -420,9 +421,9 @@ + struct device_attribute *attr, + const char *buf, size_t count) + { +- down(&hdaps_sem); ++ mutex_lock(&hdaps_mutex); + hdaps_calibrate(); +- up(&hdaps_sem); ++ mutex_unlock(&hdaps_mutex); + + return count; + } +--- linux-2.6.16.orig/drivers/hwmon/it87.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/it87.c 2006-03-22 17:06:16.000000000 +0100 +@@ -41,6 +41,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + +@@ -194,10 +195,10 @@ + struct it87_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -219,14 +220,12 @@ + }; + + +-static int it87_attach_adapter(struct i2c_adapter *adapter); + static int it87_isa_attach_adapter(struct i2c_adapter *adapter); + static int it87_detect(struct i2c_adapter *adapter, int address, int kind); + static int it87_detach_client(struct i2c_client *client); + +-static int it87_read_value(struct i2c_client *client, u8 register); +-static int it87_write_value(struct i2c_client *client, u8 register, +- u8 value); ++static int it87_read_value(struct i2c_client *client, u8 reg); ++static int it87_write_value(struct i2c_client *client, u8 reg, u8 value); + static struct it87_data *it87_update_device(struct device *dev); + static int it87_check_pwm(struct i2c_client *client); + static void it87_init_client(struct i2c_client *client, struct it87_data *data); +@@ -237,7 +236,9 @@ + .name = "it87", + }, + .id = I2C_DRIVERID_IT87, +- .attach_adapter = it87_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = it87_detect, + .detach_client = it87_detach_client, + }; + +@@ -290,11 +291,11 @@ + struct it87_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val); + it87_write_value(client, IT87_REG_VIN_MIN(nr), + data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, +@@ -307,11 +308,11 @@ + struct it87_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val); + it87_write_value(client, IT87_REG_VIN_MAX(nr), + data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -381,10 +382,10 @@ + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_high[nr] = TEMP_TO_REG(val); + it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, +@@ -397,10 +398,10 @@ + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_low[nr] = TEMP_TO_REG(val); + it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define show_temp_offset(offset) \ +@@ -440,7 +441,7 @@ + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + data->sensor &= ~(1 << nr); + data->sensor &= ~(8 << nr); +@@ -450,11 +451,11 @@ + else if (val == 2) + data->sensor |= 8 << nr; + else if (val != 0) { +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define show_sensor_offset(offset) \ +@@ -524,7 +525,7 @@ + int val = simple_strtol(buf, NULL, 10); + u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + switch (nr) { + case 0: data->fan_div[nr] = reg & 0x07; break; + case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; +@@ -533,7 +534,7 @@ + + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, +@@ -548,7 +549,7 @@ + int i, min[3]; + u8 old; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + old = it87_read_value(client, IT87_REG_FAN_DIV); + + for (i = 0; i < 3; i++) +@@ -576,7 +577,7 @@ + data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); + it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_pwm_enable(struct device *dev, +@@ -589,7 +590,7 @@ + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (val == 0) { + int tmp; +@@ -606,11 +607,11 @@ + /* set saved pwm value, clear FAN_CTLX PWM mode bit */ + it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); + } else { +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, +@@ -626,11 +627,11 @@ + if (val < 0 || val > 255) + return -EINVAL; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->manual_pwm_ctl[nr] = val; + if (data->fan_main_ctrl & (1 << nr)) + it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -696,17 +697,6 @@ + #define device_create_file_vid(client) \ + device_create_file(&client->dev, &dev_attr_cpu0_vid) + +-/* This function is called when: +- * it87_driver is inserted (when this module is loaded), for each +- available adapter +- * when a new adapter is inserted (and it87_driver is still present) */ +-static int it87_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, it87_detect); +-} +- + static int it87_isa_attach_adapter(struct i2c_adapter *adapter) + { + return it87_detect(adapter, isa_address, -1); +@@ -776,7 +766,7 @@ + + new_client = &data->client; + if (is_isa) +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; +@@ -823,7 +813,7 @@ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->type = kind; + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -950,10 +940,10 @@ + + int res; + if (i2c_is_isa_client(client)) { +- down(&data->lock); ++ mutex_lock(&data->lock); + outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); + res = inb_p(client->addr + IT87_DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return res; + } else + return i2c_smbus_read_byte_data(client, reg); +@@ -969,10 +959,10 @@ + struct it87_data *data = i2c_get_clientdata(client); + + if (i2c_is_isa_client(client)) { +- down(&data->lock); ++ mutex_lock(&data->lock); + outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); + outb_p(value, client->addr + IT87_DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return 0; + } else + return i2c_smbus_write_byte_data(client, reg, value); +@@ -1098,7 +1088,7 @@ + struct it87_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -1160,7 +1150,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm63.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm63.c 2006-03-22 17:06:16.000000000 +0100 +@@ -45,6 +45,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -126,7 +127,6 @@ + * Functions declaration + */ + +-static int lm63_attach_adapter(struct i2c_adapter *adapter); + static int lm63_detach_client(struct i2c_client *client); + + static struct lm63_data *lm63_update_device(struct device *dev); +@@ -142,7 +142,9 @@ + .driver = { + .name = "lm63", + }, +- .attach_adapter = lm63_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm63_detect, + .detach_client = lm63_detach_client, + }; + +@@ -153,7 +155,7 @@ + struct lm63_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -192,13 +194,13 @@ + struct lm63_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan[1] = FAN_TO_REG(val); + i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, + data->fan[1] & 0xFF); + i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, + data->fan[1] >> 8); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -222,12 +224,12 @@ + return -EPERM; + + val = simple_strtoul(buf, NULL, 10); +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm1_value = val <= 0 ? 0 : + val >= 255 ? 2 * data->pwm1_freq : + (val * data->pwm1_freq * 2 + 127) / 255; + i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -253,10 +255,10 @@ + struct lm63_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp8[1] = TEMP8_TO_REG(val); + i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -284,13 +286,13 @@ + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp11[nr] = TEMP11_TO_REG(val); + i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], + data->temp11[nr] >> 8); + i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], + data->temp11[nr] & 0xff); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -314,11 +316,11 @@ + long val = simple_strtol(buf, NULL, 10); + long hyst; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + hyst = TEMP8_FROM_REG(data->temp8[2]) - val; + i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, + HYST_TO_REG(hyst)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -329,9 +331,19 @@ + return sprintf(buf, "%u\n", data->alarms); + } + ++static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct lm63_data *data = lm63_update_device(dev); ++ ++ return sprintf(buf, "%u\n", (data->alarms >> attr->index) & 1); ++} ++ + static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); + static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, + set_fan, 1); ++static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); + + static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1); + static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); +@@ -339,13 +351,18 @@ + static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); + static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, + set_temp8, 1); ++static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); + + static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); ++static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); + static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 1); ++static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); + static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 2); ++static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); + static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2); ++static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); + static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, + set_temp2_crit_hyst); + +@@ -355,13 +372,6 @@ + * Real code + */ + +-static int lm63_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm63_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -427,7 +437,7 @@ + + strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -448,6 +458,8 @@ + &sensor_dev_attr_fan1_input.dev_attr); + device_create_file(&new_client->dev, + &sensor_dev_attr_fan1_min.dev_attr); ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_fan1_min_alarm.dev_attr); + } + device_create_file(&new_client->dev, &dev_attr_pwm1); + device_create_file(&new_client->dev, &dev_attr_pwm1_enable); +@@ -456,13 +468,23 @@ + device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_input_fault.dev_attr); ++ device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_min.dev_attr); + device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_min_alarm.dev_attr); ++ device_create_file(&new_client->dev, + &sensor_dev_attr_temp1_max.dev_attr); + device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp1_max_alarm.dev_attr); ++ device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_max_alarm.dev_attr); ++ device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_crit.dev_attr); ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_crit_alarm.dev_attr); + device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); + device_create_file(&new_client->dev, &dev_attr_alarms); + +@@ -530,7 +552,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm63_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + if (data->config & 0x04) { /* tachometer enabled */ +@@ -582,7 +604,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm75.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm75.c 2006-03-22 17:06:16.000000000 +0100 +@@ -25,6 +25,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include "lm75.h" + + +@@ -47,7 +48,7 @@ + struct lm75_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + u16 temp_input; /* Register values */ +@@ -55,7 +56,6 @@ + u16 temp_hyst; + }; + +-static int lm75_attach_adapter(struct i2c_adapter *adapter); + static int lm75_detect(struct i2c_adapter *adapter, int address, int kind); + static void lm75_init_client(struct i2c_client *client); + static int lm75_detach_client(struct i2c_client *client); +@@ -70,7 +70,9 @@ + .name = "lm75", + }, + .id = I2C_DRIVERID_LM75, +- .attach_adapter = lm75_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm75_detect, + .detach_client = lm75_detach_client, + }; + +@@ -91,10 +93,10 @@ + struct lm75_data *data = i2c_get_clientdata(client); \ + int temp = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = LM75_TEMP_TO_REG(temp); \ + lm75_write_value(client, reg, data->value); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + set(temp_max, LM75_REG_TEMP_OS); +@@ -104,13 +106,6 @@ + static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); + static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); + +-static int lm75_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm75_detect); +-} +- + /* This function is called by i2c_probe */ + static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) + { +@@ -188,7 +183,7 @@ + /* Fill in the remaining client fields and put it into the global list */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -264,7 +259,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm75_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -277,7 +272,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm77.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm77.c 2006-03-22 17:06:16.000000000 +0100 +@@ -32,6 +32,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END }; +@@ -51,7 +52,7 @@ + struct lm77_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + int temp_input; /* Temperatures */ +@@ -62,7 +63,6 @@ + u8 alarms; + }; + +-static int lm77_attach_adapter(struct i2c_adapter *adapter); + static int lm77_detect(struct i2c_adapter *adapter, int address, int kind); + static void lm77_init_client(struct i2c_client *client); + static int lm77_detach_client(struct i2c_client *client); +@@ -77,7 +77,9 @@ + .driver = { + .name = "lm77", + }, +- .attach_adapter = lm77_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm77_detect, + .detach_client = lm77_detach_client, + }; + +@@ -139,10 +141,10 @@ + struct lm77_data *data = i2c_get_clientdata(client); \ + long val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = val; \ + lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -157,11 +159,11 @@ + struct lm77_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_hyst = data->temp_crit - val; + lm77_write_value(client, LM77_REG_TEMP_HYST, + LM77_TEMP_TO_REG(data->temp_hyst)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -173,7 +175,7 @@ + long val = simple_strtoul(buf, NULL, 10); + int oldcrithyst; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + oldcrithyst = data->temp_crit - data->temp_hyst; + data->temp_crit = val; + data->temp_hyst = data->temp_crit - oldcrithyst; +@@ -181,7 +183,7 @@ + LM77_TEMP_TO_REG(data->temp_crit)); + lm77_write_value(client, LM77_REG_TEMP_HYST, + LM77_TEMP_TO_REG(data->temp_hyst)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -204,13 +206,6 @@ + static DEVICE_ATTR(alarms, S_IRUGO, + show_alarms, NULL); + +-static int lm77_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm77_detect); +-} +- + /* This function is called by i2c_probe */ + static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) + { +@@ -306,7 +301,7 @@ + /* Fill in the remaining client fields and put it into the global list */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -380,7 +375,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm77_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -406,7 +401,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm78.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm78.c 2006-03-22 17:06:16.000000000 +0100 +@@ -27,6 +27,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + /* Addresses to scan */ +@@ -131,10 +132,10 @@ + struct lm78_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -152,13 +153,12 @@ + }; + + +-static int lm78_attach_adapter(struct i2c_adapter *adapter); + static int lm78_isa_attach_adapter(struct i2c_adapter *adapter); + static int lm78_detect(struct i2c_adapter *adapter, int address, int kind); + static int lm78_detach_client(struct i2c_client *client); + +-static int lm78_read_value(struct i2c_client *client, u8 register); +-static int lm78_write_value(struct i2c_client *client, u8 register, u8 value); ++static int lm78_read_value(struct i2c_client *client, u8 reg); ++static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value); + static struct lm78_data *lm78_update_device(struct device *dev); + static void lm78_init_client(struct i2c_client *client); + +@@ -168,7 +168,9 @@ + .name = "lm78", + }, + .id = I2C_DRIVERID_LM78, +- .attach_adapter = lm78_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm78_detect, + .detach_client = lm78_detach_client, + }; + +@@ -207,10 +209,10 @@ + struct lm78_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val); + lm78_write_value(client, LM78_REG_IN_MIN(nr), data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -221,10 +223,10 @@ + struct lm78_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val); + lm78_write_value(client, LM78_REG_IN_MAX(nr), data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -288,10 +290,10 @@ + struct lm78_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_over = TEMP_TO_REG(val); + lm78_write_value(client, LM78_REG_TEMP_OVER, data->temp_over); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -307,10 +309,10 @@ + struct lm78_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_hyst = TEMP_TO_REG(val); + lm78_write_value(client, LM78_REG_TEMP_HYST, data->temp_hyst); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -342,10 +344,10 @@ + struct lm78_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -368,7 +370,7 @@ + unsigned long min; + u8 reg; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + min = FAN_FROM_REG(data->fan_min[nr], + DIV_FROM_REG(data->fan_div[nr])); + +@@ -380,7 +382,7 @@ + default: + dev_err(&client->dev, "fan_div value %ld not " + "supported. Choose one of 1, 2, 4 or 8!\n", val); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +@@ -398,7 +400,7 @@ + data->fan_min[nr] = + FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + lm78_write_value(client, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -464,17 +466,6 @@ + } + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + +-/* This function is called when: +- * lm78_driver is inserted (when this module is loaded), for each +- available adapter +- * when a new adapter is inserted (and lm78_driver is still present) */ +-static int lm78_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm78_detect); +-} +- + static int lm78_isa_attach_adapter(struct i2c_adapter *adapter) + { + return lm78_detect(adapter, isa_address, -1); +@@ -548,7 +539,7 @@ + + new_client = &data->client; + if (is_isa) +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; +@@ -598,7 +589,7 @@ + data->type = kind; + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -697,10 +688,10 @@ + int res; + if (i2c_is_isa_client(client)) { + struct lm78_data *data = i2c_get_clientdata(client); +- down(&data->lock); ++ mutex_lock(&data->lock); + outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); + res = inb_p(client->addr + LM78_DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return res; + } else + return i2c_smbus_read_byte_data(client, reg); +@@ -717,10 +708,10 @@ + { + if (i2c_is_isa_client(client)) { + struct lm78_data *data = i2c_get_clientdata(client); +- down(&data->lock); ++ mutex_lock(&data->lock); + outb_p(reg, client->addr + LM78_ADDR_REG_OFFSET); + outb_p(value, client->addr + LM78_DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return 0; + } else + return i2c_smbus_write_byte_data(client, reg, value); +@@ -742,7 +733,7 @@ + struct lm78_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -786,7 +777,7 @@ + data->fan_div[2] = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm80.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm80.c 2006-03-22 17:06:16.000000000 +0100 +@@ -28,6 +28,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, +@@ -108,7 +109,7 @@ + struct lm80_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -130,7 +131,6 @@ + * Functions declaration + */ + +-static int lm80_attach_adapter(struct i2c_adapter *adapter); + static int lm80_detect(struct i2c_adapter *adapter, int address, int kind); + static void lm80_init_client(struct i2c_client *client); + static int lm80_detach_client(struct i2c_client *client); +@@ -147,7 +147,9 @@ + .name = "lm80", + }, + .id = I2C_DRIVERID_LM80, +- .attach_adapter = lm80_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm80_detect, + .detach_client = lm80_detach_client, + }; + +@@ -191,10 +193,10 @@ + struct lm80_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock);\ ++ mutex_lock(&data->update_lock);\ + data->value = IN_TO_REG(val); \ + lm80_write_value(client, reg, data->value); \ +- up(&data->update_lock);\ ++ mutex_unlock(&data->update_lock);\ + return count; \ + } + set_in(min0, in_min[0], LM80_REG_IN_MIN(0)); +@@ -241,10 +243,10 @@ + struct lm80_data *data = i2c_get_clientdata(client); \ + long val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock);\ ++ mutex_lock(&data->update_lock);\ + data->value = FAN_TO_REG(val, DIV_FROM_REG(data->div)); \ + lm80_write_value(client, reg, data->value); \ +- up(&data->update_lock);\ ++ mutex_unlock(&data->update_lock);\ + return count; \ + } + set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]); +@@ -263,7 +265,7 @@ + u8 reg; + + /* Save fan_min */ +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + min = FAN_FROM_REG(data->fan_min[nr], + DIV_FROM_REG(data->fan_div[nr])); + +@@ -275,7 +277,7 @@ + default: + dev_err(&client->dev, "fan_div value %ld not " + "supported. Choose one of 1, 2, 4 or 8!\n", val); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +@@ -286,7 +288,7 @@ + /* Restore fan_min */ + data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -325,10 +327,10 @@ + struct lm80_data *data = i2c_get_clientdata(client); \ + long val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = TEMP_LIMIT_TO_REG(val); \ + lm80_write_value(client, reg, data->value); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); +@@ -386,13 +388,6 @@ + * Real code + */ + +-static int lm80_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm80_detect); +-} +- + static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) + { + int i, cur; +@@ -437,7 +432,7 @@ + /* Fill in the remaining client fields and put it into the global list */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -545,7 +540,7 @@ + struct lm80_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + dev_dbg(&client->dev, "Starting lm80 update\n"); +@@ -585,7 +580,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm83.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm83.c 2006-03-22 17:06:16.000000000 +0100 +@@ -12,6 +12,10 @@ + * Since the datasheet omits to give the chip stepping code, I give it + * here: 0x03 (at register 0xff). + * ++ * Also supports the LM82 temp sensor, which is basically a stripped down ++ * model of the LM83. Datasheet is here: ++ * http://www.national.com/pf/LM/LM82.html ++ * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or +@@ -35,6 +39,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -51,7 +56,7 @@ + * Insmod parameters + */ + +-I2C_CLIENT_INSMOD_1(lm83); ++I2C_CLIENT_INSMOD_2(lm83, lm82); + + /* + * The LM83 registers +@@ -114,7 +119,6 @@ + * Functions declaration + */ + +-static int lm83_attach_adapter(struct i2c_adapter *adapter); + static int lm83_detect(struct i2c_adapter *adapter, int address, int kind); + static int lm83_detach_client(struct i2c_client *client); + static struct lm83_data *lm83_update_device(struct device *dev); +@@ -128,7 +132,9 @@ + .name = "lm83", + }, + .id = I2C_DRIVERID_LM83, +- .attach_adapter = lm83_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm83_detect, + .detach_client = lm83_detach_client, + }; + +@@ -139,7 +145,7 @@ + struct lm83_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -171,11 +177,11 @@ + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], + data->temp[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -209,13 +215,6 @@ + * Real code + */ + +-static int lm83_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm83_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -282,6 +281,9 @@ + if (man_id == 0x01) { /* National Semiconductor */ + if (chip_id == 0x03) { + kind = lm83; ++ } else ++ if (chip_id == 0x01) { ++ kind = lm82; + } + } + +@@ -295,12 +297,15 @@ + + if (kind == lm83) { + name = "lm83"; ++ } else ++ if (kind == lm82) { ++ name = "lm82"; + } + + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -318,32 +323,46 @@ + goto exit_detach; + } + ++ /* ++ * The LM82 can only monitor one external diode which is ++ * at the same register as the LM83 temp3 entry - so we ++ * declare 1 and 3 common, and then 2 and 4 only for the LM83. ++ */ ++ + device_create_file(&new_client->dev, + &sensor_dev_attr_temp1_input.dev_attr); + device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_input.dev_attr); +- device_create_file(&new_client->dev, + &sensor_dev_attr_temp3_input.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp4_input.dev_attr); ++ + device_create_file(&new_client->dev, + &sensor_dev_attr_temp1_max.dev_attr); + device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_max.dev_attr); +- device_create_file(&new_client->dev, + &sensor_dev_attr_temp3_max.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp4_max.dev_attr); ++ + device_create_file(&new_client->dev, + &sensor_dev_attr_temp1_crit.dev_attr); + device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_crit.dev_attr); +- device_create_file(&new_client->dev, + &sensor_dev_attr_temp3_crit.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp4_crit.dev_attr); ++ + device_create_file(&new_client->dev, &dev_attr_alarms); + ++ if (kind == lm83) { ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_input.dev_attr); ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp4_input.dev_attr); ++ ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_max.dev_attr); ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp4_max.dev_attr); ++ ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp2_crit.dev_attr); ++ device_create_file(&new_client->dev, ++ &sensor_dev_attr_temp4_crit.dev_attr); ++ } ++ + return 0; + + exit_detach: +@@ -373,7 +392,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm83_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { + int nr; +@@ -393,7 +412,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm85.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm85.c 2006-03-22 17:06:16.000000000 +0100 +@@ -31,6 +31,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* Addresses to scan */ + static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; +@@ -331,10 +332,10 @@ + struct lm85_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + int valid; /* !=0 if following fields are valid */ + unsigned long last_reading; /* In jiffies */ + unsigned long last_config; /* In jiffies */ +@@ -368,13 +369,12 @@ + struct lm85_zone zone[3]; + }; + +-static int lm85_attach_adapter(struct i2c_adapter *adapter); + static int lm85_detect(struct i2c_adapter *adapter, int address, + int kind); + static int lm85_detach_client(struct i2c_client *client); + +-static int lm85_read_value(struct i2c_client *client, u8 register); +-static int lm85_write_value(struct i2c_client *client, u8 register, int value); ++static int lm85_read_value(struct i2c_client *client, u8 reg); ++static int lm85_write_value(struct i2c_client *client, u8 reg, int value); + static struct lm85_data *lm85_update_device(struct device *dev); + static void lm85_init_client(struct i2c_client *client); + +@@ -384,7 +384,9 @@ + .name = "lm85", + }, + .id = I2C_DRIVERID_LM85, +- .attach_adapter = lm85_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm85_detect, + .detach_client = lm85_detach_client, + }; + +@@ -407,10 +409,10 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val); + lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -499,10 +501,10 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm[nr] = PWM_TO_REG(val); + lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) +@@ -559,10 +561,10 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = INS_TO_REG(nr, val); + lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_in_max(struct device *dev, char *buf, int nr) +@@ -577,10 +579,10 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = INS_TO_REG(nr, val); + lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define show_in_reg(offset) \ +@@ -640,10 +642,10 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_min[nr] = TEMP_TO_REG(val); + lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_temp_max(struct device *dev, char *buf, int nr) +@@ -658,10 +660,10 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[nr] = TEMP_TO_REG(val); + lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define show_temp_reg(offset) \ +@@ -713,12 +715,12 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) + | ZONE_TO_REG(val) ; + lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), + data->autofan[nr].config); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) +@@ -733,11 +735,11 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->autofan[nr].min_pwm = PWM_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), + data->autofan[nr].min_pwm); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) +@@ -752,7 +754,7 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->autofan[nr].min_off = val; + lm85_write_value(client, LM85_REG_AFAN_SPIKE1, data->smooth[0] + | data->syncpwm3 +@@ -760,7 +762,7 @@ + | (data->autofan[1].min_off ? 0x40 : 0) + | (data->autofan[2].min_off ? 0x80 : 0) + ); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) +@@ -775,13 +777,13 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->autofan[nr].freq = FREQ_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), + (data->zone[nr].range << 4) + | data->autofan[nr].freq + ); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define pwm_auto(offset) \ +@@ -857,7 +859,7 @@ + int min; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + min = TEMP_FROM_REG(data->zone[nr].limit); + data->zone[nr].off_desired = TEMP_TO_REG(val); + data->zone[nr].hyst = HYST_TO_REG(min - val); +@@ -871,7 +873,7 @@ + (data->zone[2].hyst << 4) + ); + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) +@@ -886,7 +888,7 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->zone[nr].limit = TEMP_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), + data->zone[nr].limit); +@@ -913,7 +915,7 @@ + (data->zone[2].hyst << 4) + ); + } +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) +@@ -930,7 +932,7 @@ + int min; + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + min = TEMP_FROM_REG(data->zone[nr].limit); + data->zone[nr].max_desired = TEMP_TO_REG(val); + data->zone[nr].range = RANGE_TO_REG( +@@ -938,7 +940,7 @@ + lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), + ((data->zone[nr].range & 0x0f) << 4) + | (data->autofan[nr].freq & 0x07)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) +@@ -953,11 +955,11 @@ + struct lm85_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->zone[nr].critical = TEMP_TO_REG(val); + lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), + data->zone[nr].critical); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define temp_auto(offset) \ +@@ -1017,13 +1019,6 @@ + temp_auto(2); + temp_auto(3); + +-static int lm85_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm85_detect); +-} +- + static int lm85_detect(struct i2c_adapter *adapter, int address, + int kind) + { +@@ -1149,7 +1144,7 @@ + /* Fill in the remaining client fields */ + data->type = kind; + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -1368,7 +1363,7 @@ + struct lm85_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if ( !data->valid || + time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) { +@@ -1571,7 +1566,7 @@ + + data->valid = 1; + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm87.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm87.c 2006-03-22 17:06:16.000000000 +0100 +@@ -60,6 +60,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -150,7 +151,6 @@ + * Functions declaration + */ + +-static int lm87_attach_adapter(struct i2c_adapter *adapter); + static int lm87_detect(struct i2c_adapter *adapter, int address, int kind); + static void lm87_init_client(struct i2c_client *client); + static int lm87_detach_client(struct i2c_client *client); +@@ -165,7 +165,9 @@ + .name = "lm87", + }, + .id = I2C_DRIVERID_LM87, +- .attach_adapter = lm87_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm87_detect, + .detach_client = lm87_detach_client, + }; + +@@ -176,7 +178,7 @@ + struct lm87_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -253,11 +255,11 @@ + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]); + lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) : + LM87_REG_AIN_MIN(nr-6), data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + static void set_in_max(struct device *dev, const char *buf, int nr) +@@ -266,11 +268,11 @@ + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]); + lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) : + LM87_REG_AIN_MAX(nr-6), data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + #define set_in(offset) \ +@@ -327,10 +329,10 @@ + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_low[nr] = TEMP_TO_REG(val); + lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + static void set_temp_high(struct device *dev, const char *buf, int nr) +@@ -339,10 +341,10 @@ + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_high[nr] = TEMP_TO_REG(val); + lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + #define set_temp(offset) \ +@@ -411,11 +413,11 @@ + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, + FAN_DIV_FROM_REG(data->fan_div[nr])); + lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + } + + /* Note: we save and restore the fan minimum here, because its value is +@@ -431,7 +433,7 @@ + unsigned long min; + u8 reg; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + min = FAN_FROM_REG(data->fan_min[nr], + FAN_DIV_FROM_REG(data->fan_div[nr])); + +@@ -441,7 +443,7 @@ + case 4: data->fan_div[nr] = 2; break; + case 8: data->fan_div[nr] = 3; break; + default: +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +@@ -459,7 +461,7 @@ + data->fan_min[nr] = FAN_TO_REG(min, val); + lm87_write_value(client, LM87_REG_FAN_MIN(nr), + data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -522,10 +524,10 @@ + struct lm87_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->aout = AOUT_TO_REG(val); + lm87_write_value(client, LM87_REG_AOUT, data->aout); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); +@@ -534,13 +536,6 @@ + * Real code + */ + +-static int lm87_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm87_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -589,7 +584,7 @@ + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, "lm87", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -744,7 +739,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm87_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + int i, j; +@@ -813,7 +808,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm90.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm90.c 2006-03-22 17:06:16.000000000 +0100 +@@ -78,6 +78,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* + * Addresses to scan +@@ -174,7 +175,6 @@ + * Functions declaration + */ + +-static int lm90_attach_adapter(struct i2c_adapter *adapter); + static int lm90_detect(struct i2c_adapter *adapter, int address, + int kind); + static void lm90_init_client(struct i2c_client *client); +@@ -190,7 +190,9 @@ + .name = "lm90", + }, + .id = I2C_DRIVERID_LM90, +- .attach_adapter = lm90_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm90_detect, + .detach_client = lm90_detach_client, + }; + +@@ -201,7 +203,7 @@ + struct lm90_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + int kind; +@@ -247,13 +249,13 @@ + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if (data->kind == adt7461) + data->temp8[nr] = TEMP1_TO_REG_ADT7461(val); + else + data->temp8[nr] = TEMP1_TO_REG(val); + i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -281,7 +283,7 @@ + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if (data->kind == adt7461) + data->temp11[nr] = TEMP2_TO_REG_ADT7461(val); + else +@@ -290,7 +292,7 @@ + data->temp11[nr] >> 8); + i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], + data->temp11[nr] & 0xff); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -311,11 +313,11 @@ + long val = simple_strtol(buf, NULL, 10); + long hyst; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + hyst = TEMP1_FROM_REG(data->temp8[3]) - val; + i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, + HYST_TO_REG(hyst)); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -326,23 +328,42 @@ + return sprintf(buf, "%d\n", data->alarms); + } + +-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); +-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); +-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, +- set_temp8, 1); +-static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, +- set_temp11, 1); +-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, +- set_temp8, 2); +-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, +- set_temp11, 2); +-static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, +- set_temp8, 3); +-static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, +- set_temp8, 4); +-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, +- set_temphyst, 3); +-static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); ++static ssize_t show_alarm(struct device *dev, struct device_attribute ++ *devattr, char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct lm90_data *data = lm90_update_device(dev); ++ ++ return sprintf(buf, "%d\n", (data->alarms >> attr->index) & 1); ++} ++ ++static struct sensor_device_attribute lm90_sensor_attr[] = { ++ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0), ++ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0), ++ SENSOR_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2), ++ SENSOR_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, ++ set_temp8, 1), ++ SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5), ++ SENSOR_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, ++ set_temp11, 1), ++ SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3), ++ SENSOR_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, ++ set_temp8, 2), ++ SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6), ++ SENSOR_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, ++ set_temp11, 2), ++ SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4), ++ SENSOR_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, ++ set_temp8, 3), ++ SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0), ++ SENSOR_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, ++ set_temp8, 4), ++ SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1), ++ SENSOR_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, ++ set_temphyst, 3), ++ SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4), ++}; ++ + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); + + /* pec used for ADM1032 only */ +@@ -413,13 +434,6 @@ + return 0; + } + +-static int lm90_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm90_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -428,7 +442,7 @@ + { + struct i2c_client *new_client; + struct lm90_data *data; +- int err = 0; ++ int i, err = 0; + const char *name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) +@@ -558,7 +572,7 @@ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; + data->kind = kind; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -574,26 +588,13 @@ + goto exit_detach; + } + +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp1_input.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_input.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp1_min.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_min.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp1_max.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_max.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp1_crit.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_crit.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp1_crit_hyst.dev_attr); +- device_create_file(&new_client->dev, +- &sensor_dev_attr_temp2_crit_hyst.dev_attr); ++ for (i = 0; i < ARRAY_SIZE(lm90_sensor_attr); i++) { ++ err = device_create_file(&new_client->dev, ++ &lm90_sensor_attr[i].dev_attr); ++ if (err) ++ goto exit_class; ++ } ++ + device_create_file(&new_client->dev, &dev_attr_alarms); + + if (new_client->flags & I2C_CLIENT_PEC) +@@ -601,6 +602,9 @@ + + return 0; + ++exit_class: ++ dev_err(&new_client->dev, "Sysfs interface creation failed\n"); ++ hwmon_device_unregister(data->class_dev); + exit_detach: + i2c_detach_client(new_client); + exit_free: +@@ -646,7 +650,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm90_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { + u8 oldh, newh, l; +@@ -692,7 +696,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/lm92.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/lm92.c 2006-03-22 17:06:16.000000000 +0100 +@@ -46,6 +46,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* The LM92 and MAX6635 have 2 two-state pins for address selection, + resulting in 4 possible addresses. */ +@@ -96,7 +97,7 @@ + struct lm92_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -114,7 +115,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct lm92_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) + || !data->valid) { +@@ -134,7 +135,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +@@ -158,10 +159,10 @@ + struct lm92_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = TEMP_TO_REG(val); \ + i2c_smbus_write_word_data(client, reg, swab16(data->value)); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + set_temp(temp1_crit, LM92_REG_TEMP_CRIT); +@@ -194,11 +195,11 @@ + struct lm92_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; + i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST, + swab16(TEMP_TO_REG(data->temp1_hyst))); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -348,7 +349,7 @@ + /* Fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the i2c subsystem a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -383,13 +384,6 @@ + return err; + } + +-static int lm92_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, lm92_detect); +-} +- + static int lm92_detach_client(struct i2c_client *client) + { + struct lm92_data *data = i2c_get_clientdata(client); +@@ -414,7 +408,9 @@ + .name = "lm92", + }, + .id = I2C_DRIVERID_LM92, +- .attach_adapter = lm92_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = lm92_detect, + .detach_client = lm92_detach_client, + }; + +--- linux-2.6.16.orig/drivers/hwmon/max1619.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/max1619.c 2006-03-22 17:06:16.000000000 +0100 +@@ -33,6 +33,7 @@ + #include <linux/i2c.h> + #include <linux/hwmon.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, + 0x29, 0x2a, 0x2b, +@@ -78,7 +79,6 @@ + * Functions declaration + */ + +-static int max1619_attach_adapter(struct i2c_adapter *adapter); + static int max1619_detect(struct i2c_adapter *adapter, int address, + int kind); + static void max1619_init_client(struct i2c_client *client); +@@ -93,7 +93,9 @@ + .driver = { + .name = "max1619", + }, +- .attach_adapter = max1619_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = max1619_detect, + .detach_client = max1619_detach_client, + }; + +@@ -104,7 +106,7 @@ + struct max1619_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -141,10 +143,10 @@ + struct max1619_data *data = i2c_get_clientdata(client); \ + long val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->value = TEMP_TO_REG(val); \ + i2c_smbus_write_byte_data(client, reg, data->value); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + +@@ -175,13 +177,6 @@ + * Real code + */ + +-static int max1619_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, max1619_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -262,7 +257,7 @@ + /* We can fill in the remaining client fields */ + strlcpy(new_client->name, name, I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -330,7 +325,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct max1619_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { + dev_dbg(&client->dev, "Updating max1619 data.\n"); +@@ -353,7 +348,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/sis5595.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/sis5595.c 2006-03-22 17:06:15.000000000 +0100 +@@ -60,6 +60,7 @@ + #include <linux/err.h> + #include <linux/init.h> + #include <linux/jiffies.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + +@@ -167,9 +168,9 @@ + struct sis5595_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + char maxins; /* == 3 if temp enabled, otherwise == 4 */ +@@ -192,8 +193,8 @@ + static int sis5595_detect(struct i2c_adapter *adapter); + static int sis5595_detach_client(struct i2c_client *client); + +-static int sis5595_read_value(struct i2c_client *client, u8 register); +-static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value); ++static int sis5595_read_value(struct i2c_client *client, u8 reg); ++static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value); + static struct sis5595_data *sis5595_update_device(struct device *dev); + static void sis5595_init_client(struct i2c_client *client); + +@@ -231,10 +232,10 @@ + struct sis5595_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val); + sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -245,10 +246,10 @@ + struct sis5595_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val); + sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -310,10 +311,10 @@ + struct sis5595_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_over = TEMP_TO_REG(val); + sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -329,10 +330,10 @@ + struct sis5595_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_hyst = TEMP_TO_REG(val); + sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -364,10 +365,10 @@ + struct sis5595_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -390,7 +391,7 @@ + unsigned long val = simple_strtoul(buf, NULL, 10); + int reg; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + min = FAN_FROM_REG(data->fan_min[nr], + DIV_FROM_REG(data->fan_div[nr])); + reg = sis5595_read_value(client, SIS5595_REG_FANDIV); +@@ -403,7 +404,7 @@ + default: + dev_err(&client->dev, "fan_div value %ld not " + "supported. Choose one of 1, 2, 4 or 8!\n", val); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +@@ -419,7 +420,7 @@ + data->fan_min[nr] = + FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -527,7 +528,7 @@ + + new_client = &data->client; + new_client->addr = address; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + i2c_set_clientdata(new_client, data); + new_client->adapter = adapter; + new_client->driver = &sis5595_driver; +@@ -548,7 +549,7 @@ + strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE); + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -635,20 +636,20 @@ + int res; + + struct sis5595_data *data = i2c_get_clientdata(client); +- down(&data->lock); ++ mutex_lock(&data->lock); + outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); + res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return res; + } + + static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) + { + struct sis5595_data *data = i2c_get_clientdata(client); +- down(&data->lock); ++ mutex_lock(&data->lock); + outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); + outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return 0; + } + +@@ -667,7 +668,7 @@ + struct sis5595_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -707,7 +708,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/smsc47b397.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/smsc47b397.c 2006-03-22 17:06:15.000000000 +0100 +@@ -35,6 +35,7 @@ + #include <linux/hwmon.h> + #include <linux/err.h> + #include <linux/init.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + /* Address is autodetected, there is no default value */ +@@ -92,9 +93,9 @@ + struct smsc47b397_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + +- struct semaphore update_lock; ++ struct mutex update_lock; + unsigned long last_updated; /* in jiffies */ + int valid; + +@@ -108,10 +109,10 @@ + struct smsc47b397_data *data = i2c_get_clientdata(client); + int res; + +- down(&data->lock); ++ mutex_lock(&data->lock); + outb(reg, client->addr); + res = inb_p(client->addr + 1); +- up(&data->lock); ++ mutex_unlock(&data->lock); + return res; + } + +@@ -121,7 +122,7 @@ + struct smsc47b397_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + dev_dbg(&client->dev, "starting device update...\n"); +@@ -144,7 +145,7 @@ + dev_dbg(&client->dev, "... device update complete\n"); + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +@@ -254,14 +255,14 @@ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + new_client->adapter = adapter; + new_client->driver = &smsc47b397_driver; + new_client->flags = 0; + + strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE); + +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + if ((err = i2c_attach_client(new_client))) + goto error_free; +--- linux-2.6.16.orig/drivers/hwmon/smsc47m1.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/smsc47m1.c 2006-03-22 17:06:15.000000000 +0100 +@@ -34,6 +34,7 @@ + #include <linux/hwmon.h> + #include <linux/err.h> + #include <linux/init.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + /* Address is autodetected, there is no default value */ +@@ -102,9 +103,9 @@ + struct smsc47m1_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + +- struct semaphore update_lock; ++ struct mutex update_lock; + unsigned long last_updated; /* In jiffies */ + + u8 fan[2]; /* Register value */ +@@ -188,18 +189,18 @@ + struct smsc47m1_data *data = i2c_get_clientdata(client); + long rpmdiv, val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); + + if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) { +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + + data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); + smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), + data->fan_preload[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -220,14 +221,14 @@ + if (new_div == old_div) /* No change */ + return count; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + switch (new_div) { + case 1: data->fan_div[nr] = 0; break; + case 2: data->fan_div[nr] = 1; break; + case 4: data->fan_div[nr] = 2; break; + case 8: data->fan_div[nr] = 3; break; + default: +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +@@ -241,7 +242,7 @@ + data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); + smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), + data->fan_preload[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -257,12 +258,12 @@ + if (val < 0 || val > 255) + return -EINVAL; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm[nr] &= 0x81; /* Preserve additional bits */ + data->pwm[nr] |= PWM_TO_REG(val); + smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), + data->pwm[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -278,12 +279,12 @@ + if (val != 0 && val != 1) + return -EINVAL; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm[nr] &= 0xFE; /* preserve the other bits */ + data->pwm[nr] |= !val; + smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), + data->pwm[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } +@@ -408,13 +409,13 @@ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + new_client->adapter = adapter; + new_client->driver = &smsc47m1_driver; + new_client->flags = 0; + + strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* If no function is properly configured, there's no point in + actually registering the chip. */ +@@ -512,17 +513,17 @@ + { + int res; + +- down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); ++ mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + res = inb_p(client->addr + reg); +- up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); ++ mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + return res; + } + + static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) + { +- down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); ++ mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + outb_p(value, client->addr + reg); +- up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); ++ mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); + } + + static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, +@@ -531,7 +532,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m1_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { + int i; +@@ -558,7 +559,7 @@ + data->last_updated = jiffies; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return data; + } + +--- linux-2.6.16.orig/drivers/hwmon/via686a.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/via686a.c 2006-03-22 17:06:15.000000000 +0100 +@@ -39,6 +39,7 @@ + #include <linux/hwmon.h> + #include <linux/err.h> + #include <linux/init.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + +@@ -296,7 +297,7 @@ + struct via686a_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -355,11 +356,11 @@ + struct via686a_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val, nr); + via686a_write_value(client, VIA686A_REG_IN_MIN(nr), + data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_in_max(struct device *dev, const char *buf, +@@ -368,11 +369,11 @@ + struct via686a_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val, nr); + via686a_write_value(client, VIA686A_REG_IN_MAX(nr), + data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define show_in_offset(offset) \ +@@ -432,11 +433,11 @@ + struct via686a_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_over[nr] = TEMP_TO_REG(val); + via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], + data->temp_over[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_temp_hyst(struct device *dev, const char *buf, +@@ -445,11 +446,11 @@ + struct via686a_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_hyst[nr] = TEMP_TO_REG(val); + via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], + data->temp_hyst[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + #define show_temp_offset(offset) \ +@@ -508,10 +509,10 @@ + struct via686a_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_fan_div(struct device *dev, const char *buf, +@@ -521,12 +522,12 @@ + int val = simple_strtol(buf, NULL, 10); + int old; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + old = via686a_read_value(client, VIA686A_REG_FANDIV); + data->fan_div[nr] = DIV_TO_REG(val); + old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); + via686a_write_value(client, VIA686A_REG_FANDIV, old); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -639,7 +640,7 @@ + strlcpy(new_client->name, client_name, I2C_NAME_SIZE); + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) + goto exit_free; +@@ -733,7 +734,7 @@ + struct via686a_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -788,7 +789,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/vt8231.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/vt8231.c 2006-03-22 17:06:15.000000000 +0100 +@@ -35,6 +35,7 @@ + #include <linux/hwmon-sysfs.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + + static int force_addr; +@@ -148,7 +149,7 @@ + + struct vt8231_data { + struct i2c_client client; +- struct semaphore update_lock; ++ struct mutex update_lock; + struct class_device *class_dev; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ +@@ -223,10 +224,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); + vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -239,10 +240,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); + vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -281,11 +282,11 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, + 0, 255); + vt8231_write_value(client, regvoltmin[5], data->in_min[5]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -296,11 +297,11 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, + 0, 255); + vt8231_write_value(client, regvoltmax[5], data->in_max[5]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -351,10 +352,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); + vt8231_write_value(client, regtempmax[0], data->temp_max[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, +@@ -364,10 +365,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); + vt8231_write_value(client, regtempmin[0], data->temp_min[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -407,10 +408,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); + vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, +@@ -422,10 +423,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); + vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -520,10 +521,10 @@ + struct vt8231_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -539,7 +540,7 @@ + long min = FAN_FROM_REG(data->fan_min[nr], + DIV_FROM_REG(data->fan_div[nr])); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + switch (val) { + case 1: data->fan_div[nr] = 0; break; + case 2: data->fan_div[nr] = 1; break; +@@ -548,7 +549,7 @@ + default: + dev_err(&client->dev, "fan_div value %ld not supported." + "Choose one of 1, 2, 4 or 8!\n", val); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +@@ -558,7 +559,7 @@ + + old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); + vt8231_write_value(client, VT8231_REG_FANDIV, old); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -660,7 +661,7 @@ + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "vt8231", I2C_NAME_SIZE); + +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) +@@ -745,7 +746,7 @@ + int i; + u16 low; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -804,7 +805,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/w83627ehf.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/w83627ehf.c 2006-03-22 17:06:16.000000000 +0100 +@@ -30,10 +30,7 @@ + Supports the following chips: + + Chip #vin #fan #pwm #temp chip_id man_id +- w83627ehf - 5 - 3 0x88 0x5ca3 +- +- This is a preliminary version of the driver, only supporting the +- fan and temperature inputs. The chip does much more than that. ++ w83627ehf 10 5 - 3 0x88 0x5ca3 + */ + + #include <linux/module.h> +@@ -42,7 +39,9 @@ + #include <linux/i2c.h> + #include <linux/i2c-isa.h> + #include <linux/hwmon.h> ++#include <linux/hwmon-sysfs.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + #include "lm75.h" + +@@ -119,6 +118,14 @@ + static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; + static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; + ++/* The W83627EHF registers for nr=7,8,9 are in bank 5 */ ++#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ ++ (0x554 + (((nr) - 7) * 2))) ++#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ ++ (0x555 + (((nr) - 7) * 2))) ++#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ ++ (0x550 + (nr) - 7)) ++ + #define W83627EHF_REG_TEMP1 0x27 + #define W83627EHF_REG_TEMP1_HYST 0x3a + #define W83627EHF_REG_TEMP1_OVER 0x39 +@@ -134,6 +141,10 @@ + #define W83627EHF_REG_DIODE 0x59 + #define W83627EHF_REG_SMI_OVT 0x4C + ++#define W83627EHF_REG_ALARM1 0x459 ++#define W83627EHF_REG_ALARM2 0x45A ++#define W83627EHF_REG_ALARM3 0x45B ++ + /* + * Conversions + */ +@@ -170,6 +181,20 @@ + return (temp + 500) / 1000; + } + ++/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */ ++ ++static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 }; ++ ++static inline long in_from_reg(u8 reg, u8 nr) ++{ ++ return reg * scale_in[nr]; ++} ++ ++static inline u8 in_to_reg(u32 val, u8 nr) ++{ ++ return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255); ++} ++ + /* + * Data structures and manipulation thereof + */ +@@ -177,13 +202,16 @@ + struct w83627ehf_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + /* Register values */ ++ u8 in[10]; /* Register value */ ++ u8 in_max[10]; /* Register value */ ++ u8 in_min[10]; /* Register value */ + u8 fan[5]; + u8 fan_min[5]; + u8 fan_div[5]; +@@ -194,6 +222,7 @@ + s16 temp[2]; + s16 temp_max[2]; + s16 temp_max_hyst[2]; ++ u32 alarms; + }; + + static inline int is_word_sized(u16 reg) +@@ -230,7 +259,7 @@ + struct w83627ehf_data *data = i2c_get_clientdata(client); + int res, word_sized = is_word_sized(reg); + +- down(&data->lock); ++ mutex_lock(&data->lock); + + w83627ehf_set_bank(client, reg); + outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); +@@ -242,7 +271,7 @@ + } + w83627ehf_reset_bank(client, reg); + +- up(&data->lock); ++ mutex_unlock(&data->lock); + + return res; + } +@@ -252,7 +281,7 @@ + struct w83627ehf_data *data = i2c_get_clientdata(client); + int word_sized = is_word_sized(reg); + +- down(&data->lock); ++ mutex_lock(&data->lock); + + w83627ehf_set_bank(client, reg); + outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); +@@ -264,7 +293,7 @@ + outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); + w83627ehf_reset_bank(client, reg); + +- up(&data->lock); ++ mutex_unlock(&data->lock); + return 0; + } + +@@ -322,7 +351,7 @@ + struct w83627ehf_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ) + || !data->valid) { +@@ -347,6 +376,16 @@ + data->fan_div[3] |= (i >> 5) & 0x04; + } + ++ /* Measured voltages and limits */ ++ for (i = 0; i < 10; i++) { ++ data->in[i] = w83627ehf_read_value(client, ++ W83627EHF_REG_IN(i)); ++ data->in_min[i] = w83627ehf_read_value(client, ++ W83627EHF_REG_IN_MIN(i)); ++ data->in_max[i] = w83627ehf_read_value(client, ++ W83627EHF_REG_IN_MAX(i)); ++ } ++ + /* Measured fan speeds and limits */ + for (i = 0; i < 5; i++) { + if (!(data->has_fan & (1 << i))) +@@ -393,23 +432,136 @@ + W83627EHF_REG_TEMP_HYST[i]); + } + ++ data->alarms = w83627ehf_read_value(client, ++ W83627EHF_REG_ALARM1) | ++ (w83627ehf_read_value(client, ++ W83627EHF_REG_ALARM2) << 8) | ++ (w83627ehf_read_value(client, ++ W83627EHF_REG_ALARM3) << 16); ++ + data->last_updated = jiffies; + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return data; + } + + /* + * Sysfs callback functions + */ ++#define show_in_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, "%ld\n", in_from_reg(data->reg[nr], nr)); \ ++} ++show_in_reg(in) ++show_in_reg(in_min) ++show_in_reg(in_max) ++ ++#define store_in_reg(REG, reg) \ ++static ssize_t \ ++store_in_##reg (struct device *dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct i2c_client *client = to_i2c_client(dev); \ ++ struct w83627ehf_data *data = i2c_get_clientdata(client); \ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ ++ int nr = sensor_attr->index; \ ++ u32 val = simple_strtoul(buf, NULL, 10); \ ++ \ ++ mutex_lock(&data->update_lock); \ ++ data->in_##reg[nr] = in_to_reg(val, nr); \ ++ w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \ ++ data->in_##reg[nr]); \ ++ mutex_unlock(&data->update_lock); \ ++ return count; \ ++} ++ ++store_in_reg(MIN, min) ++store_in_reg(MAX, max) ++ ++static ssize_t show_alarm(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, "%u\n", (data->alarms >> nr) & 0x01); ++} ++ ++static struct sensor_device_attribute sda_in_input[] = { ++ SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), ++ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), ++ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), ++ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), ++ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), ++ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), ++ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), ++ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), ++ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), ++ SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), ++}; ++ ++static struct sensor_device_attribute sda_in_alarm[] = { ++ SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), ++ SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), ++ SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), ++ SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), ++ SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), ++ SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), ++ SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), ++ SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), ++ SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), ++ SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19), ++}; ++ ++static struct sensor_device_attribute sda_in_min[] = { ++ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), ++ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), ++ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), ++ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), ++ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), ++ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), ++ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), ++ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), ++ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), ++ SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), ++}; ++ ++static struct sensor_device_attribute sda_in_max[] = { ++ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), ++ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), ++ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), ++ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), ++ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), ++ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), ++ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), ++ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), ++ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), ++ SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), ++}; ++ ++static void device_create_file_in(struct device *dev, int i) ++{ ++ device_create_file(dev, &sda_in_input[i].dev_attr); ++ device_create_file(dev, &sda_in_alarm[i].dev_attr); ++ device_create_file(dev, &sda_in_min[i].dev_attr); ++ device_create_file(dev, &sda_in_max[i].dev_attr); ++} + + #define show_fan_reg(reg) \ + static ssize_t \ +-show_##reg(struct device *dev, char *buf, int nr) \ ++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", \ + fan_from_reg(data->reg[nr], \ + div_from_reg(data->fan_div[nr]))); \ +@@ -418,23 +570,28 @@ + show_fan_reg(fan_min); + + static ssize_t +-show_fan_div(struct device *dev, char *buf, int nr) ++show_fan_div(struct device *dev, struct device_attribute *attr, ++ char *buf) + { + struct w83627ehf_data *data = w83627ehf_update_device(dev); +- return sprintf(buf, "%u\n", +- div_from_reg(data->fan_div[nr])); ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; ++ return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr])); + } + + static ssize_t +-store_fan_min(struct device *dev, const char *buf, size_t count, int nr) ++store_fan_min(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) + { + struct i2c_client *client = to_i2c_client(dev); + struct w83627ehf_data *data = i2c_get_clientdata(client); ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; + unsigned int val = simple_strtoul(buf, NULL, 10); + unsigned int reg; + u8 new_div; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + if (!val) { + /* No min limit, alarm disabled */ + data->fan_min[nr] = 255; +@@ -482,63 +639,55 @@ + } + w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], + data->fan_min[nr]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return count; + } + +-#define sysfs_fan_offset(offset) \ +-static ssize_t \ +-show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \ +- char *buf) \ +-{ \ +- return show_fan(dev, buf, offset-1); \ +-} \ +-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ +- show_reg_fan_##offset, NULL); ++static struct sensor_device_attribute sda_fan_input[] = { ++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), ++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), ++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), ++ SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), ++ SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), ++}; + +-#define sysfs_fan_min_offset(offset) \ +-static ssize_t \ +-show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ +- char *buf) \ +-{ \ +- return show_fan_min(dev, buf, offset-1); \ +-} \ +-static ssize_t \ +-store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \ +- const char *buf, size_t count) \ +-{ \ +- return store_fan_min(dev, buf, count, offset-1); \ +-} \ +-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ +- show_reg_fan##offset##_min, \ +- store_reg_fan##offset##_min); ++static struct sensor_device_attribute sda_fan_alarm[] = { ++ SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), ++ SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), ++ SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 10), ++ SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 11), ++ SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23), ++}; + +-#define sysfs_fan_div_offset(offset) \ +-static ssize_t \ +-show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \ +- char *buf) \ +-{ \ +- return show_fan_div(dev, buf, offset - 1); \ +-} \ +-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \ +- show_reg_fan##offset##_div, NULL); +- +-sysfs_fan_offset(1); +-sysfs_fan_min_offset(1); +-sysfs_fan_div_offset(1); +-sysfs_fan_offset(2); +-sysfs_fan_min_offset(2); +-sysfs_fan_div_offset(2); +-sysfs_fan_offset(3); +-sysfs_fan_min_offset(3); +-sysfs_fan_div_offset(3); +-sysfs_fan_offset(4); +-sysfs_fan_min_offset(4); +-sysfs_fan_div_offset(4); +-sysfs_fan_offset(5); +-sysfs_fan_min_offset(5); +-sysfs_fan_div_offset(5); ++static struct sensor_device_attribute sda_fan_min[] = { ++ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 0), ++ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 1), ++ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 2), ++ SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 3), ++ SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, ++ store_fan_min, 4), ++}; ++ ++static struct sensor_device_attribute sda_fan_div[] = { ++ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0), ++ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1), ++ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2), ++ SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3), ++ SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), ++}; ++ ++static void device_create_file_fan(struct device *dev, int i) ++{ ++ device_create_file(dev, &sda_fan_input[i].dev_attr); ++ device_create_file(dev, &sda_fan_alarm[i].dev_attr); ++ device_create_file(dev, &sda_fan_div[i].dev_attr); ++ device_create_file(dev, &sda_fan_min[i].dev_attr); ++} + + #define show_temp1_reg(reg) \ + static ssize_t \ +@@ -561,27 +710,24 @@ + struct w83627ehf_data *data = i2c_get_clientdata(client); \ + u32 val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->temp1_##reg = temp1_to_reg(val); \ + w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ + data->temp1_##reg); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + store_temp1_reg(OVER, max); + store_temp1_reg(HYST, max_hyst); + +-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL); +-static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR, +- show_temp1_max, store_temp1_max); +-static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR, +- show_temp1_max_hyst, store_temp1_max_hyst); +- + #define show_temp_reg(reg) \ + static ssize_t \ +-show_##reg (struct device *dev, char *buf, int nr) \ ++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", \ + LM75_TEMP_FROM_REG(data->reg[nr])); \ + } +@@ -591,55 +737,45 @@ + + #define store_temp_reg(REG, reg) \ + static ssize_t \ +-store_##reg (struct device *dev, const char *buf, size_t count, int nr) \ ++store_##reg(struct device *dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ + { \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83627ehf_data *data = i2c_get_clientdata(client); \ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ ++ int nr = sensor_attr->index; \ + u32 val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->reg[nr] = LM75_TEMP_TO_REG(val); \ + w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ + data->reg[nr]); \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + store_temp_reg(OVER, temp_max); + store_temp_reg(HYST, temp_max_hyst); + +-#define sysfs_temp_offset(offset) \ +-static ssize_t \ +-show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \ +- char *buf) \ +-{ \ +- return show_temp(dev, buf, offset - 2); \ +-} \ +-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ +- show_reg_temp##offset, NULL); +- +-#define sysfs_temp_reg_offset(reg, offset) \ +-static ssize_t \ +-show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ +- char *buf) \ +-{ \ +- return show_temp_##reg(dev, buf, offset - 2); \ +-} \ +-static ssize_t \ +-store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \ +- const char *buf, size_t count) \ +-{ \ +- return store_temp_##reg(dev, buf, count, offset - 2); \ +-} \ +-static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ +- show_reg_temp##offset##_##reg, \ +- store_reg_temp##offset##_##reg); +- +-sysfs_temp_offset(2); +-sysfs_temp_reg_offset(max, 2); +-sysfs_temp_reg_offset(max_hyst, 2); +-sysfs_temp_offset(3); +-sysfs_temp_reg_offset(max, 3); +-sysfs_temp_reg_offset(max_hyst, 3); ++static struct sensor_device_attribute sda_temp[] = { ++ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), ++ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), ++ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), ++ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, ++ store_temp1_max, 0), ++ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, ++ store_temp_max, 0), ++ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, ++ store_temp_max, 1), ++ SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, ++ store_temp1_max_hyst, 0), ++ SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, ++ store_temp_max_hyst, 0), ++ SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, ++ store_temp_max_hyst, 1), ++ SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), ++ SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), ++ SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), ++}; + + /* + * Driver and client management +@@ -673,6 +809,7 @@ + { + struct i2c_client *client; + struct w83627ehf_data *data; ++ struct device *dev; + int i, err = 0; + + if (!request_region(address + REGION_OFFSET, REGION_LENGTH, +@@ -689,14 +826,15 @@ + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + client->adapter = adapter; + client->driver = &w83627ehf_driver; + client->flags = 0; ++ dev = &client->dev; + + strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the i2c layer a new client has arrived */ + if ((err = i2c_attach_client(client))) +@@ -720,42 +858,21 @@ + data->has_fan |= (1 << 4); + + /* Register sysfs hooks */ +- data->class_dev = hwmon_device_register(&client->dev); ++ data->class_dev = hwmon_device_register(dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_detach; + } + +- device_create_file(&client->dev, &dev_attr_fan1_input); +- device_create_file(&client->dev, &dev_attr_fan1_min); +- device_create_file(&client->dev, &dev_attr_fan1_div); +- device_create_file(&client->dev, &dev_attr_fan2_input); +- device_create_file(&client->dev, &dev_attr_fan2_min); +- device_create_file(&client->dev, &dev_attr_fan2_div); +- device_create_file(&client->dev, &dev_attr_fan3_input); +- device_create_file(&client->dev, &dev_attr_fan3_min); +- device_create_file(&client->dev, &dev_attr_fan3_div); +- +- if (data->has_fan & (1 << 3)) { +- device_create_file(&client->dev, &dev_attr_fan4_input); +- device_create_file(&client->dev, &dev_attr_fan4_min); +- device_create_file(&client->dev, &dev_attr_fan4_div); +- } +- if (data->has_fan & (1 << 4)) { +- device_create_file(&client->dev, &dev_attr_fan5_input); +- device_create_file(&client->dev, &dev_attr_fan5_min); +- device_create_file(&client->dev, &dev_attr_fan5_div); +- } +- +- device_create_file(&client->dev, &dev_attr_temp1_input); +- device_create_file(&client->dev, &dev_attr_temp1_max); +- device_create_file(&client->dev, &dev_attr_temp1_max_hyst); +- device_create_file(&client->dev, &dev_attr_temp2_input); +- device_create_file(&client->dev, &dev_attr_temp2_max); +- device_create_file(&client->dev, &dev_attr_temp2_max_hyst); +- device_create_file(&client->dev, &dev_attr_temp3_input); +- device_create_file(&client->dev, &dev_attr_temp3_max); +- device_create_file(&client->dev, &dev_attr_temp3_max_hyst); ++ for (i = 0; i < 10; i++) ++ device_create_file_in(dev, i); ++ ++ for (i = 0; i < 5; i++) { ++ if (data->has_fan & (1 << i)) ++ device_create_file_fan(dev, i); ++ } ++ for (i = 0; i < ARRAY_SIZE(sda_temp); i++) ++ device_create_file(dev, &sda_temp[i].dev_attr); + + return 0; + +--- linux-2.6.16.orig/drivers/hwmon/w83627hf.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/w83627hf.c 2006-03-22 17:06:21.000000000 +0100 +@@ -28,6 +28,7 @@ + w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) + w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) + w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) ++ w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) + w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) + + For other winbond chips, and for i2c support in the above chips, +@@ -45,7 +46,9 @@ + #include <linux/i2c-isa.h> + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> ++#include <linux/hwmon-sysfs.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + #include "lm75.h" + +@@ -62,7 +65,7 @@ + static unsigned short address; + + /* Insmod parameters */ +-enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf }; ++enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; + + static int reset; + module_param(reset, bool, 0); +@@ -100,6 +103,10 @@ + #define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ + #define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ + ++#define W83687THF_VID_EN 0x29 /* w83687thf only */ ++#define W83687THF_VID_CFG 0xF0 /* w83687thf only */ ++#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ ++ + static inline void + superio_outb(int reg, int val) + { +@@ -138,6 +145,7 @@ + #define W627THF_DEVID 0x82 + #define W697_DEVID 0x60 + #define W637_DEVID 0x70 ++#define W687THF_DEVID 0x85 + #define WINB_ACT_REG 0x30 + #define WINB_BASE_REG 0x60 + /* Constants specified below */ +@@ -201,11 +209,11 @@ + #define W83627HF_REG_PWM1 0x5A + #define W83627HF_REG_PWM2 0x5B + +-#define W83627THF_REG_PWM1 0x01 /* 697HF and 637HF too */ +-#define W83627THF_REG_PWM2 0x03 /* 697HF and 637HF too */ +-#define W83627THF_REG_PWM3 0x11 /* 637HF too */ ++#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ ++#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ ++#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ + +-#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF too */ ++#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */ + + static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; + static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, +@@ -285,10 +293,10 @@ + struct w83627hf_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -318,16 +326,15 @@ + Default = 3435. + Other Betas unimplemented */ + u8 vrm; +- u8 vrm_ovt; /* Register value, 627thf & 637hf only */ ++ u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ + }; + + + static int w83627hf_detect(struct i2c_adapter *adapter); + static int w83627hf_detach_client(struct i2c_client *client); + +-static int w83627hf_read_value(struct i2c_client *client, u16 register); +-static int w83627hf_write_value(struct i2c_client *client, u16 register, +- u16 value); ++static int w83627hf_read_value(struct i2c_client *client, u16 reg); ++static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); + static struct w83627hf_data *w83627hf_update_device(struct device *dev); + static void w83627hf_init_client(struct i2c_client *client); + +@@ -360,12 +367,12 @@ + \ + val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ + data->in_##reg[nr]); \ + \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + store_in_reg(MIN, min) +@@ -413,7 +420,8 @@ + long in0; + + if ((data->vrm_ovt & 0x01) && +- (w83627thf == data->type || w83637hf == data->type)) ++ (w83627thf == data->type || w83637hf == data->type ++ || w83687thf == data->type)) + + /* use VRM9 calculation */ + in0 = (long)((reg * 488 + 70000 + 50) / 100); +@@ -451,10 +459,11 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if ((data->vrm_ovt & 0x01) && +- (w83627thf == data->type || w83637hf == data->type)) ++ (w83627thf == data->type || w83637hf == data->type ++ || w83687thf == data->type)) + + /* use VRM9 calculation */ + data->in_min[0] = +@@ -465,7 +474,7 @@ + data->in_min[0] = IN_TO_REG(val); + + w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -478,10 +487,11 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if ((data->vrm_ovt & 0x01) && +- (w83627thf == data->type || w83637hf == data->type)) ++ (w83627thf == data->type || w83637hf == data->type ++ || w83687thf == data->type)) + + /* use VRM9 calculation */ + data->in_max[0] = +@@ -492,7 +502,7 @@ + data->in_max[0] = IN_TO_REG(val); + + w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -507,6 +517,10 @@ + device_create_file(&client->dev, &dev_attr_in##offset##_input); \ + device_create_file(&client->dev, &dev_attr_in##offset##_min); \ + device_create_file(&client->dev, &dev_attr_in##offset##_max); \ ++device_create_file(&client->dev, \ ++ &sensor_dev_attr_in##offset##_alarm.dev_attr); \ ++device_create_file(&client->dev, \ ++ &sensor_dev_attr_in##offset##_beep.dev_attr); \ + } while (0) + + #define show_fan_reg(reg) \ +@@ -529,13 +543,13 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr - 1] = + FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); + w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), + data->fan_min[nr - 1]); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -570,6 +584,10 @@ + do { \ + device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ + device_create_file(&client->dev, &dev_attr_fan##offset##_min); \ ++device_create_file(&client->dev, \ ++ &sensor_dev_attr_fan##offset##_alarm.dev_attr); \ ++device_create_file(&client->dev, \ ++ &sensor_dev_attr_fan##offset##_beep.dev_attr); \ + } while (0) + + #define show_temp_reg(reg) \ +@@ -597,7 +615,7 @@ + \ + val = simple_strtoul(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + \ + if (nr >= 2) { /* TEMP2 and TEMP3 */ \ + data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ +@@ -609,7 +627,7 @@ + data->temp_##reg); \ + } \ + \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + store_temp_reg(OVER, max); +@@ -651,6 +669,10 @@ + device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ + device_create_file(&client->dev, &dev_attr_temp##offset##_max); \ + device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \ ++device_create_file(&client->dev, \ ++ &sensor_dev_attr_temp##offset##_alarm.dev_attr); \ ++device_create_file(&client->dev, \ ++ &sensor_dev_attr_temp##offset##_beep.dev_attr); \ + } while (0) + + static ssize_t +@@ -693,76 +715,152 @@ + } + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); + #define device_create_file_alarms(client) \ +-device_create_file(&client->dev, &dev_attr_alarms) ++do { \ ++device_create_file(&client->dev, &dev_attr_alarms); \ ++device_create_file(&client->dev, &sensor_dev_attr_chassis_alarm.dev_attr); \ ++} while (0) + +-#define show_beep_reg(REG, reg) \ +-static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ +-{ \ +- struct w83627hf_data *data = w83627hf_update_device(dev); \ +- return sprintf(buf,"%ld\n", \ +- (long)BEEP_##REG##_FROM_REG(data->beep_##reg)); \ ++static ssize_t ++show_alarm_bit(struct device *dev, struct device_attribute *devattr, char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct w83627hf_data *data = w83627hf_update_device(dev); ++ ++ return sprintf(buf, "%u\n", (data->alarms >> attr->index) & 1); + } +-show_beep_reg(ENABLE, enable) +-show_beep_reg(MASK, mask) ++static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm_bit, NULL, 0); ++static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm_bit, NULL, 1); ++static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm_bit, NULL, 2); ++static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm_bit, NULL, 3); ++static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm_bit, NULL, 8); ++static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm_bit, NULL, 9); ++static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm_bit, NULL, 10); ++static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm_bit, NULL, 16); ++static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm_bit, NULL, 17); ++static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm_bit, NULL, 6); ++static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm_bit, NULL, 7); ++static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm_bit, NULL, 11); ++static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm_bit, NULL, 4); ++static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm_bit, NULL, 5); ++static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm_bit, NULL, 13); ++static SENSOR_DEVICE_ATTR(chassis_alarm, S_IRUGO, show_alarm_bit, NULL, 12); + +-#define BEEP_ENABLE 0 /* Store beep_enable */ +-#define BEEP_MASK 1 /* Store beep_mask */ ++static ssize_t show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct w83627hf_data *data = w83627hf_update_device(dev); ++ return sprintf(buf, "%ld\n", ++ (long)BEEP_MASK_FROM_REG(data->beep_mask)); ++} + + static ssize_t +-store_beep_reg(struct device *dev, const char *buf, size_t count, +- int update_mask) ++store_beep_mask(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) + { + struct i2c_client *client = to_i2c_client(dev); + struct w83627hf_data *data = i2c_get_clientdata(client); +- u32 val, val2; +- +- val = simple_strtoul(buf, NULL, 10); ++ u32 val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); +- +- if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ +- data->beep_mask = BEEP_MASK_TO_REG(val); +- w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, +- data->beep_mask & 0xff); +- w83627hf_write_value(client, W83781D_REG_BEEP_INTS3, +- ((data->beep_mask) >> 16) & 0xff); +- val2 = (data->beep_mask >> 8) & 0x7f; +- } else { /* We are storing beep_enable */ +- val2 = +- w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; +- data->beep_enable = BEEP_ENABLE_TO_REG(val); +- } ++ mutex_lock(&data->update_lock); + ++ data->beep_mask = BEEP_MASK_TO_REG(val); ++ w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, ++ data->beep_mask & 0xff); ++ w83627hf_write_value(client, W83781D_REG_BEEP_INTS3, ++ ((data->beep_mask) >> 16) & 0xff); + w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, +- val2 | data->beep_enable << 7); ++ ((data->beep_mask >> 8) & 0x7f) ++ | data->beep_enable << 7); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } +- +-#define sysfs_beep(REG, reg) \ +-static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ +-{ \ +- return show_beep_##reg(dev, attr, buf); \ +-} \ +-static ssize_t \ +-store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ +-{ \ +- return store_beep_reg(dev, buf, count, BEEP_##REG); \ +-} \ +-static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \ +- show_regs_beep_##reg, store_regs_beep_##reg); +- +-sysfs_beep(ENABLE, enable); +-sysfs_beep(MASK, mask); ++static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, \ ++ show_beep_mask, store_beep_mask); + + #define device_create_file_beep(client) \ + do { \ +-device_create_file(&client->dev, &dev_attr_beep_enable); \ ++device_create_file(&client->dev, &sensor_dev_attr_beep_enable.dev_attr); \ + device_create_file(&client->dev, &dev_attr_beep_mask); \ ++device_create_file(&client->dev, &sensor_dev_attr_chassis_beep.dev_attr); \ + } while (0) + + static ssize_t ++show_beep_bit(struct device *dev, struct device_attribute *devattr, char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct w83627hf_data *data = w83627hf_update_device(dev); ++ ++ return sprintf(buf, "%u\n", (data->beep_mask >> attr->index) & 1); ++} ++ ++static ssize_t ++store_beep_bit(struct device *dev, struct device_attribute *devattr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); ++ struct w83627hf_data *data = i2c_get_clientdata(client); ++ u16 beepreg[3] = { W83781D_REG_BEEP_INTS1, W83781D_REG_BEEP_INTS2, ++ W83781D_REG_BEEP_INTS3 }; ++ u32 val; ++ u8 reg; ++ ++ val = simple_strtoul(buf, NULL, 10); ++ if (val != 0 && val != 1) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ ++ reg = w83627hf_read_value(client, beepreg[attr->index >> 3]); ++ if (val) { ++ reg |= 1 << (attr->index & 0x07); ++ data->beep_mask |= 1 << attr->index; ++ } else { ++ reg &= ~(1 << (attr->index & 0x07)); ++ data->beep_mask &= ~(1 << attr->index); ++ } ++ w83627hf_write_value(client, beepreg[attr->index >> 3], reg); ++ ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 0); ++static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 1); ++static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 2); ++static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 3); ++static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 8); ++static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 9); ++static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 10); ++static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 16); ++static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 17); ++static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 6); ++static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 7); ++static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 11); ++static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 4); ++static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 5); ++static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 13); ++static SENSOR_DEVICE_ATTR(chassis_beep, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 12); ++static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, show_beep_bit, ++ store_beep_bit, 15); ++ ++static ssize_t + show_fan_div_reg(struct device *dev, char *buf, int nr) + { + struct w83627hf_data *data = w83627hf_update_device(dev); +@@ -783,7 +881,7 @@ + u8 reg; + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + /* Save fan_min */ + min = FAN_FROM_REG(data->fan_min[nr], +@@ -805,7 +903,7 @@ + data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -848,7 +946,7 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (data->type == w83627thf) { + /* bits 0-3 are reserved in 627THF */ +@@ -865,7 +963,7 @@ + data->pwm[nr - 1]); + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -907,7 +1005,7 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + switch (val) { + case 1: /* PII/Celeron diode */ +@@ -941,7 +1039,7 @@ + break; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -980,7 +1078,8 @@ + if(val != W627_DEVID && + val != W627THF_DEVID && + val != W697_DEVID && +- val != W637_DEVID) { ++ val != W637_DEVID && ++ val != W687THF_DEVID) { + superio_exit(); + return -ENODEV; + } +@@ -1034,6 +1133,8 @@ + kind = w83627thf; + else if(val == W637_DEVID) + kind = w83637hf; ++ else if (val == W687THF_DEVID) ++ kind = w83687thf; + else { + dev_info(&adapter->dev, + "Unsupported chip (dev_id=0x%02X).\n", val); +@@ -1057,7 +1158,7 @@ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + new_client->adapter = adapter; + new_client->driver = &w83627hf_driver; + new_client->flags = 0; +@@ -1071,13 +1172,15 @@ + client_name = "w83697hf"; + } else if (kind == w83637hf) { + client_name = "w83637hf"; ++ } else if (kind == w83687thf) { ++ client_name = "w83687thf"; + } + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(new_client->name, client_name, I2C_NAME_SIZE); + data->type = kind; + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -1106,7 +1209,7 @@ + device_create_file_in(new_client, 2); + device_create_file_in(new_client, 3); + device_create_file_in(new_client, 4); +- if (kind != w83627thf && kind != w83637hf) { ++ if (kind == w83627hf || kind == w83697hf) { + device_create_file_in(new_client, 5); + device_create_file_in(new_client, 6); + } +@@ -1139,7 +1242,7 @@ + + device_create_file_pwm(new_client, 1); + device_create_file_pwm(new_client, 2); +- if (kind == w83627thf || kind == w83637hf) ++ if (kind == w83627thf || kind == w83637hf || kind == w83687thf) + device_create_file_pwm(new_client, 3); + + device_create_file_sensor(new_client, 1); +@@ -1187,7 +1290,7 @@ + struct w83627hf_data *data = i2c_get_clientdata(client); + int res, word_sized; + +- down(&data->lock); ++ mutex_lock(&data->lock); + word_sized = (((reg & 0xff00) == 0x100) + || ((reg & 0xff00) == 0x200)) + && (((reg & 0x00ff) == 0x50) +@@ -1213,7 +1316,7 @@ + client->addr + W83781D_ADDR_REG_OFFSET); + outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); + } +- up(&data->lock); ++ mutex_unlock(&data->lock); + return res; + } + +@@ -1247,12 +1350,39 @@ + return res; + } + ++static int w83687thf_read_vid(struct i2c_client *client) ++{ ++ int res = 0xff; ++ ++ superio_enter(); ++ superio_select(W83627HF_LD_HWM); ++ ++ /* Make sure these GPIO pins are enabled */ ++ if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { ++ dev_dbg(&client->dev, "VID disabled, no VID function\n"); ++ goto exit; ++ } ++ ++ /* Make sure the pins are configured for input */ ++ if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { ++ dev_dbg(&client->dev, "VID configured as output, " ++ "no VID function\n"); ++ goto exit; ++ } ++ ++ res = superio_inb(W83687THF_VID_DATA) & 0x3f; ++ ++exit: ++ superio_exit(); ++ return res; ++} ++ + static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) + { + struct w83627hf_data *data = i2c_get_clientdata(client); + int word_sized; + +- down(&data->lock); ++ mutex_lock(&data->lock); + word_sized = (((reg & 0xff00) == 0x100) + || ((reg & 0xff00) == 0x200)) + && (((reg & 0x00ff) == 0x53) +@@ -1277,7 +1407,7 @@ + client->addr + W83781D_ADDR_REG_OFFSET); + outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); + } +- up(&data->lock); ++ mutex_unlock(&data->lock); + return 0; + } + +@@ -1324,10 +1454,13 @@ + data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); + } else if (w83627thf == data->type) { + data->vid = w83627thf_read_gpio5(client); ++ } else if (w83687thf == data->type) { ++ data->vid = w83687thf_read_vid(client); + } + + /* Read VRM & OVT Config only once */ +- if (w83627thf == data->type || w83637hf == data->type) { ++ if (w83627thf == data->type || w83637hf == data->type ++ || w83687thf == data->type) { + data->vrm_ovt = + w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); + } +@@ -1387,14 +1520,14 @@ + struct w83627hf_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + for (i = 0; i <= 8; i++) { + /* skip missing sensors */ + if (((data->type == w83697hf) && (i == 1)) || +- ((data->type == w83627thf || data->type == w83637hf) ++ ((data->type != w83627hf && data->type != w83697hf) + && (i == 5 || i == 6))) + continue; + data->in[i] = +@@ -1470,7 +1603,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/w83781d.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/w83781d.c 2006-03-22 17:06:16.000000000 +0100 +@@ -42,6 +42,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-vid.h> + #include <linux/err.h> ++#include <linux/mutex.h> + #include <asm/io.h> + #include "lm75.h" + +@@ -56,6 +57,10 @@ + I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " + "{bus, clientaddr, subclientaddr1, subclientaddr2}"); + ++static int reset; ++module_param(reset, bool, 0); ++MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); ++ + static int init = 1; + module_param(init, bool, 0); + MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); +@@ -226,10 +231,10 @@ + struct w83781d_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore lock; ++ struct mutex lock; + enum chips type; + +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + +@@ -262,14 +267,12 @@ + u8 vrm; + }; + +-static int w83781d_attach_adapter(struct i2c_adapter *adapter); + static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter); + static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); + static int w83781d_detach_client(struct i2c_client *client); + +-static int w83781d_read_value(struct i2c_client *client, u16 register); +-static int w83781d_write_value(struct i2c_client *client, u16 register, +- u16 value); ++static int w83781d_read_value(struct i2c_client *client, u16 reg); ++static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); + static struct w83781d_data *w83781d_update_device(struct device *dev); + static void w83781d_init_client(struct i2c_client *client); + +@@ -278,7 +281,9 @@ + .name = "w83781d", + }, + .id = I2C_DRIVERID_W83781D, +- .attach_adapter = w83781d_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = w83781d_detect, + .detach_client = w83781d_detach_client, + }; + +@@ -311,11 +316,11 @@ + \ + val = simple_strtoul(buf, NULL, 10) / 10; \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + w83781d_write_value(client, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \ + \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + store_in_reg(MIN, min); +@@ -381,13 +386,13 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->fan_min[nr - 1] = + FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); + w83781d_write_value(client, W83781D_REG_FAN_MIN(nr), + data->fan_min[nr - 1]); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -446,7 +451,7 @@ + \ + val = simple_strtol(buf, NULL, 10); \ + \ +- down(&data->update_lock); \ ++ mutex_lock(&data->update_lock); \ + \ + if (nr >= 2) { /* TEMP2 and TEMP3 */ \ + data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ +@@ -458,7 +463,7 @@ + data->temp_##reg); \ + } \ + \ +- up(&data->update_lock); \ ++ mutex_unlock(&data->update_lock); \ + return count; \ + } + store_temp_reg(OVER, max); +@@ -571,7 +576,7 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ + data->beep_mask = BEEP_MASK_TO_REG(val, data->type); +@@ -592,7 +597,7 @@ + w83781d_write_value(client, W83781D_REG_BEEP_INTS2, + val2 | data->beep_enable << 7); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -637,7 +642,7 @@ + u8 reg; + unsigned long val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + /* Save fan_min */ + min = FAN_FROM_REG(data->fan_min[nr], +@@ -662,7 +667,7 @@ + data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); + w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -709,10 +714,10 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + data->pwm[nr - 1] = PWM_TO_REG(val); + w83781d_write_value(client, W83781D_REG_PWM(nr), data->pwm[nr - 1]); +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -725,7 +730,7 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + switch (val) { + case 0: +@@ -742,11 +747,11 @@ + break; + + default: +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return -EINVAL; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -808,7 +813,7 @@ + + val = simple_strtoul(buf, NULL, 10); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + switch (val) { + case 1: /* PII/Celeron diode */ +@@ -841,7 +846,7 @@ + break; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + return count; + } + +@@ -865,18 +870,6 @@ + device_create_file(&client->dev, &dev_attr_temp##offset##_type); \ + } while (0) + +-/* This function is called when: +- * w83781d_driver is inserted (when this module is loaded), for each +- available adapter +- * when a new adapter is inserted (and w83781d_driver is still present) */ +-static int +-w83781d_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, w83781d_detect); +-} +- + static int + w83781d_isa_attach_adapter(struct i2c_adapter *adapter) + { +@@ -1073,7 +1066,7 @@ + new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; +- init_MUTEX(&data->lock); ++ mutex_init(&data->lock); + new_client->adapter = adapter; + new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; + new_client->flags = 0; +@@ -1178,7 +1171,7 @@ + data->type = kind; + + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(new_client))) +@@ -1325,7 +1318,7 @@ + int res, word_sized, bank; + struct i2c_client *cl; + +- down(&data->lock); ++ mutex_lock(&data->lock); + if (i2c_is_isa_client(client)) { + word_sized = (((reg & 0xff00) == 0x100) + || ((reg & 0xff00) == 0x200)) +@@ -1383,7 +1376,7 @@ + if (bank > 2) + i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); + } +- up(&data->lock); ++ mutex_unlock(&data->lock); + return res; + } + +@@ -1394,7 +1387,7 @@ + int word_sized, bank; + struct i2c_client *cl; + +- down(&data->lock); ++ mutex_lock(&data->lock); + if (i2c_is_isa_client(client)) { + word_sized = (((reg & 0xff00) == 0x100) + || ((reg & 0xff00) == 0x200)) +@@ -1447,7 +1440,7 @@ + if (bank > 2) + i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); + } +- up(&data->lock); ++ mutex_unlock(&data->lock); + return 0; + } + +@@ -1459,8 +1452,17 @@ + int type = data->type; + u8 tmp; + +- if (init && type != as99127f) { /* this resets registers we don't have ++ if (reset && type != as99127f) { /* this resets registers we don't have + documentation for on the as99127f */ ++ /* Resetting the chip has been the default for a long time, ++ but it causes the BIOS initializations (fan clock dividers, ++ thermal sensor types...) to be lost, so it is now optional. ++ It might even go away if nobody reports it as being useful, ++ as I see very little reason why this would be needed at ++ all. */ ++ dev_info(&client->dev, "If reset=1 solved a problem you were " ++ "having, please report!\n"); ++ + /* save these registers */ + i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); + p = w83781d_read_value(client, W83781D_REG_PWMCLK12); +@@ -1477,6 +1479,13 @@ + w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0); + } + ++ /* Disable power-on abnormal beep, as advised by the datasheet. ++ Already done if reset=1. */ ++ if (init && !reset && type != as99127f) { ++ i = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG); ++ w83781d_write_value(client, W83781D_REG_BEEP_CONFIG, i | 0x80); ++ } ++ + data->vrm = vid_which_vrm(); + + if ((type != w83781d) && (type != as99127f)) { +@@ -1533,7 +1542,7 @@ + struct w83781d_data *data = i2c_get_clientdata(client); + int i; + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { +@@ -1641,7 +1650,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/drivers/hwmon/w83l785ts.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/w83l785ts.c 2006-03-22 17:06:16.000000000 +0100 +@@ -39,6 +39,7 @@ + #include <linux/hwmon.h> + #include <linux/hwmon-sysfs.h> + #include <linux/err.h> ++#include <linux/mutex.h> + + /* How many retries on register read error */ + #define MAX_RETRIES 5 +@@ -80,7 +81,6 @@ + * Functions declaration + */ + +-static int w83l785ts_attach_adapter(struct i2c_adapter *adapter); + static int w83l785ts_detect(struct i2c_adapter *adapter, int address, + int kind); + static int w83l785ts_detach_client(struct i2c_client *client); +@@ -96,7 +96,9 @@ + .name = "w83l785ts", + }, + .id = I2C_DRIVERID_W83L785TS, +- .attach_adapter = w83l785ts_attach_adapter, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = w83l785ts_detect, + .detach_client = w83l785ts_detach_client, + }; + +@@ -107,7 +109,7 @@ + struct w83l785ts_data { + struct i2c_client client; + struct class_device *class_dev; +- struct semaphore update_lock; ++ struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + +@@ -135,13 +137,6 @@ + * Real code + */ + +-static int w83l785ts_attach_adapter(struct i2c_adapter *adapter) +-{ +- if (!(adapter->class & I2C_CLASS_HWMON)) +- return 0; +- return i2c_probe(adapter, &addr_data, w83l785ts_detect); +-} +- + /* + * The following function does more than just detection. If detection + * succeeds, it also registers the new chip. +@@ -221,7 +216,7 @@ + /* We can fill in the remaining client fields. */ + strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE); + data->valid = 0; +- init_MUTEX(&data->update_lock); ++ mutex_init(&data->update_lock); + + /* Default values in case the first read fails (unlikely). */ + data->temp[1] = data->temp[0] = 0; +@@ -299,7 +294,7 @@ + struct i2c_client *client = to_i2c_client(dev); + struct w83l785ts_data *data = i2c_get_clientdata(client); + +- down(&data->update_lock); ++ mutex_lock(&data->update_lock); + + if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) { + dev_dbg(&client->dev, "Updating w83l785ts data.\n"); +@@ -312,7 +307,7 @@ + data->valid = 1; + } + +- up(&data->update_lock); ++ mutex_unlock(&data->update_lock); + + return data; + } +--- linux-2.6.16.orig/Documentation/hwmon/w83627hf 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/Documentation/hwmon/w83627hf 2006-03-22 17:06:15.000000000 +0100 +@@ -18,6 +18,10 @@ + Prefix: 'w83637hf' + Addresses scanned: ISA address retrieved from Super I/O registers + Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf ++ * Winbond W83687THF ++ Prefix: 'w83687thf' ++ Addresses scanned: ISA address retrieved from Super I/O registers ++ Datasheet: Provided by Winbond on request + + Authors: + Frodo Looijaard <frodol@dds.nl>, +--- linux-2.6.16.orig/drivers/hwmon/Kconfig 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/Kconfig 2006-03-22 17:06:16.000000000 +0100 +@@ -236,11 +236,11 @@ + will be called lm80. + + config SENSORS_LM83 +- tristate "National Semiconductor LM83" ++ tristate "National Semiconductor LM83 and compatibles" + depends on HWMON && I2C + help + If you say yes here you get support for National Semiconductor +- LM83 sensor chips. ++ LM82 and LM83 sensor chips. + + This driver can also be built as a module. If so, the module + will be called lm83. +@@ -333,11 +333,32 @@ + help + If you say yes here you get support for the integrated fan + monitoring and control capabilities of the SMSC LPC47B27x, +- LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips. ++ LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and ++ LPC47M997 chips. ++ ++ The temperature and voltage sensor features of the LPC47M192 ++ and LPC47M997 are supported by another driver, select also ++ "SMSC LPC47M192 and compatibles" below for those. + + This driver can also be built as a module. If so, the module + will be called smsc47m1. + ++config SENSORS_SMSC47M192 ++ tristate "SMSC LPC47M192 and compatibles" ++ depends on HWMON && I2C && EXPERIMENTAL ++ select HWMON_VID ++ help ++ If you say yes here you get support for the temperature and ++ voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. ++ ++ The fan monitoring and control capabilities of these chips ++ are supported by another driver, select ++ "SMSC LPC47M10x and compatibles" above. You need both drivers ++ if you want fan control and voltage/temperature sensor support. ++ ++ This driver can also be built as a module. If so, the module ++ will be called smsc47m192. ++ + config SENSORS_SMSC47B397 + tristate "SMSC LPC47B397-NC" + depends on HWMON && I2C && EXPERIMENTAL +@@ -406,13 +427,14 @@ + will be called w83l785ts. + + config SENSORS_W83627HF +- tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF" +- depends on HWMON && I2C && EXPERIMENTAL ++ tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" ++ depends on HWMON && I2C + select I2C_ISA + select HWMON_VID + help + If you say yes here you get support for the Winbond W836X7 series +- of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF ++ of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and ++ W83697HF. + + This driver can also be built as a module. If so, the module + will be called w83627hf. +--- linux-2.6.16.orig/drivers/hwmon/hwmon-vid.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/hwmon-vid.c 2006-03-22 17:06:15.000000000 +0100 +@@ -54,6 +54,10 @@ + (IMVP-II). You can find more information in the datasheet of Max1718 + http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 + ++ The 13 specification corresponds to the Intel Pentium M series. There ++ doesn't seem to be any named specification for these. The conversion ++ tables are detailed directly in the various Pentium M datasheets: ++ http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm + */ + + /* vrm is the VRM/VRD document version multiplied by 10. +@@ -100,6 +104,8 @@ + case 17: /* Intel IMVP-II */ + return(val & 0x10 ? 975 - (val & 0xF) * 25 : + 1750 - val * 50); ++ case 13: ++ return(1708 - (val & 0x3f) * 16); + default: /* report 0 for unknown */ + printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n"); + return 0; +@@ -129,8 +135,9 @@ + static struct vrm_model vrm_models[] = { + {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */ + {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */ +- {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */ ++ {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13}, /* Pentium M (130 nm) */ + {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */ ++ {X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */ + {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ + {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ + {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ +--- linux-2.6.16.orig/Documentation/hwmon/w83781d 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/Documentation/hwmon/w83781d 2006-03-22 17:06:15.000000000 +0100 +@@ -36,6 +36,11 @@ + Use 'init=0' to bypass initializing the chip. + Try this if your computer crashes when you load the module. + ++* reset int ++ (default 0) ++ The driver used to reset the chip on load, but does no more. Use ++ 'reset=1' to restore the old behavior. Report if you need to do this. ++ + force_subclients=bus,caddr,saddr,saddr + This is used to force the i2c addresses for subclients of + a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b' +@@ -123,6 +128,25 @@ + your computer speaker. It is possible to enable all beeping globally, + or only the beeping for some alarms. + ++Individual alarm and beep bits: ++ ++0x000001: in0 ++0x000002: in1 ++0x000004: in2 ++0x000008: in3 ++0x000010: temp1 ++0x000020: temp2 (+temp3 on W83781D) ++0x000040: fan1 ++0x000080: fan2 ++0x000100: in4 ++0x000200: in5 ++0x000400: in6 ++0x000800: fan3 ++0x001000: chassis ++0x002000: temp3 (W83782D and W83627HF only) ++0x010000: in7 (W83782D and W83627HF only) ++0x020000: in8 (W83782D and W83627HF only) ++ + If an alarm triggers, it will remain triggered until the hardware register + is read at least once. This means that the cause for the alarm may + already have disappeared! Note that in the current implementation, all +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-frodo.c 2006-03-22 17:06:09.000000000 +0100 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,85 +0,0 @@ +- +-/* +- * linux/drivers/i2c/i2c-frodo.c +- * +- * Author: Abraham van der Merwe <abraham@2d3d.co.za> +- * +- * An I2C adapter driver for the 2d3D, Inc. StrongARM SA-1110 +- * Development board (Frodo). +- * +- * This source code is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License +- * version 2 as published by the Free Software Foundation. +- */ +- +-#include <linux/module.h> +-#include <linux/kernel.h> +-#include <linux/init.h> +-#include <linux/delay.h> +-#include <linux/i2c.h> +-#include <linux/i2c-algo-bit.h> +-#include <asm/hardware.h> +- +- +-static void frodo_setsda (void *data,int state) +-{ +- if (state) +- FRODO_CPLD_I2C |= FRODO_I2C_SDA_OUT; +- else +- FRODO_CPLD_I2C &= ~FRODO_I2C_SDA_OUT; +-} +- +-static void frodo_setscl (void *data,int state) +-{ +- if (state) +- FRODO_CPLD_I2C |= FRODO_I2C_SCL_OUT; +- else +- FRODO_CPLD_I2C &= ~FRODO_I2C_SCL_OUT; +-} +- +-static int frodo_getsda (void *data) +-{ +- return ((FRODO_CPLD_I2C & FRODO_I2C_SDA_IN) != 0); +-} +- +-static int frodo_getscl (void *data) +-{ +- return ((FRODO_CPLD_I2C & FRODO_I2C_SCL_IN) != 0); +-} +- +-static struct i2c_algo_bit_data bit_frodo_data = { +- .setsda = frodo_setsda, +- .setscl = frodo_setscl, +- .getsda = frodo_getsda, +- .getscl = frodo_getscl, +- .udelay = 80, +- .mdelay = 80, +- .timeout = HZ +-}; +- +-static struct i2c_adapter frodo_ops = { +- .owner = THIS_MODULE, +- .id = I2C_HW_B_FRODO, +- .algo_data = &bit_frodo_data, +- .dev = { +- .name = "Frodo adapter driver", +- }, +-}; +- +-static int __init i2c_frodo_init (void) +-{ +- return i2c_bit_add_bus(&frodo_ops); +-} +- +-static void __exit i2c_frodo_exit (void) +-{ +- i2c_bit_del_bus(&frodo_ops); +-} +- +-MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>"); +-MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo"); +-MODULE_LICENSE ("GPL"); +- +-module_init (i2c_frodo_init); +-module_exit (i2c_frodo_exit); +- +--- linux-2.6.16.orig/include/linux/i2c-id.h 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/include/linux/i2c-id.h 2006-03-22 17:06:15.000000000 +0100 +@@ -172,7 +172,6 @@ + #define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ + #define I2C_HW_B_IOC 0x010011 /* IOC bit-wiggling */ + #define I2C_HW_B_TSUNA 0x010012 /* DEC Tsunami chipset */ +-#define I2C_HW_B_FRODO 0x010013 /* 2d3D SA-1110 Development Board */ + #define I2C_HW_B_OMAHA 0x010014 /* Omaha I2C interface (ARM) */ + #define I2C_HW_B_GUIDE 0x010015 /* Guide bit-basher */ + #define I2C_HW_B_IXP2000 0x010016 /* GPIO on IXP2000 systems */ +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ite.c 2006-03-22 17:06:09.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ite.c 2006-03-22 17:06:15.000000000 +0100 +@@ -200,9 +200,7 @@ + .owner = THIS_MODULE, + .id = I2C_HW_I_IIC, + .algo_data = &iic_ite_data, +- .dev = { +- .name = "ITE IIC adapter", +- }, ++ .name = "ITE IIC adapter", + }; + + /* Called when the module is loaded. This function starts the +--- linux-2.6.16.orig/drivers/i2c/chips/isp1301_omap.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/chips/isp1301_omap.c 2006-03-22 17:06:15.000000000 +0100 +@@ -1635,8 +1635,6 @@ + .driver = { + .name = "isp1301_omap", + }, +- .id = 1301, /* FIXME "official", i2c-ids.h */ +- .class = I2C_CLASS_HWMON, + .attach_adapter = isp1301_scan_bus, + .detach_client = isp1301_detach_client, + }; +--- linux-2.6.16.orig/Documentation/i2c/busses/i2c-piix4 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/Documentation/i2c/busses/i2c-piix4 2006-03-22 17:06:16.000000000 +0100 +@@ -4,8 +4,10 @@ + * Intel 82371AB PIIX4 and PIIX4E + * Intel 82443MX (440MX) + Datasheet: Publicly available at the Intel website +- * ServerWorks OSB4, CSB5 and CSB6 southbridges ++ * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges + Datasheet: Only available via NDA from ServerWorks ++ * ATI IXP southbridges IXP200, IXP300, IXP400 ++ Datasheet: Not publicly available + * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge + Datasheet: Publicly available at the SMSC website http://www.smsc.com + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-piix4.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-piix4.c 2006-03-22 17:06:16.000000000 +0100 +@@ -22,7 +22,7 @@ + /* + Supports: + Intel PIIX4, 440MX +- Serverworks OSB4, CSB5, CSB6 ++ Serverworks OSB4, CSB5, CSB6, HT-1000 + SMSC Victory66 + + Note: we assume there can only be one device, with one SMBus interface. +@@ -406,19 +406,27 @@ + + static struct i2c_adapter piix4_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + + static struct pci_device_id piix4_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3), + .driver_data = 3 }, ++ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS), ++ .driver_data = 0 }, ++ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS), ++ .driver_data = 0 }, ++ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS), ++ .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5), + .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6), + .driver_data = 0 }, ++ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB), ++ .driver_data = 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3), +--- linux-2.6.16.orig/include/linux/pci_ids.h 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/include/linux/pci_ids.h 2006-03-22 17:06:16.000000000 +0100 +@@ -351,8 +351,11 @@ + #define PCI_DEVICE_ID_ATI_RS480 0x5950 + /* ATI IXP Chipset */ + #define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349 ++#define PCI_DEVICE_ID_ATI_IXP200_SMBUS 0x4353 ++#define PCI_DEVICE_ID_ATI_IXP300_SMBUS 0x4363 + #define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369 + #define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e ++#define PCI_DEVICE_ID_ATI_IXP400_SMBUS 0x4372 + #define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376 + #define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379 + +@@ -1369,6 +1372,7 @@ + #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 + #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 + #define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 ++#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205 + #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 + #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 + #define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ixp4xx.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ixp4xx.c 2006-03-22 17:06:16.000000000 +0100 +@@ -125,7 +125,9 @@ + drv_data->algo_data.mdelay = 10; + drv_data->algo_data.timeout = 100; + ++ drv_data->adapter.owner = THIS_MODULE; + drv_data->adapter.id = I2C_HW_B_IXP4XX; ++ drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DATA; + strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, + I2C_NAME_SIZE); + drv_data->adapter.algo_data = &drv_data->algo_data; +--- linux-2.6.16.orig/drivers/media/video/adv7170.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/adv7170.c 2006-03-22 17:06:15.000000000 +0100 +@@ -53,7 +53,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(x) (x)->name + +@@ -125,24 +124,21 @@ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ + struct adv7170 *encoder = i2c_get_clientdata(client); +- struct i2c_msg msg; + u8 block_data[32]; ++ int block_len; + +- msg.addr = client->addr; +- msg.flags = 0; + while (len >= 2) { +- msg.buf = (char *) block_data; +- msg.len = 0; +- block_data[msg.len++] = reg = data[0]; ++ block_len = 0; ++ block_data[block_len++] = reg = data[0]; + do { +- block_data[msg.len++] = ++ block_data[block_len++] = + encoder->reg[reg++] = data[1]; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && +- msg.len < 32); +- if ((ret = i2c_transfer(client->adapter, +- &msg, 1)) < 0) ++ block_len < 32); ++ if ((ret = i2c_master_send(client, block_data, ++ block_len)) < 0) + break; + } + } else { +--- linux-2.6.16.orig/drivers/media/video/adv7175.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/adv7175.c 2006-03-22 17:06:16.000000000 +0100 +@@ -49,7 +49,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +@@ -68,8 +67,6 @@ + /* ----------------------------------------------------------------------- */ + + struct adv7175 { +- unsigned char reg[128]; +- + int norm; + int input; + int enable; +@@ -95,9 +92,6 @@ + u8 reg, + u8 value) + { +- struct adv7175 *encoder = i2c_get_clientdata(client); +- +- encoder->reg[reg] = value; + return i2c_smbus_write_byte_data(client, reg, value); + } + +@@ -120,25 +114,21 @@ + * the adapter understands raw I2C */ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ +- struct adv7175 *encoder = i2c_get_clientdata(client); +- struct i2c_msg msg; + u8 block_data[32]; ++ int block_len; + +- msg.addr = client->addr; +- msg.flags = 0; + while (len >= 2) { +- msg.buf = (char *) block_data; +- msg.len = 0; +- block_data[msg.len++] = reg = data[0]; ++ block_len = 0; ++ block_data[block_len++] = reg = data[0]; + do { +- block_data[msg.len++] = +- encoder->reg[reg++] = data[1]; ++ block_data[block_len++] = data[1]; ++ reg++; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && +- msg.len < 32); +- if ((ret = i2c_transfer(client->adapter, +- &msg, 1)) < 0) ++ block_len < 32); ++ if ((ret = i2c_master_send(client, block_data, ++ block_len)) < 0) + break; + } + } else { +@@ -171,24 +161,6 @@ + adv7175_write(client, 0x05, 0x25); + } + +-#ifdef ENCODER_DUMP +-static void +-dump (struct i2c_client *client) +-{ +- struct adv7175 *encoder = i2c_get_clientdata(client); +- int i, j; +- +- printk(KERN_INFO "%s: registry dump\n", I2C_NAME(client)); +- for (i = 0; i < 182 / 8; i++) { +- printk("%s: 0x%02x -", I2C_NAME(client), i * 8); +- for (j = 0; j < 8; j++) { +- printk(" 0x%02x", encoder->reg[i * 8 + j]); +- } +- printk("\n"); +- } +-} +-#endif +- + /* ----------------------------------------------------------------------- */ + // Output filter: S-Video Composite + +@@ -407,14 +379,6 @@ + } + break; + +-#ifdef ENCODER_DUMP +- case ENCODER_DUMP: +- { +- dump(client); +- } +- break; +-#endif +- + default: + return -EINVAL; + } +@@ -424,24 +388,6 @@ + + /* ----------------------------------------------------------------------- */ + +-/* +- * Generic i2c probe +- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' +- */ +-static unsigned short normal_i2c[] = +- { I2C_ADV7175 >> 1, (I2C_ADV7175 >> 1) + 1, +- I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1, +- I2C_CLIENT_END +-}; +- +-static unsigned short ignore = I2C_CLIENT_END; +- +-static struct i2c_client_address_data addr_data = { +- .normal_i2c = normal_i2c, +- .probe = &ignore, +- .ignore = &ignore, +-}; +- + static struct i2c_driver i2c_driver_adv7175; + + static int +@@ -516,16 +462,6 @@ + } + + static int +-adv7175_attach_adapter (struct i2c_adapter *adapter) +-{ +- dprintk(1, +- KERN_INFO +- "adv7175.c: starting probe for adapter %s (0x%x)\n", +- I2C_NAME(adapter), adapter->id); +- return i2c_probe(adapter, &addr_data, &adv7175_detect_client); +-} +- +-static int + adv7175_detach_client (struct i2c_client *client) + { + struct adv7175 *encoder = i2c_get_clientdata(client); +@@ -551,7 +487,7 @@ + + .id = I2C_DRIVERID_ADV7175, + +- .attach_adapter = adv7175_attach_adapter, ++ .detect_client = adv7175_detect_client, + .detach_client = adv7175_detach_client, + .command = adv7175_command, + }; +--- linux-2.6.16.orig/drivers/media/video/bt819.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/bt819.c 2006-03-22 17:06:15.000000000 +0100 +@@ -53,7 +53,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +@@ -141,24 +140,21 @@ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ + struct bt819 *decoder = i2c_get_clientdata(client); +- struct i2c_msg msg; + u8 block_data[32]; ++ int block_len; + +- msg.addr = client->addr; +- msg.flags = 0; + while (len >= 2) { +- msg.buf = (char *) block_data; +- msg.len = 0; +- block_data[msg.len++] = reg = data[0]; ++ block_len = 0; ++ block_data[block_len++] = reg = data[0]; + do { +- block_data[msg.len++] = ++ block_data[block_len++] = + decoder->reg[reg++] = data[1]; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && +- msg.len < 32); +- if ((ret = i2c_transfer(client->adapter, +- &msg, 1)) < 0) ++ block_len < 32); ++ if ((ret = i2c_master_send(client, block_data, ++ block_len)) < 0) + break; + } + } else { +--- linux-2.6.16.orig/drivers/media/video/bt856.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/bt856.c 2006-03-22 17:06:15.000000000 +0100 +@@ -53,7 +53,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +@@ -71,17 +70,14 @@ + + /* ----------------------------------------------------------------------- */ + +-#define REG_OFFSET 0xCE ++#define REG_OFFSET 0xDA ++#define BT856_NR_REG 6 + + struct bt856 { +- unsigned char reg[32]; ++ unsigned char reg[BT856_NR_REG]; + + int norm; + int enable; +- int bright; +- int contrast; +- int hue; +- int sat; + }; + + #define I2C_BT856 0x88 +@@ -120,8 +116,8 @@ + struct bt856 *encoder = i2c_get_clientdata(client); + + printk(KERN_INFO "%s: register dump:", I2C_NAME(client)); +- for (i = 0xd6; i <= 0xde; i += 2) +- printk(" %02x", encoder->reg[i - REG_OFFSET]); ++ for (i = 0; i < BT856_NR_REG; i += 2) ++ printk(" %02x", encoder->reg[i]); + printk("\n"); + } + +--- linux-2.6.16.orig/drivers/media/video/saa7110.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/saa7110.c 2006-03-22 17:06:16.000000000 +0100 +@@ -39,7 +39,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +@@ -59,8 +58,6 @@ + #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ + #define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ + +-#define I2C_SAA7110 0x9C /* or 0x9E */ +- + #define SAA7110_NR_REG 0x35 + + struct saa7110 { +@@ -108,13 +105,8 @@ + * the adapter understands raw I2C */ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + struct saa7110 *decoder = i2c_get_clientdata(client); +- struct i2c_msg msg; + +- msg.len = len; +- msg.buf = (char *) data; +- msg.addr = client->addr; +- msg.flags = 0; +- ret = i2c_transfer(client->adapter, &msg, 1); ++ ret = i2c_master_send(client, data, len); + + /* Cache the written data */ + memcpy(decoder->reg + reg, data + 1, len - 1); +@@ -432,15 +424,13 @@ + break; + + case DECODER_DUMP: +- for (v = 0; v < 0x34; v += 16) { ++ for (v = 0; v < SAA7110_NR_REG; v += 16) { + int j; +- dprintk(1, KERN_INFO "%s: %03x\n", I2C_NAME(client), ++ dprintk(1, KERN_DEBUG "%s: %02x:", I2C_NAME(client), + v); +- for (j = 0; j < 16; j++) { +- dprintk(1, KERN_INFO " %02x", +- decoder->reg[v + j]); +- } +- dprintk(1, KERN_INFO "\n"); ++ for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++) ++ dprintk(1, " %02x", decoder->reg[v + j]); ++ dprintk(1, "\n"); + } + break; + +@@ -454,24 +444,6 @@ + + /* ----------------------------------------------------------------------- */ + +-/* +- * Generic i2c probe +- * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' +- */ +-static unsigned short normal_i2c[] = { +- I2C_SAA7110 >> 1, +- (I2C_SAA7110 >> 1) + 1, +- I2C_CLIENT_END +-}; +- +-static unsigned short ignore = I2C_CLIENT_END; +- +-static struct i2c_client_address_data addr_data = { +- .normal_i2c = normal_i2c, +- .probe = &ignore, +- .ignore = &ignore, +-}; +- + static struct i2c_driver i2c_driver_saa7110; + + static int +@@ -555,16 +527,6 @@ + } + + static int +-saa7110_attach_adapter (struct i2c_adapter *adapter) +-{ +- dprintk(1, +- KERN_INFO +- "saa7110.c: starting probe for adapter %s (0x%x)\n", +- I2C_NAME(adapter), adapter->id); +- return i2c_probe(adapter, &addr_data, &saa7110_detect_client); +-} +- +-static int + saa7110_detach_client (struct i2c_client *client) + { + struct saa7110 *decoder = i2c_get_clientdata(client); +@@ -590,7 +552,7 @@ + + .id = I2C_DRIVERID_SAA7110, + +- .attach_adapter = saa7110_attach_adapter, ++ .detect_client = saa7110_detect_client, + .detach_client = saa7110_detach_client, + .command = saa7110_command, + }; +--- linux-2.6.16.orig/drivers/media/video/saa7111.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/saa7111.c 2006-03-22 17:06:15.000000000 +0100 +@@ -52,7 +52,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +@@ -70,8 +69,10 @@ + + /* ----------------------------------------------------------------------- */ + ++#define SAA7111_NR_REG 0x18 ++ + struct saa7111 { +- unsigned char reg[32]; ++ unsigned char reg[SAA7111_NR_REG]; + + int norm; + int input; +@@ -110,24 +111,21 @@ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ + struct saa7111 *decoder = i2c_get_clientdata(client); +- struct i2c_msg msg; + u8 block_data[32]; ++ int block_len; + +- msg.addr = client->addr; +- msg.flags = 0; + while (len >= 2) { +- msg.buf = (char *) block_data; +- msg.len = 0; +- block_data[msg.len++] = reg = data[0]; ++ block_len = 0; ++ block_data[block_len++] = reg = data[0]; + do { +- block_data[msg.len++] = ++ block_data[block_len++] = + decoder->reg[reg++] = data[1]; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && +- msg.len < 32); +- if ((ret = i2c_transfer(client->adapter, +- &msg, 1)) < 0) ++ block_len < 32); ++ if ((ret = i2c_master_send(client, block_data, ++ block_len)) < 0) + break; + } + } else { +@@ -227,11 +225,11 @@ + { + int i; + +- for (i = 0; i < 32; i += 16) { ++ for (i = 0; i < SAA7111_NR_REG; i += 16) { + int j; + + printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i); +- for (j = 0; j < 16; ++j) { ++ for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) { + printk(" %02x", + saa7111_read(client, i + j)); + } +--- linux-2.6.16.orig/drivers/media/video/saa7114.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/saa7114.c 2006-03-22 17:06:15.000000000 +0100 +@@ -55,7 +55,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(x) (x)->name + +@@ -139,9 +138,6 @@ + u8 reg, + u8 value) + { +- /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ +- +- /*decoder->reg[reg] = value;*/ + return i2c_smbus_write_byte_data(client, reg, value); + } + +@@ -157,25 +153,21 @@ + * the adapter understands raw I2C */ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ +- /*struct saa7114 *decoder = i2c_get_clientdata(client);*/ +- struct i2c_msg msg; + u8 block_data[32]; ++ int block_len; + +- msg.addr = client->addr; +- msg.flags = 0; + while (len >= 2) { +- msg.buf = (char *) block_data; +- msg.len = 0; +- block_data[msg.len++] = reg = data[0]; ++ block_len = 0; ++ block_data[block_len++] = reg = data[0]; + do { +- block_data[msg.len++] = +- /*decoder->reg[reg++] =*/ data[1]; ++ block_data[block_len++] = data[1]; ++ reg++; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && +- msg.len < 32); +- if ((ret = i2c_transfer(client->adapter, +- &msg, 1)) < 0) ++ block_len < 32); ++ if ((ret = i2c_master_send(client, block_data, ++ block_len)) < 0) + break; + } + } else { +--- linux-2.6.16.orig/drivers/media/video/saa711x.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/saa711x.c 2006-03-22 17:06:15.000000000 +0100 +@@ -45,7 +45,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +--- linux-2.6.16.orig/drivers/media/video/saa7185.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/saa7185.c 2006-03-22 17:06:15.000000000 +0100 +@@ -49,7 +49,6 @@ + MODULE_LICENSE("GPL"); + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(s) (s)->name + +@@ -113,24 +112,21 @@ + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + /* do raw I2C, not smbus compatible */ + struct saa7185 *encoder = i2c_get_clientdata(client); +- struct i2c_msg msg; + u8 block_data[32]; ++ int block_len; + +- msg.addr = client->addr; +- msg.flags = 0; + while (len >= 2) { +- msg.buf = (char *) block_data; +- msg.len = 0; +- block_data[msg.len++] = reg = data[0]; ++ block_len = 0; ++ block_data[block_len++] = reg = data[0]; + do { +- block_data[msg.len++] = ++ block_data[block_len++] = + encoder->reg[reg++] = data[1]; + len -= 2; + data += 2; + } while (len >= 2 && data[0] == reg && +- msg.len < 32); +- if ((ret = i2c_transfer(client->adapter, +- &msg, 1)) < 0) ++ block_len < 32); ++ if ((ret = i2c_master_send(client, block_data, ++ block_len)) < 0) + break; + } + } else { +--- linux-2.6.16.orig/drivers/media/video/vpx3220.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/vpx3220.c 2006-03-22 17:06:15.000000000 +0100 +@@ -30,7 +30,6 @@ + #include <asm/uaccess.h> + + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + + #define I2C_NAME(x) (x)->name + +--- linux-2.6.16.orig/sound/oss/dmasound/dmasound_awacs.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/sound/oss/dmasound/dmasound_awacs.c 2006-03-22 17:06:15.000000000 +0100 +@@ -88,8 +88,6 @@ + #include <linux/pmu.h> + #endif + +-#include <linux/i2c-dev.h> +- + #include <asm/uaccess.h> + #include <asm/prom.h> + #include <asm/machdep.h> +--- linux-2.6.16.orig/sound/ppc/daca.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/sound/ppc/daca.c 2006-03-22 17:06:15.000000000 +0100 +@@ -22,7 +22,6 @@ + #include <sound/driver.h> + #include <linux/init.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <linux/kmod.h> + #include <linux/slab.h> + #include <sound/core.h> +--- linux-2.6.16.orig/sound/ppc/keywest.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/sound/ppc/keywest.c 2006-03-22 17:06:15.000000000 +0100 +@@ -23,7 +23,6 @@ + #include <linux/init.h> + #include <linux/i2c.h> + #include <linux/delay.h> +-#include <linux/i2c-dev.h> + #include <linux/slab.h> + #include <sound/core.h> + #include "pmac.h" +--- linux-2.6.16.orig/sound/ppc/toonie.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/sound/ppc/toonie.c 2006-03-22 17:06:15.000000000 +0100 +@@ -22,7 +22,6 @@ + #include <linux/init.h> + #include <linux/delay.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <linux/kmod.h> + #include <linux/slab.h> + #include <linux/interrupt.h> +--- linux-2.6.16.orig/sound/ppc/tumbler.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/sound/ppc/tumbler.c 2006-03-22 17:06:15.000000000 +0100 +@@ -28,7 +28,6 @@ + #include <linux/init.h> + #include <linux/delay.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <linux/kmod.h> + #include <linux/slab.h> + #include <linux/interrupt.h> +--- linux-2.6.16.orig/drivers/hwmon/hwmon.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/hwmon.c 2006-03-22 17:06:15.000000000 +0100 +@@ -17,6 +17,7 @@ + #include <linux/idr.h> + #include <linux/hwmon.h> + #include <linux/gfp.h> ++#include <linux/spinlock.h> + + #define HWMON_ID_PREFIX "hwmon" + #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" +@@ -24,6 +25,7 @@ + static struct class *hwmon_class; + + static DEFINE_IDR(hwmon_idr); ++static DEFINE_SPINLOCK(idr_lock); + + /** + * hwmon_device_register - register w/ hwmon sysfs class +@@ -37,20 +39,30 @@ + struct class_device *hwmon_device_register(struct device *dev) + { + struct class_device *cdev; +- int id; ++ int id, err; + +- if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0) ++again: ++ if (unlikely(idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)) + return ERR_PTR(-ENOMEM); + +- if (idr_get_new(&hwmon_idr, NULL, &id) < 0) +- return ERR_PTR(-ENOMEM); ++ spin_lock(&idr_lock); ++ err = idr_get_new(&hwmon_idr, NULL, &id); ++ spin_unlock(&idr_lock); ++ ++ if (unlikely(err == -EAGAIN)) ++ goto again; ++ else if (unlikely(err)) ++ return ERR_PTR(err); + + id = id & MAX_ID_MASK; + cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, + HWMON_ID_FORMAT, id); + +- if (IS_ERR(cdev)) ++ if (IS_ERR(cdev)) { ++ spin_lock(&idr_lock); + idr_remove(&hwmon_idr, id); ++ spin_unlock(&idr_lock); ++ } + + return cdev; + } +@@ -64,9 +76,11 @@ + { + int id; + +- if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) { ++ if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) { + class_device_unregister(cdev); ++ spin_lock(&idr_lock); + idr_remove(&hwmon_idr, id); ++ spin_unlock(&idr_lock); + } else + dev_dbg(cdev->dev, + "hwmon_device_unregister() failed: bad class ID!\n"); +--- linux-2.6.16.orig/arch/m68k/bvme6000/rtc.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/arch/m68k/bvme6000/rtc.c 2006-03-22 17:06:15.000000000 +0100 +@@ -18,6 +18,7 @@ + #include <linux/module.h> + #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ + #include <linux/smp_lock.h> ++#include <linux/bcd.h> + #include <asm/bvme6000hw.h> + + #include <asm/io.h> +@@ -32,9 +33,6 @@ + * ioctls. + */ + +-#define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) +-#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) +- + static unsigned char days_in_mo[] = + {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +--- linux-2.6.16.orig/drivers/video/matrox/matroxfb_maven.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/video/matrox/matroxfb_maven.c 2006-03-22 17:06:15.000000000 +0100 +@@ -129,7 +129,7 @@ + + struct maven_data { + struct matrox_fb_info* primary_head; +- struct i2c_client* client; ++ struct i2c_client client; + int version; + }; + +@@ -970,7 +970,7 @@ + + static int maven_program_timming(struct maven_data* md, + const struct mavenregs* m) { +- struct i2c_client* c = md->client; ++ struct i2c_client* c = &md->client; + + if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { + LR(0x80); +@@ -1007,7 +1007,7 @@ + } + + static inline int maven_resync(struct maven_data* md) { +- struct i2c_client* c = md->client; ++ struct i2c_client* c = &md->client; + maven_set_reg(c, 0x95, 0x20); /* start whole thing */ + return 0; + } +@@ -1065,48 +1065,48 @@ + maven_compute_bwlevel(md, &blacklevel, &whitelevel); + blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); + whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); +- maven_set_reg_pair(md->client, 0x0e, blacklevel); +- maven_set_reg_pair(md->client, 0x1e, whitelevel); ++ maven_set_reg_pair(&md->client, 0x0e, blacklevel); ++ maven_set_reg_pair(&md->client, 0x1e, whitelevel); + } + break; + case V4L2_CID_SATURATION: + { +- maven_set_reg(md->client, 0x20, p->value); +- maven_set_reg(md->client, 0x22, p->value); ++ maven_set_reg(&md->client, 0x20, p->value); ++ maven_set_reg(&md->client, 0x22, p->value); + } + break; + case V4L2_CID_HUE: + { +- maven_set_reg(md->client, 0x25, p->value); ++ maven_set_reg(&md->client, 0x25, p->value); + } + break; + case V4L2_CID_GAMMA: + { + const struct maven_gamma* g; + g = maven_compute_gamma(md); +- maven_set_reg(md->client, 0x83, g->reg83); +- maven_set_reg(md->client, 0x84, g->reg84); +- maven_set_reg(md->client, 0x85, g->reg85); +- maven_set_reg(md->client, 0x86, g->reg86); +- maven_set_reg(md->client, 0x87, g->reg87); +- maven_set_reg(md->client, 0x88, g->reg88); +- maven_set_reg(md->client, 0x89, g->reg89); +- maven_set_reg(md->client, 0x8a, g->reg8a); +- maven_set_reg(md->client, 0x8b, g->reg8b); ++ maven_set_reg(&md->client, 0x83, g->reg83); ++ maven_set_reg(&md->client, 0x84, g->reg84); ++ maven_set_reg(&md->client, 0x85, g->reg85); ++ maven_set_reg(&md->client, 0x86, g->reg86); ++ maven_set_reg(&md->client, 0x87, g->reg87); ++ maven_set_reg(&md->client, 0x88, g->reg88); ++ maven_set_reg(&md->client, 0x89, g->reg89); ++ maven_set_reg(&md->client, 0x8a, g->reg8a); ++ maven_set_reg(&md->client, 0x8b, g->reg8b); + } + break; + case MATROXFB_CID_TESTOUT: + { + unsigned char val +- = maven_get_reg (md->client,0x8d); ++ = maven_get_reg(&md->client,0x8d); + if (p->value) val |= 0x10; + else val &= ~0x10; +- maven_set_reg (md->client, 0x8d, val); ++ maven_set_reg(&md->client, 0x8d, val); + } + break; + case MATROXFB_CID_DEFLICKER: + { +- maven_set_reg(md->client, 0x93, maven_compute_deflicker(md)); ++ maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); + } + break; + } +@@ -1185,7 +1185,6 @@ + MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); + + md->primary_head = MINFO; +- md->client = clnt; + down_write(&ACCESS_FBINFO(altout.lock)); + ACCESS_FBINFO(outputs[1]).output = &maven_altout; + ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; +@@ -1243,19 +1242,17 @@ + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_PROTOCOL_MANGLING)) + goto ERROR0; +- if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data), +- GFP_KERNEL))) { ++ if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) { + err = -ENOMEM; + goto ERROR0; + } +- memset(new_client, 0, sizeof(*new_client) + sizeof(*data)); +- data = (struct maven_data*)(new_client + 1); ++ new_client = &data->client; + i2c_set_clientdata(new_client, data); + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &maven_driver; + new_client->flags = 0; +- strcpy(new_client->name, "maven client"); ++ strlcpy(new_client->name, "maven", I2C_NAME_SIZE); + if ((err = i2c_attach_client(new_client))) + goto ERROR3; + err = maven_init_client(new_client); +@@ -1279,12 +1276,10 @@ + static int maven_detach_client(struct i2c_client* client) { + int err; + +- if ((err = i2c_detach_client(client))) { +- printk(KERN_ERR "maven: Cannot deregister client\n"); ++ if ((err = i2c_detach_client(client))) + return err; +- } + maven_shutdown_client(client); +- kfree(client); ++ kfree(i2c_get_clientdata(client)); + return 0; + } + +@@ -1297,20 +1292,13 @@ + .detach_client = maven_detach_client, + }; + +-/* ************************** */ +- +-static int matroxfb_maven_init(void) { +- int err; +- +- err = i2c_add_driver(&maven_driver); +- if (err) { +- printk(KERN_ERR "maven: Maven driver failed to register (%d).\n", err); +- return err; +- } +- return 0; ++static int __init matroxfb_maven_init(void) ++{ ++ return i2c_add_driver(&maven_driver); + } + +-static void matroxfb_maven_exit(void) { ++static void __exit matroxfb_maven_exit(void) ++{ + i2c_del_driver(&maven_driver); + } + +--- linux-2.6.16.orig/drivers/macintosh/therm_pm72.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/macintosh/therm_pm72.c 2006-03-22 17:06:15.000000000 +0100 +@@ -104,7 +104,6 @@ + #include <linux/kernel.h> + #include <linux/delay.h> + #include <linux/sched.h> +-#include <linux/i2c.h> + #include <linux/slab.h> + #include <linux/init.h> + #include <linux/spinlock.h> +@@ -113,7 +112,6 @@ + #include <linux/reboot.h> + #include <linux/kmod.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <asm/prom.h> + #include <asm/machdep.h> + #include <asm/io.h> +--- linux-2.6.16.orig/drivers/macintosh/windfarm_lm75_sensor.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/macintosh/windfarm_lm75_sensor.c 2006-03-22 17:06:15.000000000 +0100 +@@ -15,7 +15,6 @@ + #include <linux/init.h> + #include <linux/wait.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <asm/prom.h> + #include <asm/machdep.h> + #include <asm/io.h> +--- linux-2.6.16.orig/drivers/macintosh/windfarm_max6690_sensor.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/macintosh/windfarm_max6690_sensor.c 2006-03-22 17:06:15.000000000 +0100 +@@ -11,7 +11,6 @@ + #include <linux/init.h> + #include <linux/slab.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <asm/prom.h> + #include <asm/pmac_low_i2c.h> + +--- linux-2.6.16.orig/drivers/macintosh/windfarm_smu_sat.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/drivers/macintosh/windfarm_smu_sat.c 2006-03-22 17:06:15.000000000 +0100 +@@ -13,7 +13,6 @@ + #include <linux/init.h> + #include <linux/wait.h> + #include <linux/i2c.h> +-#include <linux/i2c-dev.h> + #include <asm/semaphore.h> + #include <asm/prom.h> + #include <asm/smu.h> +--- linux-2.6.16.orig/arch/i386/kernel/traps.c 2006-03-22 17:06:08.000000000 +0100 ++++ linux-2.6.16/arch/i386/kernel/traps.c 2006-03-22 17:06:15.000000000 +0100 +@@ -166,8 +166,7 @@ + stack = (unsigned long*)context->previous_esp; + if (!stack) + break; +- printk(log_lvl); +- printk(" =======================\n"); ++ printk("%s =======================\n", log_lvl); + } + } + +@@ -196,14 +195,12 @@ + break; + if (i && ((i % 8) == 0)) { + printk("\n"); +- printk(log_lvl); +- printk(" "); ++ printk("%s ", log_lvl); + } + printk("%08lx ", *stack++); + } + printk("\n"); +- printk(log_lvl); +- printk("Call Trace:\n"); ++ printk("%sCall Trace:\n", log_lvl); + show_trace_log_lvl(task, esp, log_lvl); + } + +--- linux-2.6.16.orig/drivers/media/video/zoran_card.c 2006-03-22 17:06:07.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/zoran_card.c 2006-03-22 17:06:16.000000000 +0100 +@@ -452,6 +452,8 @@ + .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS, + .i2c_decoder = I2C_DRIVERID_SAA7110, + .i2c_encoder = I2C_DRIVERID_ADV7175, ++ .decoder_addr = 0x4e, ++ .encoder_addr = 0x2b, + .video_codec = CODEC_TYPE_ZR36060, + + .inputs = 3, +@@ -995,10 +997,7 @@ + static int __devinit + zr36057_init (struct zoran *zr) + { +- u32 *mem; +- void *vdev; +- unsigned mem_needed; +- int j; ++ int j, err; + int two = 2; + int zero = 0; + +@@ -1049,19 +1048,16 @@ + + /* allocate memory *before* doing anything to the hardware + * in case allocation fails */ +- mem_needed = BUZ_NUM_STAT_COM * 4; +- mem = kzalloc(mem_needed, GFP_KERNEL); +- vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL); +- if (!mem || !vdev) { ++ zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL); ++ zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL); ++ if (!zr->stat_com || !zr->video_dev) { + dprintk(1, + KERN_ERR + "%s: zr36057_init() - kmalloc (STAT_COM) failed\n", + ZR_DEVNAME(zr)); +- kfree(vdev); +- kfree(mem); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto exit_free; + } +- zr->stat_com = mem; + for (j = 0; j < BUZ_NUM_STAT_COM; j++) { + zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ + } +@@ -1069,16 +1065,11 @@ + /* + * Now add the template and register the device unit. + */ +- zr->video_dev = vdev; + memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); + strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); +- if (video_register_device(zr->video_dev, VFL_TYPE_GRABBER, +- video_nr) < 0) { +- zoran_unregister_i2c(zr); +- kfree((void *) zr->stat_com); +- kfree(vdev); +- return -1; +- } ++ err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr); ++ if (err < 0) ++ goto exit_unregister; + + zoran_init_hardware(zr); + if (*zr_debug > 2) +@@ -1092,6 +1083,13 @@ + zr->zoran_proc = NULL; + zr->initialized = 1; + return 0; ++ ++exit_unregister: ++ zoran_unregister_i2c(zr); ++exit_free: ++ kfree(zr->stat_com); ++ kfree(zr->video_dev); ++ return err; + } + + static void +@@ -1121,7 +1119,7 @@ + btwrite(0, ZR36057_SPGPPCR); + free_irq(zr->pci_dev->irq, zr); + /* unmap and free memory */ +- kfree((void *) zr->stat_com); ++ kfree(zr->stat_com); + zoran_proc_cleanup(zr); + iounmap(zr->zr36057_mem); + pci_disable_device(zr->pci_dev); +@@ -1349,6 +1347,14 @@ + i2c_dec_name = NULL; + } + ++ if (zoran_register_i2c(zr) < 0) { ++ dprintk(1, ++ KERN_ERR ++ "%s: find_zr36057() - can't initialize i2c bus\n", ++ ZR_DEVNAME(zr)); ++ goto zr_free_irq; ++ } ++ + if (i2c_dec_name) { + if ((result = request_module(i2c_dec_name)) < 0) { + dprintk(1, +@@ -1356,6 +1362,10 @@ + "%s: failed to load module %s: %d\n", + ZR_DEVNAME(zr), i2c_dec_name, result); + } ++ ++ i2c_probe_device(&zr->i2c_adapter, ++ zr->card.i2c_decoder, ++ zr->card.decoder_addr, 0); + } + + /* i2c encoder */ +@@ -1376,14 +1386,10 @@ + "%s: failed to load module %s: %d\n", + ZR_DEVNAME(zr), i2c_enc_name, result); + } +- } + +- if (zoran_register_i2c(zr) < 0) { +- dprintk(1, +- KERN_ERR +- "%s: find_zr36057() - can't initialize i2c bus\n", +- ZR_DEVNAME(zr)); +- goto zr_free_irq; ++ i2c_probe_device(&zr->i2c_adapter, ++ zr->card.i2c_encoder, ++ zr->card.encoder_addr, 0); + } + + dprintk(2, +--- linux-2.6.16.orig/Documentation/hwmon/lm83 2006-03-22 17:06:07.000000000 +0100 ++++ linux-2.6.16/Documentation/hwmon/lm83 2006-03-22 17:06:16.000000000 +0100 +@@ -7,6 +7,10 @@ + Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e + Datasheet: Publicly available at the National Semiconductor website + http://www.national.com/pf/LM/LM83.html ++ * National Semiconductor LM82 ++ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e ++ Datasheet: Publicly available at the National Semiconductor website ++ http://www.national.com/pf/LM/LM82.html + + + Author: Jean Delvare <khali@linux-fr.org> +@@ -15,10 +19,11 @@ + ----------- + + The LM83 is a digital temperature sensor. It senses its own temperature as +-well as the temperature of up to three external diodes. It is compatible +-with many other devices such as the LM84 and all other ADM1021 clones. +-The main difference between the LM83 and the LM84 in that the later can +-only sense the temperature of one external diode. ++well as the temperature of up to three external diodes. The LM82 is ++a stripped down version of the LM83 that only supports one external diode. ++Both are compatible with many other devices such as the LM84 and all ++other ADM1021 clones. The main difference between the LM83 and the LM84 ++in that the later can only sense the temperature of one external diode. + + Using the adm1021 driver for a LM83 should work, but only two temperatures + will be reported instead of four. +@@ -36,6 +41,9 @@ + Iwill MPX2 + Soltek SL-75DRV5 + ++The LM82 is confirmed to have been found on most AMD Geode reference ++designs and test platforms. ++ + The driver has been successfully tested by Magnus Forsström, who I'd + like to thank here. More testers will be of course welcome. + +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.16/Documentation/hwmon/smsc47m192 2006-03-22 17:06:16.000000000 +0100 +@@ -0,0 +1,102 @@ ++Kernel driver smsc47m192 ++======================== ++ ++Supported chips: ++ * SMSC LPC47M192 and LPC47M997 ++ Prefix: 'smsc47m192' ++ Addresses scanned: I2C 0x2c - 0x2d ++ Datasheet: The datasheet for LPC47M192 is publicly available from ++ http://www.smsc.com/ ++ The LPC47M997 is compatible for hardware monitoring. ++ ++Author: Hartmut Rick <linux@rick.claranet.de> ++ Special thanks to Jean Delvare for careful checking ++ of the code and many helpful comments and suggestions. ++ ++ ++Description ++----------- ++ ++This driver implements support for the hardware sensor capabilities ++of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. ++ ++These chips support 3 temperature channels and 8 voltage inputs ++as well as CPU voltage VID input. ++ ++They do also have fan monitoring and control capabilities, but the ++these features are accessed via ISA bus and are not supported by this ++driver. Use the 'smsc47m1' driver for fan monitoring and control. ++ ++Voltages and temperatures are measured by an 8-bit ADC, the resolution ++of the temperatures is 1 bit per degree C. ++Voltages are scaled such that the nominal voltage corresponds to ++192 counts, i.e. 3/4 of the full range. Thus the available range for ++each voltage channel is 0V ... 255/192*(nominal voltage), the resolution ++is 1 bit per (nominal voltage)/192. ++Both voltage and temperature values are scaled by 1000, the sys files ++show voltages in mV and temperatures in units of 0.001 degC. ++ ++The +12V analog voltage input channel (in4_input) is multiplexed with ++bit 4 of the encoded CPU voltage. This means that you either get ++a +12V voltage measurement or a 5 bit CPU VID, but not both. ++The default setting is to use the pin as 12V input, and use only 4 bit VID. ++This driver assumes that the information in the configuration register ++is correct, i.e. that the BIOS has updated the configuration if ++the motherboard has this input wired to VID4. ++ ++The temperature and voltage readings are updated once every 1.5 seconds. ++Reading them more often repeats the same values. ++ ++ ++sysfs interface ++--------------- ++ ++in0_input - +2.5V voltage input ++in1_input - CPU voltage input (nominal 2.25V) ++in2_input - +3.3V voltage input ++in3_input - +5V voltage input ++in4_input - +12V voltage input (may be missing if used as VID4) ++in5_input - Vcc voltage input (nominal 3.3V) ++ This is the supply voltage of the sensor chip itself. ++in6_input - +1.5V voltage input ++in7_input - +1.8V voltage input ++ ++in[0-7]_min, ++in[0-7]_max - lower and upper alarm thresholds for in[0-7]_input reading ++ ++ All voltages are read and written in mV. ++ ++in[0-7]_alarm - alarm flags for voltage inputs ++ These files read '1' in case of alarm, '0' otherwise. ++ ++temp1_input - chip temperature measured by on-chip diode ++temp[2-3]_input - temperature measured by external diodes (one of these would ++ typically be wired to the diode inside the CPU) ++ ++temp[1-3]_min, ++temp[1-3]_max - lower and upper alarm thresholds for temperatures ++ ++temp[1-3]_offset - temperature offset registers ++ The chip adds the offsets stored in these registers to ++ the corresponding temperature readings. ++ Note that temp1 and temp2 offsets share the same register, ++ they cannot both be different from zero at the same time. ++ Writing a non-zero number to one of them will reset the other ++ offset to zero. ++ ++ All temperatures and offsets are read and written in ++ units of 0.001 degC. ++ ++temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm, ++ '0' otherwise. ++temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3. ++ A fault is detected if the two pins for the corresponding ++ sensor are open or shorted, or any of the two is shorted ++ to ground or Vcc. '1' indicates a diode fault. ++ ++cpu0_vid - CPU voltage as received from the CPU ++ ++vrm - CPU VID standard used for decoding CPU voltage ++ ++ The *_min, *_max, *_offset and vrm files can be read and ++ written, all others are read-only. +--- linux-2.6.16.orig/Documentation/hwmon/sysfs-interface 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/Documentation/hwmon/sysfs-interface 2006-03-22 17:06:16.000000000 +0100 +@@ -218,6 +218,12 @@ + from the critical value. + Read/Write value. + ++temp[1-4]_offset ++ Temperature offset which is added to the temperature reading ++ by the chip. ++ Unit: millidegree Celsius ++ Read/Write value. ++ + If there are multiple temperature sensors, temp1_* is + generally the sensor inside the chip itself, + reported as "motherboard temperature". temp2_* to +@@ -246,9 +252,68 @@ + Read only. + + +-********* +-* Other * +-********* ++********** ++* Alarms * ++********** ++ ++Each channel or limit may have an associated alarm file, containing a ++boolean value. 1 means than an alarm condition exists, 0 means no alarm. ++ ++Usually a given chip will either use channel-related alarms, or ++limit-related alarms, not both. The driver should just reflect the hardware ++implementation. ++ ++in[0-n]_alarm ++fan[1-n]_alarm ++temp[1-n]_alarm ++ Channel alarm ++ Boolean ++ Read-only ++ ++OR ++ ++in[0-n]_min_alarm ++in[0-n]_max_alarm ++fan[1-n]_min_alarm ++temp[1-n]_min_alarm ++temp[1-n]_max_alarm ++temp[1-n]_crit_alarm ++ Limit alarm ++ Boolean ++ Read-only ++ ++In theory, a chip could provide per-limit beep masking, but no such chip ++was seen so far. ++ ++Each input channel may have an associated fault file. This can be used ++to notify open diodes, unconnected fans etc. where the hardware ++supports it. When this boolean has value 1, the measurement for that ++channel should not be trusted. ++ ++fan[1-n]_input_fault ++temp[1-n]_input_fault ++ Input fault condition ++ Boolean ++ Read-only ++ ++Some chips also offer the possibility to get beeped when an alarm occurs: ++ ++beep_enable Master beep enable ++ 0 to disable. ++ 1 to enable. ++ Read/Write ++ ++in[0-n]_beep ++fan[1-n]_beep ++temp[1-n]_beep ++ Channel beep ++ 0 to disable. ++ 1 to enable. ++ Read/write ++ ++Old drivers provided a different, non-standard interface to alarms and ++beeps. These interface files are deprecated, but will be kept around ++for compatibility reasons: + + alarms Alarm bitmask. + Read only. +@@ -259,33 +324,22 @@ + if it is still valid. + Generally a direct representation of a chip's internal + alarm registers; there is no standard for the position +- of individual bits. ++ of individual bits. For this reason, the use of this ++ interface file for new drivers is discouraged. Use ++ individual *_alarm and *_fault files instead. + Bits are defined in kernel/include/sensors.h. + +-alarms_in Alarm bitmask relative to in (voltage) channels +- Read only +- A '1' bit means an alarm, LSB corresponds to in0 and so on +- Prefered to 'alarms' for newer chips +- +-alarms_fan Alarm bitmask relative to fan channels +- Read only +- A '1' bit means an alarm, LSB corresponds to fan1 and so on +- Prefered to 'alarms' for newer chips +- +-alarms_temp Alarm bitmask relative to temp (temperature) channels +- Read only +- A '1' bit means an alarm, LSB corresponds to temp1 and so on +- Prefered to 'alarms' for newer chips +- +-beep_enable Beep/interrupt enable +- 0 to disable. +- 1 to enable. +- Read/Write +- + beep_mask Bitmask for beep. +- Same format as 'alarms' with the same bit locations. ++ Same format as 'alarms' with the same bit locations, ++ use discouraged for the same reason. Use individual ++ *_beep files instead. + Read/Write + ++ ++********* ++* Other * ++********* ++ + eeprom Raw EEPROM data in binary form. + Read only. + +--- linux-2.6.16.orig/drivers/hwmon/Makefile 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/drivers/hwmon/Makefile 2006-03-22 17:06:16.000000000 +0100 +@@ -40,6 +40,7 @@ + obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o + obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o + obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o ++obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o + obj-$(CONFIG_SENSORS_VIA686A) += via686a.o + obj-$(CONFIG_SENSORS_VT8231) += vt8231.o + obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.16/drivers/hwmon/smsc47m192.c 2006-03-22 17:06:16.000000000 +0100 +@@ -0,0 +1,638 @@ ++/* ++ smsc47m192.c - Support for hardware monitoring block of ++ SMSC LPC47M192 and LPC47M997 Super I/O chips ++ ++ Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> ++ ++ Derived from lm78.c and other chip drivers. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/jiffies.h> ++#include <linux/i2c.h> ++#include <linux/hwmon.h> ++#include <linux/hwmon-sysfs.h> ++#include <linux/hwmon-vid.h> ++#include <linux/err.h> ++ ++/* Addresses to scan */ ++static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; ++ ++/* Insmod parameters */ ++I2C_CLIENT_INSMOD_1(smsc47m192); ++ ++/* SMSC47M192 registers */ ++#define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ ++ (0x50 + (nr) - 6)) ++#define SMSC47M192_REG_IN_MAX(nr) ((nr)<6 ? (0x2b + (nr) * 2) : \ ++ (0x54 + (((nr) - 6) * 2))) ++#define SMSC47M192_REG_IN_MIN(nr) ((nr)<6 ? (0x2c + (nr) * 2) : \ ++ (0x55 + (((nr) - 6) * 2))) ++static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; ++static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; ++static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; ++#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr)==2 ? 0x1e : 0x1f) ++#define SMSC47M192_REG_ALARM1 0x41 ++#define SMSC47M192_REG_ALARM2 0x42 ++#define SMSC47M192_REG_VID 0x47 ++#define SMSC47M192_REG_VID4 0x49 ++#define SMSC47M192_REG_CONFIG 0x40 ++#define SMSC47M192_REG_SFR 0x4f ++#define SMSC47M192_REG_COMPANY_ID 0x3e ++#define SMSC47M192_REG_VERSION 0x3f ++ ++/* generalised scaling with integer rounding */ ++static inline int SCALE(long val, int mul, int div) ++{ ++ if (val < 0) ++ return (val * mul - div / 2) / div; ++ else ++ return (val * mul + div / 2) / div; ++} ++ ++/* Conversions */ ++ ++/* smsc47m192 internally scales voltage measurements */ ++static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; ++ ++static inline unsigned int IN_FROM_REG(u8 reg, int n) ++{ ++ return SCALE(reg, nom_mv[n], 192); ++} ++ ++static inline u8 IN_TO_REG(unsigned long val, int n) ++{ ++ return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); ++} ++ ++/* TEMP: 0.001 degC units (-128C to +127C) ++ REG: 1C/bit, two's complement */ ++static inline s8 TEMP_TO_REG(int val) ++{ ++ return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); ++} ++ ++static inline int TEMP_FROM_REG(s8 val) ++{ ++ return val * 1000; ++} ++ ++struct smsc47m192_data { ++ struct i2c_client client; ++ struct class_device *class_dev; ++ struct semaphore update_lock; ++ char valid; /* !=0 if following fields are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ ++ u8 in[8]; /* Register value */ ++ u8 in_max[8]; /* Register value */ ++ u8 in_min[8]; /* Register value */ ++ s8 temp[3]; /* Register value */ ++ s8 temp_max[3]; /* Register value */ ++ s8 temp_min[3]; /* Register value */ ++ s8 temp_offset[3]; /* Register value */ ++ u16 alarms; /* Register encoding, combined */ ++ u8 vid; /* Register encoding, combined */ ++ u8 vrm; ++}; ++ ++static int smsc47m192_detect(struct i2c_adapter *adapter, int address, ++ int kind); ++static int smsc47m192_detach_client(struct i2c_client *client); ++static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); ++ ++static struct i2c_driver smsc47m192_driver = { ++ .driver = { ++ .name = "smsc47m192", ++ }, ++ .class = I2C_CLASS_HWMON, ++ .address_data = &addr_data, ++ .detect_client = smsc47m192_detect, ++ .detach_client = smsc47m192_detach_client, ++}; ++ ++/* Voltages */ ++static ssize_t show_in(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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); ++} ++ ++static ssize_t show_in_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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); ++} ++ ++static ssize_t show_in_max(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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); ++} ++ ++static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ unsigned long val = simple_strtoul(buf, NULL, 10); ++ ++ down(&data->update_lock); ++ data->in_min[nr] = IN_TO_REG(val, nr); ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), ++ data->in_min[nr]); ++ up(&data->update_lock); ++ return count; ++} ++ ++static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ unsigned long val = simple_strtoul(buf, NULL, 10); ++ ++ down(&data->update_lock); ++ data->in_max[nr] = IN_TO_REG(val, nr); ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), ++ data->in_max[nr]); ++ up(&data->update_lock); ++ return count; ++} ++ ++#define show_in_offset(offset) \ ++static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ ++ show_in, NULL, offset); \ ++static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ ++ show_in_min, set_in_min, offset); \ ++static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ ++ show_in_max, set_in_max, offset); ++ ++show_in_offset(0) ++show_in_offset(1) ++show_in_offset(2) ++show_in_offset(3) ++show_in_offset(4) ++show_in_offset(5) ++show_in_offset(6) ++show_in_offset(7) ++ ++/* Temperatures */ ++static ssize_t show_temp(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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); ++} ++ ++static ssize_t show_temp_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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); ++} ++ ++static ssize_t show_temp_max(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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); ++} ++ ++static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ long val = simple_strtol(buf, NULL, 10); ++ ++ down(&data->update_lock); ++ data->temp_min[nr] = TEMP_TO_REG(val); ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], ++ data->temp_min[nr]); ++ up(&data->update_lock); ++ return count; ++} ++ ++static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ long val = simple_strtol(buf, NULL, 10); ++ ++ down(&data->update_lock); ++ data->temp_max[nr] = TEMP_TO_REG(val); ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], ++ data->temp_max[nr]); ++ up(&data->update_lock); ++ return count; ++} ++ ++static ssize_t show_temp_offset(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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); ++} ++ ++static ssize_t set_temp_offset(struct device *dev, struct device_attribute ++ *attr, const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); ++ int nr = sensor_attr->index; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); ++ long val = simple_strtol(buf, NULL, 10); ++ ++ down(&data->update_lock); ++ data->temp_offset[nr] = TEMP_TO_REG(val); ++ if (nr>1) ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); ++ else if (data->temp_offset[nr] != 0) { ++ /* offset[0] and offset[1] share the same register, ++ SFR bit 4 activates offset[0] */ ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, ++ (sfr & 0xef) | (nr==0 ? 0x10 : 0)); ++ data->temp_offset[1-nr] = 0; ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); ++ } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0)) ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_TEMP_OFFSET(nr), 0); ++ up(&data->update_lock); ++ return count; ++} ++ ++#define show_temp_index(index) \ ++static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ ++ show_temp, NULL, index-1); \ ++static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ ++ show_temp_min, set_temp_min, index-1); \ ++static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ ++ show_temp_max, set_temp_max, index-1); \ ++static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ ++ show_temp_offset, set_temp_offset, index-1); ++ ++show_temp_index(1) ++show_temp_index(2) ++show_temp_index(3) ++ ++/* VID */ ++static ssize_t show_vid(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); ++} ++static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); ++ ++static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%d\n", data->vrm); ++} ++ ++static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ data->vrm = simple_strtoul(buf, NULL, 10); ++ return count; ++} ++static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); ++ ++/* Alarms */ ++static ssize_t show_alarm(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; ++ struct smsc47m192_data *data = smsc47m192_update_device(dev); ++ return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); ++} ++ ++static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); ++static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); ++static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); ++static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000); ++static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000); ++static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); ++static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); ++static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); ++static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); ++static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); ++static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); ++static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); ++static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); ++ ++static void smsc47m192_init_client(struct i2c_client *client) ++{ ++ int i; ++ u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); ++ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); ++ ++ /* select cycle mode (pause 1 sec between updates) */ ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, ++ (sfr & 0xfd) | 0x02); ++ if (!(config & 0x01)) { ++ /* initialize alarm limits */ ++ for (i=0; i<8; i++) { ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_IN_MIN(i), 0); ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_IN_MAX(i), 0xff); ++ } ++ for (i=0; i<3; i++) { ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_TEMP_MIN[i], 0x80); ++ i2c_smbus_write_byte_data(client, ++ SMSC47M192_REG_TEMP_MAX[i], 0x7f); ++ } ++ ++ /* start monitoring */ ++ i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, ++ (config & 0xf7) | 0x01); ++ } ++} ++ ++/* This function is called by i2c_probe */ ++static int smsc47m192_detect(struct i2c_adapter *adapter, int address, ++ int kind) ++{ ++ struct i2c_client *client; ++ struct smsc47m192_data *data; ++ int err = 0; ++ int version, config; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) ++ goto exit; ++ ++ if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ client = &data->client; ++ i2c_set_clientdata(client, data); ++ client->addr = address; ++ client->adapter = adapter; ++ client->driver = &smsc47m192_driver; ++ ++ if (kind == 0) ++ kind = smsc47m192; ++ ++ /* Detection criteria from sensors_detect script */ ++ if (kind < 0) { ++ if (i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_COMPANY_ID) == 0x55 ++ && ((version = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_VERSION)) & 0xf0) == 0x20 ++ && (i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_VID) & 0x70) == 0x00 ++ && (i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_VID4) & 0xfe) == 0x80) { ++ dev_info(&adapter->dev, ++ "found SMSC47M192 or SMSC47M997, " ++ "version 2, stepping A%d\n", version & 0x0f); ++ } else { ++ dev_dbg(&adapter->dev, ++ "SMSC47M192 detection failed at 0x%02x\n", ++ address); ++ goto exit_free; ++ } ++ } ++ ++ /* Fill in the remaining client fields and put into the global list */ ++ strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); ++ data->vrm = vid_which_vrm(); ++ init_MUTEX(&data->update_lock); ++ ++ /* Tell the I2C layer a new client has arrived */ ++ if ((err = i2c_attach_client(client))) ++ goto exit_free; ++ ++ /* Initialize the SMSC47M192 chip */ ++ smsc47m192_init_client(client); ++ ++ /* Register sysfs hooks */ ++ data->class_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->class_dev)) { ++ err = PTR_ERR(data->class_dev); ++ goto exit_detach; ++ } ++ ++ device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr); ++ ++ /* Pin 110 is either in4 (+12V) or VID4 */ ++ config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); ++ if (!(config & 0x20)) { ++ device_create_file(&client->dev, ++ &sensor_dev_attr_in4_input.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_in4_min.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_in4_max.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_in4_alarm.dev_attr); ++ } ++ device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_temp1_offset.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_temp2_offset.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_temp2_input_fault.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_temp3_offset.dev_attr); ++ device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr); ++ device_create_file(&client->dev, ++ &sensor_dev_attr_temp3_input_fault.dev_attr); ++ device_create_file(&client->dev, &dev_attr_cpu0_vid); ++ device_create_file(&client->dev, &dev_attr_vrm); ++ ++ return 0; ++ ++exit_detach: ++ i2c_detach_client(client); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int smsc47m192_detach_client(struct i2c_client *client) ++{ ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ int err; ++ ++ hwmon_device_unregister(data->class_dev); ++ ++ if ((err = i2c_detach_client(client))) ++ return err; ++ ++ kfree(data); ++ ++ return 0; ++} ++ ++static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct smsc47m192_data *data = i2c_get_clientdata(client); ++ int i, config; ++ ++ down(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); ++ ++ dev_dbg(&client->dev, "Starting smsc47m192 update\n"); ++ ++ for (i = 0; i <= 7; i++) { ++ data->in[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_IN(i)); ++ data->in_min[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_IN_MIN(i)); ++ data->in_max[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_IN_MAX(i)); ++ } ++ for (i = 0; i < 3; i++) { ++ data->temp[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_TEMP[i]); ++ data->temp_max[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_TEMP_MAX[i]); ++ data->temp_min[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_TEMP_MIN[i]); ++ } ++ for (i = 1; i < 3; i++) ++ data->temp_offset[i] = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_TEMP_OFFSET(i)); ++ /* first offset is temp_offset[0] if SFR bit 4 is set, ++ temp_offset[1] otherwise */ ++ if (sfr & 0x10) { ++ data->temp_offset[0] = data->temp_offset[1]; ++ data->temp_offset[1] = 0; ++ } else ++ data->temp_offset[0] = 0; ++ ++ data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) ++ & 0x0f; ++ config = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_CONFIG); ++ if (config & 0x20) ++ data->vid |= (i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_VID4) & 0x01) << 4; ++ data->alarms = i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_ALARM1) | ++ (i2c_smbus_read_byte_data(client, ++ SMSC47M192_REG_ALARM2) << 8); ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++ up(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init smsc47m192_init(void) ++{ ++ return i2c_add_driver(&smsc47m192_driver); ++} ++ ++static void __exit smsc47m192_exit(void) ++{ ++ i2c_del_driver(&smsc47m192_driver); ++} ++ ++MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>"); ++MODULE_DESCRIPTION("SMSC47M192 driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(smsc47m192_init); ++module_exit(smsc47m192_exit); +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-sis96x.c 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-sis96x.c 2006-03-22 17:06:16.000000000 +0100 +@@ -43,13 +43,6 @@ + #include <linux/init.h> + #include <asm/io.h> + +-/* +- HISTORY: +- 2003-05-11 1.0.0 Updated from lm_sensors project for kernel 2.5 +- (was i2c-sis645.c from lm_sensors 2.7.0) +-*/ +-#define SIS96x_VERSION "1.0.0" +- + /* base address register in PCI config space */ + #define SIS96x_BAR 0x04 + +@@ -256,7 +249,7 @@ + + static struct i2c_adapter sis96x_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +@@ -337,7 +330,6 @@ + + static int __init i2c_sis96x_init(void) + { +- printk(KERN_INFO "i2c-sis96x version %s\n", SIS96x_VERSION); + return pci_register_driver(&sis96x_driver); + } + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-parport-light.c 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-parport-light.c 2006-03-22 17:06:16.000000000 +0100 +@@ -111,7 +111,7 @@ + + static struct i2c_adapter parport_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .id = I2C_HW_B_LP, + .algo_data = &parport_algo_data, + .name = "Parallel port adapter (light)", +@@ -121,9 +121,14 @@ + + static int __init i2c_parport_init(void) + { +- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { ++ if (type < 0) { ++ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); ++ return -ENODEV; ++ } ++ ++ if (type >= ARRAY_SIZE(adapter_parm)) { + printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); +- type = 0; ++ return -ENODEV; + } + + if (base == 0) { +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-parport.h 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-parport.h 2006-03-22 17:06:16.000000000 +0100 +@@ -90,7 +90,7 @@ + }, + }; + +-static int type; ++static int type = -1; + module_param(type, int, 0); + MODULE_PARM_DESC(type, + "Type of adapter:\n" +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-parport.c 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-parport.c 2006-03-22 17:06:16.000000000 +0100 +@@ -146,7 +146,7 @@ + + static struct i2c_adapter parport_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .id = I2C_HW_B_LP, + .name = "Parallel port adapter", + }; +@@ -241,9 +241,14 @@ + + static int __init i2c_parport_init(void) + { +- if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) { ++ if (type < 0) { ++ printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); ++ return -ENODEV; ++ } ++ ++ if (type >= ARRAY_SIZE(adapter_parm)) { + printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); +- type = 0; ++ return -ENODEV; + } + + return parport_register_driver(&i2c_parport_driver); +--- linux-2.6.16.orig/Documentation/i2c/busses/i2c-parport 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/Documentation/i2c/busses/i2c-parport 2006-03-22 17:06:16.000000000 +0100 +@@ -12,18 +12,22 @@ + teletext adapters) + + It currently supports the following devices: +- * Philips adapter +- * home brew teletext adapter +- * Velleman K8000 adapter +- * ELV adapter +- * Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032) +- * Barco LPT->DVI (K5800236) adapter ++ * (type=0) Philips adapter ++ * (type=1) home brew teletext adapter ++ * (type=2) Velleman K8000 adapter ++ * (type=3) ELV adapter ++ * (type=4) Analog Devices ADM1032 evaluation board ++ * (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031 ++ * (type=6) Barco LPT->DVI (K5800236) adapter + + These devices use different pinout configurations, so you have to tell + the driver what you have, using the type module parameter. There is no + way to autodetect the devices. Support for different pinout configurations + can be easily added when needed. + ++Earlier kernels defaulted to type=0 (Philips). But now, if the type ++parameter is missing, the driver will simply fail to initialize. ++ + + Building your own adapter + ------------------------- +--- linux-2.6.16.orig/Documentation/i2c/writing-clients 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/Documentation/i2c/writing-clients 2006-03-22 17:06:16.000000000 +0100 +@@ -28,7 +28,9 @@ + .driver = { + .name = "foo", + }, +- .attach_adapter = &foo_attach_adapter, ++ .class = I2C_CLASS_SOMETHING, ++ .address_data = &addr_data, ++ .detect_client = &foo_detect_client, + .detach_client = &foo_detach_client, + .command = &foo_command /* may be NULL */ + } +@@ -141,8 +143,8 @@ + are defined in i2c.h to help you support them, as well as a generic + detection algorithm. + +-You do not have to use this parameter interface; but don't try to use +-function i2c_probe() if you don't. ++You do not have to use this parameter interface; but then the i2c core won't ++be able to probe for devices for you. + + NOTE: If you want to write a `sensors' driver, the interface is slightly + different! See below. +@@ -201,35 +203,49 @@ + ----------------------- + + Whenever a new adapter is inserted, or for all adapters if the driver is +-being registered, the callback attach_adapter() is called. Now is the +-time to determine what devices are present on the adapter, and to register +-a client for each of them. +- +-The attach_adapter callback is really easy: we just call the generic +-detection function. This function will scan the bus for us, using the +-information as defined in the lists explained above. If a device is +-detected at a specific address, another callback is called. ++being registered, your driver may be notified through one of two ++callbacks, depending on the degree of control you need to exercise over ++the probing process. This is the time to determine what devices are ++present on the adapter and to register a client for each device your ++driver supports. ++ ++The easiest way to handle the probing process is to simply set the `class', ++`address_data', and `detect_client' fields in the i2c_driver structure. ++The `class' field is a bitmask of all the adapter classes which should be ++probed for devices supported by this driver. You should set it to one of ++the I2C_CLASS_* constants defined in i2c.h. The `address_data' field ++should be set to `&addr_data', which is defined by the macros explained ++above, so you do not have to define it yourself. When a new adapter is ++attached, the bus is scanned for the addresses defined in the lists above, ++and the detect_client callback gets called when a device is detected at a ++specific address. ++ ++If you prefer, you can omit the `class', `address_data', and ++`detect_client' fields from your i2c_driver structure, and instead set ++`attach_adapter'. The `attach_adapter' callback gets called every time a ++new adapter is attached and the bus needs to be scanned, so if you need to ++perform any special checks or configuration before you scan a bus for ++devices, you should use attach_adapter. If the bus is suitable, you can ++then call the generic i2c_probe function to scan for the addresses in the ++lists explained above, and the callback passed in the third parameter will ++get called for each device detected. + + int foo_attach_adapter(struct i2c_adapter *adapter) + { + return i2c_probe(adapter,&addr_data,&foo_detect_client); + } + +-Remember, structure `addr_data' is defined by the macros explained above, +-so you do not have to define it yourself. +- +-The i2c_probe function will call the foo_detect_client +-function only for those i2c addresses that actually have a device on +-them (unless a `force' parameter was used). In addition, addresses that +-are already in use (by some other registered client) are skipped. ++With either mechanism, addresses that are already in use (by some other ++registered client) are skipped. + + + The detect client function + -------------------------- + +-The detect client function is called by i2c_probe. The `kind' parameter +-contains -1 for a probed detection, 0 for a forced detection, or a positive +-number for a forced detection with a chip type forced. ++The detect client function is called by the address probing mechanism. ++The `kind' parameter contains -1 for a probed detection, 0 for a forced ++detection, or a positive number for a forced detection with a chip type ++forced. + + Below, some things are only needed if this is a `sensors' driver. Those + parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */ +--- linux-2.6.16.orig/Documentation/i2c/porting-clients 2006-03-22 17:06:00.000000000 +0100 ++++ linux-2.6.16/Documentation/i2c/porting-clients 2006-03-22 17:06:16.000000000 +0100 +@@ -100,6 +100,9 @@ + Drop any 24RF08 corruption prevention you find, as this is now done + at the i2c-core level, and doing it twice voids it. + Don't add I2C_CLIENT_ALLOW_USE to client->flags, it's the default now. ++ If you want auto probing of your driver, use driver->addr_data ++ (this is strongly encouraged if your attach_adapter is a one-liner ++ which calls i2c_probe). + + * [Init] Limits must not be set by the driver (can be done later in + user-space). Chip should not be reset default (although a module +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ali1563.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ali1563.c 2006-03-22 17:06:16.000000000 +0100 +@@ -374,7 +374,7 @@ + + static struct i2c_adapter ali1563_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &ali1563_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ali15x3.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ali15x3.c 2006-03-22 17:06:16.000000000 +0100 +@@ -470,7 +470,7 @@ + + static struct i2c_adapter ali15x3_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-amd756.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-amd756.c 2006-03-22 17:06:16.000000000 +0100 +@@ -301,7 +301,7 @@ + + struct i2c_adapter amd756_smbus = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-amd8111.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-amd8111.c 2006-03-22 17:06:16.000000000 +0100 +@@ -351,7 +351,7 @@ + smbus->adapter.owner = THIS_MODULE; + snprintf(smbus->adapter.name, I2C_NAME_SIZE, + "SMBus2 AMD8111 adapter at %04x", smbus->base); +- smbus->adapter.class = I2C_CLASS_HWMON; ++ smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DATA; + smbus->adapter.algo = &smbus_algorithm; + smbus->adapter.algo_data = smbus; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-elektor.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-elektor.c 2006-03-22 17:06:16.000000000 +0100 +@@ -202,7 +202,7 @@ + + static struct i2c_adapter pcf_isa_ops = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .id = I2C_HW_P_ELEK, + .algo_data = &pcf_isa_data, + .name = "i2c-elektor", +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-i801.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-i801.c 2006-03-22 17:06:16.000000000 +0100 +@@ -513,7 +513,7 @@ + + static struct i2c_adapter i801_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-i810.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-i810.c 2006-03-22 17:06:16.000000000 +0100 +@@ -188,6 +188,7 @@ + + static struct i2c_adapter i810_ddc_adapter = { + .owner = THIS_MODULE, ++ .class = I2C_CLASS_DATA, + .name = "I810/I815 DDC Adapter", + .algo_data = &i810_ddc_bit_data, + }; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ibm_iic.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ibm_iic.c 2006-03-22 17:06:16.000000000 +0100 +@@ -724,8 +724,9 @@ + adap = &dev->adap; + strcpy(adap->name, "IBM IIC"); + i2c_set_adapdata(adap, dev); ++ adap->owner = THIS_MODULE; + adap->id = I2C_HW_OCP; +- adap->class = I2C_CLASS_HWMON; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_DATA; + adap->algo = &iic_algo; + adap->client_register = NULL; + adap->client_unregister = NULL; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-ixp2000.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-ixp2000.c 2006-03-22 17:06:16.000000000 +0100 +@@ -117,7 +117,9 @@ + drv_data->algo_data.mdelay = 6; + drv_data->algo_data.timeout = 100; + +- drv_data->adapter.id = I2C_HW_B_IXP2000, ++ drv_data->adapter.owner = THIS_MODULE; ++ drv_data->adapter.class = I2C_CLASS_DATA; ++ drv_data->adapter.id = I2C_HW_B_IXP2000; + strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, + I2C_NAME_SIZE); + drv_data->adapter.algo_data = &drv_data->algo_data, +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-mpc.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-mpc.c 2006-03-22 17:06:16.000000000 +0100 +@@ -283,7 +283,7 @@ + .name = "MPC adapter", + .id = I2C_HW_MPC107, + .algo = &mpc_algo, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .timeout = 1, + .retries = 1 + }; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-mv64xxx.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-mv64xxx.c 2006-03-22 17:06:16.000000000 +0100 +@@ -519,7 +519,7 @@ + drv_data->adapter.id = I2C_HW_MV64XXX; + drv_data->adapter.algo = &mv64xxx_i2c_algo; + drv_data->adapter.owner = THIS_MODULE; +- drv_data->adapter.class = I2C_CLASS_HWMON; ++ drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DATA; + drv_data->adapter.timeout = pdata->timeout; + drv_data->adapter.retries = pdata->retries; + platform_set_drvdata(pd, drv_data); +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-nforce2.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-nforce2.c 2006-03-22 17:06:16.000000000 +0100 +@@ -113,7 +113,7 @@ + + static struct i2c_adapter nforce2_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-prosavage.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-prosavage.c 2006-03-22 17:06:16.000000000 +0100 +@@ -172,6 +172,7 @@ + { + int ret; + p->adap.owner = THIS_MODULE; ++ p->adap.class = I2C_CLASS_DATA; + p->adap.id = I2C_HW_B_S3VIA; + p->adap.algo_data = &p->algo; + p->adap.dev.parent = &dev->dev; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-s3c2410.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-s3c2410.c 2006-03-22 17:06:16.000000000 +0100 +@@ -580,7 +580,7 @@ + .owner = THIS_MODULE, + .algo = &s3c24xx_i2c_algorithm, + .retries = 2, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + }, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-savage4.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-savage4.c 2006-03-22 17:06:16.000000000 +0100 +@@ -146,6 +146,7 @@ + + static struct i2c_adapter savage4_i2c_adapter = { + .owner = THIS_MODULE, ++ .class = I2C_CLASS_DATA, + .name = "I2C Savage4 adapter", + .algo_data = &sav_i2c_bit_data, + }; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-sibyte.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-sibyte.c 2006-03-22 17:06:16.000000000 +0100 +@@ -31,7 +31,7 @@ + { + .owner = THIS_MODULE, + .id = I2C_HW_SIBYTE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = NULL, + .algo_data = &sibyte_board_data[0], + .name = "SiByte SMBus 0", +@@ -39,7 +39,7 @@ + { + .owner = THIS_MODULE, + .id = I2C_HW_SIBYTE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = NULL, + .algo_data = &sibyte_board_data[1], + .name = "SiByte SMBus 1", +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-sis5595.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-sis5595.c 2006-03-22 17:06:16.000000000 +0100 +@@ -365,7 +365,7 @@ + + static struct i2c_adapter sis5595_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-sis630.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-sis630.c 2006-03-22 17:06:16.000000000 +0100 +@@ -457,7 +457,7 @@ + + static struct i2c_adapter sis630_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-stub.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-stub.c 2006-03-22 17:06:16.000000000 +0100 +@@ -115,7 +115,7 @@ + + static struct i2c_adapter stub_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_ALL, + .algo = &smbus_algorithm, + .name = "SMBus stub driver", + }; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-via.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-via.c 2006-03-22 17:06:16.000000000 +0100 +@@ -87,7 +87,7 @@ + + static struct i2c_adapter vt586b_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .name = "VIA i2c", + .algo_data = &bit_data, + }; +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-viapro.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-viapro.c 2006-03-22 17:06:16.000000000 +0100 +@@ -304,7 +304,7 @@ + + static struct i2c_adapter vt596_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_HWMON, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_DATA, + .algo = &smbus_algorithm, + }; + +--- linux-2.6.16.orig/drivers/i2c/busses/i2c-voodoo3.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/i2c/busses/i2c-voodoo3.c 2006-03-22 17:06:16.000000000 +0100 +@@ -183,7 +183,7 @@ + + static struct i2c_adapter voodoo3_ddc_adapter = { + .owner = THIS_MODULE, +- .class = I2C_CLASS_DDC, ++ .class = I2C_CLASS_DATA, + .name = "DDC Voodoo3/Banshee adapter", + .algo_data = &voo_ddc_bit_data, + }; +--- linux-2.6.16.orig/drivers/video/aty/radeon_i2c.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/video/aty/radeon_i2c.c 2006-03-22 17:06:16.000000000 +0100 +@@ -75,6 +75,7 @@ + + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; ++ chan->adapter.class = I2C_CLASS_DATA; + chan->adapter.id = I2C_HW_B_RADEON; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->rinfo->pdev->dev; +--- linux-2.6.16.orig/drivers/video/i810/i810-i2c.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/video/i810/i810-i2c.c 2006-03-22 17:06:16.000000000 +0100 +@@ -85,12 +85,14 @@ + return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); + } + +-static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) ++static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name, ++ unsigned long i2c_class) + { + int rc; + + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; ++ chan->adapter.class = i2c_class; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->dev->dev; + chan->adapter.id = I2C_HW_B_I810; +@@ -130,11 +132,11 @@ + par->chan[2].par = par; + + par->chan[0].ddc_base = GPIOA; +- i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); ++ i810_setup_i2c_bus(&par->chan[0], "I810-DDC", I2C_CLASS_DATA); + par->chan[1].ddc_base = GPIOB; +- i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); ++ i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 0); + par->chan[2].ddc_base = GPIOC; +- i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); ++ i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC", 0); + } + + void i810_delete_i2c_busses(struct i810fb_par *par) +--- linux-2.6.16.orig/drivers/video/matrox/i2c-matroxfb.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/video/matrox/i2c-matroxfb.c 2006-03-22 17:06:16.000000000 +0100 +@@ -104,13 +104,15 @@ + }; + + static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, +- unsigned int data, unsigned int clock, const char* name) { ++ unsigned int data, unsigned int clock, const char* name, ++ unsigned int i2c_class) { + int err; + + b->minfo = minfo; + b->mask.data = data; + b->mask.clock = clock; + b->adapter = matrox_i2c_adapter_template; ++ b->adapter.class = i2c_class; + snprintf(b->adapter.name, I2C_NAME_SIZE, name, + minfo->fbcon.node); + i2c_set_adapdata(&b->adapter, b); +@@ -160,22 +162,28 @@ + switch (ACCESS_FBINFO(chip)) { + case MGA_2064: + case MGA_2164: +- err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0"); ++ err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, ++ DDC1B_CLK, "DDC:fb%u #0", ++ I2C_CLASS_DATA); + break; + default: +- err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0"); ++ err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, ++ DDC1_CLK, "DDC:fb%u #0", ++ I2C_CLASS_DATA); + break; + } + if (err) + goto fail_ddc1; + if (ACCESS_FBINFO(devflags.dualhead)) { +- err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1"); ++ err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, ++ "DDC:fb%u #1", I2C_CLASS_DATA); + if (err == -ENODEV) { + printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n"); + } else if (err) + printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n"); + /* Register maven bus even on G450/G550 */ +- err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u"); ++ err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, ++ "MAVEN:fb%u", 0); + if (err) + printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n"); + } +--- linux-2.6.16.orig/drivers/video/nvidia/nv_i2c.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/video/nvidia/nv_i2c.c 2006-03-22 17:06:16.000000000 +0100 +@@ -96,6 +96,7 @@ + + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; ++ chan->adapter.class = I2C_CLASS_DATA; + chan->adapter.id = I2C_HW_B_NVIDIA; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->pci_dev->dev; +--- linux-2.6.16.orig/drivers/video/riva/rivafb-i2c.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/video/riva/rivafb-i2c.c 2006-03-22 17:06:16.000000000 +0100 +@@ -98,6 +98,7 @@ + + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; ++ chan->adapter.class = I2C_CLASS_DATA; + chan->adapter.id = I2C_HW_B_RIVA; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->pdev->dev; +--- linux-2.6.16.orig/drivers/video/savage/savagefb-i2c.c 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/video/savage/savagefb-i2c.c 2006-03-22 17:06:16.000000000 +0100 +@@ -145,6 +145,7 @@ + if (chan->par) { + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; ++ chan->adapter.class = I2C_CLASS_DATA; + chan->adapter.id = I2C_HW_B_SAVAGE; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->pcidev->dev; +--- linux-2.6.16.orig/drivers/media/video/zoran.h 2006-03-22 17:05:59.000000000 +0100 ++++ linux-2.6.16/drivers/media/video/zoran.h 2006-03-22 17:06:16.000000000 +0100 +@@ -355,6 +355,7 @@ + enum card_type type; + char name[32]; + u16 i2c_decoder, i2c_encoder; /* I2C types */ ++ u16 decoder_addr, encoder_addr; /* I2C chips address */ + u16 video_vfe, video_codec; /* videocodec types */ + u16 audio_chip; /* audio type */ + u16 vendor_id, device_id; /* subsystem vendor/device ID */ |