diff options
author | Frans Meulenbroeks <fransmeulenbroeks@gmail.com> | 2012-01-05 08:41:53 -0500 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2012-03-18 21:26:27 -0400 |
commit | 2faaa9316cc5556bb3d7d0d91720820434c317ba (patch) | |
tree | c4c39ddfcd6b59d058c91b46029c1fb755f98368 /drivers/hwmon/lm80.c | |
parent | c16fa4f2ad19908a47c63d8fa436a1178438c7e7 (diff) |
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>
Diffstat (limited to 'drivers/hwmon/lm80.c')
-rw-r--r-- | drivers/hwmon/lm80.c | 132 |
1 files changed, 101 insertions, 31 deletions
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 0891b38ffec0..616f470c38b3 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c | |||
@@ -170,6 +170,8 @@ static ssize_t show_in_##suffix(struct device *dev, \ | |||
170 | { \ | 170 | { \ |
171 | int nr = to_sensor_dev_attr(attr)->index; \ | 171 | int nr = to_sensor_dev_attr(attr)->index; \ |
172 | struct lm80_data *data = lm80_update_device(dev); \ | 172 | struct lm80_data *data = lm80_update_device(dev); \ |
173 | if (IS_ERR(data)) \ | ||
174 | return PTR_ERR(data); \ | ||
173 | return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ | 175 | return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ |
174 | } | 176 | } |
175 | show_in(min, in_min) | 177 | show_in(min, in_min) |
@@ -200,6 +202,8 @@ static ssize_t show_fan_##suffix(struct device *dev, \ | |||
200 | { \ | 202 | { \ |
201 | int nr = to_sensor_dev_attr(attr)->index; \ | 203 | int nr = to_sensor_dev_attr(attr)->index; \ |
202 | struct lm80_data *data = lm80_update_device(dev); \ | 204 | struct lm80_data *data = lm80_update_device(dev); \ |
205 | if (IS_ERR(data)) \ | ||
206 | return PTR_ERR(data); \ | ||
203 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ | 207 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ |
204 | DIV_FROM_REG(data->fan_div[nr]))); \ | 208 | DIV_FROM_REG(data->fan_div[nr]))); \ |
205 | } | 209 | } |
@@ -211,6 +215,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | |||
211 | { | 215 | { |
212 | int nr = to_sensor_dev_attr(attr)->index; | 216 | int nr = to_sensor_dev_attr(attr)->index; |
213 | struct lm80_data *data = lm80_update_device(dev); | 217 | struct lm80_data *data = lm80_update_device(dev); |
218 | if (IS_ERR(data)) | ||
219 | return PTR_ERR(data); | ||
214 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 220 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); |
215 | } | 221 | } |
216 | 222 | ||
@@ -283,6 +289,8 @@ static ssize_t show_temp_input1(struct device *dev, | |||
283 | struct device_attribute *attr, char *buf) | 289 | struct device_attribute *attr, char *buf) |
284 | { | 290 | { |
285 | struct lm80_data *data = lm80_update_device(dev); | 291 | struct lm80_data *data = lm80_update_device(dev); |
292 | if (IS_ERR(data)) | ||
293 | return PTR_ERR(data); | ||
286 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp)); | 294 | return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp)); |
287 | } | 295 | } |
288 | 296 | ||
@@ -291,6 +299,8 @@ static ssize_t show_temp_##suffix(struct device *dev, \ | |||
291 | struct device_attribute *attr, char *buf) \ | 299 | struct device_attribute *attr, char *buf) \ |
292 | { \ | 300 | { \ |
293 | struct lm80_data *data = lm80_update_device(dev); \ | 301 | struct lm80_data *data = lm80_update_device(dev); \ |
302 | if (IS_ERR(data)) \ | ||
303 | return PTR_ERR(data); \ | ||
294 | return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \ | 304 | return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \ |
295 | } | 305 | } |
296 | show_temp(hot_max, temp_hot_max); | 306 | show_temp(hot_max, temp_hot_max); |
@@ -321,6 +331,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, | |||
321 | char *buf) | 331 | char *buf) |
322 | { | 332 | { |
323 | struct lm80_data *data = lm80_update_device(dev); | 333 | struct lm80_data *data = lm80_update_device(dev); |
334 | if (IS_ERR(data)) | ||
335 | return PTR_ERR(data); | ||
324 | return sprintf(buf, "%u\n", data->alarms); | 336 | return sprintf(buf, "%u\n", data->alarms); |
325 | } | 337 | } |
326 | 338 | ||
@@ -329,6 +341,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | |||
329 | { | 341 | { |
330 | int bitnr = to_sensor_dev_attr(attr)->index; | 342 | int bitnr = to_sensor_dev_attr(attr)->index; |
331 | struct lm80_data *data = lm80_update_device(dev); | 343 | struct lm80_data *data = lm80_update_device(dev); |
344 | if (IS_ERR(data)) | ||
345 | return PTR_ERR(data); | ||
332 | return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); | 346 | return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); |
333 | } | 347 | } |
334 | 348 | ||
@@ -563,50 +577,106 @@ static struct lm80_data *lm80_update_device(struct device *dev) | |||
563 | struct i2c_client *client = to_i2c_client(dev); | 577 | struct i2c_client *client = to_i2c_client(dev); |
564 | struct lm80_data *data = i2c_get_clientdata(client); | 578 | struct lm80_data *data = i2c_get_clientdata(client); |
565 | int i; | 579 | int i; |
580 | int rv; | ||
581 | int prev_rv; | ||
582 | struct lm80_data *ret = data; | ||
566 | 583 | ||
567 | mutex_lock(&data->update_lock); | 584 | mutex_lock(&data->update_lock); |
568 | 585 | ||
569 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { | 586 | if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { |
570 | dev_dbg(&client->dev, "Starting lm80 update\n"); | 587 | dev_dbg(&client->dev, "Starting lm80 update\n"); |
571 | for (i = 0; i <= 6; i++) { | 588 | for (i = 0; i <= 6; i++) { |
572 | data->in[i] = | 589 | rv = lm80_read_value(client, LM80_REG_IN(i)); |
573 | lm80_read_value(client, LM80_REG_IN(i)); | 590 | if (rv < 0) |
574 | data->in_min[i] = | 591 | goto abort; |
575 | lm80_read_value(client, LM80_REG_IN_MIN(i)); | 592 | data->in[i] = rv; |
576 | data->in_max[i] = | 593 | |
577 | lm80_read_value(client, LM80_REG_IN_MAX(i)); | 594 | rv = lm80_read_value(client, LM80_REG_IN_MIN(i)); |
595 | if (rv < 0) | ||
596 | goto abort; | ||
597 | data->in_min[i] = rv; | ||
598 | |||
599 | rv = lm80_read_value(client, LM80_REG_IN_MAX(i)); | ||
600 | if (rv < 0) | ||
601 | goto abort; | ||
602 | data->in_max[i] = rv; | ||
578 | } | 603 | } |
579 | data->fan[0] = lm80_read_value(client, LM80_REG_FAN1); | 604 | |
580 | data->fan_min[0] = | 605 | rv = lm80_read_value(client, LM80_REG_FAN1); |
581 | lm80_read_value(client, LM80_REG_FAN_MIN(1)); | 606 | if (rv < 0) |
582 | data->fan[1] = lm80_read_value(client, LM80_REG_FAN2); | 607 | goto abort; |
583 | data->fan_min[1] = | 608 | data->fan[0] = rv; |
584 | lm80_read_value(client, LM80_REG_FAN_MIN(2)); | 609 | |
585 | 610 | rv = lm80_read_value(client, LM80_REG_FAN_MIN(1)); | |
586 | data->temp = | 611 | if (rv < 0) |
587 | (lm80_read_value(client, LM80_REG_TEMP) << 8) | | 612 | goto abort; |
588 | (lm80_read_value(client, LM80_REG_RES) & 0xf0); | 613 | data->fan_min[0] = rv; |
589 | data->temp_os_max = | 614 | |
590 | lm80_read_value(client, LM80_REG_TEMP_OS_MAX); | 615 | rv = lm80_read_value(client, LM80_REG_FAN2); |
591 | data->temp_os_hyst = | 616 | if (rv < 0) |
592 | lm80_read_value(client, LM80_REG_TEMP_OS_HYST); | 617 | goto abort; |
593 | data->temp_hot_max = | 618 | data->fan[1] = rv; |
594 | lm80_read_value(client, LM80_REG_TEMP_HOT_MAX); | 619 | |
595 | data->temp_hot_hyst = | 620 | rv = lm80_read_value(client, LM80_REG_FAN_MIN(2)); |
596 | lm80_read_value(client, LM80_REG_TEMP_HOT_HYST); | 621 | if (rv < 0) |
597 | 622 | goto abort; | |
598 | i = lm80_read_value(client, LM80_REG_FANDIV); | 623 | data->fan_min[1] = rv; |
599 | data->fan_div[0] = (i >> 2) & 0x03; | 624 | |
600 | data->fan_div[1] = (i >> 4) & 0x03; | 625 | prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP); |
601 | data->alarms = lm80_read_value(client, LM80_REG_ALARM1) + | 626 | if (rv < 0) |
602 | (lm80_read_value(client, LM80_REG_ALARM2) << 8); | 627 | goto abort; |
628 | rv = lm80_read_value(client, LM80_REG_RES); | ||
629 | if (rv < 0) | ||
630 | goto abort; | ||
631 | data->temp = (prev_rv << 8) | (rv & 0xf0); | ||
632 | |||
633 | rv = lm80_read_value(client, LM80_REG_TEMP_OS_MAX); | ||
634 | if (rv < 0) | ||
635 | goto abort; | ||
636 | data->temp_os_max = rv; | ||
637 | |||
638 | rv = lm80_read_value(client, LM80_REG_TEMP_OS_HYST); | ||
639 | if (rv < 0) | ||
640 | goto abort; | ||
641 | data->temp_os_hyst = rv; | ||
642 | |||
643 | rv = lm80_read_value(client, LM80_REG_TEMP_HOT_MAX); | ||
644 | if (rv < 0) | ||
645 | goto abort; | ||
646 | data->temp_hot_max = rv; | ||
647 | |||
648 | rv = lm80_read_value(client, LM80_REG_TEMP_HOT_HYST); | ||
649 | if (rv < 0) | ||
650 | goto abort; | ||
651 | data->temp_hot_hyst = rv; | ||
652 | |||
653 | rv = lm80_read_value(client, LM80_REG_FANDIV); | ||
654 | if (rv < 0) | ||
655 | goto abort; | ||
656 | data->fan_div[0] = (rv >> 2) & 0x03; | ||
657 | data->fan_div[1] = (rv >> 4) & 0x03; | ||
658 | |||
659 | prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1); | ||
660 | if (rv < 0) | ||
661 | goto abort; | ||
662 | rv = lm80_read_value(client, LM80_REG_ALARM2); | ||
663 | if (rv < 0) | ||
664 | goto abort; | ||
665 | data->alarms = prev_rv + (rv << 8); | ||
666 | |||
603 | data->last_updated = jiffies; | 667 | data->last_updated = jiffies; |
604 | data->valid = 1; | 668 | data->valid = 1; |
605 | } | 669 | } |
670 | goto done; | ||
671 | |||
672 | abort: | ||
673 | ret = ERR_PTR(rv); | ||
674 | data->valid = 0; | ||
606 | 675 | ||
676 | done: | ||
607 | mutex_unlock(&data->update_lock); | 677 | mutex_unlock(&data->update_lock); |
608 | 678 | ||
609 | return data; | 679 | return ret; |
610 | } | 680 | } |
611 | 681 | ||
612 | static int __init sensors_lm80_init(void) | 682 | static int __init sensors_lm80_init(void) |