gpio_wdt may need to start the GPIO toggle as soon as possible, when the watchdog cannot be disabled. Raise the initcall to arch_initcall. We need to split the initiation, because of miscdev, as done in mpc8xxx_wdt.c Signed-off-by: Jean-Baptiste Theou <jtheou@xxxxxxxxxxxxxxxxxx> --- drivers/watchdog/gpio_wdt.c | 78 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/gpio_wdt.c b/drivers/watchdog/gpio_wdt.c index cbc313d..8ecfe7e 100644 --- a/drivers/watchdog/gpio_wdt.c +++ b/drivers/watchdog/gpio_wdt.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/notifier.h> #include <linux/of_gpio.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/watchdog.h> @@ -223,10 +224,11 @@ static int gpio_wdt_probe(struct platform_device *pdev) setup_timer(&priv->timer, gpio_wdt_hwping, (unsigned long)&priv->wdd); - ret = watchdog_register_device(&priv->wdd); +#ifdef MODULE + ret = gpio_wdt_init_late(); if (ret) return ret; - +#endif priv->notifier.notifier_call = gpio_wdt_notify_sys; ret = register_reboot_notifier(&priv->notifier); if (ret) @@ -235,10 +237,13 @@ static int gpio_wdt_probe(struct platform_device *pdev) if (priv->always_running) gpio_wdt_start_impl(priv); + platform_set_drvdata(pdev, priv); return 0; error_unregister: - watchdog_unregister_device(&priv->wdd); +#ifdef MODULE + ret = gpio_wdt_remove_late(&priv->wdd); +#endif return ret; } @@ -267,7 +272,72 @@ static struct platform_driver gpio_wdt_driver = { .probe = gpio_wdt_probe, .remove = gpio_wdt_remove, }; -module_platform_driver(gpio_wdt_driver); + +/* + * We do wdt initialization in two steps: arch_initcall probes the wdt + * very early to start pinging the watchdog (misc devices are not yet + * available), and later module_init() just registers the misc device. + */ +static int gpio_wdt_init_late(void) +{ + struct platform_device *pdev; + struct device_node *wdt_node; + struct gpio_wdt_priv *priv; + int ret; + + for_each_compatible_node(wdt_node, NULL, "linux,wdt-gpio") { + pdev = of_find_device_by_node(wdt_node); + priv = platform_get_drvdata(pdev); + if (&priv->wdd) { + ret = watchdog_register_device(&priv->wdd); + if (ret) + return ret; + } else { + dev_err(&pdev->dev, "Unable to register the watchdog\n"); + return -1; + } + } + return 0; +} +#ifndef MODULE +module_init(gpio_wdt_init_late); +#endif + +#ifdef MODULE +int gpio_wdt_remove_late(void) +{ + struct platform_device *pdev; + struct device_node *wdt_node; + struct gpio_wdt_priv *priv; + int ret; + + for_each_compatible_node(wdt_node, NULL, "linux,wdt-gpio") { + pdev = of_find_device_by_node(wdt_node); + priv = platform_get_drvdata(pdev); + if (&priv->wdd) { + ret = watchdog_unregister_device(&priv->wdd); + if (ret) + return ret; + } else { + dev_err(&pdev->dev, "Unable to register the watchdog\n"); + return -1; + } + } + return 0; +} +#endif + +static int __init gpio_wdt_init(void) +{ + return platform_driver_register(&gpio_wdt_driver); +} +arch_initcall(gpio_wdt_init); + +static void __exit gpio_wdt_exit(void) +{ + platform_driver_unregister(&gpio_wdt_driver); +} +module_exit(gpio_wdt_exit); MODULE_AUTHOR("Alexander Shiyan <shc_work@xxxxxxx>"); MODULE_DESCRIPTION("GPIO Watchdog"); -- 2.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html