aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog/watchdog_dev.c
diff options
context:
space:
mode:
authorWim Van Sebroeck <wim@iguana.be>2011-07-22 14:57:55 -0400
committerWim Van Sebroeck <wim@iguana.be>2011-07-28 04:01:09 -0400
commit234445b4e4542f3e0f216459245ab369a18adcf2 (patch)
treeed670bb2aa3eae41f00e5217fb786eaa9fbe6cb3 /drivers/watchdog/watchdog_dev.c
parentc2dc00e494cc476551b9beeb883910391ff59737 (diff)
watchdog: WatchDog Timer Driver Core - Add WDIOC_SETOPTIONS ioctl
This part add's the WDIOC_SETOPTIONS ioctl functionality to the WatchDog Timer Driver Core framework. Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Wim Van Sebroeck <wim@iguana.be> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/watchdog/watchdog_dev.c')
-rw-r--r--drivers/watchdog/watchdog_dev.c79
1 files changed, 72 insertions, 7 deletions
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 2fb4cecd50d8..9f5550e16ab5 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -54,14 +54,64 @@ static struct watchdog_device *wdd;
54 * If the watchdog has no own ping operation then it needs to be 54 * If the watchdog has no own ping operation then it needs to be
55 * restarted via the start operation. This wrapper function does 55 * restarted via the start operation. This wrapper function does
56 * exactly that. 56 * exactly that.
57 * We only ping when the watchdog device is running.
57 */ 58 */
58 59
59static int watchdog_ping(struct watchdog_device *wddev) 60static int watchdog_ping(struct watchdog_device *wddev)
60{ 61{
61 if (wddev->ops->ping) 62 if (test_bit(WDOG_ACTIVE, &wdd->status)) {
62 return wddev->ops->ping(wddev); /* ping the watchdog */ 63 if (wddev->ops->ping)
63 else 64 return wddev->ops->ping(wddev); /* ping the watchdog */
64 return wddev->ops->start(wddev); /* restart the watchdog */ 65 else
66 return wddev->ops->start(wddev); /* restart watchdog */
67 }
68 return 0;
69}
70
71/*
72 * watchdog_start: wrapper to start the watchdog.
73 * @wddev: the watchdog device to start
74 *
75 * Start the watchdog if it is not active and mark it active.
76 * This function returns zero on success or a negative errno code for
77 * failure.
78 */
79
80static int watchdog_start(struct watchdog_device *wddev)
81{
82 int err;
83
84 if (!test_bit(WDOG_ACTIVE, &wdd->status)) {
85 err = wddev->ops->start(wddev);
86 if (err < 0)
87 return err;
88
89 set_bit(WDOG_ACTIVE, &wdd->status);
90 }
91 return 0;
92}
93
94/*
95 * watchdog_stop: wrapper to stop the watchdog.
96 * @wddev: the watchdog device to stop
97 *
98 * Stop the watchdog if it is still active and unmark it active.
99 * This function returns zero on success or a negative errno code for
100 * failure.
101 */
102
103static int watchdog_stop(struct watchdog_device *wddev)
104{
105 int err;
106
107 if (test_bit(WDOG_ACTIVE, &wdd->status)) {
108 err = wddev->ops->stop(wddev);
109 if (err < 0)
110 return err;
111
112 clear_bit(WDOG_ACTIVE, &wdd->status);
113 }
114 return 0;
65} 115}
66 116
67/* 117/*
@@ -110,6 +160,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
110 void __user *argp = (void __user *)arg; 160 void __user *argp = (void __user *)arg;
111 int __user *p = argp; 161 int __user *p = argp;
112 unsigned int val; 162 unsigned int val;
163 int err;
113 164
114 switch (cmd) { 165 switch (cmd) {
115 case WDIOC_GETSUPPORT: 166 case WDIOC_GETSUPPORT:
@@ -120,6 +171,20 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
120 return put_user(val, p); 171 return put_user(val, p);
121 case WDIOC_GETBOOTSTATUS: 172 case WDIOC_GETBOOTSTATUS:
122 return put_user(wdd->bootstatus, p); 173 return put_user(wdd->bootstatus, p);
174 case WDIOC_SETOPTIONS:
175 if (get_user(val, p))
176 return -EFAULT;
177 if (val & WDIOS_DISABLECARD) {
178 err = watchdog_stop(wdd);
179 if (err < 0)
180 return err;
181 }
182 if (val & WDIOS_ENABLECARD) {
183 err = watchdog_start(wdd);
184 if (err < 0)
185 return err;
186 }
187 return 0;
123 case WDIOC_KEEPALIVE: 188 case WDIOC_KEEPALIVE:
124 if (!(wdd->info->options & WDIOF_KEEPALIVEPING)) 189 if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
125 return -EOPNOTSUPP; 190 return -EOPNOTSUPP;
@@ -155,7 +220,7 @@ static int watchdog_open(struct inode *inode, struct file *file)
155 if (!try_module_get(wdd->ops->owner)) 220 if (!try_module_get(wdd->ops->owner))
156 goto out; 221 goto out;
157 222
158 err = wdd->ops->start(wdd); 223 err = watchdog_start(wdd);
159 if (err < 0) 224 if (err < 0)
160 goto out_mod; 225 goto out_mod;
161 226
@@ -181,8 +246,8 @@ static int watchdog_release(struct inode *inode, struct file *file)
181{ 246{
182 int err; 247 int err;
183 248
184 err = wdd->ops->stop(wdd); 249 err = watchdog_stop(wdd);
185 if (err != 0) { 250 if (err < 0) {
186 pr_crit("%s: watchdog did not stop!\n", wdd->info->identity); 251 pr_crit("%s: watchdog did not stop!\n", wdd->info->identity);
187 watchdog_ping(wdd); 252 watchdog_ping(wdd);
188 } 253 }