From 54b54b476e63ea180c4cf7020b9f14098eb34a74 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 22 Jan 2009 14:08:28 -0800 Subject: [PATCH] add a .27 patch --- ...ce-introduce-clocksource_forward_now.patch | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 queue-2.6.27/clocksource-introduce-clocksource_forward_now.patch diff --git a/queue-2.6.27/clocksource-introduce-clocksource_forward_now.patch b/queue-2.6.27/clocksource-introduce-clocksource_forward_now.patch new file mode 100644 index 00000000000..f9e03f36cbf --- /dev/null +++ b/queue-2.6.27/clocksource-introduce-clocksource_forward_now.patch @@ -0,0 +1,200 @@ +From 9a055117d3d9cb562f83f8d4cd88772761f4cab0 Mon Sep 17 00:00:00 2001 +From: Roman Zippel +Date: Wed, 20 Aug 2008 16:37:28 -0700 +Subject: clocksource: introduce clocksource_forward_now() + +From: Roman Zippel + +commit 9a055117d3d9cb562f83f8d4cd88772761f4cab0 upstream. + +To keep the raw monotonic patch simple first introduce +clocksource_forward_now(), which takes care of the offset since the last +update_wall_time() call and adds it to the clock, so there is no need +anymore to deal with it explicitly at various places, which need to make +significant changes to the clock. + +This is also gets rid of the timekeeping_suspend_nsecs, instead of +waiting until resume, the value is accumulated during suspend. In the end +there is only a single user of __get_nsec_offset() left, so I integrated +it back to getnstimeofday(). + +Signed-off-by: Roman Zippel +Signed-off-by: Andrew Morton +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/time/timekeeping.c | 71 +++++++++++++++++++++------------------------- + 1 file changed, 33 insertions(+), 38 deletions(-) + +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -61,27 +61,23 @@ struct clocksource *clock; + + #ifdef CONFIG_GENERIC_TIME + /** +- * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook ++ * clocksource_forward_now - update clock to the current time + * +- * private function, must hold xtime_lock lock when being +- * called. Returns the number of nanoseconds since the +- * last call to update_wall_time() (adjusted by NTP scaling) ++ * Forward the current clock to update its state since the last call to ++ * update_wall_time(). This is useful before significant clock changes, ++ * as it avoids having to deal with this time offset explicitly. + */ +-static inline s64 __get_nsec_offset(void) ++static void clocksource_forward_now(void) + { + cycle_t cycle_now, cycle_delta; +- s64 ns_offset; ++ s64 nsec; + +- /* read clocksource: */ + cycle_now = clocksource_read(clock); +- +- /* calculate the delta since the last update_wall_time: */ + cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; ++ clock->cycle_last = cycle_now; + +- /* convert to nanoseconds: */ +- ns_offset = cyc2ns(clock, cycle_delta); +- +- return ns_offset; ++ nsec = cyc2ns(clock, cycle_delta); ++ timespec_add_ns(&xtime, nsec); + } + + /** +@@ -92,6 +88,7 @@ static inline s64 __get_nsec_offset(void + */ + void getnstimeofday(struct timespec *ts) + { ++ cycle_t cycle_now, cycle_delta; + unsigned long seq; + s64 nsecs; + +@@ -101,7 +98,15 @@ void getnstimeofday(struct timespec *ts) + seq = read_seqbegin(&xtime_lock); + + *ts = xtime; +- nsecs = __get_nsec_offset(); ++ ++ /* read clocksource: */ ++ cycle_now = clocksource_read(clock); ++ ++ /* calculate the delta since the last update_wall_time: */ ++ cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; ++ ++ /* convert to nanoseconds: */ ++ nsecs = cyc2ns(clock, cycle_delta); + + } while (read_seqretry(&xtime_lock, seq)); + +@@ -134,22 +139,22 @@ EXPORT_SYMBOL(do_gettimeofday); + */ + int do_settimeofday(struct timespec *tv) + { ++ struct timespec ts_delta; + unsigned long flags; +- time_t wtm_sec, sec = tv->tv_sec; +- long wtm_nsec, nsec = tv->tv_nsec; + + if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + return -EINVAL; + + write_seqlock_irqsave(&xtime_lock, flags); + +- nsec -= __get_nsec_offset(); ++ clocksource_forward_now(); ++ ++ ts_delta.tv_sec = tv->tv_sec - xtime.tv_sec; ++ ts_delta.tv_nsec = tv->tv_nsec - xtime.tv_nsec; ++ wall_to_monotonic = timespec_sub(wall_to_monotonic, ts_delta); + +- wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); +- wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); ++ xtime = *tv; + +- set_normalized_timespec(&xtime, sec, nsec); +- set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); + update_xtime_cache(0); + + clock->error = 0; +@@ -175,22 +180,17 @@ EXPORT_SYMBOL(do_settimeofday); + static void change_clocksource(void) + { + struct clocksource *new; +- cycle_t now; +- u64 nsec; + + new = clocksource_get_next(); + + if (clock == new) + return; + +- new->cycle_last = 0; +- now = clocksource_read(new); +- nsec = __get_nsec_offset(); +- timespec_add_ns(&xtime, nsec); ++ clocksource_forward_now(); + + clock = new; +- clock->cycle_last = now; +- ++ clock->cycle_last = 0; ++ clock->cycle_last = clocksource_read(new); + clock->error = 0; + clock->xtime_nsec = 0; + clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH); +@@ -205,8 +205,8 @@ static void change_clocksource(void) + */ + } + #else ++static inline void clocksource_forward_now(void) { } + static inline void change_clocksource(void) { } +-static inline s64 __get_nsec_offset(void) { return 0; } + #endif + + /** +@@ -268,8 +268,6 @@ void __init timekeeping_init(void) + + /* time in seconds when suspend began */ + static unsigned long timekeeping_suspend_time; +-/* xtime offset when we went into suspend */ +-static s64 timekeeping_suspend_nsecs; + + /** + * timekeeping_resume - Resumes the generic timekeeping subsystem. +@@ -295,8 +293,6 @@ static int timekeeping_resume(struct sys + wall_to_monotonic.tv_sec -= sleep_length; + total_sleep_time += sleep_length; + } +- /* Make sure that we have the correct xtime reference */ +- timespec_add_ns(&xtime, timekeeping_suspend_nsecs); + update_xtime_cache(0); + /* re-base the last cycle value */ + clock->cycle_last = 0; +@@ -322,8 +318,7 @@ static int timekeeping_suspend(struct sy + timekeeping_suspend_time = read_persistent_clock(); + + write_seqlock_irqsave(&xtime_lock, flags); +- /* Get the current xtime offset */ +- timekeeping_suspend_nsecs = __get_nsec_offset(); ++ clocksource_forward_now(); + timekeeping_suspended = 1; + write_sequnlock_irqrestore(&xtime_lock, flags); + +@@ -464,10 +459,10 @@ void update_wall_time(void) + */ + while (offset >= clock->cycle_interval) { + /* accumulate one interval */ +- clock->xtime_nsec += clock->xtime_interval; +- clock->cycle_last += clock->cycle_interval; + offset -= clock->cycle_interval; ++ clock->cycle_last += clock->cycle_interval; + ++ clock->xtime_nsec += clock->xtime_interval; + if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) { + clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift; + xtime.tv_sec++; -- 2.47.3