aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/clocksource.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r--kernel/time/clocksource.c47
1 files changed, 22 insertions, 25 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index e91662e87cde..76256c5aecb8 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -153,11 +153,8 @@ static unsigned long watchdog_resumed;
153#define WATCHDOG_INTERVAL (HZ >> 1) 153#define WATCHDOG_INTERVAL (HZ >> 1)
154#define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4) 154#define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4)
155 155
156static void clocksource_ratewd(struct clocksource *cs, int64_t delta) 156static void clocksource_unstable(struct clocksource *cs, int64_t delta)
157{ 157{
158 if (delta > -WATCHDOG_THRESHOLD && delta < WATCHDOG_THRESHOLD)
159 return;
160
161 printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n", 158 printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
162 cs->name, delta); 159 cs->name, delta);
163 cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG); 160 cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
@@ -183,31 +180,31 @@ static void clocksource_watchdog(unsigned long data)
183 list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { 180 list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
184 csnow = cs->read(cs); 181 csnow = cs->read(cs);
185 182
186 if (unlikely(resumed)) { 183 /* Clocksource initialized ? */
184 if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
185 cs->flags |= CLOCK_SOURCE_WATCHDOG;
187 cs->wd_last = csnow; 186 cs->wd_last = csnow;
188 continue; 187 continue;
189 } 188 }
190 189
191 /* Initialized ? */ 190 /* Check the deviation from the watchdog clocksource. */
192 if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { 191 cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask);
193 if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) && 192 cs->wd_last = csnow;
194 (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) { 193 if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
195 cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; 194 clocksource_unstable(cs, cs_nsec - wd_nsec);
196 /* 195 continue;
197 * We just marked the clocksource as 196 }
198 * highres-capable, notify the rest of the 197
199 * system as well so that we transition 198 if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) &&
200 * into high-res mode: 199 (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
201 */ 200 (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
202 tick_clock_notify(); 201 cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
203 } 202 /*
204 cs->flags |= CLOCK_SOURCE_WATCHDOG; 203 * We just marked the clocksource as highres-capable,
205 cs->wd_last = csnow; 204 * notify the rest of the system as well so that we
206 } else { 205 * transition into high-res mode:
207 cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask); 206 */
208 cs->wd_last = csnow; 207 tick_clock_notify();
209 /* Check the delta. Might remove from the list ! */
210 clocksource_ratewd(cs, cs_nsec - wd_nsec);
211 } 208 }
212 } 209 }
213 210