aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2013-01-21 20:00:11 -0500
committerJohn Stultz <john.stultz@linaro.org>2013-03-22 19:19:59 -0400
commit90adda98b89aaf68b06014ecf805b6c477daa19b (patch)
treec50d47c4c344774205569ce42e13d16a8174b02e
parent1ff3c9677bff7e468e0c487d0ffefe4e901d33f4 (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.h5
-rw-r--r--include/linux/timekeeper_internal.h2
-rw-r--r--kernel/hrtimer.c14
-rw-r--r--kernel/posix-timers.c6
-rw-r--r--kernel/time/timekeeping.c20
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);
327extern ktime_t ktime_get_real(void); 328extern ktime_t ktime_get_real(void);
328extern ktime_t ktime_get_boottime(void); 329extern ktime_t ktime_get_boottime(void);
329extern ktime_t ktime_get_monotonic_offset(void); 330extern ktime_t ktime_get_monotonic_offset(void);
330extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); 331extern ktime_t ktime_get_clocktai(void);
332extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot,
333 ktime_t *offs_tai);
331 334
332DECLARE_PER_CPU(struct tick_device, tick_cpu_device); 335DECLARE_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
95static inline int hrtimer_clockid_to_base(clockid_t clock_id) 102static 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
72static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) 73static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t)
@@ -409,6 +410,20 @@ void timekeeping_clocktai(struct timespec *ts)
409EXPORT_SYMBOL(timekeeping_clocktai); 410EXPORT_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 */
418ktime_t ktime_get_clocktai(void)
419{
420 struct timespec ts;
421
422 timekeeping_clocktai(&ts);
423 return timespec_to_ktime(ts);
424}
425EXPORT_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)
569void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) 584void __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 */
1542ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) 1558ktime_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);