diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-08-14 09:47:28 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-08-15 04:55:46 -0400 |
commit | 0a54419836254a27baecd9037103171bcbabaf67 (patch) | |
tree | ad4dc7ca1fc974a53c7fc2e972558bcb6b786afe /kernel/time/timekeeping.c | |
parent | 23ce72117c714baab794e66c8daf343bf6a912bf (diff) |
timekeeping: Move NTP adjusted clock multiplier to struct timekeeper
The clocksource structure has two multipliers, the unmodified multiplier
clock->mult_orig and the NTP corrected multiplier clock->mult. The NTP
multiplier is misplaced in the struct clocksource, this is private
information of the timekeeping code. Add the mult field to the struct
timekeeper to contain the NTP corrected value, keep the unmodifed
multiplier in clock->mult and remove clock->mult_orig.
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: <20090814134810.149047645@de.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r-- | kernel/time/timekeeping.c | 53 |
1 files changed, 24 insertions, 29 deletions
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 */ |