aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/time/tick-common.c15
-rw-r--r--kernel/time/tick-internal.h6
-rw-r--r--kernel/time/tick-sched.c9
-rw-r--r--kernel/time/timekeeping.c7
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
422static 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) { }
141static inline bool tick_broadcast_oneshot_available(void) { return tick_oneshot_possible(); } 141static 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)
145extern void tick_sched_forward_next_period(void);
146#else
147static 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
146extern void tick_nohz_init(void); 152extern 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)
52static ktime_t last_jiffies_update; 52static 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 */
58void 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 */
57static void tick_do_update_jiffies64(ktime_t now) 66static 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
139static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta) 139static 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:
2155void getboottime64(struct timespec64 *ts) 2156void 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}