clocksource: Delay clocksource watchdog highres enablement
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 14 Aug 2009 13:47:22 +0000 (15:47 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 15 Aug 2009 08:55:46 +0000 (10:55 +0200)
The clocksource watchdog marks a clock as highres capable before it
checked the deviation from the watchdog clocksource even for a single
time. Make sure that the deviation is at least checked once before
doing the switch to highres mode.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Acked-by: John Stultz <johnstul@us.ibm.com>
Cc: Daniel Walker <dwalker@fifo99.com>
LKML-Reference: <20090814134808.627795883@de.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
kernel/time/clocksource.c

index e91662e87cdef1caca601904ff404702594206b8..76256c5aecb811927ee8e3ed302cdd34dceaf982 100644 (file)
@@ -153,11 +153,8 @@ static unsigned long watchdog_resumed;
 #define WATCHDOG_INTERVAL (HZ >> 1)
 #define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4)
 
-static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
+static void clocksource_unstable(struct clocksource *cs, int64_t delta)
 {
-       if (delta > -WATCHDOG_THRESHOLD && delta < WATCHDOG_THRESHOLD)
-               return;
-
        printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
               cs->name, delta);
        cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
@@ -183,31 +180,31 @@ static void clocksource_watchdog(unsigned long data)
        list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
                csnow = cs->read(cs);
 
-               if (unlikely(resumed)) {
+               /* Clocksource initialized ? */
+               if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
+                       cs->flags |= CLOCK_SOURCE_WATCHDOG;
                        cs->wd_last = csnow;
                        continue;
                }
 
-               /* Initialized ? */
-               if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
-                       if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
-                           (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
-                               cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-                               /*
-                                * We just marked the clocksource as
-                                * highres-capable, notify the rest of the
-                                * system as well so that we transition
-                                * into high-res mode:
-                                */
-                               tick_clock_notify();
-                       }
-                       cs->flags |= CLOCK_SOURCE_WATCHDOG;
-                       cs->wd_last = csnow;
-               } else {
-                       cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask);
-                       cs->wd_last = csnow;
-                       /* Check the delta. Might remove from the list ! */
-                       clocksource_ratewd(cs, cs_nsec - wd_nsec);
+               /* Check the deviation from the watchdog clocksource. */
+               cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask);
+               cs->wd_last = csnow;
+               if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
+                       clocksource_unstable(cs, cs_nsec - wd_nsec);
+                       continue;
+               }
+
+               if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) &&
+                   (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
+                   (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
+                       cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+                       /*
+                        * We just marked the clocksource as highres-capable,
+                        * notify the rest of the system as well so that we
+                        * transition into high-res mode:
+                        */
+                       tick_clock_notify();
                }
        }