diff options
Diffstat (limited to 'drivers/watchdog/eurotechwdt.c')
-rw-r--r-- | drivers/watchdog/eurotechwdt.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index b14e9d1f164d..b94e6ef4c7a7 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c | |||
@@ -56,14 +56,15 @@ | |||
56 | #include <linux/notifier.h> | 56 | #include <linux/notifier.h> |
57 | #include <linux/reboot.h> | 57 | #include <linux/reboot.h> |
58 | #include <linux/init.h> | 58 | #include <linux/init.h> |
59 | #include <linux/io.h> | ||
60 | #include <linux/uaccess.h> | ||
59 | 61 | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/uaccess.h> | ||
62 | #include <asm/system.h> | 62 | #include <asm/system.h> |
63 | 63 | ||
64 | static unsigned long eurwdt_is_open; | 64 | static unsigned long eurwdt_is_open; |
65 | static int eurwdt_timeout; | 65 | static int eurwdt_timeout; |
66 | static char eur_expect_close; | 66 | static char eur_expect_close; |
67 | static spinlock_t eurwdt_lock; | ||
67 | 68 | ||
68 | /* | 69 | /* |
69 | * You must set these - there is no sane way to probe for this board. | 70 | * You must set these - there is no sane way to probe for this board. |
@@ -78,7 +79,9 @@ static char *ev = "int"; | |||
78 | 79 | ||
79 | static int nowayout = WATCHDOG_NOWAYOUT; | 80 | static int nowayout = WATCHDOG_NOWAYOUT; |
80 | module_param(nowayout, int, 0); | 81 | module_param(nowayout, int, 0); |
81 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 82 | MODULE_PARM_DESC(nowayout, |
83 | "Watchdog cannot be stopped once started (default=" | ||
84 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
82 | 85 | ||
83 | /* | 86 | /* |
84 | * Some symbolic names | 87 | * Some symbolic names |
@@ -137,7 +140,8 @@ static void eurwdt_activate_timer(void) | |||
137 | { | 140 | { |
138 | eurwdt_disable_timer(); | 141 | eurwdt_disable_timer(); |
139 | eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ | 142 | eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ |
140 | eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT); | 143 | eurwdt_write_reg(WDT_OUTPIN_CFG, |
144 | !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT); | ||
141 | 145 | ||
142 | /* Setting interrupt line */ | 146 | /* Setting interrupt line */ |
143 | if (irq == 2 || irq > 15 || irq < 0) { | 147 | if (irq == 2 || irq > 15 || irq < 0) { |
@@ -206,21 +210,21 @@ size_t count, loff_t *ppos) | |||
206 | 210 | ||
207 | for (i = 0; i != count; i++) { | 211 | for (i = 0; i != count; i++) { |
208 | char c; | 212 | char c; |
209 | if(get_user(c, buf+i)) | 213 | if (get_user(c, buf+i)) |
210 | return -EFAULT; | 214 | return -EFAULT; |
211 | if (c == 'V') | 215 | if (c == 'V') |
212 | eur_expect_close = 42; | 216 | eur_expect_close = 42; |
213 | } | 217 | } |
214 | } | 218 | } |
219 | spin_lock(&eurwdt_lock); | ||
215 | eurwdt_ping(); /* the default timeout */ | 220 | eurwdt_ping(); /* the default timeout */ |
221 | spin_unlock(&eurwdt_lock); | ||
216 | } | 222 | } |
217 | |||
218 | return count; | 223 | return count; |
219 | } | 224 | } |
220 | 225 | ||
221 | /** | 226 | /** |
222 | * eurwdt_ioctl: | 227 | * eurwdt_ioctl: |
223 | * @inode: inode of the device | ||
224 | * @file: file handle to the device | 228 | * @file: file handle to the device |
225 | * @cmd: watchdog command | 229 | * @cmd: watchdog command |
226 | * @arg: argument pointer | 230 | * @arg: argument pointer |
@@ -229,13 +233,14 @@ size_t count, loff_t *ppos) | |||
229 | * according to their available features. | 233 | * according to their available features. |
230 | */ | 234 | */ |
231 | 235 | ||
232 | static int eurwdt_ioctl(struct inode *inode, struct file *file, | 236 | static long eurwdt_ioctl(struct file *file, |
233 | unsigned int cmd, unsigned long arg) | 237 | unsigned int cmd, unsigned long arg) |
234 | { | 238 | { |
235 | void __user *argp = (void __user *)arg; | 239 | void __user *argp = (void __user *)arg; |
236 | int __user *p = argp; | 240 | int __user *p = argp; |
237 | static struct watchdog_info ident = { | 241 | static struct watchdog_info ident = { |
238 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
243 | | WDIOF_MAGICCLOSE, | ||
239 | .firmware_version = 1, | 244 | .firmware_version = 1, |
240 | .identity = "WDT Eurotech CPU-1220/1410", | 245 | .identity = "WDT Eurotech CPU-1220/1410", |
241 | }; | 246 | }; |
@@ -243,7 +248,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
243 | int time; | 248 | int time; |
244 | int options, retval = -EINVAL; | 249 | int options, retval = -EINVAL; |
245 | 250 | ||
246 | switch(cmd) { | 251 | switch (cmd) { |
247 | default: | 252 | default: |
248 | return -ENOTTY; | 253 | return -ENOTTY; |
249 | 254 | ||
@@ -255,7 +260,9 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
255 | return put_user(0, p); | 260 | return put_user(0, p); |
256 | 261 | ||
257 | case WDIOC_KEEPALIVE: | 262 | case WDIOC_KEEPALIVE: |
263 | spin_lock(&eurwdt_lock); | ||
258 | eurwdt_ping(); | 264 | eurwdt_ping(); |
265 | spin_unlock(&eurwdt_lock); | ||
259 | return 0; | 266 | return 0; |
260 | 267 | ||
261 | case WDIOC_SETTIMEOUT: | 268 | case WDIOC_SETTIMEOUT: |
@@ -266,8 +273,10 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
266 | if (time < 0 || time > 255) | 273 | if (time < 0 || time > 255) |
267 | return -EINVAL; | 274 | return -EINVAL; |
268 | 275 | ||
276 | spin_lock(&eurwdt_lock); | ||
269 | eurwdt_timeout = time; | 277 | eurwdt_timeout = time; |
270 | eurwdt_set_timeout(time); | 278 | eurwdt_set_timeout(time); |
279 | spin_unlock(&eurwdt_lock); | ||
271 | /* Fall */ | 280 | /* Fall */ |
272 | 281 | ||
273 | case WDIOC_GETTIMEOUT: | 282 | case WDIOC_GETTIMEOUT: |
@@ -276,6 +285,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
276 | case WDIOC_SETOPTIONS: | 285 | case WDIOC_SETOPTIONS: |
277 | if (get_user(options, p)) | 286 | if (get_user(options, p)) |
278 | return -EFAULT; | 287 | return -EFAULT; |
288 | spin_lock(&eurwdt_lock); | ||
279 | if (options & WDIOS_DISABLECARD) { | 289 | if (options & WDIOS_DISABLECARD) { |
280 | eurwdt_disable_timer(); | 290 | eurwdt_disable_timer(); |
281 | retval = 0; | 291 | retval = 0; |
@@ -285,6 +295,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
285 | eurwdt_ping(); | 295 | eurwdt_ping(); |
286 | retval = 0; | 296 | retval = 0; |
287 | } | 297 | } |
298 | spin_unlock(&eurwdt_lock); | ||
288 | return retval; | 299 | return retval; |
289 | } | 300 | } |
290 | } | 301 | } |
@@ -322,10 +333,11 @@ static int eurwdt_open(struct inode *inode, struct file *file) | |||
322 | 333 | ||
323 | static int eurwdt_release(struct inode *inode, struct file *file) | 334 | static int eurwdt_release(struct inode *inode, struct file *file) |
324 | { | 335 | { |
325 | if (eur_expect_close == 42) { | 336 | if (eur_expect_close == 42) |
326 | eurwdt_disable_timer(); | 337 | eurwdt_disable_timer(); |
327 | } else { | 338 | else { |
328 | printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n"); | 339 | printk(KERN_CRIT |
340 | "eurwdt: Unexpected close, not stopping watchdog!\n"); | ||
329 | eurwdt_ping(); | 341 | eurwdt_ping(); |
330 | } | 342 | } |
331 | clear_bit(0, &eurwdt_is_open); | 343 | clear_bit(0, &eurwdt_is_open); |
@@ -362,11 +374,11 @@ static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
362 | 374 | ||
363 | 375 | ||
364 | static const struct file_operations eurwdt_fops = { | 376 | static const struct file_operations eurwdt_fops = { |
365 | .owner = THIS_MODULE, | 377 | .owner = THIS_MODULE, |
366 | .llseek = no_llseek, | 378 | .llseek = no_llseek, |
367 | .write = eurwdt_write, | 379 | .write = eurwdt_write, |
368 | .ioctl = eurwdt_ioctl, | 380 | .unlocked_ioctl = eurwdt_ioctl, |
369 | .open = eurwdt_open, | 381 | .open = eurwdt_open, |
370 | .release = eurwdt_release, | 382 | .release = eurwdt_release, |
371 | }; | 383 | }; |
372 | 384 | ||
@@ -419,7 +431,7 @@ static int __init eurwdt_init(void) | |||
419 | int ret; | 431 | int ret; |
420 | 432 | ||
421 | ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); | 433 | ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); |
422 | if(ret) { | 434 | if (ret) { |
423 | printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); | 435 | printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); |
424 | goto out; | 436 | goto out; |
425 | } | 437 | } |
@@ -432,10 +444,13 @@ static int __init eurwdt_init(void) | |||
432 | 444 | ||
433 | ret = register_reboot_notifier(&eurwdt_notifier); | 445 | ret = register_reboot_notifier(&eurwdt_notifier); |
434 | if (ret) { | 446 | if (ret) { |
435 | printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); | 447 | printk(KERN_ERR |
448 | "eurwdt: can't register reboot notifier (err=%d)\n", ret); | ||
436 | goto outreg; | 449 | goto outreg; |
437 | } | 450 | } |
438 | 451 | ||
452 | spin_lock_init(&eurwdt_lock); | ||
453 | |||
439 | ret = misc_register(&eurwdt_miscdev); | 454 | ret = misc_register(&eurwdt_miscdev); |
440 | if (ret) { | 455 | if (ret) { |
441 | printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", | 456 | printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", |