hwmon: (adt7411) Improve locking
authorWolfram Sang <w.sang@pengutronix.de>
Fri, 5 Mar 2010 21:17:23 +0000 (22:17 +0100)
committerJean Delvare <khali@linux-fr.org>
Fri, 5 Mar 2010 21:17:23 +0000 (22:17 +0100)
Add proper locking for the cached variables. Also get rid of
ref_is_vdd, which became obsolete.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
drivers/hwmon/adt7411.c

index 9e9246f..3471884 100644 (file)
@@ -48,9 +48,9 @@ static const unsigned short normal_i2c[] = { 0x48, 0x4a, 0x4b, I2C_CLIENT_END };
 
 struct adt7411_data {
        struct mutex device_lock;       /* for "atomic" device accesses */
+       struct mutex update_lock;
        unsigned long next_update;
        int vref_cached;
-       bool ref_is_vdd;
        struct device *hwmon_dev;
 };
 
@@ -142,18 +142,18 @@ static ssize_t adt7411_show_input(struct device *dev,
        int val;
        u8 lsb_reg, lsb_shift;
 
+       mutex_lock(&data->update_lock);
        if (time_after_eq(jiffies, data->next_update)) {
                val = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3);
                if (val < 0)
-                       return val;
-               data->ref_is_vdd = val & ADT7411_CFG3_REF_VDD;
+                       goto exit_unlock;
 
-               if (data->ref_is_vdd) {
+               if (val & ADT7411_CFG3_REF_VDD) {
                        val = adt7411_read_10_bit(client,
                                        ADT7411_REG_INT_TEMP_VDD_LSB,
                                        ADT7411_REG_VDD_MSB, 2);
                        if (val < 0)
-                               return val;
+                               goto exit_unlock;
 
                        data->vref_cached = val * 7000 / 1024;
                } else {
@@ -167,9 +167,13 @@ static ssize_t adt7411_show_input(struct device *dev,
        lsb_shift = 2 * (nr & 0x03);
        val = adt7411_read_10_bit(client, lsb_reg,
                        ADT7411_REG_EXT_TEMP_AIN1_MSB + nr, lsb_shift);
+       if (val < 0)
+               goto exit_unlock;
 
-       return val < 0 ? val :
-                       sprintf(buf, "%u\n", val * data->vref_cached / 1024);
+       val = sprintf(buf, "%u\n", val * data->vref_cached / 1024);
+ exit_unlock:
+       mutex_unlock(&data->update_lock);
+       return val;
 }
 
 static ssize_t adt7411_show_bit(struct device *dev,
@@ -199,7 +203,9 @@ static ssize_t adt7411_set_bit(struct device *dev,
        ret = adt7411_modify_bit(client, s_attr2->index, s_attr2->nr, flag);
 
        /* force update */
+       mutex_lock(&data->update_lock);
        data->next_update = jiffies;
+       mutex_unlock(&data->update_lock);
 
        return ret < 0 ? ret : count;
 }
@@ -282,6 +288,7 @@ static int __devinit adt7411_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, data);
        mutex_init(&data->device_lock);
+       mutex_init(&data->update_lock);
 
        ret = adt7411_modify_bit(client, ADT7411_REG_CFG1,
                                 ADT7411_CFG1_START_MONITOR, 1);