diff options
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r-- | kernel/time/timekeeping.c | 70 |
1 files changed, 65 insertions, 5 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d66b21308f7c..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 | ||
181 | static 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 */ |
176 | static void timekeeping_update(bool clearntp) | 190 | static 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 | } |
@@ -240,7 +255,6 @@ void getnstimeofday(struct timespec *ts) | |||
240 | 255 | ||
241 | timespec_add_ns(ts, nsecs); | 256 | timespec_add_ns(ts, nsecs); |
242 | } | 257 | } |
243 | |||
244 | EXPORT_SYMBOL(getnstimeofday); | 258 | EXPORT_SYMBOL(getnstimeofday); |
245 | 259 | ||
246 | ktime_t ktime_get(void) | 260 | ktime_t ktime_get(void) |
@@ -357,8 +371,8 @@ void do_gettimeofday(struct timeval *tv) | |||
357 | tv->tv_sec = now.tv_sec; | 371 | tv->tv_sec = now.tv_sec; |
358 | tv->tv_usec = now.tv_nsec/1000; | 372 | tv->tv_usec = now.tv_nsec/1000; |
359 | } | 373 | } |
360 | |||
361 | EXPORT_SYMBOL(do_gettimeofday); | 374 | EXPORT_SYMBOL(do_gettimeofday); |
375 | |||
362 | /** | 376 | /** |
363 | * do_settimeofday - Sets the time of day | 377 | * do_settimeofday - Sets the time of day |
364 | * @tv: pointer to the timespec variable containing the new time | 378 | * @tv: pointer to the timespec variable containing the new time |
@@ -392,7 +406,6 @@ int do_settimeofday(const struct timespec *tv) | |||
392 | 406 | ||
393 | return 0; | 407 | return 0; |
394 | } | 408 | } |
395 | |||
396 | EXPORT_SYMBOL(do_settimeofday); | 409 | EXPORT_SYMBOL(do_settimeofday); |
397 | 410 | ||
398 | 411 | ||
@@ -606,6 +619,7 @@ void __init timekeeping_init(void) | |||
606 | } | 619 | } |
607 | set_normalized_timespec(&timekeeper.wall_to_monotonic, | 620 | set_normalized_timespec(&timekeeper.wall_to_monotonic, |
608 | -boot.tv_sec, -boot.tv_nsec); | 621 | -boot.tv_sec, -boot.tv_nsec); |
622 | update_rt_offset(); | ||
609 | timekeeper.total_sleep_time.tv_sec = 0; | 623 | timekeeper.total_sleep_time.tv_sec = 0; |
610 | timekeeper.total_sleep_time.tv_nsec = 0; | 624 | timekeeper.total_sleep_time.tv_nsec = 0; |
611 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | 625 | write_sequnlock_irqrestore(&timekeeper.lock, flags); |
@@ -614,6 +628,12 @@ void __init timekeeping_init(void) | |||
614 | /* time in seconds when suspend began */ | 628 | /* time in seconds when suspend began */ |
615 | static struct timespec timekeeping_suspend_time; | 629 | static struct timespec timekeeping_suspend_time; |
616 | 630 | ||
631 | static void update_sleep_time(struct timespec t) | ||
632 | { | ||
633 | timekeeper.total_sleep_time = t; | ||
634 | timekeeper.offs_boot = timespec_to_ktime(t); | ||
635 | } | ||
636 | |||
617 | /** | 637 | /** |
618 | * __timekeeping_inject_sleeptime - Internal function to add sleep interval | 638 | * __timekeeping_inject_sleeptime - Internal function to add sleep interval |
619 | * @delta: pointer to a timespec delta value | 639 | * @delta: pointer to a timespec delta value |
@@ -632,8 +652,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) | |||
632 | timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); | 652 | timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); |
633 | timekeeper.wall_to_monotonic = | 653 | timekeeper.wall_to_monotonic = |
634 | timespec_sub(timekeeper.wall_to_monotonic, *delta); | 654 | timespec_sub(timekeeper.wall_to_monotonic, *delta); |
635 | timekeeper.total_sleep_time = timespec_add( | 655 | update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta)); |
636 | timekeeper.total_sleep_time, *delta); | ||
637 | } | 656 | } |
638 | 657 | ||
639 | 658 | ||
@@ -698,6 +717,7 @@ static void timekeeping_resume(void) | |||
698 | timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); | 717 | timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); |
699 | timekeeper.ntp_error = 0; | 718 | timekeeper.ntp_error = 0; |
700 | timekeeping_suspended = 0; | 719 | timekeeping_suspended = 0; |
720 | timekeeping_update(false); | ||
701 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | 721 | write_sequnlock_irqrestore(&timekeeper.lock, flags); |
702 | 722 | ||
703 | touch_softlockup_watchdog(); | 723 | touch_softlockup_watchdog(); |
@@ -964,6 +984,9 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) | |||
964 | timekeeper.xtime.tv_sec++; | 984 | timekeeper.xtime.tv_sec++; |
965 | leap = second_overflow(timekeeper.xtime.tv_sec); | 985 | leap = second_overflow(timekeeper.xtime.tv_sec); |
966 | 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(); | ||
967 | } | 990 | } |
968 | 991 | ||
969 | /* Accumulate raw time */ | 992 | /* Accumulate raw time */ |
@@ -1079,6 +1102,9 @@ static void update_wall_time(void) | |||
1079 | timekeeper.xtime.tv_sec++; | 1102 | timekeeper.xtime.tv_sec++; |
1080 | leap = second_overflow(timekeeper.xtime.tv_sec); | 1103 | leap = second_overflow(timekeeper.xtime.tv_sec); |
1081 | 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(); | ||
1082 | } | 1108 | } |
1083 | 1109 | ||
1084 | timekeeping_update(false); | 1110 | timekeeping_update(false); |
@@ -1246,6 +1272,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
1246 | } while (read_seqretry(&timekeeper.lock, seq)); | 1272 | } while (read_seqretry(&timekeeper.lock, seq)); |
1247 | } | 1273 | } |
1248 | 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 | */ | ||
1284 | ktime_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 | |||
1249 | /** | 1309 | /** |
1250 | * 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 |
1251 | */ | 1311 | */ |