aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 6e46cacf5969..3447cfaf11e7 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -70,6 +70,12 @@ struct timekeeper {
70 /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ 70 /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
71 struct timespec raw_time; 71 struct timespec raw_time;
72 72
73 /* Offset clock monotonic -> clock realtime */
74 ktime_t offs_real;
75
76 /* Offset clock monotonic -> clock boottime */
77 ktime_t offs_boot;
78
73 /* Seqlock for all timekeeper values */ 79 /* Seqlock for all timekeeper values */
74 seqlock_t lock; 80 seqlock_t lock;
75}; 81};
@@ -172,6 +178,14 @@ static inline s64 timekeeping_get_ns_raw(void)
172 return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); 178 return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
173} 179}
174 180
181static void update_rt_offset(void)
182{
183 struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic;
184
185 set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
186 timekeeper.offs_real = timespec_to_ktime(tmp);
187}
188
175/* must hold write on timekeeper.lock */ 189/* must hold write on timekeeper.lock */
176static void timekeeping_update(bool clearntp) 190static void timekeeping_update(bool clearntp)
177{ 191{
@@ -179,6 +193,7 @@ static void timekeeping_update(bool clearntp)
179 timekeeper.ntp_error = 0; 193 timekeeper.ntp_error = 0;
180 ntp_clear(); 194 ntp_clear();
181 } 195 }
196 update_rt_offset();
182 update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, 197 update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic,
183 timekeeper.clock, timekeeper.mult); 198 timekeeper.clock, timekeeper.mult);
184} 199}
@@ -604,6 +619,7 @@ void __init timekeeping_init(void)
604 } 619 }
605 set_normalized_timespec(&timekeeper.wall_to_monotonic, 620 set_normalized_timespec(&timekeeper.wall_to_monotonic,
606 -boot.tv_sec, -boot.tv_nsec); 621 -boot.tv_sec, -boot.tv_nsec);
622 update_rt_offset();
607 timekeeper.total_sleep_time.tv_sec = 0; 623 timekeeper.total_sleep_time.tv_sec = 0;
608 timekeeper.total_sleep_time.tv_nsec = 0; 624 timekeeper.total_sleep_time.tv_nsec = 0;
609 write_sequnlock_irqrestore(&timekeeper.lock, flags); 625 write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -612,6 +628,12 @@ void __init timekeeping_init(void)
612/* time in seconds when suspend began */ 628/* time in seconds when suspend began */
613static struct timespec timekeeping_suspend_time; 629static struct timespec timekeeping_suspend_time;
614 630
631static void update_sleep_time(struct timespec t)
632{
633 timekeeper.total_sleep_time = t;
634 timekeeper.offs_boot = timespec_to_ktime(t);
635}
636
615/** 637/**
616 * __timekeeping_inject_sleeptime - Internal function to add sleep interval 638 * __timekeeping_inject_sleeptime - Internal function to add sleep interval
617 * @delta: pointer to a timespec delta value 639 * @delta: pointer to a timespec delta value
@@ -630,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
630 timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); 652 timekeeper.xtime = timespec_add(timekeeper.xtime, *delta);
631 timekeeper.wall_to_monotonic = 653 timekeeper.wall_to_monotonic =
632 timespec_sub(timekeeper.wall_to_monotonic, *delta); 654 timespec_sub(timekeeper.wall_to_monotonic, *delta);
633 timekeeper.total_sleep_time = timespec_add( 655 update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta));
634 timekeeper.total_sleep_time, *delta);
635} 656}
636 657
637 658
@@ -696,6 +717,7 @@ static void timekeeping_resume(void)
696 timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); 717 timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
697 timekeeper.ntp_error = 0; 718 timekeeper.ntp_error = 0;
698 timekeeping_suspended = 0; 719 timekeeping_suspended = 0;
720 timekeeping_update(false);
699 write_sequnlock_irqrestore(&timekeeper.lock, flags); 721 write_sequnlock_irqrestore(&timekeeper.lock, flags);
700 722
701 touch_softlockup_watchdog(); 723 touch_softlockup_watchdog();
@@ -962,6 +984,9 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
962 timekeeper.xtime.tv_sec++; 984 timekeeper.xtime.tv_sec++;
963 leap = second_overflow(timekeeper.xtime.tv_sec); 985 leap = second_overflow(timekeeper.xtime.tv_sec);
964 timekeeper.xtime.tv_sec += leap; 986 timekeeper.xtime.tv_sec += leap;
987 timekeeper.wall_to_monotonic.tv_sec -= leap;
988 if (leap)
989 clock_was_set_delayed();
965 } 990 }
966 991
967 /* Accumulate raw time */ 992 /* Accumulate raw time */
@@ -1077,6 +1102,9 @@ static void update_wall_time(void)
1077 timekeeper.xtime.tv_sec++; 1102 timekeeper.xtime.tv_sec++;
1078 leap = second_overflow(timekeeper.xtime.tv_sec); 1103 leap = second_overflow(timekeeper.xtime.tv_sec);
1079 timekeeper.xtime.tv_sec += leap; 1104 timekeeper.xtime.tv_sec += leap;
1105 timekeeper.wall_to_monotonic.tv_sec -= leap;
1106 if (leap)
1107 clock_was_set_delayed();
1080 } 1108 }
1081 1109
1082 timekeeping_update(false); 1110 timekeeping_update(false);
@@ -1244,6 +1272,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
1244 } while (read_seqretry(&timekeeper.lock, seq)); 1272 } while (read_seqretry(&timekeeper.lock, seq));
1245} 1273}
1246 1274
1275#ifdef CONFIG_HIGH_RES_TIMERS
1276/**
1277 * ktime_get_update_offsets - hrtimer helper
1278 * @offs_real: pointer to storage for monotonic -> realtime offset
1279 * @offs_boot: pointer to storage for monotonic -> boottime offset
1280 *
1281 * Returns current monotonic time and updates the offsets
1282 * Called from hrtimer_interupt() or retrigger_next_event()
1283 */
1284ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)
1285{
1286 ktime_t now;
1287 unsigned int seq;
1288 u64 secs, nsecs;
1289
1290 do {
1291 seq = read_seqbegin(&timekeeper.lock);
1292
1293 secs = timekeeper.xtime.tv_sec;
1294 nsecs = timekeeper.xtime.tv_nsec;
1295 nsecs += timekeeping_get_ns();
1296 /* If arch requires, add in gettimeoffset() */
1297 nsecs += arch_gettimeoffset();
1298
1299 *offs_real = timekeeper.offs_real;
1300 *offs_boot = timekeeper.offs_boot;
1301 } while (read_seqretry(&timekeeper.lock, seq));
1302
1303 now = ktime_add_ns(ktime_set(secs, 0), nsecs);
1304 now = ktime_sub(now, *offs_real);
1305 return now;
1306}
1307#endif
1308
1247/** 1309/**
1248 * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format 1310 * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format
1249 */ 1311 */