Add clockevent drivers for i386: lapic (local) and PIT (global).Update the timer IRQ to call into the PIT driver's event handlerand the lapic-timer IRQ to call into the lapic clockevent driver.The assignement of timer functionality is delegated to the coreframework code and replaces the compile and runtime evalution indo_timer_interrupt_hook()

/*+ * FIXME: Move this to i8253.h. There is no need to keep the access to+ * the PIT scattered all around the place -tglx+ */++/* * The timer chip is already set up at HZ interrupts per second here, * but we do not accept timer interrupts yet. We only allow the BP * to calibrate.@@ -976,13 +1001,15 @@ void (*wait_timer_tick)(void) __devinitd

/*@@ -1024,6 +1071,8 @@ static void __devinit setup_APIC_timer(u * to calibrate, since some later bootup code depends on getting * the first irq? Ugh. *+ * TODO: Fix this rather than saying "Ugh" -tglx+ * * We want to do the calibration only once since we * want to have local timer irqs syncron. CPUs connected * by the same APIC bus have the very same bus frequency.@@ -1046,7 +1095,7 @@ static int __init calibrate_APIC_clock(v * value into the APIC clock, we just want to get the * counter running for calibration. */- __setup_APIC_LVTT(1000000000);+ __setup_APIC_LVTT(1000000000, 0);

void disable_APIC_timer(void)@@ -1164,6 +1219,35 @@ void switch_APIC_timer_to_ipi(void *cpum !cpu_isset(cpu, timer_bcast_ipi)) { disable_APIC_timer(); cpu_set(cpu, timer_bcast_ipi);+#ifdef CONFIG_HIGH_RES_TIMERS+ /*+ * C3 stops the local apic timer. We can not make high+ * resolution timers and dynamic ticks work with one global+ * timer. Disable the NEXTEVT capability, so high resolution /+ * dyntick mode gets disabled too.+ *+ * There is a solution for this problem, but this is beyond the+ * scope of this initial patchset:+ *+ * When the local apic timer is unusable in C3, then we can+ * utilize the PIT to provide a global wakeup, which can be+ * directed to the CPU which has the earliest wakeup+ * point. Once the CPU is up again, the local apic is resumed+ * and can be used for the per cpu clock events again. It's not+ * hard to provide the infrastructure, but I need more insight+ * into the ACPI code to get it right.+ *+ * Disable the highres/dyntick feature in this case for now,+ * until somebody beats the ACPI clue into me. :)+ *+ * tglx+ */+ printk("Disabling NO_HZ and high resolution timers "+ "due to timer broadcasting (C3 stops local apic)\n");+ for_each_possible_cpu(cpu)+ per_cpu(lapic_events, cpu).capabilities &=+ ~CLOCK_CAP_NEXTEVT;+#endif } } EXPORT_SYMBOL(switch_APIC_timer_to_ipi);@@ -1224,6 +1308,7 @@ inline void smp_local_timer_interrupt(st fastcall void smp_apic_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id();+ struct clock_event_device *evt = &per_cpu(lapic_events, cpu);

spin_lock_irqsave(&i8253_lock, flags);- /*+ /* * Although our caller may have the read side of xtime_lock, * this is now a seqlock, and we are cheating in this routine * by having side effects on state that we cannot undo ifIndex: linux-2.6.18-mm2/arch/i386/kernel/time.c===================================================================--- linux-2.6.18-mm2.orig/arch/i386/kernel/time.c 2006-10-02 00:55:50.000000000 +0200+++ linux-2.6.18-mm2/arch/i386/kernel/time.c 2006-10-02 00:55:53.000000000 +0200@@ -163,15 +163,6 @@ EXPORT_SYMBOL(profile_pc); */ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) {- /*- * Here we are in the timer irq handler. We just have irqs locally- * disabled but we don't know if the timer_bh is running on the other- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need- * the irq version of write_lock because as just said we have irq- * locally disabled. -arca- */- write_seqlock(&xtime_lock);- #ifdef CONFIG_X86_IO_APIC if (timer_ack) { /*@@ -190,7 +181,6 @@ irqreturn_t timer_interrupt(int irq, voi