diff options
Diffstat (limited to 'drivers/watchdog/bfin_wdt.c')
-rw-r--r-- | drivers/watchdog/bfin_wdt.c | 147 |
1 files changed, 71 insertions, 76 deletions
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 03b3e3d91e7c..31b42253054e 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include <linux/reboot.h> | 24 | #include <linux/reboot.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/uaccess.h> | ||
27 | #include <asm/blackfin.h> | 28 | #include <asm/blackfin.h> |
28 | #include <asm/uaccess.h> | ||
29 | 29 | ||
30 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) | 30 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) |
31 | #define stampit() stamp("here i am") | 31 | #define stampit() stamp("here i am") |
@@ -148,7 +148,8 @@ static int bfin_wdt_set_timeout(unsigned long t) | |||
148 | int run = bfin_wdt_running(); | 148 | int run = bfin_wdt_running(); |
149 | bfin_wdt_stop(); | 149 | bfin_wdt_stop(); |
150 | bfin_write_WDOG_CNT(cnt); | 150 | bfin_write_WDOG_CNT(cnt); |
151 | if (run) bfin_wdt_start(); | 151 | if (run) |
152 | bfin_wdt_start(); | ||
152 | } | 153 | } |
153 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | 154 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); |
154 | 155 | ||
@@ -191,16 +192,15 @@ static int bfin_wdt_release(struct inode *inode, struct file *file) | |||
191 | { | 192 | { |
192 | stampit(); | 193 | stampit(); |
193 | 194 | ||
194 | if (expect_close == 42) { | 195 | if (expect_close == 42) |
195 | bfin_wdt_stop(); | 196 | bfin_wdt_stop(); |
196 | } else { | 197 | else { |
197 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 198 | printk(KERN_CRIT PFX |
199 | "Unexpected close, not stopping watchdog!\n"); | ||
198 | bfin_wdt_keepalive(); | 200 | bfin_wdt_keepalive(); |
199 | } | 201 | } |
200 | |||
201 | expect_close = 0; | 202 | expect_close = 0; |
202 | clear_bit(0, &open_check); | 203 | clear_bit(0, &open_check); |
203 | |||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
206 | 206 | ||
@@ -214,7 +214,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file) | |||
214 | * Pings the watchdog on write. | 214 | * Pings the watchdog on write. |
215 | */ | 215 | */ |
216 | static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | 216 | static ssize_t bfin_wdt_write(struct file *file, const char __user *data, |
217 | size_t len, loff_t *ppos) | 217 | size_t len, loff_t *ppos) |
218 | { | 218 | { |
219 | stampit(); | 219 | stampit(); |
220 | 220 | ||
@@ -241,7 +241,6 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | |||
241 | 241 | ||
242 | /** | 242 | /** |
243 | * bfin_wdt_ioctl - Query Device | 243 | * bfin_wdt_ioctl - Query Device |
244 | * @inode: inode of device | ||
245 | * @file: file handle of device | 244 | * @file: file handle of device |
246 | * @cmd: watchdog command | 245 | * @cmd: watchdog command |
247 | * @arg: argument | 246 | * @arg: argument |
@@ -249,8 +248,8 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | |||
249 | * Query basic information from the device or ping it, as outlined by the | 248 | * Query basic information from the device or ping it, as outlined by the |
250 | * watchdog API. | 249 | * watchdog API. |
251 | */ | 250 | */ |
252 | static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | 251 | static long bfin_wdt_ioctl(struct file *file, |
253 | unsigned int cmd, unsigned long arg) | 252 | unsigned int cmd, unsigned long arg) |
254 | { | 253 | { |
255 | void __user *argp = (void __user *)arg; | 254 | void __user *argp = (void __user *)arg; |
256 | int __user *p = argp; | 255 | int __user *p = argp; |
@@ -258,59 +257,49 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | |||
258 | stampit(); | 257 | stampit(); |
259 | 258 | ||
260 | switch (cmd) { | 259 | switch (cmd) { |
261 | default: | 260 | case WDIOC_GETSUPPORT: |
262 | return -ENOTTY; | 261 | if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) |
263 | 262 | return -EFAULT; | |
264 | case WDIOC_GETSUPPORT: | 263 | else |
265 | if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) | ||
266 | return -EFAULT; | ||
267 | else | ||
268 | return 0; | ||
269 | |||
270 | case WDIOC_GETSTATUS: | ||
271 | case WDIOC_GETBOOTSTATUS: | ||
272 | return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); | ||
273 | |||
274 | case WDIOC_KEEPALIVE: | ||
275 | bfin_wdt_keepalive(); | ||
276 | return 0; | 264 | return 0; |
277 | 265 | case WDIOC_GETSTATUS: | |
278 | case WDIOC_SETTIMEOUT: { | 266 | case WDIOC_GETBOOTSTATUS: |
279 | int new_timeout; | 267 | return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); |
280 | 268 | case WDIOC_SETOPTIONS: { | |
281 | if (get_user(new_timeout, p)) | 269 | unsigned long flags; |
282 | return -EFAULT; | 270 | int options, ret = -EINVAL; |
283 | 271 | ||
284 | if (bfin_wdt_set_timeout(new_timeout)) | 272 | if (get_user(options, p)) |
285 | return -EINVAL; | 273 | return -EFAULT; |
274 | |||
275 | spin_lock_irqsave(&bfin_wdt_spinlock, flags); | ||
276 | if (options & WDIOS_DISABLECARD) { | ||
277 | bfin_wdt_stop(); | ||
278 | ret = 0; | ||
286 | } | 279 | } |
287 | /* Fall */ | 280 | if (options & WDIOS_ENABLECARD) { |
288 | case WDIOC_GETTIMEOUT: | 281 | bfin_wdt_start(); |
289 | return put_user(timeout, p); | 282 | ret = 0; |
290 | |||
291 | case WDIOC_SETOPTIONS: { | ||
292 | unsigned long flags; | ||
293 | int options, ret = -EINVAL; | ||
294 | |||
295 | if (get_user(options, p)) | ||
296 | return -EFAULT; | ||
297 | |||
298 | spin_lock_irqsave(&bfin_wdt_spinlock, flags); | ||
299 | |||
300 | if (options & WDIOS_DISABLECARD) { | ||
301 | bfin_wdt_stop(); | ||
302 | ret = 0; | ||
303 | } | ||
304 | |||
305 | if (options & WDIOS_ENABLECARD) { | ||
306 | bfin_wdt_start(); | ||
307 | ret = 0; | ||
308 | } | ||
309 | |||
310 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | ||
311 | |||
312 | return ret; | ||
313 | } | 283 | } |
284 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | ||
285 | return ret; | ||
286 | } | ||
287 | case WDIOC_KEEPALIVE: | ||
288 | bfin_wdt_keepalive(); | ||
289 | return 0; | ||
290 | case WDIOC_SETTIMEOUT: { | ||
291 | int new_timeout; | ||
292 | |||
293 | if (get_user(new_timeout, p)) | ||
294 | return -EFAULT; | ||
295 | if (bfin_wdt_set_timeout(new_timeout)) | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | /* Fall */ | ||
299 | case WDIOC_GETTIMEOUT: | ||
300 | return put_user(timeout, p); | ||
301 | default: | ||
302 | return -ENOTTY; | ||
314 | } | 303 | } |
315 | } | 304 | } |
316 | 305 | ||
@@ -323,8 +312,8 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | |||
323 | * Handles specific events, such as turning off the watchdog during a | 312 | * Handles specific events, such as turning off the watchdog during a |
324 | * shutdown event. | 313 | * shutdown event. |
325 | */ | 314 | */ |
326 | static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, | 315 | static int bfin_wdt_notify_sys(struct notifier_block *this, |
327 | void *unused) | 316 | unsigned long code, void *unused) |
328 | { | 317 | { |
329 | stampit(); | 318 | stampit(); |
330 | 319 | ||
@@ -379,12 +368,12 @@ static int bfin_wdt_resume(struct platform_device *pdev) | |||
379 | #endif | 368 | #endif |
380 | 369 | ||
381 | static const struct file_operations bfin_wdt_fops = { | 370 | static const struct file_operations bfin_wdt_fops = { |
382 | .owner = THIS_MODULE, | 371 | .owner = THIS_MODULE, |
383 | .llseek = no_llseek, | 372 | .llseek = no_llseek, |
384 | .write = bfin_wdt_write, | 373 | .write = bfin_wdt_write, |
385 | .ioctl = bfin_wdt_ioctl, | 374 | .unlocked_ioctl = bfin_wdt_ioctl, |
386 | .open = bfin_wdt_open, | 375 | .open = bfin_wdt_open, |
387 | .release = bfin_wdt_release, | 376 | .release = bfin_wdt_release, |
388 | }; | 377 | }; |
389 | 378 | ||
390 | static struct miscdevice bfin_wdt_miscdev = { | 379 | static struct miscdevice bfin_wdt_miscdev = { |
@@ -396,8 +385,8 @@ static struct miscdevice bfin_wdt_miscdev = { | |||
396 | static struct watchdog_info bfin_wdt_info = { | 385 | static struct watchdog_info bfin_wdt_info = { |
397 | .identity = "Blackfin Watchdog", | 386 | .identity = "Blackfin Watchdog", |
398 | .options = WDIOF_SETTIMEOUT | | 387 | .options = WDIOF_SETTIMEOUT | |
399 | WDIOF_KEEPALIVEPING | | 388 | WDIOF_KEEPALIVEPING | |
400 | WDIOF_MAGICCLOSE, | 389 | WDIOF_MAGICCLOSE, |
401 | }; | 390 | }; |
402 | 391 | ||
403 | static struct notifier_block bfin_wdt_notifier = { | 392 | static struct notifier_block bfin_wdt_notifier = { |
@@ -416,14 +405,16 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev) | |||
416 | 405 | ||
417 | ret = register_reboot_notifier(&bfin_wdt_notifier); | 406 | ret = register_reboot_notifier(&bfin_wdt_notifier); |
418 | if (ret) { | 407 | if (ret) { |
419 | pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); | 408 | pr_devinit(KERN_ERR PFX |
409 | "cannot register reboot notifier (err=%d)\n", ret); | ||
420 | return ret; | 410 | return ret; |
421 | } | 411 | } |
422 | 412 | ||
423 | ret = misc_register(&bfin_wdt_miscdev); | 413 | ret = misc_register(&bfin_wdt_miscdev); |
424 | if (ret) { | 414 | if (ret) { |
425 | pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 415 | pr_devinit(KERN_ERR PFX |
426 | WATCHDOG_MINOR, ret); | 416 | "cannot register miscdev on minor=%d (err=%d)\n", |
417 | WATCHDOG_MINOR, ret); | ||
427 | unregister_reboot_notifier(&bfin_wdt_notifier); | 418 | unregister_reboot_notifier(&bfin_wdt_notifier); |
428 | return ret; | 419 | return ret; |
429 | } | 420 | } |
@@ -516,7 +507,11 @@ MODULE_LICENSE("GPL"); | |||
516 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 507 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
517 | 508 | ||
518 | module_param(timeout, uint, 0); | 509 | module_param(timeout, uint, 0); |
519 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 510 | MODULE_PARM_DESC(timeout, |
511 | "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" | ||
512 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
520 | 513 | ||
521 | module_param(nowayout, int, 0); | 514 | module_param(nowayout, int, 0); |
522 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 515 | MODULE_PARM_DESC(nowayout, |
516 | "Watchdog cannot be stopped once started (default=" | ||
517 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||