aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-omap/common.c7
-rw-r--r--include/linux/clocksource.h4
-rw-r--r--kernel/time/timekeeping.c53
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 */
254unsigned long long sched_clock(void) 254unsigned 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
263static int __init omap_init_clocksource_32k(void) 260static 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
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 */