Index: linux-2.6.15-rc2-ck1-dt/arch/i386/Kconfig
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/Kconfig
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/Kconfig
@@ -182,12 +182,12 @@ config NO_IDLE_HZ
 	  processor is idle. During system load, timer is continuous.
 	  This option saves power, as it allows the system to stay in
 	  idle mode longer. Currently the only supported timer is ACPI PM
-	  timer. TSC and HPET timers are not supported.
+	  timer.
 
 	  Note that you can disable dynamic tick timer either by
 	  passing dyntick=disable command line option, or via sysfs:
 
-	  # echo 0 > /sys/devices/system/dyn_tick/dyn_tick0/enable
+	  # echo 0 > /sys/devices/system/timer/timer0/dyn_tick
 
 config SMP
 	bool "Symmetric multi-processing support"
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/apic.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/apic.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/apic.c
@@ -933,7 +933,7 @@ void (*wait_timer_tick)(void) __devinitd
 
 #define APIC_DIVISOR 16
 
-static u32 apic_timer_val;
+static u32 apic_timer_val __read_mostly;
 #define APIC_TIMER_VAL	((apic_timer_val) / (HZ))
 
 static void __setup_APIC_LVTT(unsigned int clocks)
@@ -1223,7 +1223,7 @@ fastcall void smp_apic_timer_interrupt(s
 	 */
 	irq_enter();
 
-	dyn_tick_interrupt(LOCAL_TIMER_VECTOR, regs);
+	dyn_tick_interrupt(regs);
 
 	smp_local_timer_interrupt(regs);
 	irq_exit();
@@ -1238,7 +1238,7 @@ fastcall void smp_spurious_interrupt(str
 
 	irq_enter();
 
-	dyn_tick_interrupt(SPURIOUS_APIC_VECTOR, regs);
+	dyn_tick_interrupt(regs);
 
 	/*
 	 * Check if this really is a spurious interrupt and ACK it
@@ -1265,7 +1265,7 @@ fastcall void smp_error_interrupt(struct
 
 	irq_enter();
 
-	dyn_tick_interrupt(ERROR_APIC_VECTOR, regs);
+	dyn_tick_interrupt(regs);
 
 	/* First tickle the hardware, only then report what went on. -- REW */
 	v = apic_read(APIC_ESR);
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/dyn-tick.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/dyn-tick.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/dyn-tick.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2004 Nokia Corporation
  * Written by Tony Lindgen <tony@atomide.com> and
  * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Rewritten by Con Kolivas <kernel@kolivas.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -95,39 +96,28 @@ void setup_dyn_tick_use_apic(unsigned in
 	}
 }
 
-void dyn_tick_interrupt(int irq, struct pt_regs *regs)
+void dyn_tick_interrupt(struct pt_regs *regs)
 {
-	int all_were_sleeping = 0;
 	int cpu = smp_processor_id();
 
 	if (!cpu_isset(cpu, nohz_cpu_mask))
 		return;
 
 	spin_lock(dyn_tick_lock);
-
-	if (cpus_equal(nohz_cpu_mask, cpu_online_map))
-		all_were_sleeping = 1;
-	cpu_clear(cpu, nohz_cpu_mask);
-
-	if (all_were_sleeping) {
-		/* Recover jiffies */
-		if (irq) {
-			int lost;
-
-			lost = cur_timer->mark_offset();
-			if (lost)
-				do_timer(regs);
-		}
+	if (cpus_equal(nohz_cpu_mask, cpu_online_map)) {
+		/* All were sleeping, recover jiffies */
+		int lost = cur_timer->mark_offset();
+		if (lost && in_irq())
+			do_timer(regs);
 		if (cpu_has_local_apic())
 			enable_pit_timer();
 	}
-
+	cpu_clear(cpu, nohz_cpu_mask);
 	spin_unlock(dyn_tick_lock);
 
 	reprogram_timer(1);
 
 	conditional_run_local_timers();
-
 	/* Fixme: Enable NMI watchdog */
 }
 
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/io_apic.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/io_apic.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/io_apic.c
@@ -1180,6 +1180,7 @@ next:
 
 static struct hw_interrupt_type ioapic_level_type;
 static struct hw_interrupt_type ioapic_edge_type;
+static struct hw_interrupt_type ioapic_edge_type_irq0;
 
 #define IOAPIC_AUTO	-1
 #define IOAPIC_EDGE	0
@@ -1194,7 +1195,7 @@ static inline void ioapic_register_intr(
 		else if (vector)
 			irq_desc[vector].handler = &ioapic_edge_type;
 		else
-			irq_desc[vector].handler = IOAPIC_EDGE_TYPE_IRQ0;
+			irq_desc[vector].handler = &ioapic_edge_type_irq0;
 		set_intr_gate(vector, interrupt[vector]);
 	} else	{
 		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
@@ -1203,7 +1204,7 @@ static inline void ioapic_register_intr(
 		else if (irq)
 			irq_desc[irq].handler = &ioapic_edge_type;
 		else
-			irq_desc[irq].handler = IOAPIC_EDGE_TYPE_IRQ0;
+			irq_desc[irq].handler = &ioapic_edge_type_irq0;
 		set_intr_gate(vector, interrupt[irq]);
 	}
 }
@@ -1316,7 +1317,7 @@ static void __init setup_ExtINT_IRQ0_pin
 	 * The timer IRQ doesn't have to know that behind the
 	 * scene we have a 8259A-master in AEOI mode ...
 	 */
-	irq_desc[0].handler = IOAPIC_EDGE_TYPE_IRQ0;
+	irq_desc[0].handler = &ioapic_edge_type_irq0;
 
 	/*
 	 * Add it to the IO-APIC irq-routing table:
@@ -2094,7 +2095,7 @@ static struct hw_interrupt_type ioapic_l
 };
 
 /* Needed to disable PIT interrupts when all CPUs sleep */
-struct hw_interrupt_type ioapic_edge_type_irq0 = {
+static struct hw_interrupt_type ioapic_edge_type_irq0 __read_mostly = {
 	.typename 	= "IO-APIC-edge-irq0",
 	.startup 	= startup_edge_ioapic,
 	.shutdown 	= shutdown_edge_ioapic,
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/irq.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/irq.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/irq.c
@@ -77,7 +77,7 @@ fastcall unsigned int do_IRQ(struct pt_r
 	}
 #endif
 
-	dyn_tick_interrupt(irq, regs);
+	dyn_tick_interrupt(regs);
 
 #ifdef CONFIG_4KSTACKS
 
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/smp.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/smp.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/smp.c
@@ -314,7 +314,7 @@ fastcall void smp_invalidate_interrupt(s
 {
 	unsigned long cpu;
 
-	dyn_tick_interrupt(INVALIDATE_TLB_VECTOR, regs);
+	dyn_tick_interrupt(regs);
 
 	cpu = get_cpu();
 
@@ -604,7 +604,7 @@ fastcall void smp_reschedule_interrupt(s
 {
 	ack_APIC_irq();
 
-	dyn_tick_interrupt(RESCHEDULE_VECTOR, regs);
+	dyn_tick_interrupt(regs);
 }
 
 fastcall void smp_call_function_interrupt(struct pt_regs *regs)
@@ -615,7 +615,7 @@ fastcall void smp_call_function_interrup
 
 	ack_APIC_irq();
 
-	dyn_tick_interrupt(CALL_FUNCTION_VECTOR, regs);
+	dyn_tick_interrupt(regs);
 
 	/*
 	 * Notify initiating CPU that I've grabbed the data and am
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/timers/timer_cyclone.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/timers/timer_cyclone.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/timers/timer_cyclone.c
@@ -102,7 +102,7 @@ static int mark_offset_cyclone(void)
 	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
 		jiffies_64++;
 
-	return 1;
+	return lost;
 }
 
 static unsigned long get_offset_cyclone(void)
Index: linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/timers/timer_tsc.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/arch/i386/kernel/timers/timer_tsc.c
+++ linux-2.6.15-rc2-ck1-dt/arch/i386/kernel/timers/timer_tsc.c
@@ -184,6 +184,7 @@ static int mark_offset_tsc_hpet(void)
 {
 	unsigned long long last_offset;
  	unsigned long offset, temp, hpet_current;
+ 	int lost_ticks = 0;
 
 	write_seqlock(&monotonic_lock);
 	last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
@@ -205,7 +206,7 @@ static int mark_offset_tsc_hpet(void)
 	/* lost tick compensation */
 	offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
 	if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))) {
-		int lost_ticks = (offset - hpet_last) / hpet_tick;
+		lost_ticks = (offset - hpet_last) / hpet_tick;
 		jiffies_64 += lost_ticks;
 	}
 	hpet_last = hpet_current;
@@ -225,7 +226,7 @@ static int mark_offset_tsc_hpet(void)
 	ASM_MUL64_REG(temp, delay_at_last_interrupt,
 			hpet_usec_quotient, delay_at_last_interrupt);
 
-	return 1;
+	return lost_ticks;
 }
 #endif
 
@@ -445,12 +446,10 @@ static int mark_offset_tsc(void)
 	 * between tsc and pit reads (as noted when
 	 * usec delta is > 90% # of usecs/tick)
 	 */
-	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ)) {
+	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
 		jiffies_64++;
-		lost++;
-	}
 
-	return 1;
+	return lost;
 }
 
 static int __init init_tsc(char* override)
Index: linux-2.6.15-rc2-ck1-dt/include/asm-i386/dyn-tick.h
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/include/asm-i386/dyn-tick.h
+++ linux-2.6.15-rc2-ck1-dt/include/asm-i386/dyn-tick.h
@@ -4,6 +4,7 @@
  * Copyright (C) 2004 Nokia Corporation
  * Written by Tony Lindgen <tony@atomide.com> and
  * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Rewritten by Con Kolivas <kernel@kolivas.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,7 +21,7 @@ extern void cpufreq_delayed_get(void);
 
 #ifdef CONFIG_NO_IDLE_HZ
 extern void setup_dyn_tick_use_apic(unsigned int calibration_result);
-extern void dyn_tick_interrupt(int irq, struct pt_regs *regs);
+extern void dyn_tick_interrupt(struct pt_regs *regs);
 extern void dyn_tick_time_init(struct timer_opts *cur_timer);
 
 /*
@@ -43,10 +44,6 @@ static inline int cpu_has_local_apic(voi
 }
 #endif	/* (defined(CONFIG_SMP) || defined(CONFIG_X86_UP_APIC)) */
 
-#define IOAPIC_EDGE_TYPE_IRQ0 (&(ioapic_edge_type_irq0))
-
-extern struct hw_interrupt_type ioapic_edge_type_irq0;
-
 extern void idle_reprogram_timer(void);
 
 static inline void tsc_sanity_check(int *lost_count)
@@ -55,13 +52,11 @@ static inline void tsc_sanity_check(int 
 
 #else /* CONFIG_NO_IDLE_HZ */
 
-#define IOAPIC_EDGE_TYPE_IRQ0 (&(ioapic_edge_type))
-
 static inline void setup_dyn_tick_use_apic(unsigned int calibration_result)
 {
 }
 
-static inline void dyn_tick_interrupt(int irq, struct pt_regs *regs)
+static inline void dyn_tick_interrupt(struct pt_regs *regs)
 {
 }
 
Index: linux-2.6.15-rc2-ck1-dt/include/linux/dyn-tick.h
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/include/linux/dyn-tick.h
+++ linux-2.6.15-rc2-ck1-dt/include/linux/dyn-tick.h
@@ -4,6 +4,7 @@
  * Copyright (C) 2004 Nokia Corporation
  * Written by Tony Lindgen <tony@atomide.com> and
  * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Rewritten by Con Kolivas <kernel@kolivas.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
Index: linux-2.6.15-rc2-ck1-dt/kernel/dyn-tick.c
===================================================================
--- linux-2.6.15-rc2-ck1-dt.orig/kernel/dyn-tick.c
+++ linux-2.6.15-rc2-ck1-dt/kernel/dyn-tick.c
@@ -1,11 +1,12 @@
 /*
  * linux/kernel/dyn-tick.c
  *
- * Beginnings of generic dynamic tick timer support
+ * Generic dynamic tick timer support
  *
  * Copyright (C) 2004 Nokia Corporation
  * Written by Tony Lindgen <tony@atomide.com> and
  * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ * Rewritten by Con Kolivas <kernel@kolivas.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -24,7 +25,7 @@
 #include <linux/dyn-tick.h>
 #include <linux/rcupdate.h>
 
-#define DYN_TICK_VERSION	"051118-1"
+#define DYN_TICK_VERSION	"051122-1"
 
 int dyn_tick_enabled(void)
 {
@@ -39,20 +40,24 @@ static inline int dyn_tick_suitable(void
 /*
  * Arch independent code needed to reprogram next timer interrupt.
  * Gets called, with IRQs disabled, from cpu_idle() before entering idle loop.
+ * Significant contention is possible so avoid spinning on locks and do not
+ * reprogram timers instead.
  */
 void timer_dyn_reprogram(void)
 {
-	int cpu = smp_processor_id();
+	int cpu;
 	unsigned int delta;
 
 	if (!dyn_tick_enabled())
 		return;
 
+	cpu = smp_processor_id();
 	if (rcu_pending(cpu) || local_softirq_pending())
 		return;
 
 	/* Check if we can start skipping ticks */
-	write_seqlock(&xtime_lock);
+	if (unlikely(!write_tryseqlock(&xtime_lock)))
+		return;
 
 	delta = next_timer_interrupt() - jiffies;
 	if (delta > dyn_tick->max_skip)
@@ -61,7 +66,8 @@ void timer_dyn_reprogram(void)
 	if (delta > dyn_tick->min_skip) {
 		int idle_time = 0;
 
-		spin_lock(dyn_tick_lock);
+		if (unlikely(!spin_trylock(dyn_tick_lock)))
+			goto out_unlock;
 
 		dyn_tick->arch_reprogram(jiffies + delta);
 
@@ -73,6 +79,7 @@ void timer_dyn_reprogram(void)
 		spin_unlock(dyn_tick_lock);
 	}
 
+out_unlock:
 	write_sequnlock(&xtime_lock);
 }
 
@@ -161,7 +168,7 @@ device_initcall(init_dyn_tick_sysfs);
 /*
  * Init functions
  *
- * We need to initialize dynamic tick after calibrate delay
+ * We need to initialise dynamic tick after calibrate delay
  */
 static int __init dyn_tick_late_init(void)
 {
