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); |