aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/watchdog/00-INDEX2
-rw-r--r--Documentation/watchdog/watchdog-kernel-api.txt119
-rw-r--r--drivers/watchdog/Kconfig11
-rw-r--r--drivers/watchdog/Makefile4
-rw-r--r--drivers/watchdog/watchdog_core.c101
-rw-r--r--drivers/watchdog/watchdog_dev.c235
-rw-r--r--drivers/watchdog/watchdog_dev.h33
-rw-r--r--include/linux/watchdog.h61
8 files changed, 566 insertions, 0 deletions
diff --git a/Documentation/watchdog/00-INDEX b/Documentation/watchdog/00-INDEX
index ee994513a9b1..fc51128071c2 100644
--- a/Documentation/watchdog/00-INDEX
+++ b/Documentation/watchdog/00-INDEX
@@ -8,6 +8,8 @@ src/
8 - directory holding watchdog related example programs. 8 - directory holding watchdog related example programs.
9watchdog-api.txt 9watchdog-api.txt
10 - description of the Linux Watchdog driver API. 10 - description of the Linux Watchdog driver API.
11watchdog-kernel-api.txt
12 - description of the Linux WatchDog Timer Driver Core kernel API.
11watchdog-parameters.txt 13watchdog-parameters.txt
12 - information on driver parameters (for drivers other than 14 - information on driver parameters (for drivers other than
13 the ones that have driver-specific files here) 15 the ones that have driver-specific files here)
diff --git a/Documentation/watchdog/watchdog-kernel-api.txt b/Documentation/watchdog/watchdog-kernel-api.txt
new file mode 100644
index 000000000000..3db67e74b80e
--- /dev/null
+++ b/Documentation/watchdog/watchdog-kernel-api.txt
@@ -0,0 +1,119 @@
1The Linux WatchDog Timer Driver Core kernel API.
2===============================================
3Last reviewed: 22-Jul-2011
4
5Wim Van Sebroeck <wim@iguana.be>
6
7Introduction
8------------
9This document does not describe what a WatchDog Timer (WDT) Driver or Device is.
10It also does not describe the API which can be used by user space to communicate
11with a WatchDog Timer. If you want to know this then please read the following
12file: Documentation/watchdog/watchdog-api.txt .
13
14So what does this document describe? It describes the API that can be used by
15WatchDog Timer Drivers that want to use the WatchDog Timer Driver Core
16Framework. This framework provides all interfacing towards user space so that
17the same code does not have to be reproduced each time. This also means that
18a watchdog timer driver then only needs to provide the different routines
19(operations) that control the watchdog timer (WDT).
20
21The API
22-------
23Each watchdog timer driver that wants to use the WatchDog Timer Driver Core
24must #include <linux/watchdog.h> (you would have to do this anyway when
25writing a watchdog device driver). This include file contains following
26register/unregister routines:
27
28extern int watchdog_register_device(struct watchdog_device *);
29extern void watchdog_unregister_device(struct watchdog_device *);
30
31The watchdog_register_device routine registers a watchdog timer device.
32The parameter of this routine is a pointer to a watchdog_device structure.
33This routine returns zero on success and a negative errno code for failure.
34
35The watchdog_unregister_device routine deregisters a registered watchdog timer
36device. The parameter of this routine is the pointer to the registered
37watchdog_device structure.
38
39The watchdog device structure looks like this:
40
41struct watchdog_device {
42 const struct watchdog_info *info;
43 const struct watchdog_ops *ops;
44 void *driver_data;
45 unsigned long status;
46};
47
48It contains following fields:
49* info: a pointer to a watchdog_info structure. This structure gives some
50 additional information about the watchdog timer itself. (Like it's unique name)
51* ops: a pointer to the list of watchdog operations that the watchdog supports.
52* driver_data: a pointer to the drivers private data of a watchdog device.
53 This data should only be accessed via the watchdog_set_drvadata and
54 watchdog_get_drvdata routines.
55* status: this field contains a number of status bits that give extra
56 information about the status of the device (Like: is the device opened via
57 the /dev/watchdog interface or not, ...).
58
59The list of watchdog operations is defined as:
60
61struct watchdog_ops {
62 struct module *owner;
63 /* mandatory operations */
64 int (*start)(struct watchdog_device *);
65 int (*stop)(struct watchdog_device *);
66 /* optional operations */
67 int (*ping)(struct watchdog_device *);
68};
69
70It is important that you first define the module owner of the watchdog timer
71driver's operations. This module owner will be used to lock the module when
72the watchdog is active. (This to avoid a system crash when you unload the
73module and /dev/watchdog is still open).
74Some operations are mandatory and some are optional. The mandatory operations
75are:
76* start: this is a pointer to the routine that starts the watchdog timer
77 device.
78 The routine needs a pointer to the watchdog timer device structure as a
79 parameter. It returns zero on success or a negative errno code for failure.
80* stop: with this routine the watchdog timer device is being stopped.
81 The routine needs a pointer to the watchdog timer device structure as a
82 parameter. It returns zero on success or a negative errno code for failure.
83 Some watchdog timer hardware can only be started and not be stopped. The
84 driver supporting this hardware needs to make sure that a start and stop
85 routine is being provided. This can be done by using a timer in the driver
86 that regularly sends a keepalive ping to the watchdog timer hardware.
87
88Not all watchdog timer hardware supports the same functionality. That's why
89all other routines/operations are optional. They only need to be provided if
90they are supported. These optional routines/operations are:
91* ping: this is the routine that sends a keepalive ping to the watchdog timer
92 hardware.
93 The routine needs a pointer to the watchdog timer device structure as a
94 parameter. It returns zero on success or a negative errno code for failure.
95 Most hardware that does not support this as a separate function uses the
96 start function to restart the watchdog timer hardware. And that's also what
97 the watchdog timer driver core does: to send a keepalive ping to the watchdog
98 timer hardware it will either use the ping operation (when available) or the
99 start operation (when the ping operation is not available).
100
101The status bits should (preferably) be set with the set_bit and clear_bit alike
102bit-operations. The status bits that are defined are:
103* WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device
104 was opened via /dev/watchdog.
105 (This bit should only be used by the WatchDog Timer Driver Core).
106
107To get or set driver specific data the following two helper functions should be
108used:
109
110static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
111static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
112
113The watchdog_set_drvdata function allows you to add driver specific data. The
114arguments of this function are the watchdog device where you want to add the
115driver specific data to and a pointer to the data itself.
116
117The watchdog_get_drvdata function allows you to retrieve driver specific data.
118The argument of this function is the watchdog device where you want to retrieve
119data from. The function retruns the pointer to the driver specific data.
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 0635e72e0794..f441726ddf2b 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -28,6 +28,17 @@ menuconfig WATCHDOG
28 28
29if WATCHDOG 29if WATCHDOG
30 30
31config WATCHDOG_CORE
32 bool "WatchDog Timer Driver Core"
33 ---help---
34 Say Y here if you want to use the new watchdog timer driver core.
35 This driver provides a framework for all watchdog timer drivers
36 and gives them the /dev/watchdog interface (and later also the
37 sysfs interface).
38
39 To compile this driver as a module, choose M here: the module will
40 be called watchdog.
41
31config WATCHDOG_NOWAYOUT 42config WATCHDOG_NOWAYOUT
32 bool "Disable watchdog shutdown on close" 43 bool "Disable watchdog shutdown on close"
33 help 44 help
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 9eaa212398d7..55bd5740e910 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -2,6 +2,10 @@
2# Makefile for the WatchDog device drivers. 2# Makefile for the WatchDog device drivers.
3# 3#
4 4
5# The WatchDog Timer Driver Core.
6watchdog-objs += watchdog_core.o watchdog_dev.o
7obj-$(CONFIG_WATCHDOG_CORE) += watchdog.o
8
5# Only one watchdog can succeed. We probe the ISA/PCI/USB based 9# Only one watchdog can succeed. We probe the ISA/PCI/USB based
6# watchdog-cards first, then the architecture specific watchdog 10# watchdog-cards first, then the architecture specific watchdog
7# drivers and then the architecture independent "softdog" driver. 11# drivers and then the architecture independent "softdog" driver.
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
new file mode 100644
index 000000000000..47fc1267ad4e
--- /dev/null
+++ b/drivers/watchdog/watchdog_core.c
@@ -0,0 +1,101 @@
1/*
2 * watchdog_core.c
3 *
4 * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
5 * All Rights Reserved.
6 *
7 * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
8 *
9 * This source code is part of the generic code that can be used
10 * by all the watchdog timer drivers.
11 *
12 * Based on source code of the following authors:
13 * Matt Domsch <Matt_Domsch@dell.com>,
14 * Rob Radez <rob@osinvestor.com>,
15 * Rusty Lynch <rusty@linux.co.intel.com>
16 * Satyam Sharma <satyam@infradead.org>
17 * Randy Dunlap <randy.dunlap@oracle.com>
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
23 *
24 * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
25 * admit liability nor provide warranty for any of this software.
26 * This material is provided "AS-IS" and at no charge.
27 */
28
29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30
31#include <linux/module.h> /* For EXPORT_SYMBOL/module stuff/... */
32#include <linux/types.h> /* For standard types */
33#include <linux/errno.h> /* For the -ENODEV/... values */
34#include <linux/kernel.h> /* For printk/panic/... */
35#include <linux/watchdog.h> /* For watchdog specific items */
36#include <linux/init.h> /* For __init/__exit/... */
37
38#include "watchdog_dev.h" /* For watchdog_dev_register/... */
39
40/**
41 * watchdog_register_device() - register a watchdog device
42 * @wdd: watchdog device
43 *
44 * Register a watchdog device with the kernel so that the
45 * watchdog timer can be accessed from userspace.
46 *
47 * A zero is returned on success and a negative errno code for
48 * failure.
49 */
50int watchdog_register_device(struct watchdog_device *wdd)
51{
52 int ret;
53
54 if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
55 return -EINVAL;
56
57 /* Mandatory operations need to be supported */
58 if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
59 return -EINVAL;
60
61 /*
62 * Note: now that all watchdog_device data has been verified, we
63 * will not check this anymore in other functions. If data gets
64 * corrupted in a later stage then we expect a kernel panic!
65 */
66
67 /* We only support 1 watchdog device via the /dev/watchdog interface */
68 ret = watchdog_dev_register(wdd);
69 if (ret) {
70 pr_err("error registering /dev/watchdog (err=%d).\n", ret);
71 return ret;
72 }
73
74 return 0;
75}
76EXPORT_SYMBOL_GPL(watchdog_register_device);
77
78/**
79 * watchdog_unregister_device() - unregister a watchdog device
80 * @wdd: watchdog device to unregister
81 *
82 * Unregister a watchdog device that was previously successfully
83 * registered with watchdog_register_device().
84 */
85void watchdog_unregister_device(struct watchdog_device *wdd)
86{
87 int ret;
88
89 if (wdd == NULL)
90 return;
91
92 ret = watchdog_dev_unregister(wdd);
93 if (ret)
94 pr_err("error unregistering /dev/watchdog (err=%d).\n", ret);
95}
96EXPORT_SYMBOL_GPL(watchdog_unregister_device);
97
98MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
99MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
100MODULE_DESCRIPTION("WatchDog Timer Driver Core");
101MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
new file mode 100644
index 000000000000..366f49ce69b8
--- /dev/null
+++ b/drivers/watchdog/watchdog_dev.c
@@ -0,0 +1,235 @@
1/*
2 * watchdog_dev.c
3 *
4 * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
5 * All Rights Reserved.
6 *
7 * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
8 *
9 *
10 * This source code is part of the generic code that can be used
11 * by all the watchdog timer drivers.
12 *
13 * This part of the generic code takes care of the following
14 * misc device: /dev/watchdog.
15 *
16 * Based on source code of the following authors:
17 * Matt Domsch <Matt_Domsch@dell.com>,
18 * Rob Radez <rob@osinvestor.com>,
19 * Rusty Lynch <rusty@linux.co.intel.com>
20 * Satyam Sharma <satyam@infradead.org>
21 * Randy Dunlap <randy.dunlap@oracle.com>
22 *
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version
26 * 2 of the License, or (at your option) any later version.
27 *
28 * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
29 * admit liability nor provide warranty for any of this software.
30 * This material is provided "AS-IS" and at no charge.
31 */
32
33#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34
35#include <linux/module.h> /* For module stuff/... */
36#include <linux/types.h> /* For standard types (like size_t) */
37#include <linux/errno.h> /* For the -ENODEV/... values */
38#include <linux/kernel.h> /* For printk/panic/... */
39#include <linux/fs.h> /* For file operations */
40#include <linux/watchdog.h> /* For watchdog specific items */
41#include <linux/miscdevice.h> /* For handling misc devices */
42#include <linux/init.h> /* For __init/__exit/... */
43#include <linux/uaccess.h> /* For copy_to_user/put_user/... */
44
45/* make sure we only register one /dev/watchdog device */
46static unsigned long watchdog_dev_busy;
47/* the watchdog device behind /dev/watchdog */
48static struct watchdog_device *wdd;
49
50/*
51 * watchdog_ping: ping the watchdog.
52 * @wddev: the watchdog device to ping
53 *
54 * If the watchdog has no own ping operation then it needs to be
55 * restarted via the start operation. This wrapper function does
56 * exactly that.
57 */
58
59static int watchdog_ping(struct watchdog_device *wddev)
60{
61 if (wddev->ops->ping)
62 return wddev->ops->ping(wddev); /* ping the watchdog */
63 else
64 return wddev->ops->start(wddev); /* restart the watchdog */
65}
66
67/*
68 * watchdog_write: writes to the watchdog.
69 * @file: file from VFS
70 * @data: user address of data
71 * @len: length of data
72 * @ppos: pointer to the file offset
73 *
74 * A write to a watchdog device is defined as a keepalive ping.
75 */
76
77static ssize_t watchdog_write(struct file *file, const char __user *data,
78 size_t len, loff_t *ppos)
79{
80 size_t i;
81 char c;
82
83 if (len == 0)
84 return 0;
85
86 for (i = 0; i != len; i++) {
87 if (get_user(c, data + i))
88 return -EFAULT;
89 }
90
91 /* someone wrote to us, so we send the watchdog a keepalive ping */
92 watchdog_ping(wdd);
93
94 return len;
95}
96
97/*
98 * watchdog_open: open the /dev/watchdog device.
99 * @inode: inode of device
100 * @file: file handle to device
101 *
102 * When the /dev/watchdog device gets opened, we start the watchdog.
103 * Watch out: the /dev/watchdog device is single open, so we make sure
104 * it can only be opened once.
105 */
106
107static int watchdog_open(struct inode *inode, struct file *file)
108{
109 int err = -EBUSY;
110
111 /* the watchdog is single open! */
112 if (test_and_set_bit(WDOG_DEV_OPEN, &wdd->status))
113 return -EBUSY;
114
115 /*
116 * If the /dev/watchdog device is open, we don't want the module
117 * to be unloaded.
118 */
119 if (!try_module_get(wdd->ops->owner))
120 goto out;
121
122 err = wdd->ops->start(wdd);
123 if (err < 0)
124 goto out_mod;
125
126 /* dev/watchdog is a virtual (and thus non-seekable) filesystem */
127 return nonseekable_open(inode, file);
128
129out_mod:
130 module_put(wdd->ops->owner);
131out:
132 clear_bit(WDOG_DEV_OPEN, &wdd->status);
133 return err;
134}
135
136/*
137 * watchdog_release: release the /dev/watchdog device.
138 * @inode: inode of device
139 * @file: file handle to device
140 *
141 * This is the code for when /dev/watchdog gets closed.
142 */
143
144static int watchdog_release(struct inode *inode, struct file *file)
145{
146 int err;
147
148 err = wdd->ops->stop(wdd);
149 if (err != 0) {
150 pr_crit("%s: watchdog did not stop!\n", wdd->info->identity);
151 watchdog_ping(wdd);
152 }
153
154 /* Allow the owner module to be unloaded again */
155 module_put(wdd->ops->owner);
156
157 /* make sure that /dev/watchdog can be re-opened */
158 clear_bit(WDOG_DEV_OPEN, &wdd->status);
159
160 return 0;
161}
162
163static const struct file_operations watchdog_fops = {
164 .owner = THIS_MODULE,
165 .write = watchdog_write,
166 .open = watchdog_open,
167 .release = watchdog_release,
168};
169
170static struct miscdevice watchdog_miscdev = {
171 .minor = WATCHDOG_MINOR,
172 .name = "watchdog",
173 .fops = &watchdog_fops,
174};
175
176/*
177 * watchdog_dev_register:
178 * @watchdog: watchdog device
179 *
180 * Register a watchdog device as /dev/watchdog. /dev/watchdog
181 * is actually a miscdevice and thus we set it up like that.
182 */
183
184int watchdog_dev_register(struct watchdog_device *watchdog)
185{
186 int err;
187
188 /* Only one device can register for /dev/watchdog */
189 if (test_and_set_bit(0, &watchdog_dev_busy)) {
190 pr_err("only one watchdog can use /dev/watchdog.\n");
191 return -EBUSY;
192 }
193
194 wdd = watchdog;
195
196 err = misc_register(&watchdog_miscdev);
197 if (err != 0) {
198 pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
199 watchdog->info->identity, WATCHDOG_MINOR, err);
200 goto out;
201 }
202
203 return 0;
204
205out:
206 wdd = NULL;
207 clear_bit(0, &watchdog_dev_busy);
208 return err;
209}
210
211/*
212 * watchdog_dev_unregister:
213 * @watchdog: watchdog device
214 *
215 * Deregister the /dev/watchdog device.
216 */
217
218int watchdog_dev_unregister(struct watchdog_device *watchdog)
219{
220 /* Check that a watchdog device was registered in the past */
221 if (!test_bit(0, &watchdog_dev_busy) || !wdd)
222 return -ENODEV;
223
224 /* We can only unregister the watchdog device that was registered */
225 if (watchdog != wdd) {
226 pr_err("%s: watchdog was not registered as /dev/watchdog.\n",
227 watchdog->info->identity);
228 return -ENODEV;
229 }
230
231 misc_deregister(&watchdog_miscdev);
232 wdd = NULL;
233 clear_bit(0, &watchdog_dev_busy);
234 return 0;
235}
diff --git a/drivers/watchdog/watchdog_dev.h b/drivers/watchdog/watchdog_dev.h
new file mode 100644
index 000000000000..bc7612be25ce
--- /dev/null
+++ b/drivers/watchdog/watchdog_dev.h
@@ -0,0 +1,33 @@
1/*
2 * watchdog_core.h
3 *
4 * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>,
5 * All Rights Reserved.
6 *
7 * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>.
8 *
9 * This source code is part of the generic code that can be used
10 * by all the watchdog timer drivers.
11 *
12 * Based on source code of the following authors:
13 * Matt Domsch <Matt_Domsch@dell.com>,
14 * Rob Radez <rob@osinvestor.com>,
15 * Rusty Lynch <rusty@linux.co.intel.com>
16 * Satyam Sharma <satyam@infradead.org>
17 * Randy Dunlap <randy.dunlap@oracle.com>
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
23 *
24 * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw.
25 * admit liability nor provide warranty for any of this software.
26 * This material is provided "AS-IS" and at no charge.
27 */
28
29/*
30 * Functions/procedures to be called by the core
31 */
32int watchdog_dev_register(struct watchdog_device *);
33int watchdog_dev_unregister(struct watchdog_device *);
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index 011bcfeb9f09..5ab31bfd2906 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -59,6 +59,67 @@ struct watchdog_info {
59#define WATCHDOG_NOWAYOUT 0 59#define WATCHDOG_NOWAYOUT 0
60#endif 60#endif
61 61
62struct watchdog_ops;
63struct watchdog_device;
64
65/** struct watchdog_ops - The watchdog-devices operations
66 *
67 * @owner: The module owner.
68 * @start: The routine for starting the watchdog device.
69 * @stop: The routine for stopping the watchdog device.
70 * @ping: The routine that sends a keepalive ping to the watchdog device.
71 *
72 * The watchdog_ops structure contains a list of low-level operations
73 * that control a watchdog device. It also contains the module that owns
74 * these operations. The start and stop function are mandatory, all other
75 * functions are optonal.
76 */
77struct watchdog_ops {
78 struct module *owner;
79 /* mandatory operations */
80 int (*start)(struct watchdog_device *);
81 int (*stop)(struct watchdog_device *);
82 /* optional operations */
83 int (*ping)(struct watchdog_device *);
84};
85
86/** struct watchdog_device - The structure that defines a watchdog device
87 *
88 * @info: Pointer to a watchdog_info structure.
89 * @ops: Pointer to the list of watchdog operations.
90 * @driver-data:Pointer to the drivers private data.
91 * @status: Field that contains the devices internal status bits.
92 *
93 * The watchdog_device structure contains all information about a
94 * watchdog timer device.
95 *
96 * The driver-data field may not be accessed directly. It must be accessed
97 * via the watchdog_set_drvdata and watchdog_get_drvdata helpers.
98 */
99struct watchdog_device {
100 const struct watchdog_info *info;
101 const struct watchdog_ops *ops;
102 void *driver_data;
103 unsigned long status;
104/* Bit numbers for status flags */
105#define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */
106};
107
108/* Use the following functions to manipulate watchdog driver specific data */
109static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
110{
111 wdd->driver_data = data;
112}
113
114static inline void *watchdog_get_drvdata(struct watchdog_device *wdd)
115{
116 return wdd->driver_data;
117}
118
119/* drivers/watchdog/core/watchdog_core.c */
120extern int watchdog_register_device(struct watchdog_device *);
121extern void watchdog_unregister_device(struct watchdog_device *);
122
62#endif /* __KERNEL__ */ 123#endif /* __KERNEL__ */
63 124
64#endif /* ifndef _LINUX_WATCHDOG_H */ 125#endif /* ifndef _LINUX_WATCHDOG_H */