diff options
Diffstat (limited to 'target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch')
-rw-r--r-- | target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch b/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch new file mode 100644 index 0000000000..3e67ba2bb1 --- /dev/null +++ b/target/linux/brcm47xx/patches-3.6/544-watchdog-bcm47xx_wdt.c-add-hard-timer.patch @@ -0,0 +1,120 @@ +--- a/drivers/watchdog/bcm47xx_wdt.c ++++ b/drivers/watchdog/bcm47xx_wdt.c +@@ -31,6 +31,7 @@ + + #define WDT_DEFAULT_TIME 30 /* seconds */ + #define WDT_SOFTTIMER_MAX 3600 /* seconds */ ++#define WDT_SOFTTIMER_THRESHOLD 60 /* seconds */ + + static int timeout = WDT_DEFAULT_TIME; + static bool nowayout = WATCHDOG_NOWAYOUT; +@@ -52,6 +53,53 @@ static inline struct bcm47xx_wdt *bcm47x + return container_of(wdd, struct bcm47xx_wdt, wdd); + } + ++static int bcm47xx_wdt_hard_keepalive(struct watchdog_device *wdd) ++{ ++ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); ++ ++ wdt->timer_set_ms(wdt, wdd->timeout * 1000); ++ ++ return 0; ++} ++ ++static int bcm47xx_wdt_hard_start(struct watchdog_device *wdd) ++{ ++ return 0; ++} ++ ++static int bcm47xx_wdt_hard_stop(struct watchdog_device *wdd) ++{ ++ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); ++ ++ wdt->timer_set(wdt, 0); ++ ++ return 0; ++} ++ ++static int bcm47xx_wdt_hard_set_timeout(struct watchdog_device *wdd, ++ unsigned int new_time) ++{ ++ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); ++ u32 max_timer = wdt->max_timer_ms; ++ ++ if (new_time < 1 || new_time > max_timer / 1000) { ++ pr_warn("timeout value must be 1<=x<=%d, using %d\n", ++ max_timer / 1000, new_time); ++ return -EINVAL; ++ } ++ ++ wdd->timeout = new_time; ++ return 0; ++} ++ ++static struct watchdog_ops bcm47xx_wdt_hard_ops = { ++ .owner = THIS_MODULE, ++ .start = bcm47xx_wdt_hard_start, ++ .stop = bcm47xx_wdt_hard_stop, ++ .ping = bcm47xx_wdt_hard_keepalive, ++ .set_timeout = bcm47xx_wdt_hard_set_timeout, ++}; ++ + static void bcm47xx_wdt_soft_timer_tick(unsigned long data) + { + struct bcm47xx_wdt *wdt = (struct bcm47xx_wdt *)data; +@@ -136,15 +184,22 @@ static struct watchdog_ops bcm47xx_wdt_s + static int __devinit bcm47xx_wdt_probe(struct platform_device *pdev) + { + int ret; ++ bool soft; + struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev); + + if (!wdt) + return -ENXIO; + +- setup_timer(&wdt->soft_timer, bcm47xx_wdt_soft_timer_tick, +- (long unsigned int)wdt); ++ soft = wdt->max_timer_ms < WDT_SOFTTIMER_THRESHOLD * 1000; ++ ++ if (soft) { ++ wdt->wdd.ops = &bcm47xx_wdt_soft_ops; ++ setup_timer(&wdt->soft_timer, bcm47xx_wdt_soft_timer_tick, ++ (long unsigned int)wdt); ++ } else { ++ wdt->wdd.ops = &bcm47xx_wdt_hard_ops; ++ } + +- wdt->wdd.ops = &bcm47xx_wdt_soft_ops; + wdt->wdd.info = &bcm47xx_wdt_info; + wdt->wdd.timeout = WDT_DEFAULT_TIME; + ret = wdt->wdd.ops->set_timeout(&wdt->wdd, timeout); +@@ -162,14 +217,16 @@ static int __devinit bcm47xx_wdt_probe(s + if (ret) + goto err_notifier; + +- pr_info("BCM47xx Watchdog Timer enabled (%d seconds%s)\n", +- timeout, nowayout ? ", nowayout" : ""); ++ dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n", ++ timeout, nowayout ? ", nowayout" : "", ++ soft ? ", Software Timer" : ""); + return 0; + + err_notifier: + unregister_reboot_notifier(&wdt->notifier); + err_timer: +- del_timer_sync(&wdt->soft_timer); ++ if (soft) ++ del_timer_sync(&wdt->soft_timer); + + return ret; + } +--- a/include/linux/bcm47xx_wdt.h ++++ b/include/linux/bcm47xx_wdt.h +@@ -10,6 +10,7 @@ + struct bcm47xx_wdt { + u32 (*timer_set)(struct bcm47xx_wdt *, u32); + u32 (*timer_set_ms)(struct bcm47xx_wdt *, u32); ++ u32 max_timer_ms; + + void *driver_data; + |