diff options
-rw-r--r-- | arch/arm/plat-omap/common.c | 7 | ||||
-rw-r--r-- | include/linux/clocksource.h | 4 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 53 |
3 files changed, 27 insertions, 37 deletions
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index ebcf006406f9..95587b6c0259 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c | |||
@@ -253,11 +253,8 @@ static struct clocksource clocksource_32k = { | |||
253 | */ | 253 | */ |
254 | unsigned long long sched_clock(void) | 254 | unsigned long long sched_clock(void) |
255 | { | 255 | { |
256 | unsigned long long ret; | 256 | return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k), |
257 | 257 | clocksource_32k.mult, clocksource_32k.shift); | |
258 | ret = (unsigned long long)clocksource_32k.read(&clocksource_32k); | ||
259 | ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift; | ||
260 | return ret; | ||
261 | } | 258 | } |
262 | 259 | ||
263 | static int __init omap_init_clocksource_32k(void) | 260 | static int __init omap_init_clocksource_32k(void) |
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index e12e3095e2fb..e34015effeb6 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h | |||
@@ -149,8 +149,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc, | |||
149 | * @disable: optional function to disable the clocksource | 149 | * @disable: optional function to disable the clocksource |
150 | * @mask: bitmask for two's complement | 150 | * @mask: bitmask for two's complement |
151 | * subtraction of non 64 bit counters | 151 | * subtraction of non 64 bit counters |
152 | * @mult: cycle to nanosecond multiplier (adjusted by NTP) | 152 | * @mult: cycle to nanosecond multiplier |
153 | * @mult_orig: cycle to nanosecond multiplier (unadjusted by NTP) | ||
154 | * @shift: cycle to nanosecond divisor (power of two) | 153 | * @shift: cycle to nanosecond divisor (power of two) |
155 | * @flags: flags describing special properties | 154 | * @flags: flags describing special properties |
156 | * @vread: vsyscall based read | 155 | * @vread: vsyscall based read |
@@ -168,7 +167,6 @@ struct clocksource { | |||
168 | void (*disable)(struct clocksource *cs); | 167 | void (*disable)(struct clocksource *cs); |
169 | cycle_t mask; | 168 | cycle_t mask; |
170 | u32 mult; | 169 | u32 mult; |
171 | u32 mult_orig; | ||
172 | u32 shift; | 170 | u32 shift; |
173 | unsigned long flags; | 171 | unsigned long flags; |
174 | cycle_t (*vread)(void); | 172 | cycle_t (*vread)(void); |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index dfdab1cefe1e..f4056f6c2632 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -41,6 +41,8 @@ struct timekeeper { | |||
41 | /* Shift conversion between clock shifted nano seconds and | 41 | /* Shift conversion between clock shifted nano seconds and |
42 | * ntp shifted nano seconds. */ | 42 | * ntp shifted nano seconds. */ |
43 | int ntp_error_shift; | 43 | int ntp_error_shift; |
44 | /* NTP adjusted clock multiplier */ | ||
45 | u32 mult; | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | struct timekeeper timekeeper; | 48 | struct timekeeper timekeeper; |
@@ -66,8 +68,8 @@ static void timekeeper_setup_internals(struct clocksource *clock) | |||
66 | /* Do the ns -> cycle conversion first, using original mult */ | 68 | /* Do the ns -> cycle conversion first, using original mult */ |
67 | tmp = NTP_INTERVAL_LENGTH; | 69 | tmp = NTP_INTERVAL_LENGTH; |
68 | tmp <<= clock->shift; | 70 | tmp <<= clock->shift; |
69 | tmp += clock->mult_orig/2; | 71 | tmp += clock->mult/2; |
70 | do_div(tmp, clock->mult_orig); | 72 | do_div(tmp, clock->mult); |
71 | if (tmp == 0) | 73 | if (tmp == 0) |
72 | tmp = 1; | 74 | tmp = 1; |
73 | 75 | ||
@@ -77,13 +79,20 @@ static void timekeeper_setup_internals(struct clocksource *clock) | |||
77 | /* Go back from cycles -> shifted ns */ | 79 | /* Go back from cycles -> shifted ns */ |
78 | timekeeper.xtime_interval = (u64) interval * clock->mult; | 80 | timekeeper.xtime_interval = (u64) interval * clock->mult; |
79 | timekeeper.raw_interval = | 81 | timekeeper.raw_interval = |
80 | ((u64) interval * clock->mult_orig) >> clock->shift; | 82 | ((u64) interval * clock->mult) >> clock->shift; |
81 | 83 | ||
82 | timekeeper.xtime_nsec = 0; | 84 | timekeeper.xtime_nsec = 0; |
83 | timekeeper.shift = clock->shift; | 85 | timekeeper.shift = clock->shift; |
84 | 86 | ||
85 | timekeeper.ntp_error = 0; | 87 | timekeeper.ntp_error = 0; |
86 | timekeeper.ntp_error_shift = NTP_SCALE_SHIFT - clock->shift; | 88 | timekeeper.ntp_error_shift = NTP_SCALE_SHIFT - clock->shift; |
89 | |||
90 | /* | ||
91 | * The timekeeper keeps its own mult values for the currently | ||
92 | * active clocksource. These value will be adjusted via NTP | ||
93 | * to counteract clock drifting. | ||
94 | */ | ||
95 | timekeeper.mult = clock->mult; | ||
87 | } | 96 | } |
88 | 97 | ||
89 | /* | 98 | /* |
@@ -154,14 +163,15 @@ static void timekeeping_forward_now(void) | |||
154 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 163 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; |
155 | clock->cycle_last = cycle_now; | 164 | clock->cycle_last = cycle_now; |
156 | 165 | ||
157 | nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); | 166 | nsec = clocksource_cyc2ns(cycle_delta, timekeeper.mult, |
167 | timekeeper.shift); | ||
158 | 168 | ||
159 | /* If arch requires, add in gettimeoffset() */ | 169 | /* If arch requires, add in gettimeoffset() */ |
160 | nsec += arch_gettimeoffset(); | 170 | nsec += arch_gettimeoffset(); |
161 | 171 | ||
162 | timespec_add_ns(&xtime, nsec); | 172 | timespec_add_ns(&xtime, nsec); |
163 | 173 | ||
164 | nsec = clocksource_cyc2ns(cycle_delta, clock->mult_orig, clock->shift); | 174 | nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); |
165 | timespec_add_ns(&raw_time, nsec); | 175 | timespec_add_ns(&raw_time, nsec); |
166 | } | 176 | } |
167 | 177 | ||
@@ -193,8 +203,8 @@ void getnstimeofday(struct timespec *ts) | |||
193 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 203 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; |
194 | 204 | ||
195 | /* convert to nanoseconds: */ | 205 | /* convert to nanoseconds: */ |
196 | nsecs = clocksource_cyc2ns(cycle_delta, clock->mult, | 206 | nsecs = clocksource_cyc2ns(cycle_delta, timekeeper.mult, |
197 | clock->shift); | 207 | timekeeper.shift); |
198 | 208 | ||
199 | /* If arch requires, add in gettimeoffset() */ | 209 | /* If arch requires, add in gettimeoffset() */ |
200 | nsecs += arch_gettimeoffset(); | 210 | nsecs += arch_gettimeoffset(); |
@@ -228,8 +238,8 @@ ktime_t ktime_get(void) | |||
228 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 238 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; |
229 | 239 | ||
230 | /* convert to nanoseconds: */ | 240 | /* convert to nanoseconds: */ |
231 | nsecs += clocksource_cyc2ns(cycle_delta, clock->mult, | 241 | nsecs += clocksource_cyc2ns(cycle_delta, timekeeper.mult, |
232 | clock->shift); | 242 | timekeeper.shift); |
233 | 243 | ||
234 | } while (read_seqretry(&xtime_lock, seq)); | 244 | } while (read_seqretry(&xtime_lock, seq)); |
235 | /* | 245 | /* |
@@ -271,8 +281,8 @@ void ktime_get_ts(struct timespec *ts) | |||
271 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 281 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; |
272 | 282 | ||
273 | /* convert to nanoseconds: */ | 283 | /* convert to nanoseconds: */ |
274 | nsecs = clocksource_cyc2ns(cycle_delta, clock->mult, | 284 | nsecs = clocksource_cyc2ns(cycle_delta, timekeeper.mult, |
275 | clock->shift); | 285 | timekeeper.shift); |
276 | 286 | ||
277 | } while (read_seqretry(&xtime_lock, seq)); | 287 | } while (read_seqretry(&xtime_lock, seq)); |
278 | 288 | ||
@@ -356,22 +366,10 @@ static void change_clocksource(void) | |||
356 | 366 | ||
357 | if (new->enable && !new->enable(new)) | 367 | if (new->enable && !new->enable(new)) |
358 | return; | 368 | return; |
359 | /* | ||
360 | * The frequency may have changed while the clocksource | ||
361 | * was disabled. If so the code in ->enable() must update | ||
362 | * the mult value to reflect the new frequency. Make sure | ||
363 | * mult_orig follows this change. | ||
364 | */ | ||
365 | new->mult_orig = new->mult; | ||
366 | 369 | ||
367 | old = timekeeper.clock; | 370 | old = timekeeper.clock; |
368 | timekeeper_setup_internals(new); | 371 | timekeeper_setup_internals(new); |
369 | 372 | ||
370 | /* | ||
371 | * Save mult_orig in mult so that the value can be restored | ||
372 | * regardless if ->enable() updates the value of mult or not. | ||
373 | */ | ||
374 | old->mult = old->mult_orig; | ||
375 | if (old->disable) | 373 | if (old->disable) |
376 | old->disable(old); | 374 | old->disable(old); |
377 | 375 | ||
@@ -461,7 +459,7 @@ void getrawmonotonic(struct timespec *ts) | |||
461 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 459 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; |
462 | 460 | ||
463 | /* convert to nanoseconds: */ | 461 | /* convert to nanoseconds: */ |
464 | nsecs = clocksource_cyc2ns(cycle_delta, clock->mult_orig, | 462 | nsecs = clocksource_cyc2ns(cycle_delta, clock->mult, |
465 | clock->shift); | 463 | clock->shift); |
466 | 464 | ||
467 | *ts = raw_time; | 465 | *ts = raw_time; |
@@ -521,9 +519,6 @@ void __init timekeeping_init(void) | |||
521 | clock = clocksource_default_clock(); | 519 | clock = clocksource_default_clock(); |
522 | if (clock->enable) | 520 | if (clock->enable) |
523 | clock->enable(clock); | 521 | clock->enable(clock); |
524 | /* set mult_orig on enable */ | ||
525 | clock->mult_orig = clock->mult; | ||
526 | |||
527 | timekeeper_setup_internals(clock); | 522 | timekeeper_setup_internals(clock); |
528 | 523 | ||
529 | xtime.tv_sec = sec; | 524 | xtime.tv_sec = sec; |
@@ -697,7 +692,7 @@ static void timekeeping_adjust(s64 offset) | |||
697 | } else | 692 | } else |
698 | return; | 693 | return; |
699 | 694 | ||
700 | timekeeper.clock->mult += adj; | 695 | timekeeper.mult += adj; |
701 | timekeeper.xtime_interval += interval; | 696 | timekeeper.xtime_interval += interval; |
702 | timekeeper.xtime_nsec -= offset; | 697 | timekeeper.xtime_nsec -= offset; |
703 | timekeeper.ntp_error -= (interval - offset) << | 698 | timekeeper.ntp_error -= (interval - offset) << |
@@ -789,7 +784,7 @@ void update_wall_time(void) | |||
789 | timekeeper.ntp_error += timekeeper.xtime_nsec << | 784 | timekeeper.ntp_error += timekeeper.xtime_nsec << |
790 | timekeeper.ntp_error_shift; | 785 | timekeeper.ntp_error_shift; |
791 | 786 | ||
792 | nsecs = clocksource_cyc2ns(offset, clock->mult, clock->shift); | 787 | nsecs = clocksource_cyc2ns(offset, timekeeper.mult, timekeeper.shift); |
793 | update_xtime_cache(nsecs); | 788 | update_xtime_cache(nsecs); |
794 | 789 | ||
795 | /* check to see if there is a new clocksource to use */ | 790 | /* check to see if there is a new clocksource to use */ |