mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
hwmon: (lm80) add error handling
The LM80 driver currently does not return errors after I2C access failures. Add it. Signed-off-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
This commit is contained in:
parent
c16fa4f2ad
commit
2faaa9316c
@ -170,6 +170,8 @@ static ssize_t show_in_##suffix(struct device *dev, \
|
|||||||
{ \
|
{ \
|
||||||
int nr = to_sensor_dev_attr(attr)->index; \
|
int nr = to_sensor_dev_attr(attr)->index; \
|
||||||
struct lm80_data *data = lm80_update_device(dev); \
|
struct lm80_data *data = lm80_update_device(dev); \
|
||||||
|
if (IS_ERR(data)) \
|
||||||
|
return PTR_ERR(data); \
|
||||||
return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \
|
return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \
|
||||||
}
|
}
|
||||||
show_in(min, in_min)
|
show_in(min, in_min)
|
||||||
@ -200,6 +202,8 @@ static ssize_t show_fan_##suffix(struct device *dev, \
|
|||||||
{ \
|
{ \
|
||||||
int nr = to_sensor_dev_attr(attr)->index; \
|
int nr = to_sensor_dev_attr(attr)->index; \
|
||||||
struct lm80_data *data = lm80_update_device(dev); \
|
struct lm80_data *data = lm80_update_device(dev); \
|
||||||
|
if (IS_ERR(data)) \
|
||||||
|
return PTR_ERR(data); \
|
||||||
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \
|
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \
|
||||||
DIV_FROM_REG(data->fan_div[nr]))); \
|
DIV_FROM_REG(data->fan_div[nr]))); \
|
||||||
}
|
}
|
||||||
@ -211,6 +215,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
|
|||||||
{
|
{
|
||||||
int nr = to_sensor_dev_attr(attr)->index;
|
int nr = to_sensor_dev_attr(attr)->index;
|
||||||
struct lm80_data *data = lm80_update_device(dev);
|
struct lm80_data *data = lm80_update_device(dev);
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
|
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,6 +289,8 @@ static ssize_t show_temp_input1(struct device *dev,
|
|||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct lm80_data *data = lm80_update_device(dev);
|
struct lm80_data *data = lm80_update_device(dev);
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
|
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,6 +299,8 @@ static ssize_t show_temp_##suffix(struct device *dev, \
|
|||||||
struct device_attribute *attr, char *buf) \
|
struct device_attribute *attr, char *buf) \
|
||||||
{ \
|
{ \
|
||||||
struct lm80_data *data = lm80_update_device(dev); \
|
struct lm80_data *data = lm80_update_device(dev); \
|
||||||
|
if (IS_ERR(data)) \
|
||||||
|
return PTR_ERR(data); \
|
||||||
return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
|
return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
|
||||||
}
|
}
|
||||||
show_temp(hot_max, temp_hot_max);
|
show_temp(hot_max, temp_hot_max);
|
||||||
@ -321,6 +331,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
|
|||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct lm80_data *data = lm80_update_device(dev);
|
struct lm80_data *data = lm80_update_device(dev);
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
return sprintf(buf, "%u\n", data->alarms);
|
return sprintf(buf, "%u\n", data->alarms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,6 +341,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
|
|||||||
{
|
{
|
||||||
int bitnr = to_sensor_dev_attr(attr)->index;
|
int bitnr = to_sensor_dev_attr(attr)->index;
|
||||||
struct lm80_data *data = lm80_update_device(dev);
|
struct lm80_data *data = lm80_update_device(dev);
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return PTR_ERR(data);
|
||||||
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
|
return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,50 +577,106 @@ static struct lm80_data *lm80_update_device(struct device *dev)
|
|||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct lm80_data *data = i2c_get_clientdata(client);
|
struct lm80_data *data = i2c_get_clientdata(client);
|
||||||
int i;
|
int i;
|
||||||
|
int rv;
|
||||||
|
int prev_rv;
|
||||||
|
struct lm80_data *ret = data;
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
|
if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
|
||||||
dev_dbg(&client->dev, "Starting lm80 update\n");
|
dev_dbg(&client->dev, "Starting lm80 update\n");
|
||||||
for (i = 0; i <= 6; i++) {
|
for (i = 0; i <= 6; i++) {
|
||||||
data->in[i] =
|
rv = lm80_read_value(client, LM80_REG_IN(i));
|
||||||
lm80_read_value(client, LM80_REG_IN(i));
|
if (rv < 0)
|
||||||
data->in_min[i] =
|
goto abort;
|
||||||
lm80_read_value(client, LM80_REG_IN_MIN(i));
|
data->in[i] = rv;
|
||||||
data->in_max[i] =
|
|
||||||
lm80_read_value(client, LM80_REG_IN_MAX(i));
|
rv = lm80_read_value(client, LM80_REG_IN_MIN(i));
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->in_min[i] = rv;
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_IN_MAX(i));
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->in_max[i] = rv;
|
||||||
}
|
}
|
||||||
data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
|
|
||||||
data->fan_min[0] =
|
|
||||||
lm80_read_value(client, LM80_REG_FAN_MIN(1));
|
|
||||||
data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
|
|
||||||
data->fan_min[1] =
|
|
||||||
lm80_read_value(client, LM80_REG_FAN_MIN(2));
|
|
||||||
|
|
||||||
data->temp =
|
rv = lm80_read_value(client, LM80_REG_FAN1);
|
||||||
(lm80_read_value(client, LM80_REG_TEMP) << 8) |
|
if (rv < 0)
|
||||||
(lm80_read_value(client, LM80_REG_RES) & 0xf0);
|
goto abort;
|
||||||
data->temp_os_max =
|
data->fan[0] = rv;
|
||||||
lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
|
|
||||||
data->temp_os_hyst =
|
rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
|
||||||
lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
|
if (rv < 0)
|
||||||
data->temp_hot_max =
|
goto abort;
|
||||||
lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
|
data->fan_min[0] = rv;
|
||||||
data->temp_hot_hyst =
|
|
||||||
lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
|
rv = lm80_read_value(client, LM80_REG_FAN2);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->fan[1] = rv;
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->fan_min[1] = rv;
|
||||||
|
|
||||||
|
prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
rv = lm80_read_value(client, LM80_REG_RES);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->temp = (prev_rv << 8) | (rv & 0xf0);
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->temp_os_max = rv;
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->temp_os_hyst = rv;
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->temp_hot_max = rv;
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->temp_hot_hyst = rv;
|
||||||
|
|
||||||
|
rv = lm80_read_value(client, LM80_REG_FANDIV);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->fan_div[0] = (rv >> 2) & 0x03;
|
||||||
|
data->fan_div[1] = (rv >> 4) & 0x03;
|
||||||
|
|
||||||
|
prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
rv = lm80_read_value(client, LM80_REG_ALARM2);
|
||||||
|
if (rv < 0)
|
||||||
|
goto abort;
|
||||||
|
data->alarms = prev_rv + (rv << 8);
|
||||||
|
|
||||||
i = lm80_read_value(client, LM80_REG_FANDIV);
|
|
||||||
data->fan_div[0] = (i >> 2) & 0x03;
|
|
||||||
data->fan_div[1] = (i >> 4) & 0x03;
|
|
||||||
data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
|
|
||||||
(lm80_read_value(client, LM80_REG_ALARM2) << 8);
|
|
||||||
data->last_updated = jiffies;
|
data->last_updated = jiffies;
|
||||||
data->valid = 1;
|
data->valid = 1;
|
||||||
}
|
}
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
abort:
|
||||||
|
ret = ERR_PTR(rv);
|
||||||
|
data->valid = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
mutex_unlock(&data->update_lock);
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
return data;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init sensors_lm80_init(void)
|
static int __init sensors_lm80_init(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user