diff options
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r-- | kernel/time/clocksource.c | 47 |
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 | ||
156 | static void clocksource_ratewd(struct clocksource *cs, int64_t delta) | 156 | static 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 | ||