Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
watchdog_core.c
Go to the documentation of this file.
1 /*
2  * watchdog_core.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  * 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 <[email protected]>,
14  * Rob Radez <[email protected]>,
15  * Rusty Lynch <[email protected]>
16  * Satyam Sharma <[email protected]>
17  * Randy Dunlap <[email protected]>
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 #include <linux/idr.h> /* For ida_* macros */
38 #include <linux/err.h> /* For IS_ERR macros */
39 
40 #include "watchdog_core.h" /* For watchdog_dev_register/... */
41 
42 static DEFINE_IDA(watchdog_ida);
43 static struct class *watchdog_class;
44 
56 {
57  int ret, id, devno;
58 
59  if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
60  return -EINVAL;
61 
62  /* Mandatory operations need to be supported */
63  if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
64  return -EINVAL;
65 
66  /*
67  * Check that we have valid min and max timeout values, if
68  * not reset them both to 0 (=not used or unknown)
69  */
70  if (wdd->min_timeout > wdd->max_timeout) {
71  pr_info("Invalid min and max timeout values, resetting to 0!\n");
72  wdd->min_timeout = 0;
73  wdd->max_timeout = 0;
74  }
75 
76  /*
77  * Note: now that all watchdog_device data has been verified, we
78  * will not check this anymore in other functions. If data gets
79  * corrupted in a later stage then we expect a kernel panic!
80  */
81 
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 
88  ret = watchdog_dev_register(wdd);
89  if (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)) {
112  ida_simple_remove(&watchdog_ida, id);
113  ret = PTR_ERR(wdd->dev);
114  return ret;
115  }
116 
117  return 0;
118 }
120 
129 {
130  int ret;
131  int devno;
132 
133  if (wdd == NULL)
134  return;
135 
136  devno = wdd->cdev.dev;
137  ret = watchdog_dev_unregister(wdd);
138  if (ret)
139  pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
140  device_destroy(watchdog_class, devno);
141  ida_simple_remove(&watchdog_ida, wdd->id);
142  wdd->dev = NULL;
143 }
145 
146 static int __init watchdog_init(void)
147 {
148  int err;
149 
150  watchdog_class = class_create(THIS_MODULE, "watchdog");
151  if (IS_ERR(watchdog_class)) {
152  pr_err("couldn't create class\n");
153  return PTR_ERR(watchdog_class);
154  }
155 
156  err = watchdog_dev_init();
157  if (err < 0) {
158  class_destroy(watchdog_class);
159  return err;
160  }
161 
162  return 0;
163 }
164 
165 static void __exit watchdog_exit(void)
166 {
168  class_destroy(watchdog_class);
169  ida_destroy(&watchdog_ida);
170 }
171 
172 subsys_initcall(watchdog_init);
173 module_exit(watchdog_exit);
174 
175 MODULE_AUTHOR("Alan Cox <[email protected]>");
176 MODULE_AUTHOR("Wim Van Sebroeck <[email protected]>");
177 MODULE_DESCRIPTION("WatchDog Timer Driver Core");
178 MODULE_LICENSE("GPL");