aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt43
-rw-r--r--Documentation/watchdog/watchdog-parameters.txt5
-rw-r--r--drivers/hwmon/Kconfig6
-rw-r--r--drivers/hwmon/sch5627.c2
-rw-r--r--drivers/hwmon/sch5636.c2
-rw-r--r--drivers/hwmon/sch56xx-common.c406
-rw-r--r--drivers/hwmon/sch56xx-common.h2
-rw-r--r--drivers/watchdog/Kconfig13
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/da9052_wdt.c251
-rw-r--r--drivers/watchdog/iTCO_wdt.c6
-rw-r--r--drivers/watchdog/sp805_wdt.c249
-rw-r--r--drivers/watchdog/via_wdt.c2
-rw-r--r--drivers/watchdog/watchdog_core.c74
-rw-r--r--drivers/watchdog/watchdog_core.h (renamed from drivers/watchdog/watchdog_dev.h)8
-rw-r--r--drivers/watchdog/watchdog_dev.c375
-rw-r--r--include/linux/watchdog.h28
17 files changed, 891 insertions, 582 deletions
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
index 25fe4304f2fc..086638f6c82d 100644
--- a/Documentation/watchdog/watchdog-kernel-api.txt
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -1,6 +1,6 @@
1The Linux WatchDog Timer Driver Core kernel API. 1The Linux WatchDog Timer Driver Core kernel API.
2=============================================== 2===============================================
3Last reviewed: 16-Mar-2012 3Last reviewed: 22-May-2012
4 4
5Wim Van Sebroeck <wim@iguana.be> 5Wim Van Sebroeck <wim@iguana.be>
6 6
@@ -39,6 +39,10 @@ watchdog_device structure.
39The watchdog device structure looks like this: 39The watchdog device structure looks like this:
40 40
41struct watchdog_device { 41struct watchdog_device {
42 int id;
43 struct cdev cdev;
44 struct device *dev;
45 struct device *parent;
42 const struct watchdog_info *info; 46 const struct watchdog_info *info;
43 const struct watchdog_ops *ops; 47 const struct watchdog_ops *ops;
44 unsigned int bootstatus; 48 unsigned int bootstatus;
@@ -46,10 +50,20 @@ struct watchdog_device {
46 unsigned int min_timeout; 50 unsigned int min_timeout;
47 unsigned int max_timeout; 51 unsigned int max_timeout;
48 void *driver_data; 52 void *driver_data;
53 struct mutex lock;
49 unsigned long status; 54 unsigned long status;
50}; 55};
51 56
52It contains following fields: 57It contains following fields:
58* id: set by watchdog_register_device, id 0 is special. It has both a
59 /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old
60 /dev/watchdog miscdev. The id is set automatically when calling
61 watchdog_register_device.
62* cdev: cdev for the dynamic /dev/watchdog<id> device nodes. This
63 field is also populated by watchdog_register_device.
64* dev: device under the watchdog class (created by watchdog_register_device).
65* parent: set this to the parent device (or NULL) before calling
66 watchdog_register_device.
53* info: a pointer to a watchdog_info structure. This structure gives some 67* info: a pointer to a watchdog_info structure. This structure gives some
54 additional information about the watchdog timer itself. (Like it's unique name) 68 additional information about the watchdog timer itself. (Like it's unique name)
55* ops: a pointer to the list of watchdog operations that the watchdog supports. 69* ops: a pointer to the list of watchdog operations that the watchdog supports.
@@ -61,6 +75,7 @@ It contains following fields:
61* driver_data: a pointer to the drivers private data of a watchdog device. 75* driver_data: a pointer to the drivers private data of a watchdog device.
62 This data should only be accessed via the watchdog_set_drvdata and 76 This data should only be accessed via the watchdog_set_drvdata and
63 watchdog_get_drvdata routines. 77 watchdog_get_drvdata routines.
78* lock: Mutex for WatchDog Timer Driver Core internal use only.
64* status: this field contains a number of status bits that give extra 79* status: this field contains a number of status bits that give extra
65 information about the status of the device (Like: is the watchdog timer 80 information about the status of the device (Like: is the watchdog timer
66 running/active, is the nowayout bit set, is the device opened via 81 running/active, is the nowayout bit set, is the device opened via
@@ -78,6 +93,8 @@ struct watchdog_ops {
78 unsigned int (*status)(struct watchdog_device *); 93 unsigned int (*status)(struct watchdog_device *);
79 int (*set_timeout)(struct watchdog_device *, unsigned int); 94 int (*set_timeout)(struct watchdog_device *, unsigned int);
80 unsigned int (*get_timeleft)(struct watchdog_device *); 95 unsigned int (*get_timeleft)(struct watchdog_device *);
96 void (*ref)(struct watchdog_device *);
97 void (*unref)(struct watchdog_device *);
81 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); 98 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
82}; 99};
83 100
@@ -85,6 +102,21 @@ It is important that you first define the module owner of the watchdog timer
85driver's operations. This module owner will be used to lock the module when 102driver's operations. This module owner will be used to lock the module when
86the watchdog is active. (This to avoid a system crash when you unload the 103the watchdog is active. (This to avoid a system crash when you unload the
87module and /dev/watchdog is still open). 104module and /dev/watchdog is still open).
105
106If the watchdog_device struct is dynamically allocated, just locking the module
107is not enough and a driver also needs to define the ref and unref operations to
108ensure the structure holding the watchdog_device does not go away.
109
110The simplest (and usually sufficient) implementation of this is to:
1111) Add a kref struct to the same structure which is holding the watchdog_device
1122) Define a release callback for the kref which frees the struct holding both
1133) Call kref_init on this kref *before* calling watchdog_register_device()
1144) Define a ref operation calling kref_get on this kref
1155) Define a unref operation calling kref_put on this kref
1166) When it is time to cleanup:
117 * Do not kfree() the struct holding both, the last kref_put will do this!
118 * *After* calling watchdog_unregister_device() call kref_put on the kref
119
88Some operations are mandatory and some are optional. The mandatory operations 120Some operations are mandatory and some are optional. The mandatory operations
89are: 121are:
90* start: this is a pointer to the routine that starts the watchdog timer 122* start: this is a pointer to the routine that starts the watchdog timer
@@ -125,6 +157,10 @@ they are supported. These optional routines/operations are:
125 (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the 157 (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
126 watchdog's info structure). 158 watchdog's info structure).
127* get_timeleft: this routines returns the time that's left before a reset. 159* get_timeleft: this routines returns the time that's left before a reset.
160* ref: the operation that calls kref_get on the kref of a dynamically
161 allocated watchdog_device struct.
162* unref: the operation that calls kref_put on the kref of a dynamically
163 allocated watchdog_device struct.
128* ioctl: if this routine is present then it will be called first before we do 164* ioctl: if this routine is present then it will be called first before we do
129 our own internal ioctl call handling. This routine should return -ENOIOCTLCMD 165 our own internal ioctl call handling. This routine should return -ENOIOCTLCMD
130 if a command is not supported. The parameters that are passed to the ioctl 166 if a command is not supported. The parameters that are passed to the ioctl
@@ -144,6 +180,11 @@ bit-operations. The status bits that are defined are:
144 (This bit should only be used by the WatchDog Timer Driver Core). 180 (This bit should only be used by the WatchDog Timer Driver Core).
145* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. 181* WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog.
146 If this bit is set then the watchdog timer will not be able to stop. 182 If this bit is set then the watchdog timer will not be able to stop.
183* WDOG_UNREGISTERED: this bit gets set by the WatchDog Timer Driver Core
184 after calling watchdog_unregister_device, and then checked before calling
185 any watchdog_ops, so that you can be sure that no operations (other then
186 unref) will get called after unregister, even if userspace still holds a
187 reference to /dev/watchdog
147 188
148 To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog 189 To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog
149 timer device) you can either: 190 timer device) you can either:
diff --git a/Documentation/watchdog/watchdog-parameters.txt b/Documentation/watchdog/watchdog-parameters.txt
index 17ddd822b456..04fddbacdbde 100644
--- a/Documentation/watchdog/watchdog-parameters.txt
+++ b/Documentation/watchdog/watchdog-parameters.txt
@@ -78,6 +78,11 @@ wd0_timeout: Default watchdog0 timeout in 1/10secs
78wd1_timeout: Default watchdog1 timeout in 1/10secs 78wd1_timeout: Default watchdog1 timeout in 1/10secs
79wd2_timeout: Default watchdog2 timeout in 1/10secs 79wd2_timeout: Default watchdog2 timeout in 1/10secs
80------------------------------------------------- 80-------------------------------------------------
81da9052wdt:
82timeout: Watchdog timeout in seconds. 2<= timeout <=131, default=2.048s
83nowayout: Watchdog cannot be stopped once started
84 (default=kernel config parameter)
85-------------------------------------------------
81davinci_wdt: 86davinci_wdt:
82heartbeat: Watchdog heartbeat period in seconds from 1 to 600, default 60 87heartbeat: Watchdog heartbeat period in seconds from 1 to 600, default 60
83------------------------------------------------- 88-------------------------------------------------
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 7cd9bf42108b..6f1d167cb1ea 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1036,8 +1036,9 @@ config SENSORS_SCH56XX_COMMON
1036 1036
1037config SENSORS_SCH5627 1037config SENSORS_SCH5627
1038 tristate "SMSC SCH5627" 1038 tristate "SMSC SCH5627"
1039 depends on !PPC 1039 depends on !PPC && WATCHDOG
1040 select SENSORS_SCH56XX_COMMON 1040 select SENSORS_SCH56XX_COMMON
1041 select WATCHDOG_CORE
1041 help 1042 help
1042 If you say yes here you get support for the hardware monitoring 1043 If you say yes here you get support for the hardware monitoring
1043 features of the SMSC SCH5627 Super-I/O chip including support for 1044 features of the SMSC SCH5627 Super-I/O chip including support for
@@ -1048,8 +1049,9 @@ config SENSORS_SCH5627
1048 1049
1049config SENSORS_SCH5636 1050config SENSORS_SCH5636
1050 tristate "SMSC SCH5636" 1051 tristate "SMSC SCH5636"
1051 depends on !PPC 1052 depends on !PPC && WATCHDOG
1052 select SENSORS_SCH56XX_COMMON 1053 select SENSORS_SCH56XX_COMMON
1054 select WATCHDOG_CORE
1053 help 1055 help
1054 SMSC SCH5636 Super I/O chips include an embedded microcontroller for 1056 SMSC SCH5636 Super I/O chips include an embedded microcontroller for
1055 hardware monitoring solutions, allowing motherboard manufacturers to 1057 hardware monitoring solutions, allowing motherboard manufacturers to
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 8ec6dfbccb64..8342275378b8 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -579,7 +579,7 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
579 } 579 }
580 580
581 /* Note failing to register the watchdog is not a fatal error */ 581 /* Note failing to register the watchdog is not a fatal error */
582 data->watchdog = sch56xx_watchdog_register(data->addr, 582 data->watchdog = sch56xx_watchdog_register(&pdev->dev, data->addr,
583 (build_code << 24) | (build_id << 8) | hwmon_rev, 583 (build_code << 24) | (build_id << 8) | hwmon_rev,
584 &data->update_lock, 1); 584 &data->update_lock, 1);
585 585
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index 906d4ed32d81..96a7e68718ca 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -510,7 +510,7 @@ static int __devinit sch5636_probe(struct platform_device *pdev)
510 } 510 }
511 511
512 /* Note failing to register the watchdog is not a fatal error */ 512 /* Note failing to register the watchdog is not a fatal error */
513 data->watchdog = sch56xx_watchdog_register(data->addr, 513 data->watchdog = sch56xx_watchdog_register(&pdev->dev, data->addr,
514 (revision[0] << 8) | revision[1], 514 (revision[0] << 8) | revision[1],
515 &data->update_lock, 0); 515 &data->update_lock, 0);
516 516
diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
index ce52fc57d41d..4380f5d07be2 100644
--- a/drivers/hwmon/sch56xx-common.c
+++ b/drivers/hwmon/sch56xx-common.c
@@ -66,15 +66,10 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
66 66
67struct sch56xx_watchdog_data { 67struct sch56xx_watchdog_data {
68 u16 addr; 68 u16 addr;
69 u32 revision;
70 struct mutex *io_lock; 69 struct mutex *io_lock;
71 struct mutex watchdog_lock;
72 struct list_head list; /* member of the watchdog_data_list */
73 struct kref kref; 70 struct kref kref;
74 struct miscdevice watchdog_miscdev; 71 struct watchdog_info wdinfo;
75 unsigned long watchdog_is_open; 72 struct watchdog_device wddev;
76 char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
77 char watchdog_expect_close;
78 u8 watchdog_preset; 73 u8 watchdog_preset;
79 u8 watchdog_control; 74 u8 watchdog_control;
80 u8 watchdog_output_enable; 75 u8 watchdog_output_enable;
@@ -82,15 +77,6 @@ struct sch56xx_watchdog_data {
82 77
83static struct platform_device *sch56xx_pdev; 78static struct platform_device *sch56xx_pdev;
84 79
85/*
86 * Somewhat ugly :( global data pointer list with all sch56xx devices, so that
87 * we can find our device data as when using misc_register there is no other
88 * method to get to ones device data from the open fop.
89 */
90static LIST_HEAD(watchdog_data_list);
91/* Note this lock not only protect list access, but also data.kref access */
92static DEFINE_MUTEX(watchdog_data_mutex);
93
94/* Super I/O functions */ 80/* Super I/O functions */
95static inline int superio_inb(int base, int reg) 81static inline int superio_inb(int base, int reg)
96{ 82{
@@ -272,22 +258,22 @@ EXPORT_SYMBOL(sch56xx_read_virtual_reg12);
272 * Watchdog routines 258 * Watchdog routines
273 */ 259 */
274 260
275/* 261/* Release our data struct when we're unregistered *and*
276 * Release our data struct when the platform device has been released *and* 262 all references to our watchdog device are released */
277 * all references to our watchdog device are released. 263static void watchdog_release_resources(struct kref *r)
278 */
279static void sch56xx_watchdog_release_resources(struct kref *r)
280{ 264{
281 struct sch56xx_watchdog_data *data = 265 struct sch56xx_watchdog_data *data =
282 container_of(r, struct sch56xx_watchdog_data, kref); 266 container_of(r, struct sch56xx_watchdog_data, kref);
283 kfree(data); 267 kfree(data);
284} 268}
285 269
286static int watchdog_set_timeout(struct sch56xx_watchdog_data *data, 270static int watchdog_set_timeout(struct watchdog_device *wddev,
287 int timeout) 271 unsigned int timeout)
288{ 272{
289 int ret, resolution; 273 struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev);
274 unsigned int resolution;
290 u8 control; 275 u8 control;
276 int ret;
291 277
292 /* 1 second or 60 second resolution? */ 278 /* 1 second or 60 second resolution? */
293 if (timeout <= 255) 279 if (timeout <= 255)
@@ -298,12 +284,6 @@ static int watchdog_set_timeout(struct sch56xx_watchdog_data *data,
298 if (timeout < resolution || timeout > (resolution * 255)) 284 if (timeout < resolution || timeout > (resolution * 255))
299 return -EINVAL; 285 return -EINVAL;
300 286
301 mutex_lock(&data->watchdog_lock);
302 if (!data->addr) {
303 ret = -ENODEV;
304 goto leave;
305 }
306
307 if (resolution == 1) 287 if (resolution == 1)
308 control = data->watchdog_control | SCH56XX_WDOG_TIME_BASE_SEC; 288 control = data->watchdog_control | SCH56XX_WDOG_TIME_BASE_SEC;
309 else 289 else
@@ -316,7 +296,7 @@ static int watchdog_set_timeout(struct sch56xx_watchdog_data *data,
316 control); 296 control);
317 mutex_unlock(data->io_lock); 297 mutex_unlock(data->io_lock);
318 if (ret) 298 if (ret)
319 goto leave; 299 return ret;
320 300
321 data->watchdog_control = control; 301 data->watchdog_control = control;
322 } 302 }
@@ -326,38 +306,17 @@ static int watchdog_set_timeout(struct sch56xx_watchdog_data *data,
326 * the watchdog countdown. 306 * the watchdog countdown.
327 */ 307 */
328 data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); 308 data->watchdog_preset = DIV_ROUND_UP(timeout, resolution);
309 wddev->timeout = data->watchdog_preset * resolution;
329 310
330 ret = data->watchdog_preset * resolution; 311 return 0;
331leave:
332 mutex_unlock(&data->watchdog_lock);
333 return ret;
334}
335
336static int watchdog_get_timeout(struct sch56xx_watchdog_data *data)
337{
338 int timeout;
339
340 mutex_lock(&data->watchdog_lock);
341 if (data->watchdog_control & SCH56XX_WDOG_TIME_BASE_SEC)
342 timeout = data->watchdog_preset;
343 else
344 timeout = data->watchdog_preset * 60;
345 mutex_unlock(&data->watchdog_lock);
346
347 return timeout;
348} 312}
349 313
350static int watchdog_start(struct sch56xx_watchdog_data *data) 314static int watchdog_start(struct watchdog_device *wddev)
351{ 315{
316 struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev);
352 int ret; 317 int ret;
353 u8 val; 318 u8 val;
354 319
355 mutex_lock(&data->watchdog_lock);
356 if (!data->addr) {
357 ret = -ENODEV;
358 goto leave_unlock_watchdog;
359 }
360
361 /* 320 /*
362 * The sch56xx's watchdog cannot really be started / stopped 321 * The sch56xx's watchdog cannot really be started / stopped
363 * it is always running, but we can avoid the timer expiring 322 * it is always running, but we can avoid the timer expiring
@@ -385,18 +344,14 @@ static int watchdog_start(struct sch56xx_watchdog_data *data)
385 if (ret) 344 if (ret)
386 goto leave; 345 goto leave;
387 346
388 /* 2. Enable output (if not already enabled) */ 347 /* 2. Enable output */
389 if (!(data->watchdog_output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)) { 348 val = data->watchdog_output_enable | SCH56XX_WDOG_OUTPUT_ENABLE;
390 val = data->watchdog_output_enable | 349 ret = sch56xx_write_virtual_reg(data->addr,
391 SCH56XX_WDOG_OUTPUT_ENABLE; 350 SCH56XX_REG_WDOG_OUTPUT_ENABLE, val);
392 ret = sch56xx_write_virtual_reg(data->addr, 351 if (ret)
393 SCH56XX_REG_WDOG_OUTPUT_ENABLE, 352 goto leave;
394 val);
395 if (ret)
396 goto leave;
397 353
398 data->watchdog_output_enable = val; 354 data->watchdog_output_enable = val;
399 }
400 355
401 /* 3. Clear the watchdog event bit if set */ 356 /* 3. Clear the watchdog event bit if set */
402 val = inb(data->addr + 9); 357 val = inb(data->addr + 9);
@@ -405,234 +360,70 @@ static int watchdog_start(struct sch56xx_watchdog_data *data)
405 360
406leave: 361leave:
407 mutex_unlock(data->io_lock); 362 mutex_unlock(data->io_lock);
408leave_unlock_watchdog:
409 mutex_unlock(&data->watchdog_lock);
410 return ret; 363 return ret;
411} 364}
412 365
413static int watchdog_trigger(struct sch56xx_watchdog_data *data) 366static int watchdog_trigger(struct watchdog_device *wddev)
414{ 367{
368 struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev);
415 int ret; 369 int ret;
416 370
417 mutex_lock(&data->watchdog_lock);
418 if (!data->addr) {
419 ret = -ENODEV;
420 goto leave;
421 }
422
423 /* Reset the watchdog countdown counter */ 371 /* Reset the watchdog countdown counter */
424 mutex_lock(data->io_lock); 372 mutex_lock(data->io_lock);
425 ret = sch56xx_write_virtual_reg(data->addr, SCH56XX_REG_WDOG_PRESET, 373 ret = sch56xx_write_virtual_reg(data->addr, SCH56XX_REG_WDOG_PRESET,
426 data->watchdog_preset); 374 data->watchdog_preset);
427 mutex_unlock(data->io_lock); 375 mutex_unlock(data->io_lock);
428leave: 376
429 mutex_unlock(&data->watchdog_lock);
430 return ret; 377 return ret;
431} 378}
432 379
433static int watchdog_stop_unlocked(struct sch56xx_watchdog_data *data) 380static int watchdog_stop(struct watchdog_device *wddev)
434{ 381{
382 struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev);
435 int ret = 0; 383 int ret = 0;
436 u8 val; 384 u8 val;
437 385
438 if (!data->addr) 386 val = data->watchdog_output_enable & ~SCH56XX_WDOG_OUTPUT_ENABLE;
439 return -ENODEV; 387 mutex_lock(data->io_lock);
440 388 ret = sch56xx_write_virtual_reg(data->addr,
441 if (data->watchdog_output_enable & SCH56XX_WDOG_OUTPUT_ENABLE) { 389 SCH56XX_REG_WDOG_OUTPUT_ENABLE, val);
442 val = data->watchdog_output_enable & 390 mutex_unlock(data->io_lock);
443 ~SCH56XX_WDOG_OUTPUT_ENABLE; 391 if (ret)
444 mutex_lock(data->io_lock); 392 return ret;
445 ret = sch56xx_write_virtual_reg(data->addr,
446 SCH56XX_REG_WDOG_OUTPUT_ENABLE,
447 val);
448 mutex_unlock(data->io_lock);
449 if (ret)
450 return ret;
451
452 data->watchdog_output_enable = val;
453 }
454
455 return ret;
456}
457
458static int watchdog_stop(struct sch56xx_watchdog_data *data)
459{
460 int ret;
461
462 mutex_lock(&data->watchdog_lock);
463 ret = watchdog_stop_unlocked(data);
464 mutex_unlock(&data->watchdog_lock);
465
466 return ret;
467}
468
469static int watchdog_release(struct inode *inode, struct file *filp)
470{
471 struct sch56xx_watchdog_data *data = filp->private_data;
472
473 if (data->watchdog_expect_close) {
474 watchdog_stop(data);
475 data->watchdog_expect_close = 0;
476 } else {
477 watchdog_trigger(data);
478 pr_crit("unexpected close, not stopping watchdog!\n");
479 }
480
481 clear_bit(0, &data->watchdog_is_open);
482
483 mutex_lock(&watchdog_data_mutex);
484 kref_put(&data->kref, sch56xx_watchdog_release_resources);
485 mutex_unlock(&watchdog_data_mutex);
486 393
394 data->watchdog_output_enable = val;
487 return 0; 395 return 0;
488} 396}
489 397
490static int watchdog_open(struct inode *inode, struct file *filp) 398static void watchdog_ref(struct watchdog_device *wddev)
491{ 399{
492 struct sch56xx_watchdog_data *pos, *data = NULL; 400 struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev);
493 int ret, watchdog_is_open;
494
495 /*
496 * We get called from drivers/char/misc.c with misc_mtx hold, and we
497 * call misc_register() from sch56xx_watchdog_probe() with
498 * watchdog_data_mutex hold, as misc_register() takes the misc_mtx
499 * lock, this is a possible deadlock, so we use mutex_trylock here.
500 */
501 if (!mutex_trylock(&watchdog_data_mutex))
502 return -ERESTARTSYS;
503 list_for_each_entry(pos, &watchdog_data_list, list) {
504 if (pos->watchdog_miscdev.minor == iminor(inode)) {
505 data = pos;
506 break;
507 }
508 }
509 /* Note we can never not have found data, so we don't check for this */
510 watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
511 if (!watchdog_is_open)
512 kref_get(&data->kref);
513 mutex_unlock(&watchdog_data_mutex);
514
515 if (watchdog_is_open)
516 return -EBUSY;
517
518 filp->private_data = data;
519
520 /* Start the watchdog */
521 ret = watchdog_start(data);
522 if (ret) {
523 watchdog_release(inode, filp);
524 return ret;
525 }
526 401
527 return nonseekable_open(inode, filp); 402 kref_get(&data->kref);
528} 403}
529 404
530static ssize_t watchdog_write(struct file *filp, const char __user *buf, 405static void watchdog_unref(struct watchdog_device *wddev)
531 size_t count, loff_t *offset)
532{ 406{
533 int ret; 407 struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev);
534 struct sch56xx_watchdog_data *data = filp->private_data;
535
536 if (count) {
537 if (!nowayout) {
538 size_t i;
539
540 /* Clear it in case it was set with a previous write */
541 data->watchdog_expect_close = 0;
542
543 for (i = 0; i != count; i++) {
544 char c;
545 if (get_user(c, buf + i))
546 return -EFAULT;
547 if (c == 'V')
548 data->watchdog_expect_close = 1;
549 }
550 }
551 ret = watchdog_trigger(data);
552 if (ret)
553 return ret;
554 }
555 return count;
556}
557
558static long watchdog_ioctl(struct file *filp, unsigned int cmd,
559 unsigned long arg)
560{
561 struct watchdog_info ident = {
562 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
563 .identity = "sch56xx watchdog"
564 };
565 int i, ret = 0;
566 struct sch56xx_watchdog_data *data = filp->private_data;
567
568 switch (cmd) {
569 case WDIOC_GETSUPPORT:
570 ident.firmware_version = data->revision;
571 if (!nowayout)
572 ident.options |= WDIOF_MAGICCLOSE;
573 if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
574 ret = -EFAULT;
575 break;
576
577 case WDIOC_GETSTATUS:
578 case WDIOC_GETBOOTSTATUS:
579 ret = put_user(0, (int __user *)arg);
580 break;
581
582 case WDIOC_KEEPALIVE:
583 ret = watchdog_trigger(data);
584 break;
585 408
586 case WDIOC_GETTIMEOUT: 409 kref_put(&data->kref, watchdog_release_resources);
587 i = watchdog_get_timeout(data);
588 ret = put_user(i, (int __user *)arg);
589 break;
590
591 case WDIOC_SETTIMEOUT:
592 if (get_user(i, (int __user *)arg)) {
593 ret = -EFAULT;
594 break;
595 }
596 ret = watchdog_set_timeout(data, i);
597 if (ret >= 0)
598 ret = put_user(ret, (int __user *)arg);
599 break;
600
601 case WDIOC_SETOPTIONS:
602 if (get_user(i, (int __user *)arg)) {
603 ret = -EFAULT;
604 break;
605 }
606
607 if (i & WDIOS_DISABLECARD)
608 ret = watchdog_stop(data);
609 else if (i & WDIOS_ENABLECARD)
610 ret = watchdog_trigger(data);
611 else
612 ret = -EINVAL;
613 break;
614
615 default:
616 ret = -ENOTTY;
617 }
618 return ret;
619} 410}
620 411
621static const struct file_operations watchdog_fops = { 412static const struct watchdog_ops watchdog_ops = {
622 .owner = THIS_MODULE, 413 .owner = THIS_MODULE,
623 .llseek = no_llseek, 414 .start = watchdog_start,
624 .open = watchdog_open, 415 .stop = watchdog_stop,
625 .release = watchdog_release, 416 .ping = watchdog_trigger,
626 .write = watchdog_write, 417 .set_timeout = watchdog_set_timeout,
627 .unlocked_ioctl = watchdog_ioctl, 418 .ref = watchdog_ref,
419 .unref = watchdog_unref,
628}; 420};
629 421
630struct sch56xx_watchdog_data *sch56xx_watchdog_register( 422struct sch56xx_watchdog_data *sch56xx_watchdog_register(struct device *parent,
631 u16 addr, u32 revision, struct mutex *io_lock, int check_enabled) 423 u16 addr, u32 revision, struct mutex *io_lock, int check_enabled)
632{ 424{
633 struct sch56xx_watchdog_data *data; 425 struct sch56xx_watchdog_data *data;
634 int i, err, control, output_enable; 426 int err, control, output_enable;
635 const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
636 427
637 /* Cache the watchdog registers */ 428 /* Cache the watchdog registers */
638 mutex_lock(io_lock); 429 mutex_lock(io_lock);
@@ -656,82 +447,55 @@ struct sch56xx_watchdog_data *sch56xx_watchdog_register(
656 return NULL; 447 return NULL;
657 448
658 data->addr = addr; 449 data->addr = addr;
659 data->revision = revision;
660 data->io_lock = io_lock; 450 data->io_lock = io_lock;
661 data->watchdog_control = control;
662 data->watchdog_output_enable = output_enable;
663 mutex_init(&data->watchdog_lock);
664 INIT_LIST_HEAD(&data->list);
665 kref_init(&data->kref); 451 kref_init(&data->kref);
666 452
667 err = watchdog_set_timeout(data, 60); 453 strlcpy(data->wdinfo.identity, "sch56xx watchdog",
668 if (err < 0) 454 sizeof(data->wdinfo.identity));
669 goto error; 455 data->wdinfo.firmware_version = revision;
670 456 data->wdinfo.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT;
671 /* 457 if (!nowayout)
672 * We take the data_mutex lock early so that watchdog_open() cannot 458 data->wdinfo.options |= WDIOF_MAGICCLOSE;
673 * run when misc_register() has completed, but we've not yet added 459
674 * our data to the watchdog_data_list. 460 data->wddev.info = &data->wdinfo;
675 */ 461 data->wddev.ops = &watchdog_ops;
676 mutex_lock(&watchdog_data_mutex); 462 data->wddev.parent = parent;
677 for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) { 463 data->wddev.timeout = 60;
678 /* Register our watchdog part */ 464 data->wddev.min_timeout = 1;
679 snprintf(data->watchdog_name, sizeof(data->watchdog_name), 465 data->wddev.max_timeout = 255 * 60;
680 "watchdog%c", (i == 0) ? '\0' : ('0' + i)); 466 if (nowayout)
681 data->watchdog_miscdev.name = data->watchdog_name; 467 set_bit(WDOG_NO_WAY_OUT, &data->wddev.status);
682 data->watchdog_miscdev.fops = &watchdog_fops; 468 if (output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)
683 data->watchdog_miscdev.minor = watchdog_minors[i]; 469 set_bit(WDOG_ACTIVE, &data->wddev.status);
684 err = misc_register(&data->watchdog_miscdev); 470
685 if (err == -EBUSY) 471 /* Since the watchdog uses a downcounter there is no register to read
686 continue; 472 the BIOS set timeout from (if any was set at all) ->
687 if (err) 473 Choose a preset which will give us a 1 minute timeout */
688 break; 474 if (control & SCH56XX_WDOG_TIME_BASE_SEC)
475 data->watchdog_preset = 60; /* seconds */
476 else
477 data->watchdog_preset = 1; /* minute */
689 478
690 list_add(&data->list, &watchdog_data_list); 479 data->watchdog_control = control;
691 pr_info("Registered /dev/%s chardev major 10, minor: %d\n", 480 data->watchdog_output_enable = output_enable;
692 data->watchdog_name, watchdog_minors[i]);
693 break;
694 }
695 mutex_unlock(&watchdog_data_mutex);
696 481
482 watchdog_set_drvdata(&data->wddev, data);
483 err = watchdog_register_device(&data->wddev);
697 if (err) { 484 if (err) {
698 pr_err("Registering watchdog chardev: %d\n", err); 485 pr_err("Registering watchdog chardev: %d\n", err);
699 goto error; 486 kfree(data);
700 } 487 return NULL;
701 if (i == ARRAY_SIZE(watchdog_minors)) {
702 pr_warn("Couldn't register watchdog (no free minor)\n");
703 goto error;
704 } 488 }
705 489
706 return data; 490 return data;
707
708error:
709 kfree(data);
710 return NULL;
711} 491}
712EXPORT_SYMBOL(sch56xx_watchdog_register); 492EXPORT_SYMBOL(sch56xx_watchdog_register);
713 493
714void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data) 494void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data)
715{ 495{
716 mutex_lock(&watchdog_data_mutex); 496 watchdog_unregister_device(&data->wddev);
717 misc_deregister(&data->watchdog_miscdev); 497 kref_put(&data->kref, watchdog_release_resources);
718 list_del(&data->list); 498 /* Don't touch data after this it may have been free-ed! */
719 mutex_unlock(&watchdog_data_mutex);
720
721 mutex_lock(&data->watchdog_lock);
722 if (data->watchdog_is_open) {
723 pr_warn("platform device unregistered with watchdog "
724 "open! Stopping watchdog.\n");
725 watchdog_stop_unlocked(data);
726 }
727 /* Tell the wdog start/stop/trigger functions our dev is gone */
728 data->addr = 0;
729 data->io_lock = NULL;
730 mutex_unlock(&data->watchdog_lock);
731
732 mutex_lock(&watchdog_data_mutex);
733 kref_put(&data->kref, sch56xx_watchdog_release_resources);
734 mutex_unlock(&watchdog_data_mutex);
735} 499}
736EXPORT_SYMBOL(sch56xx_watchdog_unregister); 500EXPORT_SYMBOL(sch56xx_watchdog_unregister);
737 501
diff --git a/drivers/hwmon/sch56xx-common.h b/drivers/hwmon/sch56xx-common.h
index 7475086eb978..704ea2c6d28a 100644
--- a/drivers/hwmon/sch56xx-common.h
+++ b/drivers/hwmon/sch56xx-common.h
@@ -27,6 +27,6 @@ int sch56xx_read_virtual_reg16(u16 addr, u16 reg);
27int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg, 27int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg,
28 int high_nibble); 28 int high_nibble);
29 29
30struct sch56xx_watchdog_data *sch56xx_watchdog_register( 30struct sch56xx_watchdog_data *sch56xx_watchdog_register(struct device *parent,
31 u16 addr, u32 revision, struct mutex *io_lock, int check_enabled); 31 u16 addr, u32 revision, struct mutex *io_lock, int check_enabled);
32void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data); 32void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d92d7488be16..fe819b76de56 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -64,6 +64,18 @@ config SOFT_WATCHDOG
64 To compile this driver as a module, choose M here: the 64 To compile this driver as a module, choose M here: the
65 module will be called softdog. 65 module will be called softdog.
66 66
67config DA9052_WATCHDOG
68 tristate "Dialog DA9052 Watchdog"
69 depends on PMIC_DA9052
70 select WATCHDOG_CORE
71 help
72 Support for the watchdog in the DA9052 PMIC. Watchdog trigger
73 cause system reset.
74
75 Say Y here to include support for the DA9052 watchdog.
76 Alternatively say M to compile the driver as a module,
77 which will be called da9052_wdt.
78
67config WM831X_WATCHDOG 79config WM831X_WATCHDOG
68 tristate "WM831x watchdog" 80 tristate "WM831x watchdog"
69 depends on MFD_WM831X 81 depends on MFD_WM831X
@@ -87,6 +99,7 @@ config WM8350_WATCHDOG
87config ARM_SP805_WATCHDOG 99config ARM_SP805_WATCHDOG
88 tristate "ARM SP805 Watchdog" 100 tristate "ARM SP805 Watchdog"
89 depends on ARM_AMBA 101 depends on ARM_AMBA
102 select WATCHDOG_CORE
90 help 103 help
91 ARM Primecell SP805 Watchdog timer. This will reboot your system when 104 ARM Primecell SP805 Watchdog timer. This will reboot your system when
92 the timeout is reached. 105 the timeout is reached.
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 442bfbe0882a..572b39bed06a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
163obj-$(CONFIG_XEN_WDT) += xen_wdt.o 163obj-$(CONFIG_XEN_WDT) += xen_wdt.o
164 164
165# Architecture Independent 165# Architecture Independent
166obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o
166obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o 167obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
167obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o 168obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
168obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o 169obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
diff --git a/drivers/watchdog/da9052_wdt.c b/drivers/watchdog/da9052_wdt.c
new file mode 100644
index 000000000000..3f75129eb0a9
--- /dev/null
+++ b/drivers/watchdog/da9052_wdt.c
@@ -0,0 +1,251 @@
1/*
2 * System monitoring driver for DA9052 PMICs.
3 *
4 * Copyright(c) 2012 Dialog Semiconductor Ltd.
5 *
6 * Author: Anthony Olech <Anthony.Olech@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/delay.h>
17#include <linux/uaccess.h>
18#include <linux/platform_device.h>
19#include <linux/time.h>
20#include <linux/watchdog.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/jiffies.h>
24#include <linux/delay.h>
25
26#include <linux/mfd/da9052/reg.h>
27#include <linux/mfd/da9052/da9052.h>
28
29#define DA9052_DEF_TIMEOUT 4
30#define DA9052_TWDMIN 256
31
32struct da9052_wdt_data {
33 struct watchdog_device wdt;
34 struct da9052 *da9052;
35 struct kref kref;
36 unsigned long jpast;
37};
38
39static const struct {
40 u8 reg_val;
41 int time; /* Seconds */
42} da9052_wdt_maps[] = {
43 { 1, 2 },
44 { 2, 4 },
45 { 3, 8 },
46 { 4, 16 },
47 { 5, 32 },
48 { 5, 33 }, /* Actual time 32.768s so included both 32s and 33s */
49 { 6, 65 },
50 { 6, 66 }, /* Actual time 65.536s so include both, 65s and 66s */
51 { 7, 131 },
52};
53
54
55static void da9052_wdt_release_resources(struct kref *r)
56{
57 struct da9052_wdt_data *driver_data =
58 container_of(r, struct da9052_wdt_data, kref);
59
60 kfree(driver_data);
61}
62
63static int da9052_wdt_set_timeout(struct watchdog_device *wdt_dev,
64 unsigned int timeout)
65{
66 struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
67 struct da9052 *da9052 = driver_data->da9052;
68 int ret, i;
69
70 /*
71 * Disable the Watchdog timer before setting
72 * new time out.
73 */
74 ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
75 DA9052_CONTROLD_TWDSCALE, 0);
76 if (ret < 0) {
77 dev_err(da9052->dev, "Failed to disable watchdog bit, %d\n",
78 ret);
79 return ret;
80 }
81 if (timeout) {
82 /*
83 * To change the timeout, da9052 needs to
84 * be disabled for at least 150 us.
85 */
86 udelay(150);
87
88 /* Set the desired timeout */
89 for (i = 0; i < ARRAY_SIZE(da9052_wdt_maps); i++)
90 if (da9052_wdt_maps[i].time == timeout)
91 break;
92
93 if (i == ARRAY_SIZE(da9052_wdt_maps))
94 ret = -EINVAL;
95 else
96 ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
97 DA9052_CONTROLD_TWDSCALE,
98 da9052_wdt_maps[i].reg_val);
99 if (ret < 0) {
100 dev_err(da9052->dev,
101 "Failed to update timescale bit, %d\n", ret);
102 return ret;
103 }
104
105 wdt_dev->timeout = timeout;
106 driver_data->jpast = jiffies;
107 }
108
109 return 0;
110}
111
112static void da9052_wdt_ref(struct watchdog_device *wdt_dev)
113{
114 struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
115
116 kref_get(&driver_data->kref);
117}
118
119static void da9052_wdt_unref(struct watchdog_device *wdt_dev)
120{
121 struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
122
123 kref_put(&driver_data->kref, da9052_wdt_release_resources);
124}
125
126static int da9052_wdt_start(struct watchdog_device *wdt_dev)
127{
128 return da9052_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
129}
130
131static int da9052_wdt_stop(struct watchdog_device *wdt_dev)
132{
133 return da9052_wdt_set_timeout(wdt_dev, 0);
134}
135
136static int da9052_wdt_ping(struct watchdog_device *wdt_dev)
137{
138 struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev);
139 struct da9052 *da9052 = driver_data->da9052;
140 unsigned long msec, jnow = jiffies;
141 int ret;
142
143 /*
144 * We have a minimum time for watchdog window called TWDMIN. A write
145 * to the watchdog before this elapsed time should cause an error.
146 */
147 msec = (jnow - driver_data->jpast) * 1000/HZ;
148 if (msec < DA9052_TWDMIN)
149 mdelay(msec);
150
151 /* Reset the watchdog timer */
152 ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
153 DA9052_CONTROLD_WATCHDOG, 1 << 7);
154 if (ret < 0)
155 goto err_strobe;
156
157 /*
158 * FIXME: Reset the watchdog core, in general PMIC
159 * is supposed to do this
160 */
161 ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
162 DA9052_CONTROLD_WATCHDOG, 0 << 7);
163err_strobe:
164 return ret;
165}
166
167static struct watchdog_info da9052_wdt_info = {
168 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
169 .identity = "DA9052 Watchdog",
170};
171
172static const struct watchdog_ops da9052_wdt_ops = {
173 .owner = THIS_MODULE,
174 .start = da9052_wdt_start,
175 .stop = da9052_wdt_stop,
176 .ping = da9052_wdt_ping,
177 .set_timeout = da9052_wdt_set_timeout,
178 .ref = da9052_wdt_ref,
179 .unref = da9052_wdt_unref,
180};
181
182
183static int __devinit da9052_wdt_probe(struct platform_device *pdev)
184{
185 struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
186 struct da9052_wdt_data *driver_data;
187 struct watchdog_device *da9052_wdt;
188 int ret;
189
190 driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
191 GFP_KERNEL);
192 if (!driver_data) {
193 dev_err(da9052->dev, "Unable to alloacate watchdog device\n");
194 ret = -ENOMEM;
195 goto err;
196 }
197 driver_data->da9052 = da9052;
198
199 da9052_wdt = &driver_data->wdt;
200
201 da9052_wdt->timeout = DA9052_DEF_TIMEOUT;
202 da9052_wdt->info = &da9052_wdt_info;
203 da9052_wdt->ops = &da9052_wdt_ops;
204 watchdog_set_drvdata(da9052_wdt, driver_data);
205
206 kref_init(&driver_data->kref);
207
208 ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG,
209 DA9052_CONTROLD_TWDSCALE, 0);
210 if (ret < 0) {
211 dev_err(&pdev->dev, "Failed to disable watchdog bits, %d\n",
212 ret);
213 goto err;
214 }
215
216 ret = watchdog_register_device(&driver_data->wdt);
217 if (ret != 0) {
218 dev_err(da9052->dev, "watchdog_register_device() failed: %d\n",
219 ret);
220 goto err;
221 }
222
223 dev_set_drvdata(&pdev->dev, driver_data);
224err:
225 return ret;
226}
227
228static int __devexit da9052_wdt_remove(struct platform_device *pdev)
229{
230 struct da9052_wdt_data *driver_data = dev_get_drvdata(&pdev->dev);
231
232 watchdog_unregister_device(&driver_data->wdt);
233 kref_put(&driver_data->kref, da9052_wdt_release_resources);
234
235 return 0;
236}
237
238static struct platform_driver da9052_wdt_driver = {
239 .probe = da9052_wdt_probe,
240 .remove = __devexit_p(da9052_wdt_remove),
241 .driver = {
242 .name = "da9052-watchdog",
243 },
244};
245
246module_platform_driver(da9052_wdt_driver);
247
248MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>");
249MODULE_DESCRIPTION("DA9052 SM Device Driver");
250MODULE_LICENSE("GPL");
251MODULE_ALIAS("platform:da9052-watchdog");
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 741528b032e2..bc47e9012f37 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -575,7 +575,7 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
575 if (!request_region(iTCO_wdt_private.smi_res->start, 575 if (!request_region(iTCO_wdt_private.smi_res->start,
576 resource_size(iTCO_wdt_private.smi_res), dev->name)) { 576 resource_size(iTCO_wdt_private.smi_res), dev->name)) {
577 pr_err("I/O address 0x%04llx already in use, device disabled\n", 577 pr_err("I/O address 0x%04llx already in use, device disabled\n",
578 SMI_EN); 578 (u64)SMI_EN);
579 ret = -EBUSY; 579 ret = -EBUSY;
580 goto unmap_gcs; 580 goto unmap_gcs;
581 } 581 }
@@ -592,13 +592,13 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
592 if (!request_region(iTCO_wdt_private.tco_res->start, 592 if (!request_region(iTCO_wdt_private.tco_res->start,
593 resource_size(iTCO_wdt_private.tco_res), dev->name)) { 593 resource_size(iTCO_wdt_private.tco_res), dev->name)) {
594 pr_err("I/O address 0x%04llx already in use, device disabled\n", 594 pr_err("I/O address 0x%04llx already in use, device disabled\n",
595 TCOBASE); 595 (u64)TCOBASE);
596 ret = -EBUSY; 596 ret = -EBUSY;
597 goto unreg_smi; 597 goto unreg_smi;
598 } 598 }
599 599
600 pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n", 600 pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04llx)\n",
601 ich_info->name, ich_info->iTCO_version, TCOBASE); 601 ich_info->name, ich_info->iTCO_version, (u64)TCOBASE);
602 602
603 /* Clear out the (probably old) status */ 603 /* Clear out the (probably old) status */
604 outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */ 604 outw(0x0008, TCO1_STS); /* Clear the Time Out Status bit */
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index bbb170e50055..afcd13676542 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -16,20 +16,17 @@
16#include <linux/amba/bus.h> 16#include <linux/amba/bus.h>
17#include <linux/bitops.h> 17#include <linux/bitops.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/fs.h>
20#include <linux/init.h> 19#include <linux/init.h>
21#include <linux/io.h> 20#include <linux/io.h>
22#include <linux/ioport.h> 21#include <linux/ioport.h>
23#include <linux/kernel.h> 22#include <linux/kernel.h>
24#include <linux/math64.h> 23#include <linux/math64.h>
25#include <linux/miscdevice.h>
26#include <linux/module.h> 24#include <linux/module.h>
27#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
28#include <linux/pm.h> 26#include <linux/pm.h>
29#include <linux/slab.h> 27#include <linux/slab.h>
30#include <linux/spinlock.h> 28#include <linux/spinlock.h>
31#include <linux/types.h> 29#include <linux/types.h>
32#include <linux/uaccess.h>
33#include <linux/watchdog.h> 30#include <linux/watchdog.h>
34 31
35/* default timeout in seconds */ 32/* default timeout in seconds */
@@ -56,6 +53,7 @@
56 53
57/** 54/**
58 * struct sp805_wdt: sp805 wdt device structure 55 * struct sp805_wdt: sp805 wdt device structure
56 * @wdd: instance of struct watchdog_device
59 * @lock: spin lock protecting dev structure and io access 57 * @lock: spin lock protecting dev structure and io access
60 * @base: base address of wdt 58 * @base: base address of wdt
61 * @clk: clock structure of wdt 59 * @clk: clock structure of wdt
@@ -65,24 +63,24 @@
65 * @timeout: current programmed timeout 63 * @timeout: current programmed timeout
66 */ 64 */
67struct sp805_wdt { 65struct sp805_wdt {
66 struct watchdog_device wdd;
68 spinlock_t lock; 67 spinlock_t lock;
69 void __iomem *base; 68 void __iomem *base;
70 struct clk *clk; 69 struct clk *clk;
71 struct amba_device *adev; 70 struct amba_device *adev;
72 unsigned long status;
73 #define WDT_BUSY 0
74 #define WDT_CAN_BE_CLOSED 1
75 unsigned int load_val; 71 unsigned int load_val;
76 unsigned int timeout; 72 unsigned int timeout;
77}; 73};
78 74
79/* local variables */
80static struct sp805_wdt *wdt;
81static bool nowayout = WATCHDOG_NOWAYOUT; 75static bool nowayout = WATCHDOG_NOWAYOUT;
76module_param(nowayout, bool, 0);
77MODULE_PARM_DESC(nowayout,
78 "Set to 1 to keep watchdog running after device release");
82 79
83/* This routine finds load value that will reset system in required timout */ 80/* This routine finds load value that will reset system in required timout */
84static void wdt_setload(unsigned int timeout) 81static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
85{ 82{
83 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
86 u64 load, rate; 84 u64 load, rate;
87 85
88 rate = clk_get_rate(wdt->clk); 86 rate = clk_get_rate(wdt->clk);
@@ -103,11 +101,14 @@ static void wdt_setload(unsigned int timeout)
103 /* roundup timeout to closest positive integer value */ 101 /* roundup timeout to closest positive integer value */
104 wdt->timeout = div_u64((load + 1) * 2 + (rate / 2), rate); 102 wdt->timeout = div_u64((load + 1) * 2 + (rate / 2), rate);
105 spin_unlock(&wdt->lock); 103 spin_unlock(&wdt->lock);
104
105 return 0;
106} 106}
107 107
108/* returns number of seconds left for reset to occur */ 108/* returns number of seconds left for reset to occur */
109static u32 wdt_timeleft(void) 109static unsigned int wdt_timeleft(struct watchdog_device *wdd)
110{ 110{
111 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
111 u64 load, rate; 112 u64 load, rate;
112 113
113 rate = clk_get_rate(wdt->clk); 114 rate = clk_get_rate(wdt->clk);
@@ -123,166 +124,96 @@ static u32 wdt_timeleft(void)
123 return div_u64(load, rate); 124 return div_u64(load, rate);
124} 125}
125 126
126/* enables watchdog timers reset */ 127static int wdt_config(struct watchdog_device *wdd, bool ping)
127static void wdt_enable(void)
128{ 128{
129 spin_lock(&wdt->lock); 129 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
130 int ret;
130 131
131 writel_relaxed(UNLOCK, wdt->base + WDTLOCK); 132 if (!ping) {
132 writel_relaxed(wdt->load_val, wdt->base + WDTLOAD); 133 ret = clk_prepare(wdt->clk);
133 writel_relaxed(INT_MASK, wdt->base + WDTINTCLR); 134 if (ret) {
134 writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); 135 dev_err(&wdt->adev->dev, "clock prepare fail");
135 writel_relaxed(LOCK, wdt->base + WDTLOCK); 136 return ret;
137 }
136 138
137 /* Flush posted writes. */ 139 ret = clk_enable(wdt->clk);
138 readl_relaxed(wdt->base + WDTLOCK); 140 if (ret) {
139 spin_unlock(&wdt->lock); 141 dev_err(&wdt->adev->dev, "clock enable fail");
140} 142 clk_unprepare(wdt->clk);
143 return ret;
144 }
145 }
141 146
142/* disables watchdog timers reset */
143static void wdt_disable(void)
144{
145 spin_lock(&wdt->lock); 147 spin_lock(&wdt->lock);
146 148
147 writel_relaxed(UNLOCK, wdt->base + WDTLOCK); 149 writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
148 writel_relaxed(0, wdt->base + WDTCONTROL); 150 writel_relaxed(wdt->load_val, wdt->base + WDTLOAD);
151
152 if (!ping) {
153 writel_relaxed(INT_MASK, wdt->base + WDTINTCLR);
154 writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base +
155 WDTCONTROL);
156 }
157
149 writel_relaxed(LOCK, wdt->base + WDTLOCK); 158 writel_relaxed(LOCK, wdt->base + WDTLOCK);
150 159
151 /* Flush posted writes. */ 160 /* Flush posted writes. */
152 readl_relaxed(wdt->base + WDTLOCK); 161 readl_relaxed(wdt->base + WDTLOCK);
153 spin_unlock(&wdt->lock); 162 spin_unlock(&wdt->lock);
163
164 return 0;
154} 165}
155 166
156static ssize_t sp805_wdt_write(struct file *file, const char *data, 167static int wdt_ping(struct watchdog_device *wdd)
157 size_t len, loff_t *ppos)
158{ 168{
159 if (len) { 169 return wdt_config(wdd, true);
160 if (!nowayout) {
161 size_t i;
162
163 clear_bit(WDT_CAN_BE_CLOSED, &wdt->status);
164
165 for (i = 0; i != len; i++) {
166 char c;
167
168 if (get_user(c, data + i))
169 return -EFAULT;
170 /* Check for Magic Close character */
171 if (c == 'V') {
172 set_bit(WDT_CAN_BE_CLOSED,
173 &wdt->status);
174 break;
175 }
176 }
177 }
178 wdt_enable();
179 }
180 return len;
181} 170}
182 171
183static const struct watchdog_info ident = { 172/* enables watchdog timers reset */
184 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 173static int wdt_enable(struct watchdog_device *wdd)
185 .identity = MODULE_NAME,
186};
187
188static long sp805_wdt_ioctl(struct file *file, unsigned int cmd,
189 unsigned long arg)
190{ 174{
191 int ret = -ENOTTY; 175 return wdt_config(wdd, false);
192 unsigned int timeout;
193
194 switch (cmd) {
195 case WDIOC_GETSUPPORT:
196 ret = copy_to_user((struct watchdog_info *)arg, &ident,
197 sizeof(ident)) ? -EFAULT : 0;
198 break;
199
200 case WDIOC_GETSTATUS:
201 ret = put_user(0, (int *)arg);
202 break;
203
204 case WDIOC_KEEPALIVE:
205 wdt_enable();
206 ret = 0;
207 break;
208
209 case WDIOC_SETTIMEOUT:
210 ret = get_user(timeout, (unsigned int *)arg);
211 if (ret)
212 break;
213
214 wdt_setload(timeout);
215
216 wdt_enable();
217 /* Fall through */
218
219 case WDIOC_GETTIMEOUT:
220 ret = put_user(wdt->timeout, (unsigned int *)arg);
221 break;
222 case WDIOC_GETTIMELEFT:
223 ret = put_user(wdt_timeleft(), (unsigned int *)arg);
224 break;
225 }
226 return ret;
227} 176}
228 177
229static int sp805_wdt_open(struct inode *inode, struct file *file) 178/* disables watchdog timers reset */
179static int wdt_disable(struct watchdog_device *wdd)
230{ 180{
231 int ret = 0; 181 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
232
233 if (test_and_set_bit(WDT_BUSY, &wdt->status))
234 return -EBUSY;
235
236 ret = clk_enable(wdt->clk);
237 if (ret) {
238 dev_err(&wdt->adev->dev, "clock enable fail");
239 goto err;
240 }
241
242 wdt_enable();
243 182
244 /* can not be closed, once enabled */ 183 spin_lock(&wdt->lock);
245 clear_bit(WDT_CAN_BE_CLOSED, &wdt->status);
246 return nonseekable_open(inode, file);
247 184
248err: 185 writel_relaxed(UNLOCK, wdt->base + WDTLOCK);
249 clear_bit(WDT_BUSY, &wdt->status); 186 writel_relaxed(0, wdt->base + WDTCONTROL);
250 return ret; 187 writel_relaxed(LOCK, wdt->base + WDTLOCK);
251}
252 188
253static int sp805_wdt_release(struct inode *inode, struct file *file) 189 /* Flush posted writes. */
254{ 190 readl_relaxed(wdt->base + WDTLOCK);
255 if (!test_bit(WDT_CAN_BE_CLOSED, &wdt->status)) { 191 spin_unlock(&wdt->lock);
256 clear_bit(WDT_BUSY, &wdt->status);
257 dev_warn(&wdt->adev->dev, "Device closed unexpectedly\n");
258 return 0;
259 }
260 192
261 wdt_disable();
262 clk_disable(wdt->clk); 193 clk_disable(wdt->clk);
263 clear_bit(WDT_BUSY, &wdt->status); 194 clk_unprepare(wdt->clk);
264 195
265 return 0; 196 return 0;
266} 197}
267 198
268static const struct file_operations sp805_wdt_fops = { 199static const struct watchdog_info wdt_info = {
269 .owner = THIS_MODULE, 200 .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
270 .llseek = no_llseek, 201 .identity = MODULE_NAME,
271 .write = sp805_wdt_write,
272 .unlocked_ioctl = sp805_wdt_ioctl,
273 .open = sp805_wdt_open,
274 .release = sp805_wdt_release,
275}; 202};
276 203
277static struct miscdevice sp805_wdt_miscdev = { 204static const struct watchdog_ops wdt_ops = {
278 .minor = WATCHDOG_MINOR, 205 .owner = THIS_MODULE,
279 .name = "watchdog", 206 .start = wdt_enable,
280 .fops = &sp805_wdt_fops, 207 .stop = wdt_disable,
208 .ping = wdt_ping,
209 .set_timeout = wdt_setload,
210 .get_timeleft = wdt_timeleft,
281}; 211};
282 212
283static int __devinit 213static int __devinit
284sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) 214sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
285{ 215{
216 struct sp805_wdt *wdt;
286 int ret = 0; 217 int ret = 0;
287 218
288 if (!devm_request_mem_region(&adev->dev, adev->res.start, 219 if (!devm_request_mem_region(&adev->dev, adev->res.start,
@@ -315,19 +246,26 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
315 } 246 }
316 247
317 wdt->adev = adev; 248 wdt->adev = adev;
249 wdt->wdd.info = &wdt_info;
250 wdt->wdd.ops = &wdt_ops;
251
318 spin_lock_init(&wdt->lock); 252 spin_lock_init(&wdt->lock);
319 wdt_setload(DEFAULT_TIMEOUT); 253 watchdog_set_nowayout(&wdt->wdd, nowayout);
254 watchdog_set_drvdata(&wdt->wdd, wdt);
255 wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT);
320 256
321 ret = misc_register(&sp805_wdt_miscdev); 257 ret = watchdog_register_device(&wdt->wdd);
322 if (ret < 0) { 258 if (ret) {
323 dev_warn(&adev->dev, "cannot register misc device\n"); 259 dev_err(&adev->dev, "watchdog_register_device() failed: %d\n",
324 goto err_misc_register; 260 ret);
261 goto err_register;
325 } 262 }
263 amba_set_drvdata(adev, wdt);
326 264
327 dev_info(&adev->dev, "registration successful\n"); 265 dev_info(&adev->dev, "registration successful\n");
328 return 0; 266 return 0;
329 267
330err_misc_register: 268err_register:
331 clk_put(wdt->clk); 269 clk_put(wdt->clk);
332err: 270err:
333 dev_err(&adev->dev, "Probe Failed!!!\n"); 271 dev_err(&adev->dev, "Probe Failed!!!\n");
@@ -336,7 +274,11 @@ err:
336 274
337static int __devexit sp805_wdt_remove(struct amba_device *adev) 275static int __devexit sp805_wdt_remove(struct amba_device *adev)
338{ 276{
339 misc_deregister(&sp805_wdt_miscdev); 277 struct sp805_wdt *wdt = amba_get_drvdata(adev);
278
279 watchdog_unregister_device(&wdt->wdd);
280 amba_set_drvdata(adev, NULL);
281 watchdog_set_drvdata(&wdt->wdd, NULL);
340 clk_put(wdt->clk); 282 clk_put(wdt->clk);
341 283
342 return 0; 284 return 0;
@@ -345,28 +287,22 @@ static int __devexit sp805_wdt_remove(struct amba_device *adev)
345#ifdef CONFIG_PM 287#ifdef CONFIG_PM
346static int sp805_wdt_suspend(struct device *dev) 288static int sp805_wdt_suspend(struct device *dev)
347{ 289{
348 if (test_bit(WDT_BUSY, &wdt->status)) { 290 struct sp805_wdt *wdt = dev_get_drvdata(dev);
349 wdt_disable(); 291
350 clk_disable(wdt->clk); 292 if (watchdog_active(&wdt->wdd))
351 } 293 return wdt_disable(&wdt->wdd);
352 294
353 return 0; 295 return 0;
354} 296}
355 297
356static int sp805_wdt_resume(struct device *dev) 298static int sp805_wdt_resume(struct device *dev)
357{ 299{
358 int ret = 0; 300 struct sp805_wdt *wdt = dev_get_drvdata(dev);
359 301
360 if (test_bit(WDT_BUSY, &wdt->status)) { 302 if (watchdog_active(&wdt->wdd))
361 ret = clk_enable(wdt->clk); 303 return wdt_enable(&wdt->wdd);
362 if (ret) {
363 dev_err(dev, "clock enable fail");
364 return ret;
365 }
366 wdt_enable();
367 }
368 304
369 return ret; 305 return 0;
370} 306}
371#endif /* CONFIG_PM */ 307#endif /* CONFIG_PM */
372 308
@@ -395,11 +331,6 @@ static struct amba_driver sp805_wdt_driver = {
395 331
396module_amba_driver(sp805_wdt_driver); 332module_amba_driver(sp805_wdt_driver);
397 333
398module_param(nowayout, bool, 0);
399MODULE_PARM_DESC(nowayout,
400 "Set to 1 to keep watchdog running after device release");
401
402MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); 334MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
403MODULE_DESCRIPTION("ARM SP805 Watchdog Driver"); 335MODULE_DESCRIPTION("ARM SP805 Watchdog Driver");
404MODULE_LICENSE("GPL"); 336MODULE_LICENSE("GPL");
405MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index 5603e31afdab..aa50da3ccfe3 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -91,7 +91,7 @@ static inline void wdt_reset(void)
91static void wdt_timer_tick(unsigned long data) 91static void wdt_timer_tick(unsigned long data)
92{ 92{
93 if (time_before(jiffies, next_heartbeat) || 93 if (time_before(jiffies, next_heartbeat) ||
94 (!test_bit(WDOG_ACTIVE, &wdt_dev.status))) { 94 (!watchdog_active(&wdt_dev))) {
95 wdt_reset(); 95 wdt_reset();
96 mod_timer(&timer, jiffies + WDT_HEARTBEAT); 96 mod_timer(&timer, jiffies + WDT_HEARTBEAT);
97 } else 97 } else
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 14d768bfa267..6aa46a90ff02 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -34,8 +34,13 @@
34#include <linux/kernel.h> /* For printk/panic/... */ 34#include <linux/kernel.h> /* For printk/panic/... */
35#include <linux/watchdog.h> /* For watchdog specific items */ 35#include <linux/watchdog.h> /* For watchdog specific items */
36#include <linux/init.h> /* For __init/__exit/... */ 36#include <linux/init.h> /* For __init/__exit/... */
37#include <linux/idr.h> /* For ida_* macros */
38#include <linux/err.h> /* For IS_ERR macros */
37 39
38#include "watchdog_dev.h" /* For watchdog_dev_register/... */ 40#include "watchdog_core.h" /* For watchdog_dev_register/... */
41
42static DEFINE_IDA(watchdog_ida);
43static struct class *watchdog_class;
39 44
40/** 45/**
41 * watchdog_register_device() - register a watchdog device 46 * watchdog_register_device() - register a watchdog device
@@ -49,7 +54,7 @@
49 */ 54 */
50int watchdog_register_device(struct watchdog_device *wdd) 55int watchdog_register_device(struct watchdog_device *wdd)
51{ 56{
52 int ret; 57 int ret, id, devno;
53 58
54 if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL) 59 if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
55 return -EINVAL; 60 return -EINVAL;
@@ -74,10 +79,38 @@ int watchdog_register_device(struct watchdog_device *wdd)
74 * corrupted in a later stage then we expect a kernel panic! 79 * corrupted in a later stage then we expect a kernel panic!
75 */ 80 */
76 81
77 /* We only support 1 watchdog device via the /dev/watchdog interface */ 82 mutex_init(&wdd->lock);
83 id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL);
84 if (id < 0)
85 return id;
86 wdd->id = id;
87
78 ret = watchdog_dev_register(wdd); 88 ret = watchdog_dev_register(wdd);
79 if (ret) { 89 if (ret) {
80 pr_err("error registering /dev/watchdog (err=%d)\n", ret); 90 ida_simple_remove(&watchdog_ida, id);
91 if (!(id == 0 && ret == -EBUSY))
92 return ret;
93
94 /* Retry in case a legacy watchdog module exists */
95 id = ida_simple_get(&watchdog_ida, 1, MAX_DOGS, GFP_KERNEL);
96 if (id < 0)
97 return id;
98 wdd->id = id;
99
100 ret = watchdog_dev_register(wdd);
101 if (ret) {
102 ida_simple_remove(&watchdog_ida, id);
103 return ret;
104 }
105 }
106
107 devno = wdd->cdev.dev;
108 wdd->dev = device_create(watchdog_class, wdd->parent, devno,
109 NULL, "watchdog%d", wdd->id);
110 if (IS_ERR(wdd->dev)) {
111 watchdog_dev_unregister(wdd);
112 ida_simple_remove(&watchdog_ida, id);
113 ret = PTR_ERR(wdd->dev);
81 return ret; 114 return ret;
82 } 115 }
83 116
@@ -95,6 +128,7 @@ EXPORT_SYMBOL_GPL(watchdog_register_device);
95void watchdog_unregister_device(struct watchdog_device *wdd) 128void watchdog_unregister_device(struct watchdog_device *wdd)
96{ 129{
97 int ret; 130 int ret;
131 int devno = wdd->cdev.dev;
98 132
99 if (wdd == NULL) 133 if (wdd == NULL)
100 return; 134 return;
@@ -102,9 +136,41 @@ void watchdog_unregister_device(struct watchdog_device *wdd)
102 ret = watchdog_dev_unregister(wdd); 136 ret = watchdog_dev_unregister(wdd);
103 if (ret) 137 if (ret)
104 pr_err("error unregistering /dev/watchdog (err=%d)\n", ret); 138 pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
139 device_destroy(watchdog_class, devno);
140 ida_simple_remove(&watchdog_ida, wdd->id);
141 wdd->dev = NULL;
105} 142}
106EXPORT_SYMBOL_GPL(watchdog_unregister_device); 143EXPORT_SYMBOL_GPL(watchdog_unregister_device);
107 144
145static int __init watchdog_init(void)
146{
147 int err;
148
149 watchdog_class = class_create(THIS_MODULE, "watchdog");
150 if (IS_ERR(watchdog_class)) {
151 pr_err("couldn't create class\n");
152 return PTR_ERR(watchdog_class);
153 }
154
155 err = watchdog_dev_init();
156 if (err < 0) {
157 class_destroy(watchdog_class);
158 return err;
159 }
160
161 return 0;
162}
163
164static void __exit watchdog_exit(void)
165{
166 watchdog_dev_exit();
167 class_destroy(watchdog_class);
168 ida_destroy(&watchdog_ida);
169}
170
171subsys_initcall(watchdog_init);
172module_exit(watchdog_exit);
173
108MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>"); 174MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
109MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>"); 175MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
110MODULE_DESCRIPTION("WatchDog Timer Driver Core"); 176MODULE_DESCRIPTION("WatchDog Timer Driver Core");
diff --git a/drivers/watchdog/watchdog_dev.h b/drivers/watchdog/watchdog_core.h
index bc7612be25ce..6c951418fca7 100644
--- a/drivers/watchdog/watchdog_dev.h
+++ b/drivers/watchdog/watchdog_core.h
@@ -26,8 +26,12 @@
26 * This material is provided "AS-IS" and at no charge. 26 * This material is provided "AS-IS" and at no charge.
27 */ 27 */
28 28
29#define MAX_DOGS 32 /* Maximum number of watchdog devices */
30
29/* 31/*
30 * Functions/procedures to be called by the core 32 * Functions/procedures to be called by the core
31 */ 33 */
32int watchdog_dev_register(struct watchdog_device *); 34extern int watchdog_dev_register(struct watchdog_device *);
33int watchdog_dev_unregister(struct watchdog_device *); 35extern int watchdog_dev_unregister(struct watchdog_device *);
36extern int __init watchdog_dev_init(void);
37extern void __exit watchdog_dev_exit(void);
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 8558da912c42..672d169bf1da 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -42,10 +42,12 @@
42#include <linux/init.h> /* For __init/__exit/... */ 42#include <linux/init.h> /* For __init/__exit/... */
43#include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 43#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
44 44
45/* make sure we only register one /dev/watchdog device */ 45#include "watchdog_core.h"
46static unsigned long watchdog_dev_busy; 46
47/* the dev_t structure to store the dynamically allocated watchdog devices */
48static dev_t watchdog_devt;
47/* the watchdog device behind /dev/watchdog */ 49/* the watchdog device behind /dev/watchdog */
48static struct watchdog_device *wdd; 50static struct watchdog_device *old_wdd;
49 51
50/* 52/*
51 * watchdog_ping: ping the watchdog. 53 * watchdog_ping: ping the watchdog.
@@ -59,13 +61,26 @@ static struct watchdog_device *wdd;
59 61
60static int watchdog_ping(struct watchdog_device *wddev) 62static int watchdog_ping(struct watchdog_device *wddev)
61{ 63{
62 if (test_bit(WDOG_ACTIVE, &wddev->status)) { 64 int err = 0;
63 if (wddev->ops->ping) 65
64 return wddev->ops->ping(wddev); /* ping the watchdog */ 66 mutex_lock(&wddev->lock);
65 else 67
66 return wddev->ops->start(wddev); /* restart watchdog */ 68 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
69 err = -ENODEV;
70 goto out_ping;
67 } 71 }
68 return 0; 72
73 if (!watchdog_active(wddev))
74 goto out_ping;
75
76 if (wddev->ops->ping)
77 err = wddev->ops->ping(wddev); /* ping the watchdog */
78 else
79 err = wddev->ops->start(wddev); /* restart watchdog */
80
81out_ping:
82 mutex_unlock(&wddev->lock);
83 return err;
69} 84}
70 85
71/* 86/*
@@ -79,16 +94,25 @@ static int watchdog_ping(struct watchdog_device *wddev)
79 94
80static int watchdog_start(struct watchdog_device *wddev) 95static int watchdog_start(struct watchdog_device *wddev)
81{ 96{
82 int err; 97 int err = 0;
83 98
84 if (!test_bit(WDOG_ACTIVE, &wddev->status)) { 99 mutex_lock(&wddev->lock);
85 err = wddev->ops->start(wddev);
86 if (err < 0)
87 return err;
88 100
89 set_bit(WDOG_ACTIVE, &wddev->status); 101 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
102 err = -ENODEV;
103 goto out_start;
90 } 104 }
91 return 0; 105
106 if (watchdog_active(wddev))
107 goto out_start;
108
109 err = wddev->ops->start(wddev);
110 if (err == 0)
111 set_bit(WDOG_ACTIVE, &wddev->status);
112
113out_start:
114 mutex_unlock(&wddev->lock);
115 return err;
92} 116}
93 117
94/* 118/*
@@ -103,22 +127,155 @@ static int watchdog_start(struct watchdog_device *wddev)
103 127
104static int watchdog_stop(struct watchdog_device *wddev) 128static int watchdog_stop(struct watchdog_device *wddev)
105{ 129{
106 int err = -EBUSY; 130 int err = 0;
107 131
108 if (test_bit(WDOG_NO_WAY_OUT, &wddev->status)) { 132 mutex_lock(&wddev->lock);
109 pr_info("%s: nowayout prevents watchdog to be stopped!\n", 133
110 wddev->info->identity); 134 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
111 return err; 135 err = -ENODEV;
136 goto out_stop;
112 } 137 }
113 138
114 if (test_bit(WDOG_ACTIVE, &wddev->status)) { 139 if (!watchdog_active(wddev))
115 err = wddev->ops->stop(wddev); 140 goto out_stop;
116 if (err < 0)
117 return err;
118 141
142 if (test_bit(WDOG_NO_WAY_OUT, &wddev->status)) {
143 dev_info(wddev->dev, "nowayout prevents watchdog being stopped!\n");
144 err = -EBUSY;
145 goto out_stop;
146 }
147
148 err = wddev->ops->stop(wddev);
149 if (err == 0)
119 clear_bit(WDOG_ACTIVE, &wddev->status); 150 clear_bit(WDOG_ACTIVE, &wddev->status);
151
152out_stop:
153 mutex_unlock(&wddev->lock);
154 return err;
155}
156
157/*
158 * watchdog_get_status: wrapper to get the watchdog status
159 * @wddev: the watchdog device to get the status from
160 * @status: the status of the watchdog device
161 *
162 * Get the watchdog's status flags.
163 */
164
165static int watchdog_get_status(struct watchdog_device *wddev,
166 unsigned int *status)
167{
168 int err = 0;
169
170 *status = 0;
171 if (!wddev->ops->status)
172 return -EOPNOTSUPP;
173
174 mutex_lock(&wddev->lock);
175
176 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
177 err = -ENODEV;
178 goto out_status;
120 } 179 }
121 return 0; 180
181 *status = wddev->ops->status(wddev);
182
183out_status:
184 mutex_unlock(&wddev->lock);
185 return err;
186}
187
188/*
189 * watchdog_set_timeout: set the watchdog timer timeout
190 * @wddev: the watchdog device to set the timeout for
191 * @timeout: timeout to set in seconds
192 */
193
194static int watchdog_set_timeout(struct watchdog_device *wddev,
195 unsigned int timeout)
196{
197 int err;
198
199 if ((wddev->ops->set_timeout == NULL) ||
200 !(wddev->info->options & WDIOF_SETTIMEOUT))
201 return -EOPNOTSUPP;
202
203 if ((wddev->max_timeout != 0) &&
204 (timeout < wddev->min_timeout || timeout > wddev->max_timeout))
205 return -EINVAL;
206
207 mutex_lock(&wddev->lock);
208
209 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
210 err = -ENODEV;
211 goto out_timeout;
212 }
213
214 err = wddev->ops->set_timeout(wddev, timeout);
215
216out_timeout:
217 mutex_unlock(&wddev->lock);
218 return err;
219}
220
221/*
222 * watchdog_get_timeleft: wrapper to get the time left before a reboot
223 * @wddev: the watchdog device to get the remaining time from
224 * @timeleft: the time that's left
225 *
226 * Get the time before a watchdog will reboot (if not pinged).
227 */
228
229static int watchdog_get_timeleft(struct watchdog_device *wddev,
230 unsigned int *timeleft)
231{
232 int err = 0;
233
234 *timeleft = 0;
235 if (!wddev->ops->get_timeleft)
236 return -EOPNOTSUPP;
237
238 mutex_lock(&wddev->lock);
239
240 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
241 err = -ENODEV;
242 goto out_timeleft;
243 }
244
245 *timeleft = wddev->ops->get_timeleft(wddev);
246
247out_timeleft:
248 mutex_unlock(&wddev->lock);
249 return err;
250}
251
252/*
253 * watchdog_ioctl_op: call the watchdog drivers ioctl op if defined
254 * @wddev: the watchdog device to do the ioctl on
255 * @cmd: watchdog command
256 * @arg: argument pointer
257 */
258
259static int watchdog_ioctl_op(struct watchdog_device *wddev, unsigned int cmd,
260 unsigned long arg)
261{
262 int err;
263
264 if (!wddev->ops->ioctl)
265 return -ENOIOCTLCMD;
266
267 mutex_lock(&wddev->lock);
268
269 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
270 err = -ENODEV;
271 goto out_ioctl;
272 }
273
274 err = wddev->ops->ioctl(wddev, cmd, arg);
275
276out_ioctl:
277 mutex_unlock(&wddev->lock);
278 return err;
122} 279}
123 280
124/* 281/*
@@ -136,6 +293,7 @@ static int watchdog_stop(struct watchdog_device *wddev)
136static ssize_t watchdog_write(struct file *file, const char __user *data, 293static ssize_t watchdog_write(struct file *file, const char __user *data,
137 size_t len, loff_t *ppos) 294 size_t len, loff_t *ppos)
138{ 295{
296 struct watchdog_device *wdd = file->private_data;
139 size_t i; 297 size_t i;
140 char c; 298 char c;
141 299
@@ -175,23 +333,24 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
175static long watchdog_ioctl(struct file *file, unsigned int cmd, 333static long watchdog_ioctl(struct file *file, unsigned int cmd,
176 unsigned long arg) 334 unsigned long arg)
177{ 335{
336 struct watchdog_device *wdd = file->private_data;
178 void __user *argp = (void __user *)arg; 337 void __user *argp = (void __user *)arg;
179 int __user *p = argp; 338 int __user *p = argp;
180 unsigned int val; 339 unsigned int val;
181 int err; 340 int err;
182 341
183 if (wdd->ops->ioctl) { 342 err = watchdog_ioctl_op(wdd, cmd, arg);
184 err = wdd->ops->ioctl(wdd, cmd, arg); 343 if (err != -ENOIOCTLCMD)
185 if (err != -ENOIOCTLCMD) 344 return err;
186 return err;
187 }
188 345
189 switch (cmd) { 346 switch (cmd) {
190 case WDIOC_GETSUPPORT: 347 case WDIOC_GETSUPPORT:
191 return copy_to_user(argp, wdd->info, 348 return copy_to_user(argp, wdd->info,
192 sizeof(struct watchdog_info)) ? -EFAULT : 0; 349 sizeof(struct watchdog_info)) ? -EFAULT : 0;
193 case WDIOC_GETSTATUS: 350 case WDIOC_GETSTATUS:
194 val = wdd->ops->status ? wdd->ops->status(wdd) : 0; 351 err = watchdog_get_status(wdd, &val);
352 if (err)
353 return err;
195 return put_user(val, p); 354 return put_user(val, p);
196 case WDIOC_GETBOOTSTATUS: 355 case WDIOC_GETBOOTSTATUS:
197 return put_user(wdd->bootstatus, p); 356 return put_user(wdd->bootstatus, p);
@@ -215,15 +374,9 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
215 watchdog_ping(wdd); 374 watchdog_ping(wdd);
216 return 0; 375 return 0;
217 case WDIOC_SETTIMEOUT: 376 case WDIOC_SETTIMEOUT:
218 if ((wdd->ops->set_timeout == NULL) ||
219 !(wdd->info->options & WDIOF_SETTIMEOUT))
220 return -EOPNOTSUPP;
221 if (get_user(val, p)) 377 if (get_user(val, p))
222 return -EFAULT; 378 return -EFAULT;
223 if ((wdd->max_timeout != 0) && 379 err = watchdog_set_timeout(wdd, val);
224 (val < wdd->min_timeout || val > wdd->max_timeout))
225 return -EINVAL;
226 err = wdd->ops->set_timeout(wdd, val);
227 if (err < 0) 380 if (err < 0)
228 return err; 381 return err;
229 /* If the watchdog is active then we send a keepalive ping 382 /* If the watchdog is active then we send a keepalive ping
@@ -237,21 +390,21 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
237 return -EOPNOTSUPP; 390 return -EOPNOTSUPP;
238 return put_user(wdd->timeout, p); 391 return put_user(wdd->timeout, p);
239 case WDIOC_GETTIMELEFT: 392 case WDIOC_GETTIMELEFT:
240 if (!wdd->ops->get_timeleft) 393 err = watchdog_get_timeleft(wdd, &val);
241 return -EOPNOTSUPP; 394 if (err)
242 395 return err;
243 return put_user(wdd->ops->get_timeleft(wdd), p); 396 return put_user(val, p);
244 default: 397 default:
245 return -ENOTTY; 398 return -ENOTTY;
246 } 399 }
247} 400}
248 401
249/* 402/*
250 * watchdog_open: open the /dev/watchdog device. 403 * watchdog_open: open the /dev/watchdog* devices.
251 * @inode: inode of device 404 * @inode: inode of device
252 * @file: file handle to device 405 * @file: file handle to device
253 * 406 *
254 * When the /dev/watchdog device gets opened, we start the watchdog. 407 * When the /dev/watchdog* device gets opened, we start the watchdog.
255 * Watch out: the /dev/watchdog device is single open, so we make sure 408 * Watch out: the /dev/watchdog device is single open, so we make sure
256 * it can only be opened once. 409 * it can only be opened once.
257 */ 410 */
@@ -259,6 +412,13 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
259static int watchdog_open(struct inode *inode, struct file *file) 412static int watchdog_open(struct inode *inode, struct file *file)
260{ 413{
261 int err = -EBUSY; 414 int err = -EBUSY;
415 struct watchdog_device *wdd;
416
417 /* Get the corresponding watchdog device */
418 if (imajor(inode) == MISC_MAJOR)
419 wdd = old_wdd;
420 else
421 wdd = container_of(inode->i_cdev, struct watchdog_device, cdev);
262 422
263 /* the watchdog is single open! */ 423 /* the watchdog is single open! */
264 if (test_and_set_bit(WDOG_DEV_OPEN, &wdd->status)) 424 if (test_and_set_bit(WDOG_DEV_OPEN, &wdd->status))
@@ -275,6 +435,11 @@ static int watchdog_open(struct inode *inode, struct file *file)
275 if (err < 0) 435 if (err < 0)
276 goto out_mod; 436 goto out_mod;
277 437
438 file->private_data = wdd;
439
440 if (wdd->ops->ref)
441 wdd->ops->ref(wdd);
442
278 /* dev/watchdog is a virtual (and thus non-seekable) filesystem */ 443 /* dev/watchdog is a virtual (and thus non-seekable) filesystem */
279 return nonseekable_open(inode, file); 444 return nonseekable_open(inode, file);
280 445
@@ -286,9 +451,9 @@ out:
286} 451}
287 452
288/* 453/*
289 * watchdog_release: release the /dev/watchdog device. 454 * watchdog_release: release the watchdog device.
290 * @inode: inode of device 455 * @inode: inode of device
291 * @file: file handle to device 456 * @file: file handle to device
292 * 457 *
293 * This is the code for when /dev/watchdog gets closed. We will only 458 * This is the code for when /dev/watchdog gets closed. We will only
294 * stop the watchdog when we have received the magic char (and nowayout 459 * stop the watchdog when we have received the magic char (and nowayout
@@ -297,6 +462,7 @@ out:
297 462
298static int watchdog_release(struct inode *inode, struct file *file) 463static int watchdog_release(struct inode *inode, struct file *file)
299{ 464{
465 struct watchdog_device *wdd = file->private_data;
300 int err = -EBUSY; 466 int err = -EBUSY;
301 467
302 /* 468 /*
@@ -310,7 +476,10 @@ static int watchdog_release(struct inode *inode, struct file *file)
310 476
311 /* If the watchdog was not stopped, send a keepalive ping */ 477 /* If the watchdog was not stopped, send a keepalive ping */
312 if (err < 0) { 478 if (err < 0) {
313 pr_crit("%s: watchdog did not stop!\n", wdd->info->identity); 479 mutex_lock(&wdd->lock);
480 if (!test_bit(WDOG_UNREGISTERED, &wdd->status))
481 dev_crit(wdd->dev, "watchdog did not stop!\n");
482 mutex_unlock(&wdd->lock);
314 watchdog_ping(wdd); 483 watchdog_ping(wdd);
315 } 484 }
316 485
@@ -320,6 +489,10 @@ static int watchdog_release(struct inode *inode, struct file *file)
320 /* make sure that /dev/watchdog can be re-opened */ 489 /* make sure that /dev/watchdog can be re-opened */
321 clear_bit(WDOG_DEV_OPEN, &wdd->status); 490 clear_bit(WDOG_DEV_OPEN, &wdd->status);
322 491
492 /* Note wdd may be gone after this, do not use after this! */
493 if (wdd->ops->unref)
494 wdd->ops->unref(wdd);
495
323 return 0; 496 return 0;
324} 497}
325 498
@@ -338,62 +511,92 @@ static struct miscdevice watchdog_miscdev = {
338}; 511};
339 512
340/* 513/*
341 * watchdog_dev_register: 514 * watchdog_dev_register: register a watchdog device
342 * @watchdog: watchdog device 515 * @watchdog: watchdog device
343 * 516 *
344 * Register a watchdog device as /dev/watchdog. /dev/watchdog 517 * Register a watchdog device including handling the legacy
345 * is actually a miscdevice and thus we set it up like that. 518 * /dev/watchdog node. /dev/watchdog is actually a miscdevice and
519 * thus we set it up like that.
346 */ 520 */
347 521
348int watchdog_dev_register(struct watchdog_device *watchdog) 522int watchdog_dev_register(struct watchdog_device *watchdog)
349{ 523{
350 int err; 524 int err, devno;
351 525
352 /* Only one device can register for /dev/watchdog */ 526 if (watchdog->id == 0) {
353 if (test_and_set_bit(0, &watchdog_dev_busy)) { 527 watchdog_miscdev.parent = watchdog->parent;
354 pr_err("only one watchdog can use /dev/watchdog\n"); 528 err = misc_register(&watchdog_miscdev);
355 return -EBUSY; 529 if (err != 0) {
530 pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
531 watchdog->info->identity, WATCHDOG_MINOR, err);
532 if (err == -EBUSY)
533 pr_err("%s: a legacy watchdog module is probably present.\n",
534 watchdog->info->identity);
535 return err;
536 }
537 old_wdd = watchdog;
356 } 538 }
357 539
358 wdd = watchdog; 540 /* Fill in the data structures */
359 541 devno = MKDEV(MAJOR(watchdog_devt), watchdog->id);
360 err = misc_register(&watchdog_miscdev); 542 cdev_init(&watchdog->cdev, &watchdog_fops);
361 if (err != 0) { 543 watchdog->cdev.owner = watchdog->ops->owner;
362 pr_err("%s: cannot register miscdev on minor=%d (err=%d)\n", 544
363 watchdog->info->identity, WATCHDOG_MINOR, err); 545 /* Add the device */
364 goto out; 546 err = cdev_add(&watchdog->cdev, devno, 1);
547 if (err) {
548 pr_err("watchdog%d unable to add device %d:%d\n",
549 watchdog->id, MAJOR(watchdog_devt), watchdog->id);
550 if (watchdog->id == 0) {
551 misc_deregister(&watchdog_miscdev);
552 old_wdd = NULL;
553 }
365 } 554 }
366
367 return 0;
368
369out:
370 wdd = NULL;
371 clear_bit(0, &watchdog_dev_busy);
372 return err; 555 return err;
373} 556}
374 557
375/* 558/*
376 * watchdog_dev_unregister: 559 * watchdog_dev_unregister: unregister a watchdog device
377 * @watchdog: watchdog device 560 * @watchdog: watchdog device
378 * 561 *
379 * Deregister the /dev/watchdog device. 562 * Unregister the watchdog and if needed the legacy /dev/watchdog device.
380 */ 563 */
381 564
382int watchdog_dev_unregister(struct watchdog_device *watchdog) 565int watchdog_dev_unregister(struct watchdog_device *watchdog)
383{ 566{
384 /* Check that a watchdog device was registered in the past */ 567 mutex_lock(&watchdog->lock);
385 if (!test_bit(0, &watchdog_dev_busy) || !wdd) 568 set_bit(WDOG_UNREGISTERED, &watchdog->status);
386 return -ENODEV; 569 mutex_unlock(&watchdog->lock);
387 570
388 /* We can only unregister the watchdog device that was registered */ 571 cdev_del(&watchdog->cdev);
389 if (watchdog != wdd) { 572 if (watchdog->id == 0) {
390 pr_err("%s: watchdog was not registered as /dev/watchdog\n", 573 misc_deregister(&watchdog_miscdev);
391 watchdog->info->identity); 574 old_wdd = NULL;
392 return -ENODEV;
393 } 575 }
394
395 misc_deregister(&watchdog_miscdev);
396 wdd = NULL;
397 clear_bit(0, &watchdog_dev_busy);
398 return 0; 576 return 0;
399} 577}
578
579/*
580 * watchdog_dev_init: init dev part of watchdog core
581 *
582 * Allocate a range of chardev nodes to use for watchdog devices
583 */
584
585int __init watchdog_dev_init(void)
586{
587 int err = alloc_chrdev_region(&watchdog_devt, 0, MAX_DOGS, "watchdog");
588 if (err < 0)
589 pr_err("watchdog: unable to allocate char dev region\n");
590 return err;
591}
592
593/*
594 * watchdog_dev_exit: exit dev part of watchdog core
595 *
596 * Release the range of chardev nodes used for watchdog devices
597 */
598
599void __exit watchdog_dev_exit(void)
600{
601 unregister_chrdev_region(watchdog_devt, MAX_DOGS);
602}
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index ac40716b44e9..da70f0facd2b 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -45,6 +45,8 @@ struct watchdog_info {
45#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ 45#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */
46#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ 46#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */
47#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */ 47#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */
48#define WDIOF_ALARMONLY 0x0400 /* Watchdog triggers a management or
49 other external alarm not a reboot */
48#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ 50#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */
49 51
50#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ 52#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */
@@ -54,6 +56,8 @@ struct watchdog_info {
54#ifdef __KERNEL__ 56#ifdef __KERNEL__
55 57
56#include <linux/bitops.h> 58#include <linux/bitops.h>
59#include <linux/device.h>
60#include <linux/cdev.h>
57 61
58struct watchdog_ops; 62struct watchdog_ops;
59struct watchdog_device; 63struct watchdog_device;
@@ -67,6 +71,8 @@ struct watchdog_device;
67 * @status: The routine that shows the status of the watchdog device. 71 * @status: The routine that shows the status of the watchdog device.
68 * @set_timeout:The routine for setting the watchdog devices timeout value. 72 * @set_timeout:The routine for setting the watchdog devices timeout value.
69 * @get_timeleft:The routine that get's the time that's left before a reset. 73 * @get_timeleft:The routine that get's the time that's left before a reset.
74 * @ref: The ref operation for dyn. allocated watchdog_device structs
75 * @unref: The unref operation for dyn. allocated watchdog_device structs
70 * @ioctl: The routines that handles extra ioctl calls. 76 * @ioctl: The routines that handles extra ioctl calls.
71 * 77 *
72 * The watchdog_ops structure contains a list of low-level operations 78 * The watchdog_ops structure contains a list of low-level operations
@@ -84,11 +90,17 @@ struct watchdog_ops {
84 unsigned int (*status)(struct watchdog_device *); 90 unsigned int (*status)(struct watchdog_device *);
85 int (*set_timeout)(struct watchdog_device *, unsigned int); 91 int (*set_timeout)(struct watchdog_device *, unsigned int);
86 unsigned int (*get_timeleft)(struct watchdog_device *); 92 unsigned int (*get_timeleft)(struct watchdog_device *);
93 void (*ref)(struct watchdog_device *);
94 void (*unref)(struct watchdog_device *);
87 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); 95 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
88}; 96};
89 97
90/** struct watchdog_device - The structure that defines a watchdog device 98/** struct watchdog_device - The structure that defines a watchdog device
91 * 99 *
100 * @id: The watchdog's ID. (Allocated by watchdog_register_device)
101 * @cdev: The watchdog's Character device.
102 * @dev: The device for our watchdog
103 * @parent: The parent bus device
92 * @info: Pointer to a watchdog_info structure. 104 * @info: Pointer to a watchdog_info structure.
93 * @ops: Pointer to the list of watchdog operations. 105 * @ops: Pointer to the list of watchdog operations.
94 * @bootstatus: Status of the watchdog device at boot. 106 * @bootstatus: Status of the watchdog device at boot.
@@ -96,6 +108,7 @@ struct watchdog_ops {
96 * @min_timeout:The watchdog devices minimum timeout value. 108 * @min_timeout:The watchdog devices minimum timeout value.
97 * @max_timeout:The watchdog devices maximum timeout value. 109 * @max_timeout:The watchdog devices maximum timeout value.
98 * @driver-data:Pointer to the drivers private data. 110 * @driver-data:Pointer to the drivers private data.
111 * @lock: Lock for watchdog core internal use only.
99 * @status: Field that contains the devices internal status bits. 112 * @status: Field that contains the devices internal status bits.
100 * 113 *
101 * The watchdog_device structure contains all information about a 114 * The watchdog_device structure contains all information about a
@@ -103,8 +116,15 @@ struct watchdog_ops {
103 * 116 *
104 * The driver-data field may not be accessed directly. It must be accessed 117 * The driver-data field may not be accessed directly. It must be accessed
105 * via the watchdog_set_drvdata and watchdog_get_drvdata helpers. 118 * via the watchdog_set_drvdata and watchdog_get_drvdata helpers.
119 *
120 * The lock field is for watchdog core internal use only and should not be
121 * touched.
106 */ 122 */
107struct watchdog_device { 123struct watchdog_device {
124 int id;
125 struct cdev cdev;
126 struct device *dev;
127 struct device *parent;
108 const struct watchdog_info *info; 128 const struct watchdog_info *info;
109 const struct watchdog_ops *ops; 129 const struct watchdog_ops *ops;
110 unsigned int bootstatus; 130 unsigned int bootstatus;
@@ -112,12 +132,14 @@ struct watchdog_device {
112 unsigned int min_timeout; 132 unsigned int min_timeout;
113 unsigned int max_timeout; 133 unsigned int max_timeout;
114 void *driver_data; 134 void *driver_data;
135 struct mutex lock;
115 unsigned long status; 136 unsigned long status;
116/* Bit numbers for status flags */ 137/* Bit numbers for status flags */
117#define WDOG_ACTIVE 0 /* Is the watchdog running/active */ 138#define WDOG_ACTIVE 0 /* Is the watchdog running/active */
118#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */ 139#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */
119#define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */ 140#define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */
120#define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */ 141#define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */
142#define WDOG_UNREGISTERED 4 /* Has the device been unregistered */
121}; 143};
122 144
123#ifdef CONFIG_WATCHDOG_NOWAYOUT 145#ifdef CONFIG_WATCHDOG_NOWAYOUT
@@ -128,6 +150,12 @@ struct watchdog_device {
128#define WATCHDOG_NOWAYOUT_INIT_STATUS 0 150#define WATCHDOG_NOWAYOUT_INIT_STATUS 0
129#endif 151#endif
130 152
153/* Use the following function to check wether or not the watchdog is active */
154static inline bool watchdog_active(struct watchdog_device *wdd)
155{
156 return test_bit(WDOG_ACTIVE, &wdd->status);
157}
158
131/* Use the following function to set the nowayout feature */ 159/* Use the following function to set the nowayout feature */
132static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout) 160static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool nowayout)
133{ 161{