diff options
-rw-r--r-- | drivers/watchdog/alim7101_wdt.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index 996b2f7d330e..665e0e7dfe1e 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c | |||
@@ -301,6 +301,28 @@ static struct miscdevice wdt_miscdev = { | |||
301 | .fops = &wdt_fops, | 301 | .fops = &wdt_fops, |
302 | }; | 302 | }; |
303 | 303 | ||
304 | static int wdt_restart_handle(struct notifier_block *this, unsigned long mode, | ||
305 | void *cmd) | ||
306 | { | ||
307 | /* | ||
308 | * Cobalt devices have no way of rebooting themselves other | ||
309 | * than getting the watchdog to pull reset, so we restart the | ||
310 | * watchdog on reboot with no heartbeat. | ||
311 | */ | ||
312 | wdt_change(WDT_ENABLE); | ||
313 | |||
314 | /* loop until the watchdog fires */ | ||
315 | while (true) | ||
316 | ; | ||
317 | |||
318 | return NOTIFY_DONE; | ||
319 | } | ||
320 | |||
321 | static struct notifier_block wdt_restart_handler = { | ||
322 | .notifier_call = wdt_restart_handle, | ||
323 | .priority = 128, | ||
324 | }; | ||
325 | |||
304 | /* | 326 | /* |
305 | * Notifier for system down | 327 | * Notifier for system down |
306 | */ | 328 | */ |
@@ -311,15 +333,6 @@ static int wdt_notify_sys(struct notifier_block *this, | |||
311 | if (code == SYS_DOWN || code == SYS_HALT) | 333 | if (code == SYS_DOWN || code == SYS_HALT) |
312 | wdt_turnoff(); | 334 | wdt_turnoff(); |
313 | 335 | ||
314 | if (code == SYS_RESTART) { | ||
315 | /* | ||
316 | * Cobalt devices have no way of rebooting themselves other | ||
317 | * than getting the watchdog to pull reset, so we restart the | ||
318 | * watchdog on reboot with no heartbeat | ||
319 | */ | ||
320 | wdt_change(WDT_ENABLE); | ||
321 | pr_info("Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second\n"); | ||
322 | } | ||
323 | return NOTIFY_DONE; | 336 | return NOTIFY_DONE; |
324 | } | 337 | } |
325 | 338 | ||
@@ -338,6 +351,7 @@ static void __exit alim7101_wdt_unload(void) | |||
338 | /* Deregister */ | 351 | /* Deregister */ |
339 | misc_deregister(&wdt_miscdev); | 352 | misc_deregister(&wdt_miscdev); |
340 | unregister_reboot_notifier(&wdt_notifier); | 353 | unregister_reboot_notifier(&wdt_notifier); |
354 | unregister_restart_handler(&wdt_restart_handler); | ||
341 | pci_dev_put(alim7101_pmu); | 355 | pci_dev_put(alim7101_pmu); |
342 | } | 356 | } |
343 | 357 | ||
@@ -390,11 +404,17 @@ static int __init alim7101_wdt_init(void) | |||
390 | goto err_out; | 404 | goto err_out; |
391 | } | 405 | } |
392 | 406 | ||
407 | rc = register_restart_handler(&wdt_restart_handler); | ||
408 | if (rc) { | ||
409 | pr_err("cannot register restart handler (err=%d)\n", rc); | ||
410 | goto err_out_reboot; | ||
411 | } | ||
412 | |||
393 | rc = misc_register(&wdt_miscdev); | 413 | rc = misc_register(&wdt_miscdev); |
394 | if (rc) { | 414 | if (rc) { |
395 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", | 415 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", |
396 | wdt_miscdev.minor, rc); | 416 | wdt_miscdev.minor, rc); |
397 | goto err_out_reboot; | 417 | goto err_out_restart; |
398 | } | 418 | } |
399 | 419 | ||
400 | if (nowayout) | 420 | if (nowayout) |
@@ -404,6 +424,8 @@ static int __init alim7101_wdt_init(void) | |||
404 | timeout, nowayout); | 424 | timeout, nowayout); |
405 | return 0; | 425 | return 0; |
406 | 426 | ||
427 | err_out_restart: | ||
428 | unregister_restart_handler(&wdt_restart_handler); | ||
407 | err_out_reboot: | 429 | err_out_reboot: |
408 | unregister_reboot_notifier(&wdt_notifier); | 430 | unregister_reboot_notifier(&wdt_notifier); |
409 | err_out: | 431 | err_out: |