aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/watchdog/mixcomwd.c133
1 files changed, 63 insertions, 70 deletions
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 1adf1d56027d..2248a8187590 100644
--- a/drivers/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
@@ -29,7 +29,8 @@
29 * - support for one more type board 29 * - support for one more type board
30 * 30 *
31 * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com> 31 * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
32 * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT 32 * - added nowayout module option to override
33 * CONFIG_WATCHDOG_NOWAYOUT
33 * 34 *
34 * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com> 35 * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com>
35 * - make mixcomwd_opened unsigned, 36 * - make mixcomwd_opened unsigned,
@@ -53,8 +54,8 @@
53#include <linux/init.h> 54#include <linux/init.h>
54#include <linux/jiffies.h> 55#include <linux/jiffies.h>
55#include <linux/timer.h> 56#include <linux/timer.h>
56#include <asm/uaccess.h> 57#include <linux/uaccess.h>
57#include <asm/io.h> 58#include <linux/io.h>
58 59
59/* 60/*
60 * We have two types of cards that can be probed: 61 * We have two types of cards that can be probed:
@@ -108,18 +109,19 @@ static char expect_close;
108 109
109static int nowayout = WATCHDOG_NOWAYOUT; 110static int nowayout = WATCHDOG_NOWAYOUT;
110module_param(nowayout, int, 0); 111module_param(nowayout, int, 0);
111MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 112MODULE_PARM_DESC(nowayout,
113 "Watchdog cannot be stopped once started (default="
114 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
112 115
113static void mixcomwd_ping(void) 116static void mixcomwd_ping(void)
114{ 117{
115 outb_p(55,watchdog_port); 118 outb_p(55, watchdog_port);
116 return; 119 return;
117} 120}
118 121
119static void mixcomwd_timerfun(unsigned long d) 122static void mixcomwd_timerfun(unsigned long d)
120{ 123{
121 mixcomwd_ping(); 124 mixcomwd_ping();
122
123 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); 125 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
124} 126}
125 127
@@ -129,22 +131,22 @@ static void mixcomwd_timerfun(unsigned long d)
129 131
130static int mixcomwd_open(struct inode *inode, struct file *file) 132static int mixcomwd_open(struct inode *inode, struct file *file)
131{ 133{
132 if(test_and_set_bit(0,&mixcomwd_opened)) { 134 if (test_and_set_bit(0, &mixcomwd_opened))
133 return -EBUSY; 135 return -EBUSY;
134 } 136
135 mixcomwd_ping(); 137 mixcomwd_ping();
136 138
137 if (nowayout) { 139 if (nowayout)
138 /* 140 /*
139 * fops_get() code via open() has already done 141 * fops_get() code via open() has already done
140 * a try_module_get() so it is safe to do the 142 * a try_module_get() so it is safe to do the
141 * __module_get(). 143 * __module_get().
142 */ 144 */
143 __module_get(THIS_MODULE); 145 __module_get(THIS_MODULE);
144 } else { 146 else {
145 if(mixcomwd_timer_alive) { 147 if (mixcomwd_timer_alive) {
146 del_timer(&mixcomwd_timer); 148 del_timer(&mixcomwd_timer);
147 mixcomwd_timer_alive=0; 149 mixcomwd_timer_alive = 0;
148 } 150 }
149 } 151 }
150 return nonseekable_open(inode, file); 152 return nonseekable_open(inode, file);
@@ -153,26 +155,27 @@ static int mixcomwd_open(struct inode *inode, struct file *file)
153static int mixcomwd_release(struct inode *inode, struct file *file) 155static int mixcomwd_release(struct inode *inode, struct file *file)
154{ 156{
155 if (expect_close == 42) { 157 if (expect_close == 42) {
156 if(mixcomwd_timer_alive) { 158 if (mixcomwd_timer_alive) {
157 printk(KERN_ERR PFX "release called while internal timer alive"); 159 printk(KERN_ERR PFX
160 "release called while internal timer alive");
158 return -EBUSY; 161 return -EBUSY;
159 } 162 }
160 mixcomwd_timer_alive=1; 163 mixcomwd_timer_alive = 1;
161 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); 164 mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
162 } else { 165 } else
163 printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); 166 printk(KERN_CRIT PFX
164 } 167 "WDT device closed unexpectedly. WDT will not stop!\n");
165 168
166 clear_bit(0,&mixcomwd_opened); 169 clear_bit(0, &mixcomwd_opened);
167 expect_close=0; 170 expect_close = 0;
168 return 0; 171 return 0;
169} 172}
170 173
171 174
172static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) 175static ssize_t mixcomwd_write(struct file *file, const char __user *data,
176 size_t len, loff_t *ppos)
173{ 177{
174 if(len) 178 if (len) {
175 {
176 if (!nowayout) { 179 if (!nowayout) {
177 size_t i; 180 size_t i;
178 181
@@ -192,8 +195,8 @@ static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t
192 return len; 195 return len;
193} 196}
194 197
195static int mixcomwd_ioctl(struct inode *inode, struct file *file, 198static long mixcomwd_ioctl(struct file *file,
196 unsigned int cmd, unsigned long arg) 199 unsigned int cmd, unsigned long arg)
197{ 200{
198 void __user *argp = (void __user *)arg; 201 void __user *argp = (void __user *)arg;
199 int __user *p = argp; 202 int __user *p = argp;
@@ -204,32 +207,23 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
204 .identity = "MixCOM watchdog", 207 .identity = "MixCOM watchdog",
205 }; 208 };
206 209
207 switch(cmd) 210 switch (cmd) {
208 { 211 case WDIOC_GETSTATUS:
209 case WDIOC_GETSTATUS: 212 status = mixcomwd_opened;
210 status=mixcomwd_opened; 213 if (!nowayout)
211 if (!nowayout) { 214 status |= mixcomwd_timer_alive;
212 status|=mixcomwd_timer_alive; 215 return put_user(status, p);
213 } 216 case WDIOC_GETBOOTSTATUS:
214 if (copy_to_user(p, &status, sizeof(int))) { 217 return put_user(0, p);
215 return -EFAULT; 218 case WDIOC_GETSUPPORT:
216 } 219 if (copy_to_user(argp, &ident, sizeof(ident)))
217 break; 220 return -EFAULT;
218 case WDIOC_GETBOOTSTATUS: 221 break;
219 if (copy_to_user(p, &status, sizeof(int))) { 222 case WDIOC_KEEPALIVE:
220 return -EFAULT; 223 mixcomwd_ping();
221 } 224 break;
222 break; 225 default:
223 case WDIOC_GETSUPPORT: 226 return -ENOTTY;
224 if (copy_to_user(argp, &ident, sizeof(ident))) {
225 return -EFAULT;
226 }
227 break;
228 case WDIOC_KEEPALIVE:
229 mixcomwd_ping();
230 break;
231 default:
232 return -ENOTTY;
233 } 227 }
234 return 0; 228 return 0;
235} 229}
@@ -238,7 +232,7 @@ static const struct file_operations mixcomwd_fops = {
238 .owner = THIS_MODULE, 232 .owner = THIS_MODULE,
239 .llseek = no_llseek, 233 .llseek = no_llseek,
240 .write = mixcomwd_write, 234 .write = mixcomwd_write,
241 .ioctl = mixcomwd_ioctl, 235 .unlocked_ioctl = mixcomwd_ioctl,
242 .open = mixcomwd_open, 236 .open = mixcomwd_open,
243 .release = mixcomwd_release, 237 .release = mixcomwd_release,
244}; 238};
@@ -253,15 +247,14 @@ static int __init checkcard(int port, int card_id)
253{ 247{
254 int id; 248 int id;
255 249
256 if (!request_region(port, 1, "MixCOM watchdog")) { 250 if (!request_region(port, 1, "MixCOM watchdog"))
257 return 0; 251 return 0;
258 }
259 252
260 id=inb_p(port); 253 id = inb_p(port);
261 if (card_id==MIXCOM_ID) 254 if (card_id == MIXCOM_ID)
262 id &= 0x3f; 255 id &= 0x3f;
263 256
264 if (id!=card_id) { 257 if (id != card_id) {
265 release_region(port, 1); 258 release_region(port, 1);
266 return 0; 259 return 0;
267 } 260 }
@@ -270,9 +263,7 @@ static int __init checkcard(int port, int card_id)
270 263
271static int __init mixcomwd_init(void) 264static int __init mixcomwd_init(void)
272{ 265{
273 int i; 266 int i, ret, found = 0;
274 int ret;
275 int found=0;
276 267
277 for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) { 268 for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) {
278 if (checkcard(mixcomwd_io_info[i].ioport, 269 if (checkcard(mixcomwd_io_info[i].ioport,
@@ -283,20 +274,22 @@ static int __init mixcomwd_init(void)
283 } 274 }
284 275
285 if (!found) { 276 if (!found) {
286 printk(KERN_ERR PFX "No card detected, or port not available.\n"); 277 printk(KERN_ERR PFX
278 "No card detected, or port not available.\n");
287 return -ENODEV; 279 return -ENODEV;
288 } 280 }
289 281
290 ret = misc_register(&mixcomwd_miscdev); 282 ret = misc_register(&mixcomwd_miscdev);
291 if (ret) 283 if (ret) {
292 { 284 printk(KERN_ERR PFX
293 printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", 285 "cannot register miscdev on minor=%d (err=%d)\n",
294 WATCHDOG_MINOR, ret); 286 WATCHDOG_MINOR, ret);
295 goto error_misc_register_watchdog; 287 goto error_misc_register_watchdog;
296 } 288 }
297 289
298 printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n", 290 printk(KERN_INFO
299 VERSION, watchdog_port); 291 "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
292 VERSION, watchdog_port);
300 293
301 return 0; 294 return 0;
302 295
@@ -309,15 +302,15 @@ error_misc_register_watchdog:
309static void __exit mixcomwd_exit(void) 302static void __exit mixcomwd_exit(void)
310{ 303{
311 if (!nowayout) { 304 if (!nowayout) {
312 if(mixcomwd_timer_alive) { 305 if (mixcomwd_timer_alive) {
313 printk(KERN_WARNING PFX "I quit now, hardware will" 306 printk(KERN_WARNING PFX "I quit now, hardware will"
314 " probably reboot!\n"); 307 " probably reboot!\n");
315 del_timer_sync(&mixcomwd_timer); 308 del_timer_sync(&mixcomwd_timer);
316 mixcomwd_timer_alive=0; 309 mixcomwd_timer_alive = 0;
317 } 310 }
318 } 311 }
319 misc_deregister(&mixcomwd_miscdev); 312 misc_deregister(&mixcomwd_miscdev);
320 release_region(watchdog_port,1); 313 release_region(watchdog_port, 1);
321} 314}
322 315
323module_init(mixcomwd_init); 316module_init(mixcomwd_init);