diff options
-rw-r--r-- | kernel/time/tick-common.c | 15 | ||||
-rw-r--r-- | kernel/time/tick-internal.h | 6 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 9 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 7 |
4 files changed, 34 insertions, 3 deletions
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 49edc1c4f3e6..099572ca4a8f 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -419,6 +419,19 @@ void tick_suspend_local(void) | |||
419 | clockevents_shutdown(td->evtdev); | 419 | clockevents_shutdown(td->evtdev); |
420 | } | 420 | } |
421 | 421 | ||
422 | static void tick_forward_next_period(void) | ||
423 | { | ||
424 | ktime_t delta, now = ktime_get(); | ||
425 | u64 n; | ||
426 | |||
427 | delta = ktime_sub(now, tick_next_period); | ||
428 | n = ktime_divns(delta, tick_period); | ||
429 | tick_next_period += n * tick_period; | ||
430 | if (tick_next_period < now) | ||
431 | tick_next_period += tick_period; | ||
432 | tick_sched_forward_next_period(); | ||
433 | } | ||
434 | |||
422 | /** | 435 | /** |
423 | * tick_resume_local - Resume the local tick device | 436 | * tick_resume_local - Resume the local tick device |
424 | * | 437 | * |
@@ -431,6 +444,8 @@ void tick_resume_local(void) | |||
431 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); | 444 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); |
432 | bool broadcast = tick_resume_check_broadcast(); | 445 | bool broadcast = tick_resume_check_broadcast(); |
433 | 446 | ||
447 | tick_forward_next_period(); | ||
448 | |||
434 | clockevents_tick_resume(td->evtdev); | 449 | clockevents_tick_resume(td->evtdev); |
435 | if (!broadcast) { | 450 | if (!broadcast) { |
436 | if (td->mode == TICKDEV_MODE_PERIODIC) | 451 | if (td->mode == TICKDEV_MODE_PERIODIC) |
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index e277284c2831..21efab7485ca 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
@@ -141,6 +141,12 @@ static inline void tick_check_oneshot_broadcast_this_cpu(void) { } | |||
141 | static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); } | 141 | static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); } |
142 | #endif /* !(BROADCAST && ONESHOT) */ | 142 | #endif /* !(BROADCAST && ONESHOT) */ |
143 | 143 | ||
144 | #if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS) | ||
145 | extern void tick_sched_forward_next_period(void); | ||
146 | #else | ||
147 | static inline void tick_sched_forward_next_period(void) { } | ||
148 | #endif | ||
149 | |||
144 | /* NO_HZ_FULL internal */ | 150 | /* NO_HZ_FULL internal */ |
145 | #ifdef CONFIG_NO_HZ_FULL | 151 | #ifdef CONFIG_NO_HZ_FULL |
146 | extern void tick_nohz_init(void); | 152 | extern void tick_nohz_init(void); |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 29a5733eff83..f53e37b5d248 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -52,6 +52,15 @@ struct tick_sched *tick_get_tick_sched(int cpu) | |||
52 | static ktime_t last_jiffies_update; | 52 | static ktime_t last_jiffies_update; |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * Called after resume. Make sure that jiffies are not fast forwarded due to | ||
56 | * clock monotonic being forwarded by the suspended time. | ||
57 | */ | ||
58 | void tick_sched_forward_next_period(void) | ||
59 | { | ||
60 | last_jiffies_update = tick_next_period; | ||
61 | } | ||
62 | |||
63 | /* | ||
55 | * Must be called with interrupts disabled ! | 64 | * Must be called with interrupts disabled ! |
56 | */ | 65 | */ |
57 | static void tick_do_update_jiffies64(ktime_t now) | 66 | static void tick_do_update_jiffies64(ktime_t now) |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index a2b7f583e64e..b509fe7acd64 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -138,7 +138,9 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec64 wtm) | |||
138 | 138 | ||
139 | static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta) | 139 | static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta) |
140 | { | 140 | { |
141 | tk->offs_boot = ktime_add(tk->offs_boot, delta); | 141 | /* Update both bases so mono and raw stay coupled. */ |
142 | tk->tkr_mono.base += delta; | ||
143 | tk->tkr_raw.base += delta; | ||
142 | 144 | ||
143 | /* Accumulate time spent in suspend */ | 145 | /* Accumulate time spent in suspend */ |
144 | tk->time_suspended += delta; | 146 | tk->time_suspended += delta; |
@@ -1622,7 +1624,6 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk, | |||
1622 | return; | 1624 | return; |
1623 | } | 1625 | } |
1624 | tk_xtime_add(tk, delta); | 1626 | tk_xtime_add(tk, delta); |
1625 | tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, *delta)); | ||
1626 | tk_update_sleep_time(tk, timespec64_to_ktime(*delta)); | 1627 | tk_update_sleep_time(tk, timespec64_to_ktime(*delta)); |
1627 | tk_debug_account_sleep_time(delta); | 1628 | tk_debug_account_sleep_time(delta); |
1628 | } | 1629 | } |
@@ -2155,7 +2156,7 @@ out: | |||
2155 | void getboottime64(struct timespec64 *ts) | 2156 | void getboottime64(struct timespec64 *ts) |
2156 | { | 2157 | { |
2157 | struct timekeeper *tk = &tk_core.timekeeper; | 2158 | struct timekeeper *tk = &tk_core.timekeeper; |
2158 | ktime_t t = ktime_sub(tk->offs_real, tk->offs_boot); | 2159 | ktime_t t = ktime_sub(tk->offs_real, tk->time_suspended); |
2159 | 2160 | ||
2160 | *ts = ktime_to_timespec64(t); | 2161 | *ts = ktime_to_timespec64(t); |
2161 | } | 2162 | } |