Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
watchdog_dev.c
Go to the documentation of this file.
1 /*
2  * watchdog_dev.c
3  *
4  * (c) Copyright 2008-2011 Alan Cox <[email protected]>,
5  * All Rights Reserved.
6  *
7  * (c) Copyright 2008-2011 Wim Van Sebroeck <[email protected]>.
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 <[email protected]>,
18  * Rob Radez <[email protected]>,
19  * Rusty Lynch <[email protected]>
20  * Satyam Sharma <[email protected]>
21  * Randy Dunlap <[email protected]>
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 #include "watchdog_core.h"
46 
47 /* the dev_t structure to store the dynamically allocated watchdog devices */
48 static dev_t watchdog_devt;
49 /* the watchdog device behind /dev/watchdog */
50 static struct watchdog_device *old_wdd;
51 
52 /*
53  * watchdog_ping: ping the watchdog.
54  * @wddev: the watchdog device to ping
55  *
56  * If the watchdog has no own ping operation then it needs to be
57  * restarted via the start operation. This wrapper function does
58  * exactly that.
59  * We only ping when the watchdog device is running.
60  */
61 
62 static int watchdog_ping(struct watchdog_device *wddev)
63 {
64  int err = 0;
65 
66  mutex_lock(&wddev->lock);
67 
68  if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
69  err = -ENODEV;
70  goto out_ping;
71  }
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 
81 out_ping:
82  mutex_unlock(&wddev->lock);
83  return err;
84 }
85 
86 /*
87  * watchdog_start: wrapper to start the watchdog.
88  * @wddev: the watchdog device to start
89  *
90  * Start the watchdog if it is not active and mark it active.
91  * This function returns zero on success or a negative errno code for
92  * failure.
93  */
94 
95 static int watchdog_start(struct watchdog_device *wddev)
96 {
97  int err = 0;
98 
99  mutex_lock(&wddev->lock);
100 
101  if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
102  err = -ENODEV;
103  goto out_start;
104  }
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 
113 out_start:
114  mutex_unlock(&wddev->lock);
115  return err;
116 }
117 
118 /*
119  * watchdog_stop: wrapper to stop the watchdog.
120  * @wddev: the watchdog device to stop
121  *
122  * Stop the watchdog if it is still active and unmark it active.
123  * This function returns zero on success or a negative errno code for
124  * failure.
125  * If the 'nowayout' feature was set, the watchdog cannot be stopped.
126  */
127 
128 static int watchdog_stop(struct watchdog_device *wddev)
129 {
130  int err = 0;
131 
132  mutex_lock(&wddev->lock);
133 
134  if (test_bit(WDOG_UNREGISTERED, &wddev->status)) {
135  err = -ENODEV;
136  goto out_stop;
137  }
138 
139  if (!watchdog_active(wddev))
140  goto out_stop;
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)
150  clear_bit(WDOG_ACTIVE, &wddev->status);
151 
152 out_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 
165 static 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;
179  }
180 
181  *status = wddev->ops->status(wddev);
182 
183 out_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 
194 static 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 
216 out_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 
229 static 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 
247 out_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 
259 static 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 
276 out_ioctl:
277  mutex_unlock(&wddev->lock);
278  return err;
279 }
280 
281 /*
282  * watchdog_write: writes to the watchdog.
283  * @file: file from VFS
284  * @data: user address of data
285  * @len: length of data
286  * @ppos: pointer to the file offset
287  *
288  * A write to a watchdog device is defined as a keepalive ping.
289  * Writing the magic 'V' sequence allows the next close to turn
290  * off the watchdog (if 'nowayout' is not set).
291  */
292 
293 static ssize_t watchdog_write(struct file *file, const char __user *data,
294  size_t len, loff_t *ppos)
295 {
296  struct watchdog_device *wdd = file->private_data;
297  size_t i;
298  char c;
299 
300  if (len == 0)
301  return 0;
302 
303  /*
304  * Note: just in case someone wrote the magic character
305  * five months ago...
306  */
308 
309  /* scan to see whether or not we got the magic character */
310  for (i = 0; i != len; i++) {
311  if (get_user(c, data + i))
312  return -EFAULT;
313  if (c == 'V')
315  }
316 
317  /* someone wrote to us, so we send the watchdog a keepalive ping */
318  watchdog_ping(wdd);
319 
320  return len;
321 }
322 
323 /*
324  * watchdog_ioctl: handle the different ioctl's for the watchdog device.
325  * @file: file handle to the device
326  * @cmd: watchdog command
327  * @arg: argument pointer
328  *
329  * The watchdog API defines a common set of functions for all watchdogs
330  * according to their available features.
331  */
332 
333 static long watchdog_ioctl(struct file *file, unsigned int cmd,
334  unsigned long arg)
335 {
336  struct watchdog_device *wdd = file->private_data;
337  void __user *argp = (void __user *)arg;
338  int __user *p = argp;
339  unsigned int val;
340  int err;
341 
342  err = watchdog_ioctl_op(wdd, cmd, arg);
343  if (err != -ENOIOCTLCMD)
344  return err;
345 
346  switch (cmd) {
347  case WDIOC_GETSUPPORT:
348  return copy_to_user(argp, wdd->info,
349  sizeof(struct watchdog_info)) ? -EFAULT : 0;
350  case WDIOC_GETSTATUS:
351  err = watchdog_get_status(wdd, &val);
352  if (err == -ENODEV)
353  return err;
354  return put_user(val, p);
355  case WDIOC_GETBOOTSTATUS:
356  return put_user(wdd->bootstatus, p);
357  case WDIOC_SETOPTIONS:
358  if (get_user(val, p))
359  return -EFAULT;
360  if (val & WDIOS_DISABLECARD) {
361  err = watchdog_stop(wdd);
362  if (err < 0)
363  return err;
364  }
365  if (val & WDIOS_ENABLECARD) {
366  err = watchdog_start(wdd);
367  if (err < 0)
368  return err;
369  }
370  return 0;
371  case WDIOC_KEEPALIVE:
372  if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
373  return -EOPNOTSUPP;
374  watchdog_ping(wdd);
375  return 0;
376  case WDIOC_SETTIMEOUT:
377  if (get_user(val, p))
378  return -EFAULT;
379  err = watchdog_set_timeout(wdd, val);
380  if (err < 0)
381  return err;
382  /* If the watchdog is active then we send a keepalive ping
383  * to make sure that the watchdog keep's running (and if
384  * possible that it takes the new timeout) */
385  watchdog_ping(wdd);
386  /* Fall */
387  case WDIOC_GETTIMEOUT:
388  /* timeout == 0 means that we don't know the timeout */
389  if (wdd->timeout == 0)
390  return -EOPNOTSUPP;
391  return put_user(wdd->timeout, p);
392  case WDIOC_GETTIMELEFT:
393  err = watchdog_get_timeleft(wdd, &val);
394  if (err)
395  return err;
396  return put_user(val, p);
397  default:
398  return -ENOTTY;
399  }
400 }
401 
402 /*
403  * watchdog_open: open the /dev/watchdog* devices.
404  * @inode: inode of device
405  * @file: file handle to device
406  *
407  * When the /dev/watchdog* device gets opened, we start the watchdog.
408  * Watch out: the /dev/watchdog device is single open, so we make sure
409  * it can only be opened once.
410  */
411 
412 static int watchdog_open(struct inode *inode, struct file *file)
413 {
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);
422 
423  /* the watchdog is single open! */
425  return -EBUSY;
426 
427  /*
428  * If the /dev/watchdog device is open, we don't want the module
429  * to be unloaded.
430  */
431  if (!try_module_get(wdd->ops->owner))
432  goto out;
433 
434  err = watchdog_start(wdd);
435  if (err < 0)
436  goto out_mod;
437 
438  file->private_data = wdd;
439 
440  if (wdd->ops->ref)
441  wdd->ops->ref(wdd);
442 
443  /* dev/watchdog is a virtual (and thus non-seekable) filesystem */
444  return nonseekable_open(inode, file);
445 
446 out_mod:
447  module_put(wdd->ops->owner);
448 out:
450  return err;
451 }
452 
453 /*
454  * watchdog_release: release the watchdog device.
455  * @inode: inode of device
456  * @file: file handle to device
457  *
458  * This is the code for when /dev/watchdog gets closed. We will only
459  * stop the watchdog when we have received the magic char (and nowayout
460  * was not set), else the watchdog will keep running.
461  */
462 
463 static int watchdog_release(struct inode *inode, struct file *file)
464 {
465  struct watchdog_device *wdd = file->private_data;
466  int err = -EBUSY;
467 
468  /*
469  * We only stop the watchdog if we received the magic character
470  * or if WDIOF_MAGICCLOSE is not set. If nowayout was set then
471  * watchdog_stop will fail.
472  */
474  !(wdd->info->options & WDIOF_MAGICCLOSE))
475  err = watchdog_stop(wdd);
476 
477  /* If the watchdog was not stopped, send a keepalive ping */
478  if (err < 0) {
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);
483  watchdog_ping(wdd);
484  }
485 
486  /* Allow the owner module to be unloaded again */
487  module_put(wdd->ops->owner);
488 
489  /* make sure that /dev/watchdog can be re-opened */
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 
496  return 0;
497 }
498 
499 static const struct file_operations watchdog_fops = {
500  .owner = THIS_MODULE,
501  .write = watchdog_write,
502  .unlocked_ioctl = watchdog_ioctl,
503  .open = watchdog_open,
504  .release = watchdog_release,
505 };
506 
507 static struct miscdevice watchdog_miscdev = {
508  .minor = WATCHDOG_MINOR,
509  .name = "watchdog",
510  .fops = &watchdog_fops,
511 };
512 
513 /*
514  * watchdog_dev_register: register a watchdog device
515  * @watchdog: watchdog device
516  *
517  * Register a watchdog device including handling the legacy
518  * /dev/watchdog node. /dev/watchdog is actually a miscdevice and
519  * thus we set it up like that.
520  */
521 
523 {
524  int err, devno;
525 
526  if (watchdog->id == 0) {
527  watchdog_miscdev.parent = watchdog->parent;
528  err = misc_register(&watchdog_miscdev);
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;
538  }
539 
540  /* Fill in the data structures */
541  devno = MKDEV(MAJOR(watchdog_devt), watchdog->id);
542  cdev_init(&watchdog->cdev, &watchdog_fops);
543  watchdog->cdev.owner = watchdog->ops->owner;
544 
545  /* Add the device */
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  }
554  }
555  return err;
556 }
557 
558 /*
559  * watchdog_dev_unregister: unregister a watchdog device
560  * @watchdog: watchdog device
561  *
562  * Unregister the watchdog and if needed the legacy /dev/watchdog device.
563  */
564 
566 {
567  mutex_lock(&watchdog->lock);
568  set_bit(WDOG_UNREGISTERED, &watchdog->status);
569  mutex_unlock(&watchdog->lock);
570 
571  cdev_del(&watchdog->cdev);
572  if (watchdog->id == 0) {
573  misc_deregister(&watchdog_miscdev);
574  old_wdd = NULL;
575  }
576  return 0;
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 
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 
600 {
601  unregister_chrdev_region(watchdog_devt, MAX_DOGS);
602 }