CRISv32: Better handling of watchdog bite
authorJesper Nilsson <jespern@axis.com>
Tue, 7 Oct 2014 10:59:24 +0000 (12:59 +0200)
committerJesper Nilsson <jespern@axis.com>
Fri, 19 Dec 2014 23:04:39 +0000 (00:04 +0100)
Don't enter watchdog handling if we're already in watchdog handling.

Also some minor formatting tweaks.

Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
arch/cris/arch-v32/kernel/time.c

index 73745ce..eb74dab 100644 (file)
@@ -57,7 +57,6 @@ static int __init etrax_init_cont_rotime(void)
 }
 arch_initcall(etrax_init_cont_rotime);
 
-
 unsigned long timer_regs[NR_CPUS] =
 {
        regi_timer0,
@@ -69,9 +68,8 @@ unsigned long timer_regs[NR_CPUS] =
 extern int set_rtc_mmss(unsigned long nowtime);
 
 #ifdef CONFIG_CPU_FREQ
-static int
-cris_time_freq_notifier(struct notifier_block *nb, unsigned long val,
-                       void *data);
+static int cris_time_freq_notifier(struct notifier_block *nb,
+                                  unsigned long val, void *data);
 
 static struct notifier_block cris_time_freq_notifier_block = {
        .notifier_call = cris_time_freq_notifier,
@@ -88,7 +86,6 @@ unsigned long get_ns_in_jiffie(void)
        return ns;
 }
 
-
 /* From timer MDS describing the hardware watchdog:
  * 4.3.1 Watchdog Operation
  * The watchdog timer is an 8-bit timer with a configurable start value.
@@ -110,11 +107,18 @@ static short int watchdog_key = 42;  /* arbitrary 7 bit number */
  * is used though, so set this really low. */
 #define WATCHDOG_MIN_FREE_PAGES 8
 
+/* for reliable NICE_DOGGY behaviour */
+static int bite_in_progress;
+
 void reset_watchdog(void)
 {
 #if defined(CONFIG_ETRAX_WATCHDOG)
        reg_timer_rw_wd_ctrl wd_ctrl = { 0 };
 
+#if defined(CONFIG_ETRAX_WATCHDOG_NICE_DOGGY)
+       if (unlikely(bite_in_progress))
+               return;
+#endif
        /* Only keep watchdog happy as long as we have memory left! */
        if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) {
                /* Reset the watchdog with the inverse of the old key */
@@ -149,7 +153,9 @@ void handle_watchdog_bite(struct pt_regs *regs)
 #if defined(CONFIG_ETRAX_WATCHDOG)
        extern int cause_of_death;
 
+       nmi_enter();
        oops_in_progress = 1;
+       bite_in_progress = 1;
        printk(KERN_WARNING "Watchdog bite\n");
 
        /* Check if forced restart or unexpected watchdog */
@@ -171,6 +177,7 @@ void handle_watchdog_bite(struct pt_regs *regs)
        printk(KERN_WARNING "Oops: bitten by watchdog\n");
        show_registers(regs);
        oops_in_progress = 0;
+       printk("\n"); /* Flush mtdoops.  */
 #ifndef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
        reset_watchdog();
 #endif
@@ -203,7 +210,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
        /* Reset watchdog otherwise it resets us! */
        reset_watchdog();
 
-        /* Update statistics. */
+       /* Update statistics. */
        update_process_times(user_mode(regs));
 
        cris_do_profile(regs); /* Save profiling information */
@@ -214,7 +221,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
 
        /* Call the real timer interrupt handler */
        xtime_update(1);
-        return IRQ_HANDLED;
+       return IRQ_HANDLED;
 }
 
 /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */
@@ -294,14 +301,13 @@ void __init time_init(void)
 
 #ifdef CONFIG_CPU_FREQ
        cpufreq_register_notifier(&cris_time_freq_notifier_block,
-               CPUFREQ_TRANSITION_NOTIFIER);
+                                 CPUFREQ_TRANSITION_NOTIFIER);
 #endif
 }
 
 #ifdef CONFIG_CPU_FREQ
-static int
-cris_time_freq_notifier(struct notifier_block *nb, unsigned long val,
-                       void *data)
+static int cris_time_freq_notifier(struct notifier_block *nb,
+                                  unsigned long val, void *data)
 {
        struct cpufreq_freqs *freqs = data;
        if (val == CPUFREQ_POSTCHANGE) {