--- /dev/null
+From c7dcf87a6881bf796faee83003163eb3de41a309 Mon Sep 17 00:00:00 2001
+From: John Stultz <johnstul@us.ibm.com>
+Date: Fri, 13 Aug 2010 11:30:58 -0700
+Subject: time: Workaround gcc loop optimization that causes 64bit div errors
+
+From: John Stultz <johnstul@us.ibm.com>
+
+commit c7dcf87a6881bf796faee83003163eb3de41a309 upstream.
+
+Early 4.3 versions of gcc apparently aggressively optimize the raw
+time accumulation loop, replacing it with a divide.
+
+On 32bit systems, this causes the following link errors:
+ undefined reference to `__umoddi3'
+ undefined reference to `__udivdi3'
+
+The gcc issue has been fixed in 4.4 and greater.
+
+This patch replaces the accumulation loop with a do_div, as suggested
+by Linus.
+
+Signed-off-by: John Stultz <johnstul@us.ibm.com>
+CC: Jason Wessel <jason.wessel@windriver.com>
+CC: Larry Finger <Larry.Finger@lwfinger.net>
+CC: Ingo Molnar <mingo@elte.hu>
+CC: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/timekeeping.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -756,9 +756,10 @@ static cycle_t logarithmic_accumulation(
+ /* Accumulate raw time */
+ raw_nsecs = timekeeper.raw_interval << shift;
+ raw_nsecs += raw_time.tv_nsec;
+- while (raw_nsecs >= NSEC_PER_SEC) {
+- raw_nsecs -= NSEC_PER_SEC;
+- raw_time.tv_sec++;
++ if (raw_nsecs >= NSEC_PER_SEC) {
++ u64 raw_secs = raw_nsecs;
++ raw_nsecs = do_div(raw_secs, NSEC_PER_SEC);
++ raw_time.tv_sec += raw_secs;
+ }
+ raw_time.tv_nsec = raw_nsecs;
+
--- /dev/null
+From deda2e81961e96be4f2c09328baca4710a2fd1a0 Mon Sep 17 00:00:00 2001
+From: Jason Wessel <jason.wessel@windriver.com>
+Date: Mon, 9 Aug 2010 14:20:09 -0700
+Subject: timekeeping: Fix overflow in rawtime tv_nsec on 32 bit archs
+
+From: Jason Wessel <jason.wessel@windriver.com>
+
+commit deda2e81961e96be4f2c09328baca4710a2fd1a0 upstream.
+
+The tv_nsec is a long and when added to the shifted interval it can wrap
+and become negative which later causes looping problems in the
+getrawmonotonic(). The edge case occurs when the system has slept for
+a short period of time of ~2 seconds.
+
+A trace printk of the values in this patch illustrate the problem:
+
+ftrace time stamp: log
+43.716079: logarithmic_accumulation: raw: 3d0913 tv_nsec d687faa
+43.718513: logarithmic_accumulation: raw: 3d0913 tv_nsec da588bd
+43.722161: logarithmic_accumulation: raw: 3d0913 tv_nsec de291d0
+46.349925: logarithmic_accumulation: raw: 7a122600 tv_nsec e1f9ae3
+46.349930: logarithmic_accumulation: raw: 1e848980 tv_nsec 8831c0e3
+
+The kernel starts looping at 46.349925 in the getrawmonotonic() due to
+the negative value from adding the raw value to tv_nsec.
+
+A simple solution is to accumulate into a u64, and then normalize it
+to a timespec_t.
+
+Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
+ [ Reworked variable names and simplified some of the code. - John ]
+Signed-off-by: John Stultz <johnstul@us.ibm.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/timekeeping.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -736,6 +736,7 @@ static void timekeeping_adjust(s64 offse
+ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
+ {
+ u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift;
++ u64 raw_nsecs;
+
+ /* If the offset is smaller then a shifted interval, do nothing */
+ if (offset < timekeeper.cycle_interval<<shift)
+@@ -752,12 +753,14 @@ static cycle_t logarithmic_accumulation(
+ second_overflow();
+ }
+
+- /* Accumulate into raw time */
+- raw_time.tv_nsec += timekeeper.raw_interval << shift;;
+- while (raw_time.tv_nsec >= NSEC_PER_SEC) {
+- raw_time.tv_nsec -= NSEC_PER_SEC;
++ /* Accumulate raw time */
++ raw_nsecs = timekeeper.raw_interval << shift;
++ raw_nsecs += raw_time.tv_nsec;
++ while (raw_nsecs >= NSEC_PER_SEC) {
++ raw_nsecs -= NSEC_PER_SEC;
+ raw_time.tv_sec++;
+ }
++ raw_time.tv_nsec = raw_nsecs;
+
+ /* Accumulate error between NTP and clock interval */
+ timekeeper.ntp_error += tick_length << shift;