diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2014-07-16 17:05:10 -0400 |
|---|---|---|
| committer | John Stultz <john.stultz@linaro.org> | 2014-07-23 18:01:51 -0400 |
| commit | 3a97837784acbf9fed699fc04d1799b0eb742fdf (patch) | |
| tree | 12297634077b24bcc6a01b779205043fc2a2a1f1 | |
| parent | 6438e0ddc870f282f7ad46c050c211063a574687 (diff) | |
clocksource: Make delta calculation a function
We want to move the TSC sanity check into core code to make NMI safe
accessors to clock monotonic[_raw] possible. For this we need to
sanity check the delta calculation. Create a helper function and
convert all sites to use it.
[ Build fix from jstultz ]
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
| -rw-r--r-- | kernel/time/clocksource.c | 12 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 26 | ||||
| -rw-r--r-- | kernel/time/timekeeping_internal.h | 6 |
3 files changed, 27 insertions, 17 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index ba3e502c955a..2e949cc9c9f1 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/kthread.h> | 32 | #include <linux/kthread.h> |
| 33 | 33 | ||
| 34 | #include "tick-internal.h" | 34 | #include "tick-internal.h" |
| 35 | #include "timekeeping_internal.h" | ||
| 35 | 36 | ||
| 36 | void timecounter_init(struct timecounter *tc, | 37 | void timecounter_init(struct timecounter *tc, |
| 37 | const struct cyclecounter *cc, | 38 | const struct cyclecounter *cc, |
| @@ -249,7 +250,7 @@ void clocksource_mark_unstable(struct clocksource *cs) | |||
| 249 | static void clocksource_watchdog(unsigned long data) | 250 | static void clocksource_watchdog(unsigned long data) |
| 250 | { | 251 | { |
| 251 | struct clocksource *cs; | 252 | struct clocksource *cs; |
| 252 | cycle_t csnow, wdnow; | 253 | cycle_t csnow, wdnow, delta; |
| 253 | int64_t wd_nsec, cs_nsec; | 254 | int64_t wd_nsec, cs_nsec; |
| 254 | int next_cpu, reset_pending; | 255 | int next_cpu, reset_pending; |
| 255 | 256 | ||
| @@ -282,11 +283,12 @@ static void clocksource_watchdog(unsigned long data) | |||
| 282 | continue; | 283 | continue; |
| 283 | } | 284 | } |
| 284 | 285 | ||
| 285 | wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask, | 286 | delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask); |
| 286 | watchdog->mult, watchdog->shift); | 287 | wd_nsec = clocksource_cyc2ns(delta, watchdog->mult, |
| 288 | watchdog->shift); | ||
| 287 | 289 | ||
| 288 | cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) & | 290 | delta = clocksource_delta(csnow, cs->cs_last, cs->mask); |
| 289 | cs->mask, cs->mult, cs->shift); | 291 | cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift); |
| 290 | cs->cs_last = csnow; | 292 | cs->cs_last = csnow; |
| 291 | cs->wd_last = wdnow; | 293 | cs->wd_last = wdnow; |
| 292 | 294 | ||
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index af8051f4420d..531805013786 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -173,7 +173,7 @@ static inline u32 arch_gettimeoffset(void) { return 0; } | |||
| 173 | 173 | ||
| 174 | static inline s64 timekeeping_get_ns(struct timekeeper *tk) | 174 | static inline s64 timekeeping_get_ns(struct timekeeper *tk) |
| 175 | { | 175 | { |
| 176 | cycle_t cycle_now, cycle_delta; | 176 | cycle_t cycle_now, delta; |
| 177 | struct clocksource *clock; | 177 | struct clocksource *clock; |
| 178 | s64 nsec; | 178 | s64 nsec; |
| 179 | 179 | ||
| @@ -182,9 +182,9 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk) | |||
| 182 | cycle_now = clock->read(clock); | 182 | cycle_now = clock->read(clock); |
| 183 | 183 | ||
| 184 | /* calculate the delta since the last update_wall_time: */ | 184 | /* calculate the delta since the last update_wall_time: */ |
| 185 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 185 | delta = clocksource_delta(cycle_now, clock->cycle_last, clock->mask); |
| 186 | 186 | ||
| 187 | nsec = cycle_delta * tk->mult + tk->xtime_nsec; | 187 | nsec = delta * tk->mult + tk->xtime_nsec; |
| 188 | nsec >>= tk->shift; | 188 | nsec >>= tk->shift; |
| 189 | 189 | ||
| 190 | /* If arch requires, add in get_arch_timeoffset() */ | 190 | /* If arch requires, add in get_arch_timeoffset() */ |
| @@ -193,7 +193,7 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk) | |||
| 193 | 193 | ||
| 194 | static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | 194 | static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) |
| 195 | { | 195 | { |
| 196 | cycle_t cycle_now, cycle_delta; | 196 | cycle_t cycle_now, delta; |
| 197 | struct clocksource *clock; | 197 | struct clocksource *clock; |
| 198 | s64 nsec; | 198 | s64 nsec; |
| 199 | 199 | ||
| @@ -202,10 +202,10 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | |||
| 202 | cycle_now = clock->read(clock); | 202 | cycle_now = clock->read(clock); |
| 203 | 203 | ||
| 204 | /* calculate the delta since the last update_wall_time: */ | 204 | /* calculate the delta since the last update_wall_time: */ |
| 205 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 205 | delta = clocksource_delta(cycle_now, clock->cycle_last, clock->mask); |
| 206 | 206 | ||
| 207 | /* convert delta to nanoseconds. */ | 207 | /* convert delta to nanoseconds. */ |
| 208 | nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); | 208 | nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift); |
| 209 | 209 | ||
| 210 | /* If arch requires, add in get_arch_timeoffset() */ | 210 | /* If arch requires, add in get_arch_timeoffset() */ |
| 211 | return nsec + arch_gettimeoffset(); | 211 | return nsec + arch_gettimeoffset(); |
| @@ -336,23 +336,23 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action) | |||
| 336 | */ | 336 | */ |
| 337 | static void timekeeping_forward_now(struct timekeeper *tk) | 337 | static void timekeeping_forward_now(struct timekeeper *tk) |
| 338 | { | 338 | { |
| 339 | cycle_t cycle_now, cycle_delta; | 339 | cycle_t cycle_now, delta; |
| 340 | struct clocksource *clock; | 340 | struct clocksource *clock; |
| 341 | s64 nsec; | 341 | s64 nsec; |
| 342 | 342 | ||
| 343 | clock = tk->clock; | 343 | clock = tk->clock; |
| 344 | cycle_now = clock->read(clock); | 344 | cycle_now = clock->read(clock); |
| 345 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 345 | delta = clocksource_delta(cycle_now, clock->cycle_last, clock->mask); |
| 346 | tk->cycle_last = clock->cycle_last = cycle_now; | 346 | tk->cycle_last = clock->cycle_last = cycle_now; |
| 347 | 347 | ||
| 348 | tk->xtime_nsec += cycle_delta * tk->mult; | 348 | tk->xtime_nsec += delta * tk->mult; |
| 349 | 349 | ||
| 350 | /* If arch requires, add in get_arch_timeoffset() */ | 350 | /* If arch requires, add in get_arch_timeoffset() */ |
| 351 | tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift; | 351 | tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift; |
| 352 | 352 | ||
| 353 | tk_normalize_xtime(tk); | 353 | tk_normalize_xtime(tk); |
| 354 | 354 | ||
| 355 | nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); | 355 | nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift); |
| 356 | timespec64_add_ns(&tk->raw_time, nsec); | 356 | timespec64_add_ns(&tk->raw_time, nsec); |
| 357 | } | 357 | } |
| 358 | 358 | ||
| @@ -1026,7 +1026,8 @@ static void timekeeping_resume(void) | |||
| 1026 | u32 shift = clock->shift; | 1026 | u32 shift = clock->shift; |
| 1027 | s64 nsec = 0; | 1027 | s64 nsec = 0; |
| 1028 | 1028 | ||
| 1029 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | 1029 | cycle_delta = clocksource_delta(cycle_now, clock->cycle_last, |
| 1030 | clock->mask); | ||
| 1030 | 1031 | ||
| 1031 | /* | 1032 | /* |
| 1032 | * "cycle_delta * mutl" may cause 64 bits overflow, if the | 1033 | * "cycle_delta * mutl" may cause 64 bits overflow, if the |
| @@ -1432,7 +1433,8 @@ void update_wall_time(void) | |||
| 1432 | #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET | 1433 | #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET |
| 1433 | offset = real_tk->cycle_interval; | 1434 | offset = real_tk->cycle_interval; |
| 1434 | #else | 1435 | #else |
| 1435 | offset = (clock->read(clock) - clock->cycle_last) & clock->mask; | 1436 | offset = clocksource_delta(clock->read(clock), clock->cycle_last, |
| 1437 | clock->mask); | ||
| 1436 | #endif | 1438 | #endif |
| 1437 | 1439 | ||
| 1438 | /* Check if there's really nothing to do */ | 1440 | /* Check if there's really nothing to do */ |
diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h index e3d28ad236f9..05dfa6b25dc4 100644 --- a/kernel/time/timekeeping_internal.h +++ b/kernel/time/timekeeping_internal.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | /* | 3 | /* |
| 4 | * timekeeping debug functions | 4 | * timekeeping debug functions |
| 5 | */ | 5 | */ |
| 6 | #include <linux/clocksource.h> | ||
| 6 | #include <linux/time.h> | 7 | #include <linux/time.h> |
| 7 | 8 | ||
| 8 | #ifdef CONFIG_DEBUG_FS | 9 | #ifdef CONFIG_DEBUG_FS |
| @@ -11,4 +12,9 @@ extern void tk_debug_account_sleep_time(struct timespec64 *t); | |||
| 11 | #define tk_debug_account_sleep_time(x) | 12 | #define tk_debug_account_sleep_time(x) |
| 12 | #endif | 13 | #endif |
| 13 | 14 | ||
| 15 | static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) | ||
| 16 | { | ||
| 17 | return (now - last) & mask; | ||
| 18 | } | ||
| 19 | |||
| 14 | #endif /* _TIMEKEEPING_INTERNAL_H */ | 20 | #endif /* _TIMEKEEPING_INTERNAL_H */ |
