aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/timekeeping.c53
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
46struct timekeeper timekeeper; 48struct 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 */