diff options
| author | John Stultz <john.stultz@linaro.org> | 2013-01-21 20:00:11 -0500 |
|---|---|---|
| committer | John Stultz <john.stultz@linaro.org> | 2013-03-22 19:19:59 -0400 |
| commit | 90adda98b89aaf68b06014ecf805b6c477daa19b (patch) | |
| tree | c50d47c4c344774205569ce42e13d16a8174b02e | |
| parent | 1ff3c9677bff7e468e0c487d0ffefe4e901d33f4 (diff) | |
hrtimer: Add hrtimer support for CLOCK_TAI
Add hrtimer support for CLOCK_TAI, as well as posix timer interfaces.
Signed-off-by: John Stultz <john.stultz@linaro.org>
| -rw-r--r-- | include/linux/hrtimer.h | 5 | ||||
| -rw-r--r-- | include/linux/timekeeper_internal.h | 2 | ||||
| -rw-r--r-- | kernel/hrtimer.c | 14 | ||||
| -rw-r--r-- | kernel/posix-timers.c | 6 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 20 |
5 files changed, 44 insertions, 3 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index cc07d2777bbe..d19a5c2d2270 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
| @@ -157,6 +157,7 @@ enum hrtimer_base_type { | |||
| 157 | HRTIMER_BASE_MONOTONIC, | 157 | HRTIMER_BASE_MONOTONIC, |
| 158 | HRTIMER_BASE_REALTIME, | 158 | HRTIMER_BASE_REALTIME, |
| 159 | HRTIMER_BASE_BOOTTIME, | 159 | HRTIMER_BASE_BOOTTIME, |
| 160 | HRTIMER_BASE_TAI, | ||
| 160 | HRTIMER_MAX_CLOCK_BASES, | 161 | HRTIMER_MAX_CLOCK_BASES, |
| 161 | }; | 162 | }; |
| 162 | 163 | ||
| @@ -327,7 +328,9 @@ extern ktime_t ktime_get(void); | |||
| 327 | extern ktime_t ktime_get_real(void); | 328 | extern ktime_t ktime_get_real(void); |
| 328 | extern ktime_t ktime_get_boottime(void); | 329 | extern ktime_t ktime_get_boottime(void); |
| 329 | extern ktime_t ktime_get_monotonic_offset(void); | 330 | extern ktime_t ktime_get_monotonic_offset(void); |
| 330 | extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); | 331 | extern ktime_t ktime_get_clocktai(void); |
| 332 | extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot, | ||
| 333 | ktime_t *offs_tai); | ||
| 331 | 334 | ||
| 332 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); | 335 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); |
| 333 | 336 | ||
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h index ff94f436f8b7..26700d870506 100644 --- a/include/linux/timekeeper_internal.h +++ b/include/linux/timekeeper_internal.h | |||
| @@ -64,6 +64,8 @@ struct timekeeper { | |||
| 64 | struct timespec raw_time; | 64 | struct timespec raw_time; |
| 65 | /* The current UTC to TAI offset in seconds */ | 65 | /* The current UTC to TAI offset in seconds */ |
| 66 | s32 tai_offset; | 66 | s32 tai_offset; |
| 67 | /* Offset clock monotonic -> clock tai */ | ||
| 68 | ktime_t offs_tai; | ||
| 67 | 69 | ||
| 68 | /* Seqlock for all timekeeper values */ | 70 | /* Seqlock for all timekeeper values */ |
| 69 | seqlock_t lock; | 71 | seqlock_t lock; |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index cc47812d3feb..258720741d3e 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -83,6 +83,12 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = | |||
| 83 | .get_time = &ktime_get_boottime, | 83 | .get_time = &ktime_get_boottime, |
| 84 | .resolution = KTIME_LOW_RES, | 84 | .resolution = KTIME_LOW_RES, |
| 85 | }, | 85 | }, |
| 86 | { | ||
| 87 | .index = HRTIMER_BASE_TAI, | ||
| 88 | .clockid = CLOCK_TAI, | ||
| 89 | .get_time = &ktime_get_clocktai, | ||
| 90 | .resolution = KTIME_LOW_RES, | ||
| 91 | }, | ||
| 86 | } | 92 | } |
| 87 | }; | 93 | }; |
| 88 | 94 | ||
| @@ -90,6 +96,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { | |||
| 90 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, | 96 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, |
| 91 | [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, | 97 | [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, |
| 92 | [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, | 98 | [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, |
| 99 | [CLOCK_TAI] = HRTIMER_BASE_TAI, | ||
| 93 | }; | 100 | }; |
| 94 | 101 | ||
| 95 | static inline int hrtimer_clockid_to_base(clockid_t clock_id) | 102 | static inline int hrtimer_clockid_to_base(clockid_t clock_id) |
| @@ -106,8 +113,10 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) | |||
| 106 | { | 113 | { |
| 107 | ktime_t xtim, mono, boot; | 114 | ktime_t xtim, mono, boot; |
| 108 | struct timespec xts, tom, slp; | 115 | struct timespec xts, tom, slp; |
| 116 | s32 tai_offset; | ||
| 109 | 117 | ||
| 110 | get_xtime_and_monotonic_and_sleep_offset(&xts, &tom, &slp); | 118 | get_xtime_and_monotonic_and_sleep_offset(&xts, &tom, &slp); |
| 119 | tai_offset = timekeeping_get_tai_offset(); | ||
| 111 | 120 | ||
| 112 | xtim = timespec_to_ktime(xts); | 121 | xtim = timespec_to_ktime(xts); |
| 113 | mono = ktime_add(xtim, timespec_to_ktime(tom)); | 122 | mono = ktime_add(xtim, timespec_to_ktime(tom)); |
| @@ -115,6 +124,8 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) | |||
| 115 | base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim; | 124 | base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim; |
| 116 | base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono; | 125 | base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono; |
| 117 | base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot; | 126 | base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot; |
| 127 | base->clock_base[HRTIMER_BASE_TAI].softirq_time = | ||
| 128 | ktime_add(xtim, ktime_set(tai_offset, 0)); | ||
| 118 | } | 129 | } |
| 119 | 130 | ||
| 120 | /* | 131 | /* |
| @@ -651,8 +662,9 @@ static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) | |||
| 651 | { | 662 | { |
| 652 | ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; | 663 | ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; |
| 653 | ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; | 664 | ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; |
| 665 | ktime_t *offs_tai = &base->clock_base[HRTIMER_BASE_TAI].offset; | ||
| 654 | 666 | ||
| 655 | return ktime_get_update_offsets(offs_real, offs_boot); | 667 | return ktime_get_update_offsets(offs_real, offs_boot, offs_tai); |
| 656 | } | 668 | } |
| 657 | 669 | ||
| 658 | /* | 670 | /* |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index fbfc5f1b7710..2a2e173d0a7a 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
| @@ -269,6 +269,12 @@ static __init int init_posix_timers(void) | |||
| 269 | struct k_clock clock_tai = { | 269 | struct k_clock clock_tai = { |
| 270 | .clock_getres = hrtimer_get_res, | 270 | .clock_getres = hrtimer_get_res, |
| 271 | .clock_get = posix_get_tai, | 271 | .clock_get = posix_get_tai, |
| 272 | .nsleep = common_nsleep, | ||
| 273 | .nsleep_restart = hrtimer_nanosleep_restart, | ||
| 274 | .timer_create = common_timer_create, | ||
| 275 | .timer_set = common_timer_set, | ||
| 276 | .timer_get = common_timer_get, | ||
| 277 | .timer_del = common_timer_del, | ||
| 272 | }; | 278 | }; |
| 273 | struct k_clock clock_boottime = { | 279 | struct k_clock clock_boottime = { |
| 274 | .clock_getres = hrtimer_get_res, | 280 | .clock_getres = hrtimer_get_res, |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 8a842756572d..8061ae0be7bd 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
| @@ -67,6 +67,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) | |||
| 67 | tk->wall_to_monotonic = wtm; | 67 | tk->wall_to_monotonic = wtm; |
| 68 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); | 68 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); |
| 69 | tk->offs_real = timespec_to_ktime(tmp); | 69 | tk->offs_real = timespec_to_ktime(tmp); |
| 70 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tk->tai_offset, 0)); | ||
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | 73 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) |
| @@ -409,6 +410,20 @@ void timekeeping_clocktai(struct timespec *ts) | |||
| 409 | EXPORT_SYMBOL(timekeeping_clocktai); | 410 | EXPORT_SYMBOL(timekeeping_clocktai); |
| 410 | 411 | ||
| 411 | 412 | ||
| 413 | /** | ||
| 414 | * ktime_get_clocktai - Returns the TAI time of day in a ktime | ||
| 415 | * | ||
| 416 | * Returns the time of day in a ktime. | ||
| 417 | */ | ||
| 418 | ktime_t ktime_get_clocktai(void) | ||
| 419 | { | ||
| 420 | struct timespec ts; | ||
| 421 | |||
| 422 | timekeeping_clocktai(&ts); | ||
| 423 | return timespec_to_ktime(ts); | ||
| 424 | } | ||
| 425 | EXPORT_SYMBOL(ktime_get_clocktai); | ||
| 426 | |||
| 412 | #ifdef CONFIG_NTP_PPS | 427 | #ifdef CONFIG_NTP_PPS |
| 413 | 428 | ||
| 414 | /** | 429 | /** |
| @@ -569,6 +584,7 @@ s32 timekeeping_get_tai_offset(void) | |||
| 569 | void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) | 584 | void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) |
| 570 | { | 585 | { |
| 571 | tk->tai_offset = tai_offset; | 586 | tk->tai_offset = tai_offset; |
| 587 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tai_offset, 0)); | ||
| 572 | } | 588 | } |
| 573 | 589 | ||
| 574 | /** | 590 | /** |
| @@ -1539,7 +1555,8 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
| 1539 | * Returns current monotonic time and updates the offsets | 1555 | * Returns current monotonic time and updates the offsets |
| 1540 | * Called from hrtimer_interupt() or retrigger_next_event() | 1556 | * Called from hrtimer_interupt() or retrigger_next_event() |
| 1541 | */ | 1557 | */ |
| 1542 | ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) | 1558 | ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot, |
| 1559 | ktime_t *offs_tai) | ||
| 1543 | { | 1560 | { |
| 1544 | struct timekeeper *tk = &timekeeper; | 1561 | struct timekeeper *tk = &timekeeper; |
| 1545 | ktime_t now; | 1562 | ktime_t now; |
| @@ -1554,6 +1571,7 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) | |||
| 1554 | 1571 | ||
| 1555 | *offs_real = tk->offs_real; | 1572 | *offs_real = tk->offs_real; |
| 1556 | *offs_boot = tk->offs_boot; | 1573 | *offs_boot = tk->offs_boot; |
| 1574 | *offs_tai = tk->offs_tai; | ||
| 1557 | } while (read_seqretry(&tk->lock, seq)); | 1575 | } while (read_seqretry(&tk->lock, seq)); |
| 1558 | 1576 | ||
| 1559 | now = ktime_add_ns(ktime_set(secs, 0), nsecs); | 1577 | now = ktime_add_ns(ktime_set(secs, 0), nsecs); |
