acpi-avoid-bogus-ec-timeout-when-ec-is-in-polling-mode.patch
x86-add-io-delay-quirk-for-presario-f700.patch
x86-fix-memmap-exactmap-boot-argument.patch
+timer-fix-01.patch
+timer-fix-02.patch
+timer-fix-03.patch
+timer-fix-04.patch
+timer-fix-05.patch
+timer-fix-06.patch
+timer-fix-07.patch
+timer-fix-08.patch
+timer-fix-09.patch
+timer-fix-10.patch
+timer-fix-11.patch
--- /dev/null
+From 7c1e76897492d92b6a1c2d6892494d39ded9680c Mon Sep 17 00:00:00 2001
+From: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+Date: Wed, 3 Sep 2008 21:36:50 +0000
+Subject: clockevents: prevent clockevent event_handler ending up handler_noop
+
+From: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+commit 7c1e76897492d92b6a1c2d6892494d39ded9680c upstream
+
+There is a ordering related problem with clockevents code, due to which
+clockevents_register_device() called after tickless/highres switch
+will not work. The new clockevent ends up with clockevents_handle_noop as
+event handler, resulting in no timer activity.
+
+The problematic path seems to be
+
+* old device already has hrtimer_interrupt as the event_handler
+* new clockevent device registers with a higher rating
+* tick_check_new_device() is called
+ * clockevents_exchange_device() gets called
+ * old->event_handler is set to clockevents_handle_noop
+ * tick_setup_device() is called for the new device
+ * which sets new->event_handler using the old->event_handler which is noop.
+
+Change the ordering so that new device inherits the proper handler.
+
+This does not have any issue in normal case as most likely all the clockevent
+devices are setup before the highres switch. But, can potentially be affecting
+some corner case where HPET force detect happens after the highres switch.
+This was a problem with HPET in MSI mode code that we have been experimenting
+with.
+
+Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+Signed-off-by: Shaohua Li <shaohua.li@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/clockchips.h | 2 ++
+ kernel/time/clockevents.c | 3 +--
+ kernel/time/tick-common.c | 1 +
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/include/linux/clockchips.h
++++ b/include/linux/clockchips.h
+@@ -127,6 +127,8 @@ extern int clockevents_register_notifier
+ extern int clockevents_program_event(struct clock_event_device *dev,
+ ktime_t expires, ktime_t now);
+
++extern void clockevents_handle_noop(struct clock_event_device *dev);
++
+ #ifdef CONFIG_GENERIC_CLOCKEVENTS
+ extern void clockevents_notify(unsigned long reason, void *arg);
+ #else
+--- a/kernel/time/clockevents.c
++++ b/kernel/time/clockevents.c
+@@ -177,7 +177,7 @@ void clockevents_register_device(struct
+ /*
+ * Noop handler when we shut down an event device
+ */
+-static void clockevents_handle_noop(struct clock_event_device *dev)
++void clockevents_handle_noop(struct clock_event_device *dev)
+ {
+ }
+
+@@ -199,7 +199,6 @@ void clockevents_exchange_device(struct
+ * released list and do a notify add later.
+ */
+ if (old) {
+- old->event_handler = clockevents_handle_noop;
+ clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
+ list_del(&old->list);
+ list_add(&old->list, &clockevents_released);
+--- a/kernel/time/tick-common.c
++++ b/kernel/time/tick-common.c
+@@ -161,6 +161,7 @@ static void tick_setup_device(struct tic
+ } else {
+ handler = td->evtdev->event_handler;
+ next_event = td->evtdev->next_event;
++ td->evtdev->event_handler = clockevents_handle_noop;
+ }
+
+ td->evtdev = newdev;
--- /dev/null
+From d4496b39559c6d43f83e4c08b899984f8b8089b5 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 3 Sep 2008 21:36:57 +0000
+Subject: clockevents: prevent endless loop in periodic broadcast handler
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit d4496b39559c6d43f83e4c08b899984f8b8089b5 upstream
+
+The reprogramming of the periodic broadcast handler was broken,
+when the first programming returned -ETIME. The clockevents code
+stores the new expiry value in the clock events device next_event field
+only when the programming time has not been elapsed yet. The loop in
+question calculates the new expiry value from the next_event value
+and therefor never increases.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/tick-broadcast.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -174,6 +174,8 @@ static void tick_do_periodic_broadcast(v
+ */
+ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
+ {
++ ktime_t next;
++
+ tick_do_periodic_broadcast();
+
+ /*
+@@ -184,10 +186,13 @@ static void tick_handle_periodic_broadca
+
+ /*
+ * Setup the next period for devices, which do not have
+- * periodic mode:
++ * periodic mode. We read dev->next_event first and add to it
++ * when the event alrady expired. clockevents_program_event()
++ * sets dev->next_event only when the event is really
++ * programmed to the device.
+ */
+- for (;;) {
+- ktime_t next = ktime_add(dev->next_event, tick_period);
++ for (next = dev->next_event; ;) {
++ next = ktime_add(next, tick_period);
+
+ if (!clockevents_program_event(dev, next, ktime_get()))
+ return;
--- /dev/null
+From 7205656ab48da29a95d7f55e43a81db755d3cb3a Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 3 Sep 2008 21:37:03 +0000
+Subject: clockevents: enforce reprogram in oneshot setup
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 7205656ab48da29a95d7f55e43a81db755d3cb3a upstream
+
+In tick_oneshot_setup we program the device to the given next_event,
+but we do not check the return value. We need to make sure that the
+device is programmed enforced so the interrupt handler engine starts
+working. Split out the reprogramming function from tick_program_event()
+and call it with the device, which was handed in to tick_setup_oneshot().
+Set the force argument, so the devices is firing an interrupt.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/tick-oneshot.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+--- a/kernel/time/tick-oneshot.c
++++ b/kernel/time/tick-oneshot.c
+@@ -23,11 +23,11 @@
+ #include "tick-internal.h"
+
+ /**
+- * tick_program_event
++ * tick_program_event internal worker function
+ */
+-int tick_program_event(ktime_t expires, int force)
++static int __tick_program_event(struct clock_event_device *dev,
++ ktime_t expires, int force)
+ {
+- struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+ ktime_t now = ktime_get();
+
+ while (1) {
+@@ -41,6 +41,16 @@ int tick_program_event(ktime_t expires,
+ }
+
+ /**
++ * tick_program_event
++ */
++int tick_program_event(ktime_t expires, int force)
++{
++ struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
++
++ return __tick_program_event(dev, expires, force);
++}
++
++/**
+ * tick_resume_onshot - resume oneshot mode
+ */
+ void tick_resume_oneshot(void)
+@@ -61,7 +71,7 @@ void tick_setup_oneshot(struct clock_eve
+ {
+ newdev->event_handler = handler;
+ clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
+- clockevents_program_event(newdev, next_event, ktime_get());
++ __tick_program_event(newdev, next_event, 1);
+ }
+
+ /**
--- /dev/null
+From 9c17bcda991000351cb2373f78be7e4b1c44caa3 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 3 Sep 2008 21:37:08 +0000
+Subject: clockevents: prevent multiple init/shutdown
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 9c17bcda991000351cb2373f78be7e4b1c44caa3 upstream
+
+While chasing the C1E/HPET bugreports I went through the clock events
+code inch by inch and found that the broadcast device can be initialized
+and shutdown multiple times. Multiple shutdowns are not critical, but
+useless waste of time. Multiple initializations are simply broken. Another
+CPU might have the device in use already after the first initialization and
+the second init could just render it unusable again.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/tick-broadcast.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -209,7 +209,7 @@ static void tick_do_broadcast_on_off(voi
+ struct clock_event_device *bc, *dev;
+ struct tick_device *td;
+ unsigned long flags, *reason = why;
+- int cpu;
++ int cpu, bc_stopped;
+
+ spin_lock_irqsave(&tick_broadcast_lock, flags);
+
+@@ -227,6 +227,8 @@ static void tick_do_broadcast_on_off(voi
+ if (!tick_device_is_functional(dev))
+ goto out;
+
++ bc_stopped = cpus_empty(tick_broadcast_mask);
++
+ switch (*reason) {
+ case CLOCK_EVT_NOTIFY_BROADCAST_ON:
+ case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
+@@ -248,9 +250,10 @@ static void tick_do_broadcast_on_off(voi
+ break;
+ }
+
+- if (cpus_empty(tick_broadcast_mask))
+- clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
+- else {
++ if (cpus_empty(tick_broadcast_mask)) {
++ if (!bc_stopped)
++ clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
++ } else if (bc_stopped) {
+ if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+ tick_broadcast_start_periodic(bc);
+ else
+@@ -500,9 +503,12 @@ static void tick_broadcast_clear_oneshot
+ */
+ void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+ {
+- bc->event_handler = tick_handle_oneshot_broadcast;
+- clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+- bc->next_event.tv64 = KTIME_MAX;
++ /* Set it up only once ! */
++ if (bc->event_handler != tick_handle_oneshot_broadcast) {
++ bc->event_handler = tick_handle_oneshot_broadcast;
++ clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
++ bc->next_event.tv64 = KTIME_MAX;
++ }
+ }
+
+ /*
--- /dev/null
+From 1fb9b7d29d8e85ba3196eaa7ab871bf76fc98d36 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 3 Sep 2008 21:37:14 +0000
+Subject: [PATCH] clockevents: prevent endless loop lockup
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 1fb9b7d29d8e85ba3196eaa7ab871bf76fc98d36 upstream
+
+The C1E/HPET bug reports on AMDX2/RS690 systems where tracked down to a
+too small value of the HPET minumum delta for programming an event.
+
+The clockevents code needs to enforce an interrupt event on the clock event
+device in some cases. The enforcement code was stupid and naive, as it just
+added the minimum delta to the current time and tried to reprogram the device.
+When the minimum delta is too small, then this loops forever.
+
+Add a sanity check. Allow reprogramming to fail 3 times, then print a warning
+and double the minimum delta value to make sure, that this does not happen again.
+Use the same function for both tick-oneshot and tick-broadcast code.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/tick-broadcast.c | 10 +---------
+ kernel/time/tick-internal.h | 2 ++
+ kernel/time/tick-oneshot.c | 36 ++++++++++++++++++++++++++++++------
+ 3 files changed, 33 insertions(+), 15 deletions(-)
+
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -370,16 +370,8 @@ cpumask_t *tick_get_broadcast_oneshot_ma
+ static int tick_broadcast_set_event(ktime_t expires, int force)
+ {
+ struct clock_event_device *bc = tick_broadcast_device.evtdev;
+- ktime_t now = ktime_get();
+- int res;
+
+- for(;;) {
+- res = clockevents_program_event(bc, expires, now);
+- if (!res || !force)
+- return res;
+- now = ktime_get();
+- expires = ktime_add(now, ktime_set(0, bc->min_delta_ns));
+- }
++ return tick_dev_program_event(bc, expires, force);
+ }
+
+ int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
+--- a/kernel/time/tick-internal.h
++++ b/kernel/time/tick-internal.h
+@@ -17,6 +17,8 @@ extern void tick_handle_periodic(struct
+ extern void tick_setup_oneshot(struct clock_event_device *newdev,
+ void (*handler)(struct clock_event_device *),
+ ktime_t nextevt);
++extern int tick_dev_program_event(struct clock_event_device *dev,
++ ktime_t expires, int force);
+ extern int tick_program_event(ktime_t expires, int force);
+ extern void tick_oneshot_notify(void);
+ extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
+--- a/kernel/time/tick-oneshot.c
++++ b/kernel/time/tick-oneshot.c
+@@ -25,18 +25,42 @@
+ /**
+ * tick_program_event internal worker function
+ */
+-static int __tick_program_event(struct clock_event_device *dev,
+- ktime_t expires, int force)
++int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires,
++ int force)
+ {
+ ktime_t now = ktime_get();
++ int i;
+
+- while (1) {
++ for (i = 0;;) {
+ int ret = clockevents_program_event(dev, expires, now);
+
+ if (!ret || !force)
+ return ret;
++
++ /*
++ * We tried 2 times to program the device with the given
++ * min_delta_ns. If that's not working then we double it
++ * and emit a warning.
++ */
++ if (++i > 2) {
++ printk(KERN_WARNING "CE: __tick_program_event of %s is "
++ "stuck %llx %llx\n", dev->name ? dev->name : "?",
++ now.tv64, expires.tv64);
++ printk(KERN_WARNING
++ "CE: increasing min_delta_ns %ld to %ld nsec\n",
++ dev->min_delta_ns, dev->min_delta_ns << 1);
++ WARN_ON(1);
++
++ /* Double the min. delta and try again */
++ if (!dev->min_delta_ns)
++ dev->min_delta_ns = 5000;
++ else
++ dev->min_delta_ns <<= 1;
++ i = 0;
++ }
++
+ now = ktime_get();
+- expires = ktime_add(now, ktime_set(0, dev->min_delta_ns));
++ expires = ktime_add_ns(now, dev->min_delta_ns);
+ }
+ }
+
+@@ -47,7 +71,7 @@ int tick_program_event(ktime_t expires,
+ {
+ struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
+
+- return __tick_program_event(dev, expires, force);
++ return tick_dev_program_event(dev, expires, force);
+ }
+
+ /**
+@@ -71,7 +95,7 @@ void tick_setup_oneshot(struct clock_eve
+ {
+ newdev->event_handler = handler;
+ clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT);
+- __tick_program_event(newdev, next_event, 1);
++ tick_dev_program_event(newdev, next_event, 1);
+ }
+
+ /**
--- /dev/null
+From 7cfb0435330364f90f274a26ecdc5f47f738498c Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 3 Sep 2008 21:37:24 +0000
+Subject: HPET: make minimum reprogramming delta useful
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 7cfb0435330364f90f274a26ecdc5f47f738498c upstream
+
+The minimum reprogramming delta was hardcoded in HPET ticks,
+which is stupid as it does not work with faster running HPETs.
+The C1E idle patches made this prominent on AMD/RS690 chipsets,
+where the HPET runs with 25MHz. Set it to 5us which seems to be
+a reasonable value and fixes the problems on the bug reporters
+machines. We have a further sanity check now in the clock events,
+which increases the delta when it is not sufficient.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Luiz Fernando N. Capitulino <lcapitulino@mandriva.com.br>
+Tested-by: Dmitry Nezhevenko <dion@inhex.net>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/hpet.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -223,8 +223,8 @@ static void hpet_legacy_clockevent_regis
+ /* Calculate the min / max delta */
+ hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+ &hpet_clockevent);
+- hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30,
+- &hpet_clockevent);
++ /* 5 usec minimum reprogramming delta. */
++ hpet_clockevent.min_delta_ns = 5000;
+
+ /*
+ * Start hpet with the boot cpu mask and make it
--- /dev/null
+From 7300711e8c6824fcfbd42a126980ff50439d8dd0 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 6 Sep 2008 03:01:45 +0200
+Subject: clockevents: broadcast fixup possible waiters
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 7300711e8c6824fcfbd42a126980ff50439d8dd0 upstream
+
+Until the C1E patches arrived there where no users of periodic broadcast
+before switching to oneshot mode. Now we need to trigger a possible
+waiter for a periodic broadcast when switching to oneshot mode.
+Otherwise we can starve them for ever.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/tick-broadcast.c | 37 ++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 36 insertions(+), 1 deletion(-)
+
+--- a/kernel/time/tick-broadcast.c
++++ b/kernel/time/tick-broadcast.c
+@@ -490,6 +490,18 @@ static void tick_broadcast_clear_oneshot
+ cpu_clear(cpu, tick_broadcast_oneshot_mask);
+ }
+
++static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires)
++{
++ struct tick_device *td;
++ int cpu;
++
++ for_each_cpu_mask_nr(cpu, *mask) {
++ td = &per_cpu(tick_cpu_device, cpu);
++ if (td->evtdev)
++ td->evtdev->next_event = expires;
++ }
++}
++
+ /**
+ * tick_broadcast_setup_oneshot - setup the broadcast device
+ */
+@@ -497,9 +509,32 @@ void tick_broadcast_setup_oneshot(struct
+ {
+ /* Set it up only once ! */
+ if (bc->event_handler != tick_handle_oneshot_broadcast) {
++ int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
++ int cpu = smp_processor_id();
++ cpumask_t mask;
++
+ bc->event_handler = tick_handle_oneshot_broadcast;
+ clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+- bc->next_event.tv64 = KTIME_MAX;
++
++ /* Take the do_timer update */
++ tick_do_timer_cpu = cpu;
++
++ /*
++ * We must be careful here. There might be other CPUs
++ * waiting for periodic broadcast. We need to set the
++ * oneshot_mask bits for those and program the
++ * broadcast device to fire.
++ */
++ mask = tick_broadcast_mask;
++ cpu_clear(cpu, mask);
++ cpus_or(tick_broadcast_oneshot_mask,
++ tick_broadcast_oneshot_mask, mask);
++
++ if (was_periodic && !cpus_empty(mask)) {
++ tick_broadcast_init_next_event(&mask, tick_next_period);
++ tick_broadcast_set_event(tick_next_period, 1);
++ } else
++ bc->next_event.tv64 = KTIME_MAX;
+ }
+ }
+
--- /dev/null
+From f7676254f179eac6b5244a80195ec8ae0e9d4606 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 6 Sep 2008 03:03:32 +0200
+Subject: x86: HPET fix moronic 32/64bit thinko
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit f7676254f179eac6b5244a80195ec8ae0e9d4606 upstream
+
+We use the HPET only in 32bit mode because:
+1) some HPETs are 32bit only
+2) on i386 there is no way to read/write the HPET atomic 64bit wide
+
+The HPET code unification done by the "moron of the year" did
+not take into account that unsigned long is different on 32 and
+64 bit.
+
+This thinko results in a possible endless loop in the clockevents
+code, when the return comparison fails due to the 64bit/332bit
+unawareness.
+
+unsigned long cnt = (u32) hpet_read() + delta can wrap over 32bit.
+but the final compare will fail and return -ETIME causing endless
+loops.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/hpet.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -283,15 +283,15 @@ static void hpet_legacy_set_mode(enum cl
+ }
+
+ static int hpet_legacy_next_event(unsigned long delta,
+- struct clock_event_device *evt)
++ struct clock_event_device *evt)
+ {
+- unsigned long cnt;
++ u32 cnt;
+
+ cnt = hpet_readl(HPET_COUNTER);
+- cnt += delta;
++ cnt += (u32) delta;
+ hpet_writel(cnt, HPET_T0_CMP);
+
+- return ((long)(hpet_readl(HPET_COUNTER) - cnt ) > 0) ? -ETIME : 0;
++ return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+ }
+
+ /*
--- /dev/null
+From 72d43d9bc9210d24d09202eaf219eac09e17b339 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 6 Sep 2008 03:06:08 +0200
+Subject: x86: HPET: read back compare register before reading counter
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 72d43d9bc9210d24d09202eaf219eac09e17b339 upstream
+
+After fixing the u32 thinko I sill had occasional hickups on ATI chipsets
+with small deltas. There seems to be a delay between writing the compare
+register and the transffer to the internal register which triggers the
+interrupt. Reading back the value makes sure, that it hit the internal
+match register befor we compare against the counter value.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/hpet.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -291,6 +291,13 @@ static int hpet_legacy_next_event(unsign
+ cnt += (u32) delta;
+ hpet_writel(cnt, HPET_T0_CMP);
+
++ /*
++ * We need to read back the CMP register to make sure that
++ * what we wrote hit the chip before we compare it to the
++ * counter.
++ */
++ WARN_ON((u32)hpet_readl(HPET_T0_CMP) != cnt);
++
+ return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
+ }
+
--- /dev/null
+From 4ff4b9e19a80b73959ebeb28d1df40176686f0a8 Mon Sep 17 00:00:00 2001
+From: Maciej W. Rozycki <macro@linux-mips.org>
+Date: Fri, 5 Sep 2008 14:05:31 -0700
+Subject: ntp: fix calculation of the next jiffie to trigger RTC sync
+
+From: Maciej W. Rozycki <macro@linux-mips.org>
+
+commit 4ff4b9e19a80b73959ebeb28d1df40176686f0a8 upstream
+
+We have a bug in the calculation of the next jiffie to trigger the RTC
+synchronisation. The aim here is to run sync_cmos_clock() as close as
+possible to the middle of a second. Which means we want this function to
+be called less than or equal to half a jiffie away from when now.tv_nsec
+equals 5e8 (500000000).
+
+If this is not the case for a given call to the function, for this purpose
+instead of updating the RTC we calculate the offset in nanoseconds to the
+next point in time where now.tv_nsec will be equal 5e8. The calculated
+offset is then converted to jiffies as these are the unit used by the
+timer.
+
+Hovewer timespec_to_jiffies() used here uses a ceil()-type rounding mode,
+where the resulting value is rounded up. As a result the range of
+now.tv_nsec when the timer will trigger is from 5e8 to 5e8 + TICK_NSEC
+rather than the desired 5e8 - TICK_NSEC / 2 to 5e8 + TICK_NSEC / 2.
+
+As a result if for example sync_cmos_clock() happens to be called at the
+time when now.tv_nsec is between 5e8 + TICK_NSEC / 2 and 5e8 to 5e8 +
+TICK_NSEC, it will simply be rescheduled HZ jiffies later, falling in the
+same range of now.tv_nsec again. Similarly for cases offsetted by an
+integer multiple of TICK_NSEC.
+
+This change addresses the problem by subtracting TICK_NSEC / 2 from the
+nanosecond offset to the next point in time where now.tv_nsec will be
+equal 5e8, effectively shifting the following rounding in
+timespec_to_jiffies() so that it produces a rounded-to-nearest result.
+
+Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/ntp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/time/ntp.c
++++ b/kernel/time/ntp.c
+@@ -245,7 +245,7 @@ static void sync_cmos_clock(unsigned lon
+ if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
+ fail = update_persistent_clock(now);
+
+- next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;
++ next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2);
+ if (next.tv_nsec <= 0)
+ next.tv_nsec += NSEC_PER_SEC;
+
--- /dev/null
+From 61c22c34c6f80a8e89cff5ff717627c54cc14fd4 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 9 Sep 2008 21:38:57 +0200
+Subject: clockevents: remove WARN_ON which was used to gather information
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 61c22c34c6f80a8e89cff5ff717627c54cc14fd4 upstream
+
+The issue of the endless reprogramming loop due to a too small
+min_delta_ns was fixed with the previous updates of the clock events
+code, but we had no information about the spread of this problem. I
+added a WARN_ON to get automated information via kerneloops.org and to
+get some direct reports, which allowed me to analyse the affected
+machines.
+
+The WARN_ON has served its purpose and would be annoying for a release
+kernel. Remove it and just keep the information about the increase of
+the min_delta_ns value.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/time/tick-oneshot.c | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+--- a/kernel/time/tick-oneshot.c
++++ b/kernel/time/tick-oneshot.c
+@@ -43,19 +43,17 @@ int tick_dev_program_event(struct clock_
+ * and emit a warning.
+ */
+ if (++i > 2) {
+- printk(KERN_WARNING "CE: __tick_program_event of %s is "
+- "stuck %llx %llx\n", dev->name ? dev->name : "?",
+- now.tv64, expires.tv64);
+- printk(KERN_WARNING
+- "CE: increasing min_delta_ns %ld to %ld nsec\n",
+- dev->min_delta_ns, dev->min_delta_ns << 1);
+- WARN_ON(1);
+-
+- /* Double the min. delta and try again */
++ /* Increase the min. delta and try again */
+ if (!dev->min_delta_ns)
+ dev->min_delta_ns = 5000;
+ else
+- dev->min_delta_ns <<= 1;
++ dev->min_delta_ns += dev->min_delta_ns >> 1;
++
++ printk(KERN_WARNING
++ "CE: %s increasing min_delta_ns to %lu nsec\n",
++ dev->name ? dev->name : "?",
++ dev->min_delta_ns << 1);
++
+ i = 0;
+ }
+