OSDN Git Service

Merge branch 'upstream' of git://git.infradead.org/users/pcmoore/selinux into for...
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / drivers / watchdog / dw_wdt.c
index b34a2e4..d0bb949 100644 (file)
@@ -51,6 +51,8 @@
 /* The maximum TOP (timeout period) value that can be set in the watchdog. */
 #define DW_WDT_MAX_TOP         15
 
+#define DW_WDT_DEFAULT_SECONDS 30
+
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
@@ -96,6 +98,12 @@ static inline void dw_wdt_set_next_heartbeat(void)
        dw_wdt.next_heartbeat = jiffies + dw_wdt_get_top() * HZ;
 }
 
+static void dw_wdt_keepalive(void)
+{
+       writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
+              WDOG_COUNTER_RESTART_REG_OFFSET);
+}
+
 static int dw_wdt_set_top(unsigned top_s)
 {
        int i, top_val = DW_WDT_MAX_TOP;
@@ -110,21 +118,27 @@ static int dw_wdt_set_top(unsigned top_s)
                        break;
                }
 
-       /* Set the new value in the watchdog. */
+       /*
+        * Set the new value in the watchdog.  Some versions of dw_wdt
+        * have have TOPINIT in the TIMEOUT_RANGE register (as per
+        * CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1).  On those we
+        * effectively get a pat of the watchdog right here.
+        */
        writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT,
                dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
 
+       /*
+        * Add an explicit pat to handle versions of the watchdog that
+        * don't have TOPINIT.  This won't hurt on versions that have
+        * it.
+        */
+       dw_wdt_keepalive();
+
        dw_wdt_set_next_heartbeat();
 
        return dw_wdt_top_in_seconds(top_val);
 }
 
-static void dw_wdt_keepalive(void)
-{
-       writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
-              WDOG_COUNTER_RESTART_REG_OFFSET);
-}
-
 static int dw_wdt_restart_handle(struct notifier_block *this,
                                unsigned long mode, void *cmd)
 {
@@ -167,9 +181,9 @@ static int dw_wdt_open(struct inode *inode, struct file *filp)
        if (!dw_wdt_is_enabled()) {
                /*
                 * The watchdog is not currently enabled. Set the timeout to
-                * the maximum and then start it.
+                * something reasonable and then start it.
                 */
-               dw_wdt_set_top(DW_WDT_MAX_TOP);
+               dw_wdt_set_top(DW_WDT_DEFAULT_SECONDS);
                writel(WDOG_CONTROL_REG_WDT_EN_MASK,
                       dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
        }