OSDN Git Service

hwmon: (ad7418) Catch I2C errors
authorBrandon Maier <brandon.maier@rockwellcollins.com>
Thu, 7 Feb 2019 21:50:36 +0000 (15:50 -0600)
committerGuenter Roeck <linux@roeck-us.net>
Mon, 18 Feb 2019 22:23:29 +0000 (14:23 -0800)
If there is an i2c failure, the ad7416 reports its temperature as 0C.
Return an error code so users can properly detect errors.

Signed-off-by: Brandon Maier <brandon.maier@rockwellcollins.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/ad7418.c

index 76f0a5c..a20d5eb 100644 (file)
@@ -54,10 +54,11 @@ struct ad7418_data {
        u16                     in[4];
 };
 
-static struct ad7418_data *ad7418_update_device(struct device *dev)
+static int ad7418_update_device(struct device *dev)
 {
        struct ad7418_data *data = dev_get_drvdata(dev);
        struct i2c_client *client = data->client;
+       s32 val;
 
        mutex_lock(&data->lock);
 
@@ -67,47 +68,74 @@ static struct ad7418_data *ad7418_update_device(struct device *dev)
                int i, ch;
 
                /* read config register and clear channel bits */
-               cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+               val = i2c_smbus_read_byte_data(client, AD7418_REG_CONF);
+               if (val < 0)
+                       goto abort;
+
+               cfg = val;
                cfg &= 0x1F;
 
-               i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
+               val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
                                                cfg | AD7418_CH_TEMP);
+               if (val < 0)
+                       goto abort;
+
                udelay(30);
 
                for (i = 0; i < 3; i++) {
-                       data->temp[i] =
-                               i2c_smbus_read_word_swapped(client,
-                                               AD7418_REG_TEMP[i]);
+                       val = i2c_smbus_read_word_swapped(client,
+                                                         AD7418_REG_TEMP[i]);
+                       if (val < 0)
+                               goto abort;
+
+                       data->temp[i] = val;
                }
 
                for (i = 0, ch = 4; i < data->adc_max; i++, ch--) {
-                       i2c_smbus_write_byte_data(client,
-                                       AD7418_REG_CONF,
+                       val = i2c_smbus_write_byte_data(client, AD7418_REG_CONF,
                                        cfg | AD7418_REG_ADC_CH(ch));
+                       if (val < 0)
+                               goto abort;
 
                        udelay(15);
-                       data->in[data->adc_max - 1 - i] =
-                               i2c_smbus_read_word_swapped(client,
-                                               AD7418_REG_ADC);
+                       val = i2c_smbus_read_word_swapped(client,
+                                                         AD7418_REG_ADC);
+                       if (val < 0)
+                               goto abort;
+
+                       data->in[data->adc_max - 1 - i] = val;
                }
 
                /* restore old configuration value */
-               i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg);
+               val = i2c_smbus_write_word_swapped(client, AD7418_REG_CONF,
+                                                  cfg);
+               if (val < 0)
+                       goto abort;
 
                data->last_updated = jiffies;
                data->valid = 1;
        }
 
        mutex_unlock(&data->lock);
+       return 0;
 
-       return data;
+abort:
+       data->valid = 0;
+       mutex_unlock(&data->lock);
+       return val;
 }
 
 static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
                         char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       struct ad7418_data *data = ad7418_update_device(dev);
+       struct ad7418_data *data = dev_get_drvdata(dev);
+       int ret;
+
+       ret = ad7418_update_device(dev);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n",
                LM75_TEMP_FROM_REG(data->temp[attr->index]));
 }
@@ -116,7 +144,12 @@ static ssize_t adc_show(struct device *dev, struct device_attribute *devattr,
                        char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       struct ad7418_data *data = ad7418_update_device(dev);
+       struct ad7418_data *data = dev_get_drvdata(dev);
+       int ret;
+
+       ret = ad7418_update_device(dev);
+       if (ret < 0)
+               return ret;
 
        return sprintf(buf, "%d\n",
                ((data->in[attr->index] >> 6) * 2500 + 512) / 1024);