diff options
| author | Ingo Molnar <mingo@kernel.org> | 2014-01-12 08:13:31 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2014-01-12 08:13:31 -0500 |
| commit | d05d24a984f8e14086771a158083dbe6facb769e (patch) | |
| tree | 0e897dc8cee3b884eef194b620c62d8a8fa8594c /kernel | |
| parent | dba861461f88c12249ac78fb877866c04f99deb3 (diff) | |
| parent | 38aef31ce7773624c8f09ff58c4c27b3b955faaf (diff) | |
Merge branch 'fortglx/3.14/time' of git://git.linaro.org/people/john.stultz/linux into timers/core
Pull timekeeping updates from John Stultz.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/time/tick-common.c | 1 | ||||
| -rw-r--r-- | kernel/time/tick-internal.h | 1 | ||||
| -rw-r--r-- | kernel/time/tick-sched.c | 1 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 53 |
4 files changed, 29 insertions, 27 deletions
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 162b03ab0ad2..20b2fe37d105 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
| @@ -85,6 +85,7 @@ static void tick_periodic(int cpu) | |||
| 85 | 85 | ||
| 86 | do_timer(1); | 86 | do_timer(1); |
| 87 | write_sequnlock(&jiffies_lock); | 87 | write_sequnlock(&jiffies_lock); |
| 88 | update_wall_time(); | ||
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | update_process_times(user_mode(get_irq_regs())); | 91 | update_process_times(user_mode(get_irq_regs())); |
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index e2bced59b6dd..8329669b51ec 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
| @@ -155,3 +155,4 @@ static inline int tick_device_is_functional(struct clock_event_device *dev) | |||
| 155 | #endif | 155 | #endif |
| 156 | 156 | ||
| 157 | extern void do_timer(unsigned long ticks); | 157 | extern void do_timer(unsigned long ticks); |
| 158 | extern void update_wall_time(void); | ||
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 52cee12b3302..0ddd020bbaf2 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
| @@ -86,6 +86,7 @@ static void tick_do_update_jiffies64(ktime_t now) | |||
| 86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); | 86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); |
| 87 | } | 87 | } |
| 88 | write_sequnlock(&jiffies_lock); | 88 | write_sequnlock(&jiffies_lock); |
| 89 | update_wall_time(); | ||
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | /* | 92 | /* |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 87b4f00284c9..0aa4ce81bc16 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -77,7 +77,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) | |||
| 77 | tk->wall_to_monotonic = wtm; | 77 | tk->wall_to_monotonic = wtm; |
| 78 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); | 78 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); |
| 79 | tk->offs_real = timespec_to_ktime(tmp); | 79 | tk->offs_real = timespec_to_ktime(tmp); |
| 80 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tk->tai_offset, 0)); | 80 | tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tk->tai_offset, 0)); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | 83 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) |
| @@ -90,8 +90,9 @@ static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | |||
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | /** | 92 | /** |
| 93 | * timekeeper_setup_internals - Set up internals to use clocksource clock. | 93 | * tk_setup_internals - Set up internals to use clocksource clock. |
| 94 | * | 94 | * |
| 95 | * @tk: The target timekeeper to setup. | ||
| 95 | * @clock: Pointer to clocksource. | 96 | * @clock: Pointer to clocksource. |
| 96 | * | 97 | * |
| 97 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment | 98 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment |
| @@ -595,7 +596,7 @@ s32 timekeeping_get_tai_offset(void) | |||
| 595 | static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) | 596 | static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) |
| 596 | { | 597 | { |
| 597 | tk->tai_offset = tai_offset; | 598 | tk->tai_offset = tai_offset; |
| 598 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tai_offset, 0)); | 599 | tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tai_offset, 0)); |
| 599 | } | 600 | } |
| 600 | 601 | ||
| 601 | /** | 602 | /** |
| @@ -610,6 +611,7 @@ void timekeeping_set_tai_offset(s32 tai_offset) | |||
| 610 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 611 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
| 611 | write_seqcount_begin(&timekeeper_seq); | 612 | write_seqcount_begin(&timekeeper_seq); |
| 612 | __timekeeping_set_tai_offset(tk, tai_offset); | 613 | __timekeeping_set_tai_offset(tk, tai_offset); |
| 614 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); | ||
| 613 | write_seqcount_end(&timekeeper_seq); | 615 | write_seqcount_end(&timekeeper_seq); |
| 614 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 616 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
| 615 | clock_was_set(); | 617 | clock_was_set(); |
| @@ -1023,6 +1025,8 @@ static int timekeeping_suspend(void) | |||
| 1023 | timekeeping_suspend_time = | 1025 | timekeeping_suspend_time = |
| 1024 | timespec_add(timekeeping_suspend_time, delta_delta); | 1026 | timespec_add(timekeeping_suspend_time, delta_delta); |
| 1025 | } | 1027 | } |
| 1028 | |||
| 1029 | timekeeping_update(tk, TK_MIRROR); | ||
| 1026 | write_seqcount_end(&timekeeper_seq); | 1030 | write_seqcount_end(&timekeeper_seq); |
| 1027 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1031 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
| 1028 | 1032 | ||
| @@ -1130,16 +1134,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) | |||
| 1130 | * we can adjust by 1. | 1134 | * we can adjust by 1. |
| 1131 | */ | 1135 | */ |
| 1132 | error >>= 2; | 1136 | error >>= 2; |
| 1133 | /* | ||
| 1134 | * XXX - In update_wall_time, we round up to the next | ||
| 1135 | * nanosecond, and store the amount rounded up into | ||
| 1136 | * the error. This causes the likely below to be unlikely. | ||
| 1137 | * | ||
| 1138 | * The proper fix is to avoid rounding up by using | ||
| 1139 | * the high precision tk->xtime_nsec instead of | ||
| 1140 | * xtime.tv_nsec everywhere. Fixing this will take some | ||
| 1141 | * time. | ||
| 1142 | */ | ||
| 1143 | if (likely(error <= interval)) | 1137 | if (likely(error <= interval)) |
| 1144 | adj = 1; | 1138 | adj = 1; |
| 1145 | else | 1139 | else |
| @@ -1255,7 +1249,7 @@ out_adjust: | |||
| 1255 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | 1249 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) |
| 1256 | { | 1250 | { |
| 1257 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; | 1251 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; |
| 1258 | unsigned int action = 0; | 1252 | unsigned int clock_set = 0; |
| 1259 | 1253 | ||
| 1260 | while (tk->xtime_nsec >= nsecps) { | 1254 | while (tk->xtime_nsec >= nsecps) { |
| 1261 | int leap; | 1255 | int leap; |
| @@ -1277,11 +1271,10 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
| 1277 | 1271 | ||
| 1278 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); | 1272 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); |
| 1279 | 1273 | ||
| 1280 | clock_was_set_delayed(); | 1274 | clock_set = TK_CLOCK_WAS_SET; |
| 1281 | action = TK_CLOCK_WAS_SET; | ||
| 1282 | } | 1275 | } |
| 1283 | } | 1276 | } |
| 1284 | return action; | 1277 | return clock_set; |
| 1285 | } | 1278 | } |
| 1286 | 1279 | ||
| 1287 | /** | 1280 | /** |
| @@ -1294,7 +1287,8 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
| 1294 | * Returns the unconsumed cycles. | 1287 | * Returns the unconsumed cycles. |
| 1295 | */ | 1288 | */ |
| 1296 | static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | 1289 | static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, |
| 1297 | u32 shift) | 1290 | u32 shift, |
| 1291 | unsigned int *clock_set) | ||
| 1298 | { | 1292 | { |
| 1299 | cycle_t interval = tk->cycle_interval << shift; | 1293 | cycle_t interval = tk->cycle_interval << shift; |
| 1300 | u64 raw_nsecs; | 1294 | u64 raw_nsecs; |
| @@ -1308,7 +1302,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | |||
| 1308 | tk->cycle_last += interval; | 1302 | tk->cycle_last += interval; |
| 1309 | 1303 | ||
| 1310 | tk->xtime_nsec += tk->xtime_interval << shift; | 1304 | tk->xtime_nsec += tk->xtime_interval << shift; |
| 1311 | accumulate_nsecs_to_secs(tk); | 1305 | *clock_set |= accumulate_nsecs_to_secs(tk); |
| 1312 | 1306 | ||
| 1313 | /* Accumulate raw time */ | 1307 | /* Accumulate raw time */ |
| 1314 | raw_nsecs = (u64)tk->raw_interval << shift; | 1308 | raw_nsecs = (u64)tk->raw_interval << shift; |
| @@ -1359,14 +1353,14 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk) | |||
| 1359 | * update_wall_time - Uses the current clocksource to increment the wall time | 1353 | * update_wall_time - Uses the current clocksource to increment the wall time |
| 1360 | * | 1354 | * |
| 1361 | */ | 1355 | */ |
| 1362 | static void update_wall_time(void) | 1356 | void update_wall_time(void) |
| 1363 | { | 1357 | { |
| 1364 | struct clocksource *clock; | 1358 | struct clocksource *clock; |
| 1365 | struct timekeeper *real_tk = &timekeeper; | 1359 | struct timekeeper *real_tk = &timekeeper; |
| 1366 | struct timekeeper *tk = &shadow_timekeeper; | 1360 | struct timekeeper *tk = &shadow_timekeeper; |
| 1367 | cycle_t offset; | 1361 | cycle_t offset; |
| 1368 | int shift = 0, maxshift; | 1362 | int shift = 0, maxshift; |
| 1369 | unsigned int action; | 1363 | unsigned int clock_set = 0; |
| 1370 | unsigned long flags; | 1364 | unsigned long flags; |
| 1371 | 1365 | ||
| 1372 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 1366 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
| @@ -1401,7 +1395,8 @@ static void update_wall_time(void) | |||
| 1401 | maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; | 1395 | maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; |
| 1402 | shift = min(shift, maxshift); | 1396 | shift = min(shift, maxshift); |
| 1403 | while (offset >= tk->cycle_interval) { | 1397 | while (offset >= tk->cycle_interval) { |
| 1404 | offset = logarithmic_accumulation(tk, offset, shift); | 1398 | offset = logarithmic_accumulation(tk, offset, shift, |
| 1399 | &clock_set); | ||
| 1405 | if (offset < tk->cycle_interval<<shift) | 1400 | if (offset < tk->cycle_interval<<shift) |
| 1406 | shift--; | 1401 | shift--; |
| 1407 | } | 1402 | } |
| @@ -1419,7 +1414,7 @@ static void update_wall_time(void) | |||
| 1419 | * Finally, make sure that after the rounding | 1414 | * Finally, make sure that after the rounding |
| 1420 | * xtime_nsec isn't larger than NSEC_PER_SEC | 1415 | * xtime_nsec isn't larger than NSEC_PER_SEC |
| 1421 | */ | 1416 | */ |
| 1422 | action = accumulate_nsecs_to_secs(tk); | 1417 | clock_set |= accumulate_nsecs_to_secs(tk); |
| 1423 | 1418 | ||
| 1424 | write_seqcount_begin(&timekeeper_seq); | 1419 | write_seqcount_begin(&timekeeper_seq); |
| 1425 | /* Update clock->cycle_last with the new value */ | 1420 | /* Update clock->cycle_last with the new value */ |
| @@ -1435,10 +1430,12 @@ static void update_wall_time(void) | |||
| 1435 | * updating. | 1430 | * updating. |
| 1436 | */ | 1431 | */ |
| 1437 | memcpy(real_tk, tk, sizeof(*tk)); | 1432 | memcpy(real_tk, tk, sizeof(*tk)); |
| 1438 | timekeeping_update(real_tk, action); | 1433 | timekeeping_update(real_tk, clock_set); |
| 1439 | write_seqcount_end(&timekeeper_seq); | 1434 | write_seqcount_end(&timekeeper_seq); |
| 1440 | out: | 1435 | out: |
| 1441 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1436 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
| 1437 | if (clock_set) | ||
| 1438 | clock_was_set(); | ||
| 1442 | } | 1439 | } |
| 1443 | 1440 | ||
| 1444 | /** | 1441 | /** |
| @@ -1583,7 +1580,6 @@ struct timespec get_monotonic_coarse(void) | |||
| 1583 | void do_timer(unsigned long ticks) | 1580 | void do_timer(unsigned long ticks) |
| 1584 | { | 1581 | { |
| 1585 | jiffies_64 += ticks; | 1582 | jiffies_64 += ticks; |
| 1586 | update_wall_time(); | ||
| 1587 | calc_global_load(ticks); | 1583 | calc_global_load(ticks); |
| 1588 | } | 1584 | } |
| 1589 | 1585 | ||
| @@ -1698,12 +1694,14 @@ int do_adjtimex(struct timex *txc) | |||
| 1698 | 1694 | ||
| 1699 | if (tai != orig_tai) { | 1695 | if (tai != orig_tai) { |
| 1700 | __timekeeping_set_tai_offset(tk, tai); | 1696 | __timekeeping_set_tai_offset(tk, tai); |
| 1701 | update_pvclock_gtod(tk, true); | 1697 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); |
| 1702 | clock_was_set_delayed(); | ||
| 1703 | } | 1698 | } |
| 1704 | write_seqcount_end(&timekeeper_seq); | 1699 | write_seqcount_end(&timekeeper_seq); |
| 1705 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1700 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
| 1706 | 1701 | ||
| 1702 | if (tai != orig_tai) | ||
| 1703 | clock_was_set(); | ||
| 1704 | |||
| 1707 | ntp_notify_cmos_timer(); | 1705 | ntp_notify_cmos_timer(); |
| 1708 | 1706 | ||
| 1709 | return ret; | 1707 | return ret; |
| @@ -1739,4 +1737,5 @@ void xtime_update(unsigned long ticks) | |||
| 1739 | write_seqlock(&jiffies_lock); | 1737 | write_seqlock(&jiffies_lock); |
| 1740 | do_timer(ticks); | 1738 | do_timer(ticks); |
| 1741 | write_sequnlock(&jiffies_lock); | 1739 | write_sequnlock(&jiffies_lock); |
| 1740 | update_wall_time(); | ||
| 1742 | } | 1741 | } |
