summaryrefslogtreecommitdiff
path: root/packages/linux/ixp4xx-kernel/2.6.16/linux-2.6.16-i2c.patch
diff options
context:
space:
mode:
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.patch13671
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, &reg))) {
+- 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 */