aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/fschmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/fschmd.c')
-rw-r--r--drivers/hwmon/fschmd.c450
1 files changed, 406 insertions, 44 deletions
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index 967170368933..d07f4ef75092 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -1,6 +1,6 @@
1/* fschmd.c 1/* fschmd.c
2 * 2 *
3 * Copyright (C) 2007 Hans de Goede <j.w.r.degoede@hhs.nl> 3 * Copyright (C) 2007,2008 Hans de Goede <hdegoede@redhat.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -42,11 +42,20 @@
42#include <linux/mutex.h> 42#include <linux/mutex.h>
43#include <linux/sysfs.h> 43#include <linux/sysfs.h>
44#include <linux/dmi.h> 44#include <linux/dmi.h>
45#include <linux/fs.h>
46#include <linux/watchdog.h>
47#include <linux/miscdevice.h>
48#include <linux/uaccess.h>
49#include <linux/kref.h>
45 50
46/* Addresses to scan */ 51/* Addresses to scan */
47static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; 52static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
48 53
49/* Insmod parameters */ 54/* Insmod parameters */
55static int nowayout = WATCHDOG_NOWAYOUT;
56module_param(nowayout, int, 0);
57MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
58 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
50I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); 59I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
51 60
52/* 61/*
@@ -63,19 +72,26 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
63#define FSCHMD_REG_EVENT_STATE 0x04 72#define FSCHMD_REG_EVENT_STATE 0x04
64#define FSCHMD_REG_CONTROL 0x05 73#define FSCHMD_REG_CONTROL 0x05
65 74
66#define FSCHMD_CONTROL_ALERT_LED_MASK 0x01 75#define FSCHMD_CONTROL_ALERT_LED 0x01
67 76
68/* watchdog (support to be implemented) */ 77/* watchdog */
69#define FSCHMD_REG_WDOG_PRESET 0x28 78#define FSCHMD_REG_WDOG_PRESET 0x28
70#define FSCHMD_REG_WDOG_STATE 0x23 79#define FSCHMD_REG_WDOG_STATE 0x23
71#define FSCHMD_REG_WDOG_CONTROL 0x21 80#define FSCHMD_REG_WDOG_CONTROL 0x21
72 81
82#define FSCHMD_WDOG_CONTROL_TRIGGER 0x10
83#define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */
84#define FSCHMD_WDOG_CONTROL_STOP 0x20
85#define FSCHMD_WDOG_CONTROL_RESOLUTION 0x40
86
87#define FSCHMD_WDOG_STATE_CARDRESET 0x02
88
73/* voltages, weird order is to keep the same order as the old drivers */ 89/* voltages, weird order is to keep the same order as the old drivers */
74static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; 90static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 };
75 91
76/* minimum pwm at which the fan is driven (pwm can by increased depending on 92/* minimum pwm at which the fan is driven (pwm can by increased depending on
77 the temp. Notice that for the scy some fans share there minimum speed. 93 the temp. Notice that for the scy some fans share there minimum speed.
78 Also notice that with the scy the sensor order is different then with the 94 Also notice that with the scy the sensor order is different than with the
79 other chips, this order was in the 2.4 driver and kept for consistency. */ 95 other chips, this order was in the 2.4 driver and kept for consistency. */
80static const u8 FSCHMD_REG_FAN_MIN[5][6] = { 96static const u8 FSCHMD_REG_FAN_MIN[5][6] = {
81 { 0x55, 0x65 }, /* pos */ 97 { 0x55, 0x65 }, /* pos */
@@ -115,8 +131,8 @@ static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = {
115static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; 131static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 };
116 132
117/* Fan status register bitmasks */ 133/* Fan status register bitmasks */
118#define FSCHMD_FAN_ALARM_MASK 0x04 /* called fault by FSC! */ 134#define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */
119#define FSCHMD_FAN_NOT_PRESENT_MASK 0x08 /* not documented */ 135#define FSCHMD_FAN_NOT_PRESENT 0x08 /* not documented */
120 136
121 137
122/* actual temperature registers */ 138/* actual temperature registers */
@@ -158,14 +174,11 @@ static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */
158static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; 174static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 };
159 175
160/* temp status register bitmasks */ 176/* temp status register bitmasks */
161#define FSCHMD_TEMP_WORKING_MASK 0x01 177#define FSCHMD_TEMP_WORKING 0x01
162#define FSCHMD_TEMP_ALERT_MASK 0x02 178#define FSCHMD_TEMP_ALERT 0x02
163/* there only really is an alarm if the sensor is working and alert == 1 */ 179/* there only really is an alarm if the sensor is working and alert == 1 */
164#define FSCHMD_TEMP_ALARM_MASK \ 180#define FSCHMD_TEMP_ALARM_MASK \
165 (FSCHMD_TEMP_WORKING_MASK | FSCHMD_TEMP_ALERT_MASK) 181 (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT)
166
167/* our driver name */
168#define FSCHMD_NAME "fschmd"
169 182
170/* 183/*
171 * Functions declarations 184 * Functions declarations
@@ -195,7 +208,7 @@ MODULE_DEVICE_TABLE(i2c, fschmd_id);
195static struct i2c_driver fschmd_driver = { 208static struct i2c_driver fschmd_driver = {
196 .class = I2C_CLASS_HWMON, 209 .class = I2C_CLASS_HWMON,
197 .driver = { 210 .driver = {
198 .name = FSCHMD_NAME, 211 .name = "fschmd",
199 }, 212 },
200 .probe = fschmd_probe, 213 .probe = fschmd_probe,
201 .remove = fschmd_remove, 214 .remove = fschmd_remove,
@@ -209,14 +222,26 @@ static struct i2c_driver fschmd_driver = {
209 */ 222 */
210 223
211struct fschmd_data { 224struct fschmd_data {
225 struct i2c_client *client;
212 struct device *hwmon_dev; 226 struct device *hwmon_dev;
213 struct mutex update_lock; 227 struct mutex update_lock;
228 struct mutex watchdog_lock;
229 struct list_head list; /* member of the watchdog_data_list */
230 struct kref kref;
231 struct miscdevice watchdog_miscdev;
214 int kind; 232 int kind;
233 unsigned long watchdog_is_open;
234 char watchdog_expect_close;
235 char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
215 char valid; /* zero until following fields are valid */ 236 char valid; /* zero until following fields are valid */
216 unsigned long last_updated; /* in jiffies */ 237 unsigned long last_updated; /* in jiffies */
217 238
218 /* register values */ 239 /* register values */
240 u8 revision; /* chip revision */
219 u8 global_control; /* global control register */ 241 u8 global_control; /* global control register */
242 u8 watchdog_control; /* watchdog control register */
243 u8 watchdog_state; /* watchdog status register */
244 u8 watchdog_preset; /* watchdog counter preset on trigger val */
220 u8 volt[3]; /* 12, 5, battery voltage */ 245 u8 volt[3]; /* 12, 5, battery voltage */
221 u8 temp_act[5]; /* temperature */ 246 u8 temp_act[5]; /* temperature */
222 u8 temp_status[5]; /* status of sensor */ 247 u8 temp_status[5]; /* status of sensor */
@@ -228,11 +253,28 @@ struct fschmd_data {
228}; 253};
229 254
230/* Global variables to hold information read from special DMI tables, which are 255/* Global variables to hold information read from special DMI tables, which are
231 available on FSC machines with an fscher or later chip. */ 256 available on FSC machines with an fscher or later chip. There is no need to
257 protect these with a lock as they are only modified from our attach function
258 which always gets called with the i2c-core lock held and never accessed
259 before the attach function is done with them. */
232static int dmi_mult[3] = { 490, 200, 100 }; 260static int dmi_mult[3] = { 490, 200, 100 };
233static int dmi_offset[3] = { 0, 0, 0 }; 261static int dmi_offset[3] = { 0, 0, 0 };
234static int dmi_vref = -1; 262static int dmi_vref = -1;
235 263
264/* Somewhat ugly :( global data pointer list with all fschmd devices, so that
265 we can find our device data as when using misc_register there is no other
266 method to get to ones device data from the open fop. */
267static LIST_HEAD(watchdog_data_list);
268/* Note this lock not only protect list access, but also data.kref access */
269static DEFINE_MUTEX(watchdog_data_mutex);
270
271/* Release our data struct when we're detached from the i2c client *and* all
272 references to our watchdog device are released */
273static void fschmd_release_resources(struct kref *ref)
274{
275 struct fschmd_data *data = container_of(ref, struct fschmd_data, kref);
276 kfree(data);
277}
236 278
237/* 279/*
238 * Sysfs attr show / store functions 280 * Sysfs attr show / store functions
@@ -300,7 +342,7 @@ static ssize_t show_temp_fault(struct device *dev,
300 struct fschmd_data *data = fschmd_update_device(dev); 342 struct fschmd_data *data = fschmd_update_device(dev);
301 343
302 /* bit 0 set means sensor working ok, so no fault! */ 344 /* bit 0 set means sensor working ok, so no fault! */
303 if (data->temp_status[index] & FSCHMD_TEMP_WORKING_MASK) 345 if (data->temp_status[index] & FSCHMD_TEMP_WORKING)
304 return sprintf(buf, "0\n"); 346 return sprintf(buf, "0\n");
305 else 347 else
306 return sprintf(buf, "1\n"); 348 return sprintf(buf, "1\n");
@@ -385,7 +427,7 @@ static ssize_t show_fan_alarm(struct device *dev,
385 int index = to_sensor_dev_attr(devattr)->index; 427 int index = to_sensor_dev_attr(devattr)->index;
386 struct fschmd_data *data = fschmd_update_device(dev); 428 struct fschmd_data *data = fschmd_update_device(dev);
387 429
388 if (data->fan_status[index] & FSCHMD_FAN_ALARM_MASK) 430 if (data->fan_status[index] & FSCHMD_FAN_ALARM)
389 return sprintf(buf, "1\n"); 431 return sprintf(buf, "1\n");
390 else 432 else
391 return sprintf(buf, "0\n"); 433 return sprintf(buf, "0\n");
@@ -397,7 +439,7 @@ static ssize_t show_fan_fault(struct device *dev,
397 int index = to_sensor_dev_attr(devattr)->index; 439 int index = to_sensor_dev_attr(devattr)->index;
398 struct fschmd_data *data = fschmd_update_device(dev); 440 struct fschmd_data *data = fschmd_update_device(dev);
399 441
400 if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT_MASK) 442 if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT)
401 return sprintf(buf, "1\n"); 443 return sprintf(buf, "1\n");
402 else 444 else
403 return sprintf(buf, "0\n"); 445 return sprintf(buf, "0\n");
@@ -449,7 +491,7 @@ static ssize_t show_alert_led(struct device *dev,
449{ 491{
450 struct fschmd_data *data = fschmd_update_device(dev); 492 struct fschmd_data *data = fschmd_update_device(dev);
451 493
452 if (data->global_control & FSCHMD_CONTROL_ALERT_LED_MASK) 494 if (data->global_control & FSCHMD_CONTROL_ALERT_LED)
453 return sprintf(buf, "1\n"); 495 return sprintf(buf, "1\n");
454 else 496 else
455 return sprintf(buf, "0\n"); 497 return sprintf(buf, "0\n");
@@ -467,9 +509,9 @@ static ssize_t store_alert_led(struct device *dev,
467 reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); 509 reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL);
468 510
469 if (v) 511 if (v)
470 reg |= FSCHMD_CONTROL_ALERT_LED_MASK; 512 reg |= FSCHMD_CONTROL_ALERT_LED;
471 else 513 else
472 reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; 514 reg &= ~FSCHMD_CONTROL_ALERT_LED;
473 515
474 i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); 516 i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg);
475 517
@@ -551,7 +593,265 @@ static struct sensor_device_attribute fschmd_fan_attr[] = {
551 593
552 594
553/* 595/*
554 * Real code 596 * Watchdog routines
597 */
598
599static int watchdog_set_timeout(struct fschmd_data *data, int timeout)
600{
601 int ret, resolution;
602 int kind = data->kind + 1; /* 0-x array index -> 1-x module param */
603
604 /* 2 second or 60 second resolution? */
605 if (timeout <= 510 || kind == fscpos || kind == fscscy)
606 resolution = 2;
607 else
608 resolution = 60;
609
610 if (timeout < resolution || timeout > (resolution * 255))
611 return -EINVAL;
612
613 mutex_lock(&data->watchdog_lock);
614 if (!data->client) {
615 ret = -ENODEV;
616 goto leave;
617 }
618
619 if (resolution == 2)
620 data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_RESOLUTION;
621 else
622 data->watchdog_control |= FSCHMD_WDOG_CONTROL_RESOLUTION;
623
624 data->watchdog_preset = DIV_ROUND_UP(timeout, resolution);
625
626 /* Write new timeout value */
627 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_PRESET,
628 data->watchdog_preset);
629 /* Write new control register, do not trigger! */
630 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL,
631 data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER);
632
633 ret = data->watchdog_preset * resolution;
634
635leave:
636 mutex_unlock(&data->watchdog_lock);
637 return ret;
638}
639
640static int watchdog_get_timeout(struct fschmd_data *data)
641{
642 int timeout;
643
644 mutex_lock(&data->watchdog_lock);
645 if (data->watchdog_control & FSCHMD_WDOG_CONTROL_RESOLUTION)
646 timeout = data->watchdog_preset * 60;
647 else
648 timeout = data->watchdog_preset * 2;
649 mutex_unlock(&data->watchdog_lock);
650
651 return timeout;
652}
653
654static int watchdog_trigger(struct fschmd_data *data)
655{
656 int ret = 0;
657
658 mutex_lock(&data->watchdog_lock);
659 if (!data->client) {
660 ret = -ENODEV;
661 goto leave;
662 }
663
664 data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER;
665 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL,
666 data->watchdog_control);
667leave:
668 mutex_unlock(&data->watchdog_lock);
669 return ret;
670}
671
672static int watchdog_stop(struct fschmd_data *data)
673{
674 int ret = 0;
675
676 mutex_lock(&data->watchdog_lock);
677 if (!data->client) {
678 ret = -ENODEV;
679 goto leave;
680 }
681
682 data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED;
683 /* Don't store the stop flag in our watchdog control register copy, as
684 its a write only bit (read always returns 0) */
685 i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL,
686 data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP);
687leave:
688 mutex_unlock(&data->watchdog_lock);
689 return ret;
690}
691
692static int watchdog_open(struct inode *inode, struct file *filp)
693{
694 struct fschmd_data *pos, *data = NULL;
695
696 /* We get called from drivers/char/misc.c with misc_mtx hold, and we
697 call misc_register() from fschmd_probe() with watchdog_data_mutex
698 hold, as misc_register() takes the misc_mtx lock, this is a possible
699 deadlock, so we use mutex_trylock here. */
700 if (!mutex_trylock(&watchdog_data_mutex))
701 return -ERESTARTSYS;
702 list_for_each_entry(pos, &watchdog_data_list, list) {
703 if (pos->watchdog_miscdev.minor == iminor(inode)) {
704 data = pos;
705 break;
706 }
707 }
708 /* Note we can never not have found data, so we don't check for this */
709 kref_get(&data->kref);
710 mutex_unlock(&watchdog_data_mutex);
711
712 if (test_and_set_bit(0, &data->watchdog_is_open))
713 return -EBUSY;
714
715 /* Start the watchdog */
716 watchdog_trigger(data);
717 filp->private_data = data;
718
719 return nonseekable_open(inode, filp);
720}
721
722static int watchdog_release(struct inode *inode, struct file *filp)
723{
724 struct fschmd_data *data = filp->private_data;
725
726 if (data->watchdog_expect_close) {
727 watchdog_stop(data);
728 data->watchdog_expect_close = 0;
729 } else {
730 watchdog_trigger(data);
731 dev_crit(&data->client->dev,
732 "unexpected close, not stopping watchdog!\n");
733 }
734
735 clear_bit(0, &data->watchdog_is_open);
736
737 mutex_lock(&watchdog_data_mutex);
738 kref_put(&data->kref, fschmd_release_resources);
739 mutex_unlock(&watchdog_data_mutex);
740
741 return 0;
742}
743
744static ssize_t watchdog_write(struct file *filp, const char __user *buf,
745 size_t count, loff_t *offset)
746{
747 size_t ret;
748 struct fschmd_data *data = filp->private_data;
749
750 if (count) {
751 if (!nowayout) {
752 size_t i;
753
754 /* Clear it in case it was set with a previous write */
755 data->watchdog_expect_close = 0;
756
757 for (i = 0; i != count; i++) {
758 char c;
759 if (get_user(c, buf + i))
760 return -EFAULT;
761 if (c == 'V')
762 data->watchdog_expect_close = 1;
763 }
764 }
765 ret = watchdog_trigger(data);
766 if (ret < 0)
767 return ret;
768 }
769 return count;
770}
771
772static int watchdog_ioctl(struct inode *inode, struct file *filp,
773 unsigned int cmd, unsigned long arg)
774{
775 static struct watchdog_info ident = {
776 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
777 WDIOF_CARDRESET,
778 .identity = "FSC watchdog"
779 };
780 int i, ret = 0;
781 struct fschmd_data *data = filp->private_data;
782
783 switch (cmd) {
784 case WDIOC_GETSUPPORT:
785 ident.firmware_version = data->revision;
786 if (!nowayout)
787 ident.options |= WDIOF_MAGICCLOSE;
788 if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
789 ret = -EFAULT;
790 break;
791
792 case WDIOC_GETSTATUS:
793 ret = put_user(0, (int __user *)arg);
794 break;
795
796 case WDIOC_GETBOOTSTATUS:
797 if (data->watchdog_state & FSCHMD_WDOG_STATE_CARDRESET)
798 ret = put_user(WDIOF_CARDRESET, (int __user *)arg);
799 else
800 ret = put_user(0, (int __user *)arg);
801 break;
802
803 case WDIOC_KEEPALIVE:
804 ret = watchdog_trigger(data);
805 break;
806
807 case WDIOC_GETTIMEOUT:
808 i = watchdog_get_timeout(data);
809 ret = put_user(i, (int __user *)arg);
810 break;
811
812 case WDIOC_SETTIMEOUT:
813 if (get_user(i, (int __user *)arg)) {
814 ret = -EFAULT;
815 break;
816 }
817 ret = watchdog_set_timeout(data, i);
818 if (ret > 0)
819 ret = put_user(ret, (int __user *)arg);
820 break;
821
822 case WDIOC_SETOPTIONS:
823 if (get_user(i, (int __user *)arg)) {
824 ret = -EFAULT;
825 break;
826 }
827
828 if (i & WDIOS_DISABLECARD)
829 ret = watchdog_stop(data);
830 else if (i & WDIOS_ENABLECARD)
831 ret = watchdog_trigger(data);
832 else
833 ret = -EINVAL;
834
835 break;
836 default:
837 ret = -ENOTTY;
838 }
839
840 return ret;
841}
842
843static struct file_operations watchdog_fops = {
844 .owner = THIS_MODULE,
845 .llseek = no_llseek,
846 .open = watchdog_open,
847 .release = watchdog_release,
848 .write = watchdog_write,
849 .ioctl = watchdog_ioctl,
850};
851
852
853/*
854 * Detect, register, unregister and update device functions
555 */ 855 */
556 856
557/* DMI decode routine to read voltage scaling factors from special DMI tables, 857/* DMI decode routine to read voltage scaling factors from special DMI tables,
@@ -661,9 +961,9 @@ static int fschmd_probe(struct i2c_client *client,
661 const struct i2c_device_id *id) 961 const struct i2c_device_id *id)
662{ 962{
663 struct fschmd_data *data; 963 struct fschmd_data *data;
664 u8 revision;
665 const char * const names[5] = { "Poseidon", "Hermes", "Scylla", 964 const char * const names[5] = { "Poseidon", "Hermes", "Scylla",
666 "Heracles", "Heimdall" }; 965 "Heracles", "Heimdall" };
966 const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
667 int i, err; 967 int i, err;
668 enum chips kind = id->driver_data; 968 enum chips kind = id->driver_data;
669 969
@@ -673,6 +973,13 @@ static int fschmd_probe(struct i2c_client *client,
673 973
674 i2c_set_clientdata(client, data); 974 i2c_set_clientdata(client, data);
675 mutex_init(&data->update_lock); 975 mutex_init(&data->update_lock);
976 mutex_init(&data->watchdog_lock);
977 INIT_LIST_HEAD(&data->list);
978 kref_init(&data->kref);
979 /* Store client pointer in our data struct for watchdog usage
980 (where the client is found through a data ptr instead of the
981 otherway around) */
982 data->client = client;
676 983
677 if (kind == fscpos) { 984 if (kind == fscpos) {
678 /* The Poseidon has hardwired temp limits, fill these 985 /* The Poseidon has hardwired temp limits, fill these
@@ -683,16 +990,27 @@ static int fschmd_probe(struct i2c_client *client,
683 } 990 }
684 991
685 /* Read the special DMI table for fscher and newer chips */ 992 /* Read the special DMI table for fscher and newer chips */
686 if (kind == fscher || kind >= fschrc) { 993 if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) {
687 dmi_walk(fschmd_dmi_decode); 994 dmi_walk(fschmd_dmi_decode);
688 if (dmi_vref == -1) { 995 if (dmi_vref == -1) {
689 printk(KERN_WARNING FSCHMD_NAME 996 dev_warn(&client->dev,
690 ": Couldn't get voltage scaling factors from " 997 "Couldn't get voltage scaling factors from "
691 "BIOS DMI table, using builtin defaults\n"); 998 "BIOS DMI table, using builtin defaults\n");
692 dmi_vref = 33; 999 dmi_vref = 33;
693 } 1000 }
694 } 1001 }
695 1002
1003 /* Read in some never changing registers */
1004 data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
1005 data->global_control = i2c_smbus_read_byte_data(client,
1006 FSCHMD_REG_CONTROL);
1007 data->watchdog_control = i2c_smbus_read_byte_data(client,
1008 FSCHMD_REG_WDOG_CONTROL);
1009 data->watchdog_state = i2c_smbus_read_byte_data(client,
1010 FSCHMD_REG_WDOG_STATE);
1011 data->watchdog_preset = i2c_smbus_read_byte_data(client,
1012 FSCHMD_REG_WDOG_PRESET);
1013
696 /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ 1014 /* i2c kind goes from 1-5, we want from 0-4 to address arrays */
697 data->kind = kind - 1; 1015 data->kind = kind - 1;
698 1016
@@ -735,9 +1053,43 @@ static int fschmd_probe(struct i2c_client *client,
735 goto exit_detach; 1053 goto exit_detach;
736 } 1054 }
737 1055
738 revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); 1056 /* We take the data_mutex lock early so that watchdog_open() cannot
739 printk(KERN_INFO FSCHMD_NAME ": Detected FSC %s chip, revision: %d\n", 1057 run when misc_register() has completed, but we've not yet added
740 names[data->kind], (int) revision); 1058 our data to the watchdog_data_list (and set the default timeout) */
1059 mutex_lock(&watchdog_data_mutex);
1060 for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) {
1061 /* Register our watchdog part */
1062 snprintf(data->watchdog_name, sizeof(data->watchdog_name),
1063 "watchdog%c", (i == 0) ? '\0' : ('0' + i));
1064 data->watchdog_miscdev.name = data->watchdog_name;
1065 data->watchdog_miscdev.fops = &watchdog_fops;
1066 data->watchdog_miscdev.minor = watchdog_minors[i];
1067 err = misc_register(&data->watchdog_miscdev);
1068 if (err == -EBUSY)
1069 continue;
1070 if (err) {
1071 data->watchdog_miscdev.minor = 0;
1072 dev_err(&client->dev,
1073 "Registering watchdog chardev: %d\n", err);
1074 break;
1075 }
1076
1077 list_add(&data->list, &watchdog_data_list);
1078 watchdog_set_timeout(data, 60);
1079 dev_info(&client->dev,
1080 "Registered watchdog chardev major 10, minor: %d\n",
1081 watchdog_minors[i]);
1082 break;
1083 }
1084 if (i == ARRAY_SIZE(watchdog_minors)) {
1085 data->watchdog_miscdev.minor = 0;
1086 dev_warn(&client->dev, "Couldn't register watchdog chardev "
1087 "(due to no free minor)\n");
1088 }
1089 mutex_unlock(&watchdog_data_mutex);
1090
1091 dev_info(&client->dev, "Detected FSC %s chip, revision: %d\n",
1092 names[data->kind], (int) data->revision);
741 1093
742 return 0; 1094 return 0;
743 1095
@@ -751,6 +1103,24 @@ static int fschmd_remove(struct i2c_client *client)
751 struct fschmd_data *data = i2c_get_clientdata(client); 1103 struct fschmd_data *data = i2c_get_clientdata(client);
752 int i; 1104 int i;
753 1105
1106 /* Unregister the watchdog (if registered) */
1107 if (data->watchdog_miscdev.minor) {
1108 misc_deregister(&data->watchdog_miscdev);
1109 if (data->watchdog_is_open) {
1110 dev_warn(&client->dev,
1111 "i2c client detached with watchdog open! "
1112 "Stopping watchdog.\n");
1113 watchdog_stop(data);
1114 }
1115 mutex_lock(&watchdog_data_mutex);
1116 list_del(&data->list);
1117 mutex_unlock(&watchdog_data_mutex);
1118 /* Tell the watchdog code the client is gone */
1119 mutex_lock(&data->watchdog_lock);
1120 data->client = NULL;
1121 mutex_unlock(&data->watchdog_lock);
1122 }
1123
754 /* Check if registered in case we're called from fschmd_detect 1124 /* Check if registered in case we're called from fschmd_detect
755 to cleanup after an error */ 1125 to cleanup after an error */
756 if (data->hwmon_dev) 1126 if (data->hwmon_dev)
@@ -765,7 +1135,10 @@ static int fschmd_remove(struct i2c_client *client)
765 device_remove_file(&client->dev, 1135 device_remove_file(&client->dev,
766 &fschmd_fan_attr[i].dev_attr); 1136 &fschmd_fan_attr[i].dev_attr);
767 1137
768 kfree(data); 1138 mutex_lock(&watchdog_data_mutex);
1139 kref_put(&data->kref, fschmd_release_resources);
1140 mutex_unlock(&watchdog_data_mutex);
1141
769 return 0; 1142 return 0;
770} 1143}
771 1144
@@ -798,7 +1171,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
798 data->temp_act[i] < data->temp_max[i]) 1171 data->temp_act[i] < data->temp_max[i])
799 i2c_smbus_write_byte_data(client, 1172 i2c_smbus_write_byte_data(client,
800 FSCHMD_REG_TEMP_STATE[data->kind][i], 1173 FSCHMD_REG_TEMP_STATE[data->kind][i],
801 FSCHMD_TEMP_ALERT_MASK); 1174 FSCHMD_TEMP_ALERT);
802 } 1175 }
803 1176
804 for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { 1177 for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) {
@@ -816,28 +1189,17 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
816 FSCHMD_REG_FAN_MIN[data->kind][i]); 1189 FSCHMD_REG_FAN_MIN[data->kind][i]);
817 1190
818 /* reset fan status if speed is back to > 0 */ 1191 /* reset fan status if speed is back to > 0 */
819 if ((data->fan_status[i] & FSCHMD_FAN_ALARM_MASK) && 1192 if ((data->fan_status[i] & FSCHMD_FAN_ALARM) &&
820 data->fan_act[i]) 1193 data->fan_act[i])
821 i2c_smbus_write_byte_data(client, 1194 i2c_smbus_write_byte_data(client,
822 FSCHMD_REG_FAN_STATE[data->kind][i], 1195 FSCHMD_REG_FAN_STATE[data->kind][i],
823 FSCHMD_FAN_ALARM_MASK); 1196 FSCHMD_FAN_ALARM);
824 } 1197 }
825 1198
826 for (i = 0; i < 3; i++) 1199 for (i = 0; i < 3; i++)
827 data->volt[i] = i2c_smbus_read_byte_data(client, 1200 data->volt[i] = i2c_smbus_read_byte_data(client,
828 FSCHMD_REG_VOLT[i]); 1201 FSCHMD_REG_VOLT[i]);
829 1202
830 data->global_control = i2c_smbus_read_byte_data(client,
831 FSCHMD_REG_CONTROL);
832
833 /* To be implemented in the future
834 data->watchdog[0] = i2c_smbus_read_byte_data(client,
835 FSCHMD_REG_WDOG_PRESET);
836 data->watchdog[1] = i2c_smbus_read_byte_data(client,
837 FSCHMD_REG_WDOG_STATE);
838 data->watchdog[2] = i2c_smbus_read_byte_data(client,
839 FSCHMD_REG_WDOG_CONTROL); */
840
841 data->last_updated = jiffies; 1203 data->last_updated = jiffies;
842 data->valid = 1; 1204 data->valid = 1;
843 } 1205 }
@@ -857,7 +1219,7 @@ static void __exit fschmd_exit(void)
857 i2c_del_driver(&fschmd_driver); 1219 i2c_del_driver(&fschmd_driver);
858} 1220}
859 1221
860MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); 1222MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
861MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " 1223MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and "
862 "Heimdall driver"); 1224 "Heimdall driver");
863MODULE_LICENSE("GPL"); 1225MODULE_LICENSE("GPL");