diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 00:45:08 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 00:45:08 (GMT) |
commit | 78c4def67e8eebe602655a3dec9aa08f0e2f7c4b (patch) | |
tree | 8c0c756bbff7325f5c2a773f8cc64d8390ebe5b5 /kernel/time/timekeeping.c | |
parent | 7e6628e4bcb3b3546c625ec63ca724f28ab14f0c (diff) | |
parent | 942c3c5c329274fa6de5998cb911cf3d0a42d0b1 (diff) | |
download | linux-fsl-qoriq-78c4def67e8eebe602655a3dec9aa08f0e2f7c4b.tar.xz |
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
hrtimer: Make lookup table const
RTC: Disable CONFIG_RTC_CLASS from being built as a module
timers: Fix alarmtimer build issues when CONFIG_RTC_CLASS=n
timers: Remove delayed irqwork from alarmtimers implementation
timers: Improve alarmtimer comments and minor fixes
timers: Posix interface for alarm-timers
timers: Introduce in-kernel alarm-timer interface
timers: Add rb_init_node() to allow for stack allocated rb nodes
time: Add timekeeping_inject_sleeptime
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r-- | kernel/time/timekeeping.c | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 8ad5d57..8e6a05a 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -596,6 +596,58 @@ void __init timekeeping_init(void) static struct timespec timekeeping_suspend_time; /** + * __timekeeping_inject_sleeptime - Internal function to add sleep interval + * @delta: pointer to a timespec delta value + * + * Takes a timespec offset measuring a suspend interval and properly + * adds the sleep offset to the timekeeping variables. + */ +static void __timekeeping_inject_sleeptime(struct timespec *delta) +{ + xtime = timespec_add(xtime, *delta); + wall_to_monotonic = timespec_sub(wall_to_monotonic, *delta); + total_sleep_time = timespec_add(total_sleep_time, *delta); +} + + +/** + * timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values + * @delta: pointer to a timespec delta value + * + * This hook is for architectures that cannot support read_persistent_clock + * because their RTC/persistent clock is only accessible when irqs are enabled. + * + * This function should only be called by rtc_resume(), and allows + * a suspend offset to be injected into the timekeeping values. + */ +void timekeeping_inject_sleeptime(struct timespec *delta) +{ + unsigned long flags; + struct timespec ts; + + /* Make sure we don't set the clock twice */ + read_persistent_clock(&ts); + if (!(ts.tv_sec == 0 && ts.tv_nsec == 0)) + return; + + write_seqlock_irqsave(&xtime_lock, flags); + timekeeping_forward_now(); + + __timekeeping_inject_sleeptime(delta); + + timekeeper.ntp_error = 0; + ntp_clear(); + update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, + timekeeper.mult); + + write_sequnlock_irqrestore(&xtime_lock, flags); + + /* signal hrtimers about time change */ + clock_was_set(); +} + + +/** * timekeeping_resume - Resumes the generic timekeeping subsystem. * * This is for the generic clocksource timekeeping. @@ -615,9 +667,7 @@ static void timekeeping_resume(void) if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) { ts = timespec_sub(ts, timekeeping_suspend_time); - xtime = timespec_add(xtime, ts); - wall_to_monotonic = timespec_sub(wall_to_monotonic, ts); - total_sleep_time = timespec_add(total_sleep_time, ts); + __timekeeping_inject_sleeptime(&ts); } /* re-base the last cycle value */ timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); |