linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
@ 2007-06-16 10:36 Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
                   ` (27 more replies)
  0 siblings, 28 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

The following patch series contains:

- dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)

- updates and improvements to high resolution timer / dynticks 

- high resolution timer / dynticks support for x86_64

The x86_64 support is based on an initial patch from Chris Wright. Thanks Chris !

The patch set has been tested in the -hrt and -rt trees for quite a while
and the initial problems have been sorted out. Thanks to the folks from the
PowerTop project for testing and feedback.

The -hrt tree at http://www.tglx.de/projects/hrtimers/2.6.22-rc4/ contains
also an hpet force patch series from Venki Pallipadi, but I leave this up to
Venki to send it mainline wards.

Changes since V1:

- simplified the idle breakage fixup

- fixed a resume bug (making the famous VAIO work again)

- added a clocksource settimeofday hook for PPC (Tony Breeds)

Thanks,

	tglx
-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 14:36   ` Bernhard Rosenkraenzer
  2007-06-16 10:36 ` [patch-mm 02/25] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown Thomas Gleixner
                   ` (26 subsequent siblings)
  27 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Adam Belay, Len Brown,
	Dave Miller, Paul Mundt, Russell King

[-- Attachment #1: cpuidle-fix-sparc-arm-sh-idle.patch --]
[-- Type: text/plain, Size: 1914 bytes --]

The cpuidle patches moved the tick nohz handling from irq_exit into
the inner idle loop. The change is correct as it covers non interrupt
based wakeups (e.g DMA) on x86 as well, but the move breaks ARM, SH
and SPARC64. 

Keep the original implementation and deselet the irq exit code for
those architectures which have non irq idle wakeups.

This way the non affected architectures are not burdened with the
extra changes in the idle implementation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Belay <abelay@novell.com>
Cc: Len Brown <lenb@kernel.org>
Cc: Dave Miller <davem@davemloft.net>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>

---
 arch/i386/Kconfig |    4 ++++
 kernel/softirq.c  |    5 +++++
 2 files changed, 9 insertions(+)

Index: linux-2.6.22-rc4-mm/arch/i386/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/Kconfig	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/Kconfig	2007-06-16 12:10:22.000000000 +0200
@@ -31,6 +31,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST
 	default y
 	depends on X86_LOCAL_APIC
 
+config NONIRQ_WAKEUP
+	bool
+	default y
+
 config LOCKDEP_SUPPORT
 	bool
 	default y
Index: linux-2.6.22-rc4-mm/kernel/softirq.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/softirq.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/softirq.c	2007-06-16 12:10:22.000000000 +0200
@@ -304,6 +304,11 @@ void irq_exit(void)
 	if (!in_interrupt() && local_softirq_pending())
 		invoke_softirq();
 
+#if defined(CONFIG_NO_HZ) && !defined(CONFIG_NONIRQ_WAKEUP)
+	/* Make sure that timer wheel updates are propagated */
+	if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
+		tick_nohz_stop_sched_tick();a
+#endif
 	preempt_enable_no_resched();
 }
 

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 02/25] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 03/25] Clockevents remove prototypes of removed functions Thomas Gleixner
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Udo A. Steinberg,
	Len Brown

[-- Attachment #1: acpi-move-timer-broadcast-before-arb-dis.patch --]
[-- Type: text/plain, Size: 1568 bytes --]

From: Udo A. Steinberg <us15@os.inf.tu-dresden.de>

The chipset doc for IHC4 tells us:

1.In general, software should not attempt any non-posted accesses during
arbiter disable except to the ICH4's power management registers. This implies
that interrupt handlers for any unmasked hardware interrupts and SMI/NMI should
check ARB_DIS status before reading from ICH devices.

So it's not a good idea to access ICH devices after arbiter shut down.

Signed-off-by: Udo A. Steinberg <us15@os.inf.tu-dresden.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Len Brown <lenb@kernel.org>

---
 drivers/acpi/processor_idle.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/drivers/acpi/processor_idle.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/acpi/processor_idle.c	2007-06-16 12:10:22.000000000 +0200
@@ -978,6 +978,12 @@ static int acpi_idle_enter_c3(struct cpu
 		return 0;
 	}
 
+	/*
+	 * Must be done before busmaster disable as we might need to
+	 * access HPET !
+	 */
+	acpi_state_timer_broadcast(pr, cx, 1);
+
 	/* disable bus master */
 	if (pr->flags.bm_check) {
 		spin_lock(&c3_lock);
@@ -997,7 +1003,6 @@ static int acpi_idle_enter_c3(struct cpu
 
 	/* Get start time (ticks) */
 	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
-	acpi_state_timer_broadcast(pr, cx, 1);
 	acpi_idle_do_entry(cx);
 	t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 03/25] Clockevents remove prototypes of removed functions
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 02/25] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 04/25] Timekeeping: Fixup shadow variable argument Thomas Gleixner
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: clockevents-remove-unused-code.patch --]
[-- Type: text/plain, Size: 976 bytes --]

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/clockchips.h |    4 ----
 1 file changed, 4 deletions(-)

Index: linux-2.6.22-rc4-mm/include/linux/clockchips.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/linux/clockchips.h	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/clockchips.h	2007-06-16 12:10:22.000000000 +0200
@@ -119,10 +119,6 @@ extern void clockevents_register_device(
 
 extern void clockevents_exchange_device(struct clock_event_device *old,
 					struct clock_event_device *new);
-extern
-struct clock_event_device *clockevents_request_device(unsigned int features,
-						      cpumask_t cpumask);
-extern void clockevents_release_device(struct clock_event_device *dev);
 extern void clockevents_set_mode(struct clock_event_device *dev,
 				 enum clock_event_mode mode);
 extern int clockevents_register_notifier(struct notifier_block *nb);

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 04/25] Timekeeping: Fixup shadow variable argument
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (2 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 03/25] Clockevents remove prototypes of removed functions Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 05/25] timer.c cleanup recently introduced whitespace damage Thomas Gleixner
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz

[-- Attachment #1: timekeeping-c-fixup-clock-shadow-global-variable.patch --]
[-- Type: text/plain, Size: 1222 bytes --]

clocksource_adjust() has a clock argument, which shadows the file 
global clock variable. Fix this up.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>

---
 kernel/time/timekeeping.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Index: linux-2.6.22-rc4-mm/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/timekeeping.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/timekeeping.c	2007-06-16 12:10:23.000000000 +0200
@@ -401,7 +401,7 @@ static __always_inline int clocksource_b
  * this is optimized for the most common adjustments of -1,0,1,
  * for other values we can do a bit more work.
  */
-static void clocksource_adjust(struct clocksource *clock, s64 offset)
+static void clocksource_adjust(s64 offset)
 {
 	s64 error, interval = clock->cycle_interval;
 	int adj;
@@ -476,7 +476,7 @@ void update_wall_time(void)
 	}
 
 	/* correct the clock when NTP error is too big */
-	clocksource_adjust(clock, offset);
+	clocksource_adjust(offset);
 
 	/* store full nanoseconds into xtime */
 	xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 05/25] timer.c cleanup recently introduced whitespace damage
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (3 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 04/25] Timekeeping: Fixup shadow variable argument Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 06/25] clockevents: Fix resume logic Thomas Gleixner
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: timer-fix-whitespace.patch --]
[-- Type: text/plain, Size: 3066 bytes --]

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/timer.c |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

Index: linux-2.6.22-rc4-mm/kernel/timer.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/timer.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/timer.c	2007-06-16 12:10:23.000000000 +0200
@@ -103,14 +103,14 @@ static inline tvec_base_t *tbase_get_bas
 static inline void timer_set_deferrable(struct timer_list *timer)
 {
 	timer->base = ((tvec_base_t *)((unsigned long)(timer->base) |
-	                               TBASE_DEFERRABLE_FLAG));
+				       TBASE_DEFERRABLE_FLAG));
 }
 
 static inline void
 timer_set_base(struct timer_list *timer, tvec_base_t *new_base)
 {
 	timer->base = (tvec_base_t *)((unsigned long)(new_base) |
-	                              tbase_get_deferrable(timer->base));
+				      tbase_get_deferrable(timer->base));
 }
 
 /**
@@ -445,10 +445,10 @@ EXPORT_SYMBOL(__mod_timer);
 void add_timer_on(struct timer_list *timer, int cpu)
 {
 	tvec_base_t *base = per_cpu(tvec_bases, cpu);
-  	unsigned long flags;
+	unsigned long flags;
 
 	timer_stats_timer_set_start_info(timer);
-  	BUG_ON(timer_pending(timer) || !timer->function);
+	BUG_ON(timer_pending(timer) || !timer->function);
 	spin_lock_irqsave(&base->lock, flags);
 	timer_set_base(timer, base);
 	internal_add_timer(base, timer);
@@ -627,7 +627,7 @@ static inline void __run_timers(tvec_bas
 	while (time_after_eq(jiffies, base->timer_jiffies)) {
 		struct list_head work_list;
 		struct list_head *head = &work_list;
- 		int index = base->timer_jiffies & TVR_MASK;
+		int index = base->timer_jiffies & TVR_MASK;
 
 		/*
 		 * Cascade timers:
@@ -644,8 +644,8 @@ static inline void __run_timers(tvec_bas
 			unsigned long data;
 
 			timer = list_first_entry(head, struct timer_list,entry);
- 			fn = timer->function;
- 			data = timer->data;
+			fn = timer->function;
+			data = timer->data;
 
 			timer_stats_account_timer(timer);
 
@@ -689,8 +689,8 @@ static unsigned long __next_timer_interr
 	index = slot = timer_jiffies & TVR_MASK;
 	do {
 		list_for_each_entry(nte, base->tv1.vec + slot, entry) {
- 			if (tbase_get_deferrable(nte->base))
- 				continue;
+			if (tbase_get_deferrable(nte->base))
+				continue;
 
 			found = 1;
 			expires = nte->expires;
@@ -834,7 +834,7 @@ void update_process_times(int user_tick)
 	if (rcu_pending(cpu))
 		rcu_check_callbacks(cpu, user_tick);
 	scheduler_tick();
- 	run_posix_cpu_timers(p);
+	run_posix_cpu_timers(p);
 }
 
 /*
@@ -909,7 +909,7 @@ static inline void update_times(unsigned
 	update_wall_time();
 	calc_load(ticks);
 }
-  
+
 /*
  * The 64-bit jiffies value is not atomic - you MUST NOT read it
  * without sampling the sequence number in xtime_lock.
@@ -1105,7 +1105,7 @@ asmlinkage long sys_gettid(void)
 /**
  * do_sysinfo - fill in sysinfo struct
  * @info: pointer to buffer to fill
- */ 
+ */
 int do_sysinfo(struct sysinfo *info)
 {
 	unsigned long mem_total, sav_total;

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 06/25] clockevents: Fix resume logic
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (4 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 05/25] timer.c cleanup recently introduced whitespace damage Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 18:51   ` Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic) Oleg Verych
  2007-06-16 10:36 ` [patch-mm 07/25] Tick management: spread timer interrupt Thomas Gleixner
                   ` (21 subsequent siblings)
  27 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: clockevents-fix-resume-logic.patch --]
[-- Type: text/plain, Size: 12498 bytes --]

We need to make sure, that the clockevent devices are resumed, before
the tick is resumed. The current resume logic does not guarantee this.

Add CLOCK_EVT_MODE_RESUME and call the set mode functions of the clock
event devices before resuming the tick / oneshot functionality.

Fixup the existing users.

This removes the sysfs entry for the HPET, which is now controlled by
the clockevents resume code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/arm/mach-davinci/time.c      |    2 +
 arch/arm/mach-imx/time.c          |    1 
 arch/arm/mach-ixp4xx/common.c     |    2 +
 arch/arm/mach-omap1/time.c        |    1 
 arch/arm/plat-omap/timer32k.c     |    2 +
 arch/i386/kernel/apic.c           |    3 +
 arch/i386/kernel/hpet.c           |   71 ++------------------------------------
 arch/i386/kernel/i8253.c          |   26 ++++++-------
 arch/i386/kernel/vmiclock.c       |    1 
 arch/i386/xen/time.c              |    1 
 arch/sh/kernel/timers/timer-tmu.c |    1 
 arch/sparc64/kernel/time.c        |    1 
 include/linux/clockchips.h        |    1 
 kernel/time/tick-broadcast.c      |    6 ++-
 kernel/time/tick-common.c         |   16 +++++---
 15 files changed, 47 insertions(+), 88 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/apic.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c	2007-06-16 12:10:23.000000000 +0200
@@ -263,6 +263,9 @@ static void lapic_timer_setup(enum clock
 		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
 		apic_write_around(APIC_LVTT, v);
 		break;
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here */
+		break;
 	}
 
 	local_irq_restore(flags);
Index: linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/hpet.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-16 12:10:23.000000000 +0200
@@ -187,6 +187,10 @@ static void hpet_set_mode(enum clock_eve
 		cfg &= ~HPET_TN_ENABLE;
 		hpet_writel(cfg, HPET_T0_CFG);
 		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		hpet_enable_int();
+		break;
 	}
 }
 
@@ -217,6 +221,7 @@ static struct clocksource clocksource_hp
 	.mask		= HPET_MASK,
 	.shift		= HPET_SHIFT,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.resume		= hpet_start_counter,
 };
 
 /*
@@ -313,7 +318,6 @@ int __init hpet_enable(void)
 
 	clocksource_register(&clocksource_hpet);
 
-
 	if (id & HPET_ID_LEGSUP) {
 		hpet_enable_int();
 		hpet_reserve_platform_timers(id);
@@ -546,68 +550,3 @@ irqreturn_t hpet_rtc_interrupt(int irq, 
 	return IRQ_HANDLED;
 }
 #endif
-
-
-/*
- * Suspend/resume part
- */
-
-#ifdef CONFIG_PM
-
-static int hpet_suspend(struct sys_device *sys_device, pm_message_t state)
-{
-	unsigned long cfg = hpet_readl(HPET_CFG);
-
-	cfg &= ~(HPET_CFG_ENABLE|HPET_CFG_LEGACY);
-	hpet_writel(cfg, HPET_CFG);
-
-	return 0;
-}
-
-static int hpet_resume(struct sys_device *sys_device)
-{
-	unsigned int id;
-
-	hpet_start_counter();
-
-	id = hpet_readl(HPET_ID);
-
-	if (id & HPET_ID_LEGSUP)
-		hpet_enable_int();
-
-	return 0;
-}
-
-static struct sysdev_class hpet_class = {
-	set_kset_name("hpet"),
-	.suspend	= hpet_suspend,
-	.resume		= hpet_resume,
-};
-
-static struct sys_device hpet_device = {
-	.id		= 0,
-	.cls		= &hpet_class,
-};
-
-
-static __init int hpet_register_sysfs(void)
-{
-	int err;
-
-	if (!is_hpet_capable())
-		return 0;
-
-	err = sysdev_class_register(&hpet_class);
-
-	if (!err) {
-		err = sysdev_register(&hpet_device);
-		if (err)
-			sysdev_class_unregister(&hpet_class);
-	}
-
-	return err;
-}
-
-device_initcall(hpet_register_sysfs);
-
-#endif
Index: linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/i8253.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-16 12:10:23.000000000 +0200
@@ -3,11 +3,11 @@
  *
  */
 #include <linux/clockchips.h>
-#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
-#include <linux/sysdev.h>
 #include <linux/module.h>
-#include <linux/init.h>
+#include <linux/spinlock.h>
 
 #include <asm/smp.h>
 #include <asm/delay.h>
@@ -42,26 +42,24 @@ static void init_pit_timer(enum clock_ev
 	case CLOCK_EVT_MODE_PERIODIC:
 		/* binary, mode 2, LSB/MSB, ch 0 */
 		outb_p(0x34, PIT_MODE);
-		udelay(10);
 		outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
-		udelay(10);
 		outb(LATCH >> 8 , PIT_CH0);	/* MSB */
 		break;
 
-	/*
-	 * Avoid unnecessary state transitions, as it confuses
-	 * Geode / Cyrix based boxen.
-	 */
 	case CLOCK_EVT_MODE_SHUTDOWN:
-		if (evt->mode == CLOCK_EVT_MODE_UNUSED)
-			break;
 	case CLOCK_EVT_MODE_UNUSED:
-		if (evt->mode == CLOCK_EVT_MODE_SHUTDOWN)
-			break;
+		outb_p(0x30, PIT_MODE);
+		outb_p(0, PIT_CH0);	/* LSB */
+		outb_p(0, PIT_CH0);	/* MSB */
+		break;
+
 	case CLOCK_EVT_MODE_ONESHOT:
 		/* One shot setup */
 		outb_p(0x38, PIT_MODE);
-		udelay(10);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here */
 		break;
 	}
 	spin_unlock_irqrestore(&i8253_lock, flags);
Index: linux-2.6.22-rc4-mm/include/linux/clockchips.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/linux/clockchips.h	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/clockchips.h	2007-06-16 12:10:23.000000000 +0200
@@ -23,6 +23,7 @@ enum clock_event_mode {
 	CLOCK_EVT_MODE_SHUTDOWN,
 	CLOCK_EVT_MODE_PERIODIC,
 	CLOCK_EVT_MODE_ONESHOT,
+	CLOCK_EVT_MODE_RESUME,
 };
 
 /* Clock event notification values */
Index: linux-2.6.22-rc4-mm/kernel/time/tick-broadcast.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/tick-broadcast.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-broadcast.c	2007-06-16 12:10:23.000000000 +0200
@@ -49,7 +49,7 @@ cpumask_t *tick_get_broadcast_mask(void)
  */
 static void tick_broadcast_start_periodic(struct clock_event_device *bc)
 {
-	if (bc && bc->mode == CLOCK_EVT_MODE_SHUTDOWN)
+	if (bc)
 		tick_setup_periodic(bc, 1);
 }
 
@@ -299,7 +299,7 @@ void tick_suspend_broadcast(void)
 	spin_lock_irqsave(&tick_broadcast_lock, flags);
 
 	bc = tick_broadcast_device.evtdev;
-	if (bc && tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
+	if (bc)
 		clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
 
 	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
@@ -316,6 +316,8 @@ int tick_resume_broadcast(void)
 	bc = tick_broadcast_device.evtdev;
 
 	if (bc) {
+		clockevents_set_mode(bc, CLOCK_EVT_MODE_RESUME);
+
 		switch (tick_broadcast_device.mode) {
 		case TICKDEV_MODE_PERIODIC:
 			if(!cpus_empty(tick_broadcast_mask))
Index: linux-2.6.22-rc4-mm/kernel/time/tick-common.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/tick-common.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-common.c	2007-06-16 12:10:23.000000000 +0200
@@ -318,12 +318,17 @@ static void tick_resume(void)
 {
 	struct tick_device *td = &__get_cpu_var(tick_cpu_device);
 	unsigned long flags;
+	int broadcast = tick_resume_broadcast();
 
 	spin_lock_irqsave(&tick_device_lock, flags);
-	if (td->mode == TICKDEV_MODE_PERIODIC)
-		tick_setup_periodic(td->evtdev, 0);
-	else
-		tick_resume_oneshot();
+	clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
+
+	if (!broadcast) {
+		if (td->mode == TICKDEV_MODE_PERIODIC)
+			tick_setup_periodic(td->evtdev, 0);
+		else
+			tick_resume_oneshot();
+	}
 	spin_unlock_irqrestore(&tick_device_lock, flags);
 }
 
@@ -360,8 +365,7 @@ static int tick_notify(struct notifier_b
 		break;
 
 	case CLOCK_EVT_NOTIFY_RESUME:
-		if (!tick_resume_broadcast())
-			tick_resume();
+		tick_resume();
 		break;
 
 	default:
Index: linux-2.6.22-rc4-mm/arch/arm/mach-davinci/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/arm/mach-davinci/time.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-davinci/time.c	2007-06-16 12:10:23.000000000 +0200
@@ -285,6 +285,8 @@ static void davinci_set_mode(enum clock_
 	case CLOCK_EVT_MODE_SHUTDOWN:
 		t->opts = TIMER_OPTS_DISABLED;
 		break;
+	case CLOCK_EVT_MODE_RESUME:
+		break;
 	}
 }
 
Index: linux-2.6.22-rc4-mm/arch/arm/mach-imx/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/arm/mach-imx/time.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-imx/time.c	2007-06-16 12:10:23.000000000 +0200
@@ -159,6 +159,7 @@ static void imx_set_mode(enum clock_even
 		break;
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
 		/* Left event sources disabled, no more interrupts appears */
 		break;
 	}
Index: linux-2.6.22-rc4-mm/arch/arm/mach-ixp4xx/common.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/arm/mach-ixp4xx/common.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-ixp4xx/common.c	2007-06-16 12:10:23.000000000 +0200
@@ -459,6 +459,8 @@ static void ixp4xx_set_mode(enum clock_e
 	default:
 		osrt = opts = 0;
 		break;
+	case CLOCK_EVT_MODE_RESUME:
+		break;
 	}
 
 	*IXP4XX_OSRT1 = osrt | opts;
Index: linux-2.6.22-rc4-mm/arch/arm/mach-omap1/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/arm/mach-omap1/time.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-omap1/time.c	2007-06-16 12:10:23.000000000 +0200
@@ -156,6 +156,7 @@ static void omap_mpu_set_mode(enum clock
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
 		break;
 	}
 }
Index: linux-2.6.22-rc4-mm/arch/arm/plat-omap/timer32k.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/arm/plat-omap/timer32k.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/plat-omap/timer32k.c	2007-06-16 12:10:23.000000000 +0200
@@ -156,6 +156,8 @@ static void omap_32k_timer_set_mode(enum
 	case CLOCK_EVT_MODE_SHUTDOWN:
 		omap_32k_timer_stop();
 		break;
+	case CLOCK_EVT_MODE_RESUME:
+		break;
 	}
 }
 
Index: linux-2.6.22-rc4-mm/arch/i386/kernel/vmiclock.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/vmiclock.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/vmiclock.c	2007-06-16 12:10:23.000000000 +0200
@@ -142,6 +142,7 @@ static void vmi_timer_set_mode(enum cloc
 
 	switch (mode) {
 	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_RESUME:
 		break;
 	case CLOCK_EVT_MODE_PERIODIC:
 		cycles_per_hz = vmi_timer_ops.get_cycle_frequency();
Index: linux-2.6.22-rc4-mm/arch/i386/xen/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/xen/time.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/xen/time.c	2007-06-16 12:10:23.000000000 +0200
@@ -407,6 +407,7 @@ static void xen_timerop_set_mode(enum cl
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_RESUME:
 		break;
 
 	case CLOCK_EVT_MODE_UNUSED:
Index: linux-2.6.22-rc4-mm/arch/sh/kernel/timers/timer-tmu.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/sh/kernel/timers/timer-tmu.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sh/kernel/timers/timer-tmu.c	2007-06-16 12:10:23.000000000 +0200
@@ -80,6 +80,7 @@ static void tmu_set_mode(enum clock_even
 		break;
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
 		break;
 	}
 }
Index: linux-2.6.22-rc4-mm/arch/sparc64/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/sparc64/kernel/time.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sparc64/kernel/time.c	2007-06-16 12:10:23.000000000 +0200
@@ -938,6 +938,7 @@ static void sparc64_timer_setup(enum clo
 {
 	switch (mode) {
 	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_RESUME:
 		break;
 
 	case CLOCK_EVT_MODE_SHUTDOWN:

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 07/25] Tick management: spread timer interrupt
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (5 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 06/25] clockevents: Fix resume logic Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 08/25] i386: PIT stop only, when in periodic or oneshot mode Thomas Gleixner
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz

[-- Attachment #1: tick-spread-timer-interrupts.patch --]
[-- Type: text/plain, Size: 1574 bytes --]

From: john stultz <johnstul@us.ibm.com>

After discussing w/ Thomas over IRC, it seems the issue is the sched
tick fires on every cpu at the same time, causing extra lock contention.

This smaller change, adds an extra offset per cpu so the ticks don't
line up. This patch also drops the idle latency from 40us down to under
20us.

Signed-off-by: john stultz <johnstul@us.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/tick-sched.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/kernel/time/tick-sched.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/tick-sched.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-sched.c	2007-06-16 12:10:23.000000000 +0200
@@ -573,6 +573,7 @@ void tick_setup_sched_timer(void)
 {
 	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 	ktime_t now = ktime_get();
+	u64 offset;
 
 	/*
 	 * Emulate tick processing via per-CPU hrtimers:
@@ -581,8 +582,12 @@ void tick_setup_sched_timer(void)
 	ts->sched_timer.function = tick_sched_timer;
 	ts->sched_timer.cb_mode = HRTIMER_CB_IRQSAFE_NO_SOFTIRQ;
 
-	/* Get the next period */
+	/* Get the next period (per cpu)*/
 	ts->sched_timer.expires = tick_init_jiffy_update();
+	offset = ktime_to_ns(tick_period) >> 1;
+	do_div(offset, NR_CPUS);
+	offset *= smp_processor_id();
+	ts->sched_timer.expires = ktime_add_ns(ts->sched_timer.expires, offset);
 
 	for (;;) {
 		hrtimer_forward(&ts->sched_timer, now, tick_period);

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 08/25] i386: PIT stop only, when in periodic or oneshot mode
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (6 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 07/25] Tick management: spread timer interrupt Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 09/25] clockevents: Fix device replacement Thomas Gleixner
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: i386-add-another-pit-quirk.patch --]
[-- Type: text/plain, Size: 1004 bytes --]

The patch is necessary on one of my boxen, where programming the stop
sequence twice leads to PIT malfunction.

Sigh !

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/i386/kernel/i8253.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/i8253.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-16 12:10:23.000000000 +0200
@@ -48,9 +48,12 @@ static void init_pit_timer(enum clock_ev
 
 	case CLOCK_EVT_MODE_SHUTDOWN:
 	case CLOCK_EVT_MODE_UNUSED:
-		outb_p(0x30, PIT_MODE);
-		outb_p(0, PIT_CH0);	/* LSB */
-		outb_p(0, PIT_CH0);	/* MSB */
+		if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
+		    evt->mode == CLOCK_EVT_MODE_ONESHOT) {
+			outb_p(0x30, PIT_MODE);
+			outb_p(0, PIT_CH0);
+			outb_p(0, PIT_CH0);
+		}
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 09/25] clockevents: Fix device replacement
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (7 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 08/25] i386: PIT stop only, when in periodic or oneshot mode Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 10/25] highres: Improve debug output Thomas Gleixner
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: clockevents-broadcast-fix-device-replacement.patch --]
[-- Type: text/plain, Size: 2022 bytes --]

When a device is replaced by a better rated device, then the broadcast
mode needs to be evaluated again. When the new device has no requirement
for broadcasting, then the broadcast bits for the CPU must be cleared.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/tick-broadcast.c |   29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/kernel/time/tick-broadcast.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/tick-broadcast.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-broadcast.c	2007-06-16 12:10:23.000000000 +0200
@@ -31,6 +31,12 @@ struct tick_device tick_broadcast_device
 static cpumask_t tick_broadcast_mask;
 static DEFINE_SPINLOCK(tick_broadcast_lock);
 
+#ifdef CONFIG_TICK_ONESHOT
+static void tick_broadcast_clear_oneshot(int cpu);
+#else
+static inline void tick_broadcast_clear_oneshot(int cpu) { }
+#endif
+
 /*
  * Debugging: see timer_list.c
  */
@@ -99,8 +105,19 @@ int tick_device_uses_broadcast(struct cl
 		cpu_set(cpu, tick_broadcast_mask);
 		tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
 		ret = 1;
-	}
+	} else {
+		/*
+		 * When the new device is not affected by the stop
+		 * feature and the cpu is marked in the broadcast mask
+		 * then clear the broadcast bit.
+		 */
+		if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
+			int cpu = smp_processor_id();
 
+			cpu_clear(cpu, tick_broadcast_mask);
+			tick_broadcast_clear_oneshot(cpu);
+		}
+	}
 	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 	return ret;
 }
@@ -487,6 +504,16 @@ out:
 	spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
+/*
+ * Reset the one shot broadcast for a cpu
+ *
+ * Called with tick_broadcast_lock held
+ */
+static void tick_broadcast_clear_oneshot(int cpu)
+{
+	cpu_clear(cpu, tick_broadcast_oneshot_mask);
+}
+
 /**
  * tick_broadcast_setup_highres - setup the broadcast device for highres
  */

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 10/25] highres: Improve debug output
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (8 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 09/25] clockevents: Fix device replacement Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 11/25] hrtimer: speedup hrtimer_enqueue Thomas Gleixner
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: highres-improve-debug-output.patch --]
[-- Type: text/plain, Size: 2879 bytes --]

From: Ingo Molnar <mingo@elte.hu>

Add some more debug information to the hrtimer and clock events code.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/i386/kernel/apic.c    |    3 +++
 kernel/hrtimer.c           |    5 ++++-
 kernel/time/tick-oneshot.c |   15 ++++++++++++++-
 3 files changed, 21 insertions(+), 2 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/apic.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c	2007-06-16 12:10:23.000000000 +0200
@@ -524,6 +524,9 @@ void __init setup_boot_APIC_clock(void)
 		 */
 		if (nmi_watchdog != NMI_IO_APIC)
 			lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+		else
+			printk(KERN_WARNING "APIC timer registered as dummy,"
+			       " due to nmi_watchdog=1!\n");
 	}
 
 	/* Setup the lapic or request the broadcast */
Index: linux-2.6.22-rc4-mm/kernel/hrtimer.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/hrtimer.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/hrtimer.c	2007-06-16 12:10:23.000000000 +0200
@@ -558,7 +558,8 @@ static inline int hrtimer_enqueue_reprog
  */
 static int hrtimer_switch_to_hres(void)
 {
-	struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases);
+	int cpu = smp_processor_id();
+	struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu);
 	unsigned long flags;
 
 	if (base->hres_active)
@@ -568,6 +569,8 @@ static int hrtimer_switch_to_hres(void)
 
 	if (tick_init_highres()) {
 		local_irq_restore(flags);
+		printk(KERN_WARNING "Could not switch to high resolution "
+				    "mode on CPU %d\n", cpu);
 		return 0;
 	}
 	base->hres_active = 1;
Index: linux-2.6.22-rc4-mm/kernel/time/tick-oneshot.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/tick-oneshot.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-oneshot.c	2007-06-16 12:10:23.000000000 +0200
@@ -73,8 +73,21 @@ int tick_switch_to_oneshot(void (*handle
 	struct clock_event_device *dev = td->evtdev;
 
 	if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
-	    !tick_device_is_functional(dev))
+		    !tick_device_is_functional(dev)) {
+
+		printk(KERN_INFO "Clockevents: "
+		       "could not switch to one-shot mode:");
+		if (!dev) {
+			printk(" no tick device\n");
+		} else {
+			if (!tick_device_is_functional(dev))
+				printk(" %s is not functional.\n", dev->name);
+			else if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
+				printk(" %s does not support one-shot mode.\n",
+				       dev->name);
+		}
 		return -EINVAL;
+	}
 
 	td->mode = TICKDEV_MODE_ONESHOT;
 	dev->event_handler = handler;

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 11/25] hrtimer: speedup hrtimer_enqueue
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (9 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 10/25] highres: Improve debug output Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 12/25] pcspkr: use the global PIT lock Thomas Gleixner
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: hrtimer-speedup-enqueue.patch --]
[-- Type: text/plain, Size: 1543 bytes --]

From: Ingo Molnar <mingo@elte.hu>

Speedup hrtimer_enqueue by evaluating the rbtree insertion result.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/hrtimer.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

Index: linux-2.6.22-rc4-mm/kernel/hrtimer.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/hrtimer.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/hrtimer.c	2007-06-16 12:10:23.000000000 +0200
@@ -686,6 +686,7 @@ static void enqueue_hrtimer(struct hrtim
 	struct rb_node **link = &base->active.rb_node;
 	struct rb_node *parent = NULL;
 	struct hrtimer *entry;
+	int leftmost = 1;
 
 	/*
 	 * Find the right place in the rbtree:
@@ -697,18 +698,19 @@ static void enqueue_hrtimer(struct hrtim
 		 * We dont care about collisions. Nodes with
 		 * the same expiry time stay together.
 		 */
-		if (timer->expires.tv64 < entry->expires.tv64)
+		if (timer->expires.tv64 < entry->expires.tv64) {
 			link = &(*link)->rb_left;
-		else
+		} else {
 			link = &(*link)->rb_right;
+			leftmost = 0;
+		}
 	}
 
 	/*
 	 * Insert the timer to the rbtree and check whether it
 	 * replaces the first pending timer
 	 */
-	if (!base->first || timer->expires.tv64 <
-	    rb_entry(base->first, struct hrtimer, node)->expires.tv64) {
+	if (leftmost) {
 		/*
 		 * Reprogram the clock event device. When the timer is already
 		 * expired hrtimer_enqueue_reprogram has either called the

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 12/25] pcspkr: use the global PIT lock
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (10 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 11/25] hrtimer: speedup hrtimer_enqueue Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 13/25] i386: hpet assumes boot cpu is 0 Thomas Gleixner
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: pcspkr-use-the-global-pit-lock.patch --]
[-- Type: text/plain, Size: 2642 bytes --]

Replace the pcspkr private PIT lock by the global PIT lock to
serialize the PIT access all over the place.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/x86_64/kernel/time.c   |    2 ++
 drivers/input/misc/pcspkr.c |   11 ++++++++---
 include/asm-x86_64/i8253.h  |    6 ++++++
 3 files changed, 16 insertions(+), 3 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/time.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-16 12:10:23.000000000 +0200
@@ -33,6 +33,7 @@
 #include <acpi/acpi_bus.h>
 #endif
 #include <asm/8253pit.h>
+#include <asm/i8253.h>
 #include <asm/pgtable.h>
 #include <asm/vsyscall.h>
 #include <asm/timex.h>
@@ -51,6 +52,7 @@ static char *timename = NULL;
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 DEFINE_SPINLOCK(i8253_lock);
+EXPORT_SYMBOL(i8253_lock);
 
 volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
 
Index: linux-2.6.22-rc4-mm/drivers/input/misc/pcspkr.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/drivers/input/misc/pcspkr.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/input/misc/pcspkr.c	2007-06-16 12:10:23.000000000 +0200
@@ -24,7 +24,12 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@u
 MODULE_DESCRIPTION("PC Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
-static DEFINE_SPINLOCK(i8253_beep_lock);
+#ifdef CONFIG_X86
+/* Use the global PIT lock ! */
+#include <asm/i8253.h>
+#else
+static DEFINE_SPINLOCK(i8253_lock);
+#endif
 
 static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -43,7 +48,7 @@ static int pcspkr_event(struct input_dev
 	if (value > 20 && value < 32767)
 		count = PIT_TICK_RATE / value;
 
-	spin_lock_irqsave(&i8253_beep_lock, flags);
+	spin_lock_irqsave(&i8253_lock, flags);
 
 	if (count) {
 		/* enable counter 2 */
@@ -58,7 +63,7 @@ static int pcspkr_event(struct input_dev
 		outb(inb_p(0x61) & 0xFC, 0x61);
 	}
 
-	spin_unlock_irqrestore(&i8253_beep_lock, flags);
+	spin_unlock_irqrestore(&i8253_lock, flags);
 
 	return 0;
 }
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/i8253.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/i8253.h	2007-06-16 12:10:23.000000000 +0200
@@ -0,0 +1,6 @@
+#ifndef __ASM_I8253_H__
+#define __ASM_I8253_H__
+
+extern spinlock_t i8253_lock;
+
+#endif	/* __ASM_I8253_H__ */

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 13/25] i386: hpet assumes boot cpu is 0
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (11 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 12/25] pcspkr: use the global PIT lock Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 14/25] NTP: Move the cmos update code into ntp.c Thomas Gleixner
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: i386-hpet-fix-cpu0-assumption.patch --]
[-- Type: text/plain, Size: 996 bytes --]

From: Chris Wright <chrisw@sous-sol.org>

I fixed this in x86_64.  Looks like the kind of thing that will break
voyager on i386.

Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/i386/kernel/hpet.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/hpet.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-16 12:10:24.000000000 +0200
@@ -325,7 +325,7 @@ int __init hpet_enable(void)
 		 * Start hpet with the boot cpu mask and make it
 		 * global after the IO_APIC has been initialized.
 		 */
-		hpet_clockevent.cpumask =cpumask_of_cpu(0);
+		hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
 		clockevents_register_device(&hpet_clockevent);
 		global_clock_event = &hpet_clockevent;
 		return 1;

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 14/25] NTP: Move the cmos update code into ntp.c
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (12 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 13/25] i386: hpet assumes boot cpu is 0 Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-19  8:26   ` Franck Bui-Huu
  2007-06-16 10:36 ` [patch-mm 15/25] clocksource: add settimeofday hook for PPC Thomas Gleixner
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz, David Miller

[-- Attachment #1: ntp-make-cmos-update-generic.patch --]
[-- Type: text/plain, Size: 9147 bytes --]

i386 and sparc64 have the identical code to update the cmos clock.
Move it into kernel/time/ntp.c as there are other architectures
coming along with the same requirements.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: john stultz <johnstul@us.ibm.com>
Cc: David Miller <davem@davemloft.net>

---
 arch/i386/Kconfig          |    4 +++
 arch/i386/kernel/time.c    |   50 +-------------------------------------
 arch/sparc64/Kconfig       |    4 +++
 arch/sparc64/kernel/time.c |   53 +---------------------------------------
 include/asm-i386/timer.h   |    1 
 include/linux/time.h       |    2 +
 kernel/time/ntp.c          |   59 ++++++++++++++++++++++++++++++++++++++++++---
 7 files changed, 70 insertions(+), 103 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/i386/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/Kconfig	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/Kconfig	2007-06-16 12:10:24.000000000 +0200
@@ -18,6 +18,10 @@ config GENERIC_TIME
 	bool
 	default y
 
+config GENERIC_CMOS_UPDATE
+	bool
+	default y
+
 config CLOCKSOURCE_WATCHDOG
 	bool
 	default y
Index: linux-2.6.22-rc4-mm/arch/i386/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/time.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/time.c	2007-06-16 12:10:24.000000000 +0200
@@ -207,55 +207,9 @@ unsigned long read_persistent_clock(void
 	return retval;
 }
 
-static void sync_cmos_clock(unsigned long dummy);
-
-static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
-int no_sync_cmos_clock;
-
-static void sync_cmos_clock(unsigned long dummy)
-{
-	struct timeval now, next;
-	int fail = 1;
-
-	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 * This code is run on a timer.  If the clock is set, that timer
-	 * may not expire at the correct time.  Thus, we adjust...
-	 */
-	if (!ntp_synced())
-		/*
-		 * Not synced, exit, do not restart a timer (if one is
-		 * running, let it run out).
-		 */
-		return;
-
-	do_gettimeofday(&now);
-	if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
-	    now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
-		fail = set_rtc_mmss(now.tv_sec);
-
-	next.tv_usec = USEC_AFTER - now.tv_usec;
-	if (next.tv_usec <= 0)
-		next.tv_usec += USEC_PER_SEC;
-
-	if (!fail)
-		next.tv_sec = 659;
-	else
-		next.tv_sec = 0;
-
-	if (next.tv_usec >= USEC_PER_SEC) {
-		next.tv_sec++;
-		next.tv_usec -= USEC_PER_SEC;
-	}
-	mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
-}
-
-void notify_arch_cmos_timer(void)
+int update_persistent_clock(struct timespec now)
 {
-	if (!no_sync_cmos_clock)
-		mod_timer(&sync_cmos_timer, jiffies + 1);
+	return set_rtc_mmss(now.tv_sec);
 }
 
 extern void (*late_time_init)(void);
Index: linux-2.6.22-rc4-mm/arch/sparc64/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/sparc64/kernel/time.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sparc64/kernel/time.c	2007-06-16 12:10:24.000000000 +0200
@@ -403,58 +403,9 @@ static struct sparc64_tick_ops hbtick_op
 
 static unsigned long timer_ticks_per_nsec_quotient __read_mostly;
 
-#define TICK_SIZE (tick_nsec / 1000)
-
-#define USEC_AFTER	500000
-#define USEC_BEFORE	500000
-
-static void sync_cmos_clock(unsigned long dummy);
-
-static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
-
-static void sync_cmos_clock(unsigned long dummy)
-{
-	struct timeval now, next;
-	int fail = 1;
-
-	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
-	 * This code is run on a timer.  If the clock is set, that timer
-	 * may not expire at the correct time.  Thus, we adjust...
-	 */
-	if (!ntp_synced())
-		/*
-		 * Not synced, exit, do not restart a timer (if one is
-		 * running, let it run out).
-		 */
-		return;
-
-	do_gettimeofday(&now);
-	if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
-	    now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
-		fail = set_rtc_mmss(now.tv_sec);
-
-	next.tv_usec = USEC_AFTER - now.tv_usec;
-	if (next.tv_usec <= 0)
-		next.tv_usec += USEC_PER_SEC;
-
-	if (!fail)
-		next.tv_sec = 659;
-	else
-		next.tv_sec = 0;
-
-	if (next.tv_usec >= USEC_PER_SEC) {
-		next.tv_sec++;
-		next.tv_usec -= USEC_PER_SEC;
-	}
-	mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
-}
-
-void notify_arch_cmos_timer(void)
+int update_persistent_clock(struct timespec now)
 {
-	mod_timer(&sync_cmos_timer, jiffies + 1);
+	return set_rtc_mmss(now.tv_sec);
 }
 
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
Index: linux-2.6.22-rc4-mm/include/linux/time.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/linux/time.h	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/time.h	2007-06-16 12:10:24.000000000 +0200
@@ -93,6 +93,8 @@ extern struct timespec wall_to_monotonic
 extern seqlock_t xtime_lock __attribute__((weak));
 
 extern unsigned long read_persistent_clock(void);
+extern int update_persistent_clock(struct timespec now);
+extern int no_sync_cmos_clock __read_mostly;
 void timekeeping_init(void);
 
 static inline unsigned long get_seconds(void)
Index: linux-2.6.22-rc4-mm/kernel/time/ntp.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/ntp.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/ntp.c	2007-06-16 12:10:24.000000000 +0200
@@ -10,6 +10,7 @@
 
 #include <linux/mm.h>
 #include <linux/time.h>
+#include <linux/timer.h>
 #include <linux/timex.h>
 #include <linux/jiffies.h>
 #include <linux/hrtimer.h>
@@ -187,12 +188,64 @@ u64 current_tick_length(void)
 	return tick_length;
 }
 
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
 
-void __attribute__ ((weak)) notify_arch_cmos_timer(void)
+/* Disable the cmos update - used by virtualization and embedded */
+int no_sync_cmos_clock  __read_mostly;
+
+static void sync_cmos_clock(unsigned long dummy);
+
+static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
+
+static void sync_cmos_clock(unsigned long dummy)
 {
-	return;
+	struct timespec now, next;
+	int fail = 1;
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 * This code is run on a timer.  If the clock is set, that timer
+	 * may not expire at the correct time.  Thus, we adjust...
+	 */
+	if (!ntp_synced())
+		/*
+		 * Not synced, exit, do not restart a timer (if one is
+		 * running, let it run out).
+		 */
+		return;
+
+	getnstimeofday(&now);
+	if (abs(xtime.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2)
+		fail = update_persistent_clock(now);
+
+	next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec;
+	if (next.tv_nsec <= 0)
+		next.tv_nsec += NSEC_PER_SEC;
+
+	if (!fail)
+		next.tv_sec = 659;
+	else
+		next.tv_sec = 0;
+
+	if (next.tv_nsec >= NSEC_PER_SEC) {
+		next.tv_sec++;
+		next.tv_nsec -= NSEC_PER_SEC;
+	}
+	mod_timer(&sync_cmos_timer, jiffies + timespec_to_jiffies(&next));
 }
 
+static void notify_cmos_timer(void)
+{
+	if (no_sync_cmos_clock)
+		mod_timer(&sync_cmos_timer, jiffies + 1);
+}
+
+#else
+static inline void notify_cmos_timer(void) { }
+#endif
+
 /* adjtimex mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
@@ -357,6 +410,6 @@ leave:	if ((time_status & (STA_UNSYNC|ST
 	txc->stbcnt	   = 0;
 	write_sequnlock_irq(&xtime_lock);
 	do_gettimeofday(&txc->time);
-	notify_arch_cmos_timer();
+	notify_cmos_timer();
 	return(result);
 }
Index: linux-2.6.22-rc4-mm/arch/sparc64/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/sparc64/Kconfig	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sparc64/Kconfig	2007-06-16 12:10:24.000000000 +0200
@@ -23,6 +23,10 @@ config GENERIC_TIME
 	bool
 	default y
 
+config GENERIC_CMOS_UPDATE
+	bool
+	default y
+
 config GENERIC_CLOCKEVENTS
 	bool
 	default y
Index: linux-2.6.22-rc4-mm/include/asm-i386/timer.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/timer.h	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/timer.h	2007-06-16 12:10:24.000000000 +0200
@@ -12,7 +12,6 @@ unsigned long native_calculate_cpu_khz(v
 
 extern int timer_ack;
 extern int no_timer_check;
-extern int no_sync_cmos_clock;
 extern int recalibrate_cpu_khz(void);
 
 #ifndef CONFIG_PARAVIRT

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 15/25] clocksource: add settimeofday hook for PPC
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (13 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 14/25] NTP: Move the cmos update code into ntp.c Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 15:51   ` Daniel Walker
  2007-06-16 10:36 ` [patch-mm 16/25] x86_64: untangle asm/hpet.h from asm/timex.h Thomas Gleixner
                   ` (12 subsequent siblings)
  27 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Tony Breeds, john stultz

[-- Attachment #1: clocksource-add-settimeofday-hook.patch --]
[-- Type: text/plain, Size: 2260 bytes --]

From: Tony Breeds <tony@bakeyournoodle.com >

I'm working on a clocksource implementation for all powerpc platforms.
some of these platforms needs to do a little work as part of the
settimeofday() syscall and I can't see a way to do that without adding
this hook to clocksource.

From: Tony Breeds <tony@bakeyournoodle.com>

Add per clocksource hook to settimeofday().

Some clocksources need to do extra work as part of the settimeofday call, this
hook make it easy to do so.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>

---

 include/linux/clocksource.h |    3 +++
 kernel/time/timekeeping.c   |    3 +++
 2 files changed, 6 insertions(+)

Index: linux-2.6.22-rc4-mm/include/linux/clocksource.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/linux/clocksource.h	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/clocksource.h	2007-06-16 12:10:24.000000000 +0200
@@ -50,6 +50,7 @@ struct clocksource;
  * @flags:		flags describing special properties
  * @vread:		vsyscall based read
  * @resume:		resume function for the clocksource, if necessary
+ * @settimeofday:	[Optional] Do arch specific work during do_settimeofday
  * @cycle_interval:	Used internally by timekeeping core, please ignore.
  * @xtime_interval:	Used internally by timekeeping core, please ignore.
  */
@@ -68,6 +69,8 @@ struct clocksource {
 	cycle_t (*vread)(void);
 	void (*resume)(void);
 
+	void (*settimeofday)(struct clocksource *cs, struct timespec *ts);
+
 	/* timekeeping specific data, ignore */
 	cycle_t cycle_interval;
 	u64	xtime_interval;
Index: linux-2.6.22-rc4-mm/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/time/timekeeping.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/timekeeping.c	2007-06-16 12:10:24.000000000 +0200
@@ -159,6 +159,9 @@ int do_settimeofday(struct timespec *tv)
 	clock->error = 0;
 	ntp_clear();
 
+	if (clock->settimeofday)
+		clock->settimeofday(clock, tv);
+
 	update_vsyscall(&xtime, clock);
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 16/25] x86_64: untangle asm/hpet.h from asm/timex.h
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (14 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 15/25] clocksource: add settimeofday hook for PPC Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 17/25] x86_64: Use generic cmos update Thomas Gleixner
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz

[-- Attachment #1: x86-64-untangle-hpet-headers.patch --]
[-- Type: text/plain, Size: 2741 bytes --]

From:	Chris Wright <chrisw@sous-sol.org>

When making changes to x86_64 timers, I noticed that touching
hpet.h triggered an unreasonably large rebuild.  Untangling
it from timex.h quiets the extra rebuild quite a bit.

Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Andi Kleen <ak@suse.de>

---
 drivers/char/rtc.c         |    2 +-
 include/asm-x86_64/apic.h  |    2 ++
 include/asm-x86_64/hpet.h  |    1 -
 include/asm-x86_64/timex.h |    1 -
 4 files changed, 3 insertions(+), 3 deletions(-)

Index: linux-2.6.22-rc4-mm/drivers/char/rtc.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/drivers/char/rtc.c	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/char/rtc.c	2007-06-16 12:10:24.000000000 +0200
@@ -82,7 +82,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#if defined(__i386__)
+#if defined(__i386__) || defined(__x86_64__)
 #include <asm/hpet.h>
 #endif
 
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/timex.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/timex.h	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/timex.h	2007-06-16 12:10:24.000000000 +0200
@@ -9,7 +9,6 @@
 #include <asm/8253pit.h>
 #include <asm/msr.h>
 #include <asm/vsyscall.h>
-#include <asm/hpet.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/tsc.h>
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/apic.h	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h	2007-06-16 12:10:24.000000000 +0200
@@ -86,6 +86,8 @@ extern void setup_apic_routing(void);
 extern void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
 				   unsigned char msg_type, unsigned char mask);
 
+extern int apic_is_clustered_box(void);
+
 #define K8_APIC_EXT_LVT_BASE    0x500
 #define K8_APIC_EXT_INT_MSG_FIX 0x0
 #define K8_APIC_EXT_INT_MSG_SMI 0x2
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/hpet.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/hpet.h	2007-06-16 12:10:21.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/hpet.h	2007-06-16 12:10:24.000000000 +0200
@@ -55,7 +55,6 @@
 
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
-extern int apic_is_clustered_box(void);
 extern int hpet_arch_init(void);
 extern int hpet_timer_stop_set_go(unsigned long tick);
 extern int hpet_reenable(void);

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 17/25] x86_64: Use generic cmos update
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (15 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 16/25] x86_64: untangle asm/hpet.h from asm/timex.h Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 18/25] i386: move setup_pit_timer to the correct header file Thomas Gleixner
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz

[-- Attachment #1: x86-64-use-generic-cmos-update.patch --]
[-- Type: text/plain, Size: 2897 bytes --]

Use the generic cmos update function in kernel/time/ntp.c

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Andi Kleen <ak@suse.de>

---
 arch/x86_64/Kconfig       |    4 ++++
 arch/x86_64/kernel/time.c |   25 +++++++++----------------
 2 files changed, 13 insertions(+), 16 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/time.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-16 12:10:24.000000000 +0200
@@ -82,8 +82,9 @@ EXPORT_SYMBOL(profile_pc);
  * sheet for details.
  */
 
-static void set_rtc_mmss(unsigned long nowtime)
+static int set_rtc_mmss(unsigned long nowtime)
 {
+	int retval = 0;
 	int real_seconds, real_minutes, cmos_minutes;
 	unsigned char control, freq_select;
 
@@ -123,6 +124,7 @@ static void set_rtc_mmss(unsigned long n
 	if (abs(real_minutes - cmos_minutes) >= 30) {
 		printk(KERN_WARNING "time.c: can't update CMOS clock "
 		       "from %d to %d\n", cmos_minutes, real_minutes);
+		retval = -1;
 	} else {
 		BIN_TO_BCD(real_seconds);
 		BIN_TO_BCD(real_minutes);
@@ -142,12 +144,17 @@ static void set_rtc_mmss(unsigned long n
 	CMOS_WRITE(freq_select, RTC_FREQ_SELECT);
 
 	spin_unlock(&rtc_lock);
+
+	return retval;
 }
 
+int update_persistent_clock(struct timespec now)
+{
+	return set_rtc_mmss(now.tv_sec);
+}
 
 void main_timer_handler(void)
 {
-	static unsigned long rtc_update = 0;
 /*
  * Here we are in the timer irq handler. We have irqs locally disabled (so we
  * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
@@ -175,20 +182,6 @@ void main_timer_handler(void)
 	if (!using_apic_timer)
 		smp_local_timer_interrupt();
 
-/*
- * If we have an externally synchronized Linux clock, then update CMOS clock
- * accordingly every ~11 minutes. set_rtc_mmss() will be called in the jiffy
- * closest to exactly 500 ms before the next second. If the update fails, we
- * don't care, as it'll be updated on the next turn, and the problem (time way
- * off) isn't likely to go away much sooner anyway.
- */
-
-	if (ntp_synced() && xtime.tv_sec > rtc_update &&
-		abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2) {
-		set_rtc_mmss(xtime.tv_sec);
-		rtc_update = xtime.tv_sec + 660;
-	}
- 
 	write_sequnlock(&xtime_lock);
 }
 
Index: linux-2.6.22-rc4-mm/arch/x86_64/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/Kconfig	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/Kconfig	2007-06-16 12:10:24.000000000 +0200
@@ -32,6 +32,10 @@ config GENERIC_TIME_VSYSCALL
 	bool
 	default y
 
+config GENERIC_CMOS_UPDATE
+	bool
+	default y
+
 config ZONE_DMA32
 	bool
 	default y

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 18/25] i386: move setup_pit_timer to the correct header file
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (16 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 17/25] x86_64: Use generic cmos update Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 19/25] x86-64: remove dead code and other janitor work in tsc.c Thomas Gleixner
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: i386-move-pit-setup-to-i8253-h.patch --]
[-- Type: text/plain, Size: 1292 bytes --]

setup_pit_timer is declared in asm-i386/timer.h. Move it to the
pit header file, so it can be used by x86_64 as well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andi Kleen <ak@suse.de>

---
 include/asm-i386/i8253.h |    2 ++
 include/asm-i386/timer.h |    1 -
 2 files changed, 2 insertions(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/include/asm-i386/i8253.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/i8253.h	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/i8253.h	2007-06-16 12:10:24.000000000 +0200
@@ -18,4 +18,6 @@ static inline void pit_interrupt_hook(vo
 	global_clock_event->event_handler(global_clock_event);
 }
 
+extern void setup_pit_timer(void);
+
 #endif	/* __ASM_I8253_H__ */
Index: linux-2.6.22-rc4-mm/include/asm-i386/timer.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/timer.h	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/timer.h	2007-06-16 12:10:24.000000000 +0200
@@ -6,7 +6,6 @@
 
 #define TICK_SIZE (tick_nsec / 1000)
 
-void setup_pit_timer(void);
 unsigned long long native_sched_clock(void);
 unsigned long native_calculate_cpu_khz(void);
 

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 19/25] x86-64: remove dead code and other janitor work in tsc.c
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (17 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 18/25] i386: move setup_pit_timer to the correct header file Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 20/25] x86_64: Convert to cleckevents Thomas Gleixner
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz

[-- Attachment #1: x86-64-remove-dead-code-tsc-c.patch --]
[-- Type: text/plain, Size: 2816 bytes --]

Remove unused code and variables and do some codingstyle / whitespace
cleanups while at it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Andi Kleen <ak@suse.de>

---
 arch/x86_64/kernel/tsc.c |   41 +++++++++++------------------------------
 1 file changed, 11 insertions(+), 30 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/tsc.c	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/tsc.c	2007-06-16 12:10:24.000000000 +0200
@@ -35,25 +35,9 @@ static inline int check_tsc_unstable(voi
  * first tick after the change will be slightly wrong.
  */
 
-#include <linux/workqueue.h>
-
-static unsigned int cpufreq_delayed_issched = 0;
-static unsigned int cpufreq_init = 0;
-static struct work_struct cpufreq_delayed_get_work;
-
-static void handle_cpufreq_delayed_get(struct work_struct *v)
-{
-	unsigned int cpu;
-	for_each_online_cpu(cpu) {
-		cpufreq_get(cpu);
-	}
-	cpufreq_delayed_issched = 0;
-}
-
-static unsigned int  ref_freq = 0;
-static unsigned long loops_per_jiffy_ref = 0;
-
-static unsigned long tsc_khz_ref = 0;
+static unsigned int  ref_freq;
+static unsigned long loops_per_jiffy_ref;
+static unsigned long tsc_khz_ref;
 
 static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 				 void *data)
@@ -97,10 +81,8 @@ static struct notifier_block time_cpufre
 
 static int __init cpufreq_tsc(void)
 {
-	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get);
-	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
-				       CPUFREQ_TRANSITION_NOTIFIER))
-		cpufreq_init = 1;
+	cpufreq_register_notifier(&time_cpufreq_notifier_block,
+				  CPUFREQ_TRANSITION_NOTIFIER);
 	return 0;
 }
 
@@ -108,8 +90,6 @@ core_initcall(cpufreq_tsc);
 
 #endif
 
-static int tsc_unstable = 0;
-
 /*
  * Make an educated guess if the TSC is trustworthy and synchronized
  * over all CPUs.
@@ -122,17 +102,18 @@ __cpuinit int unsynchronized_tsc(void)
 #endif
 	/* Most intel systems have synchronized TSCs except for
 	   multi node systems */
- 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
 #ifdef CONFIG_ACPI
 		/* But TSC doesn't tick in C3 so don't use it there */
-		if (acpi_gbl_FADT.header.length > 0 && acpi_gbl_FADT.C3latency < 1000)
+		if (acpi_gbl_FADT.header.length > 0 &&
+		    acpi_gbl_FADT.C3latency < 1000)
 			return 1;
 #endif
- 		return 0;
+		return 0;
 	}
 
- 	/* Assume multi socket systems are not synchronized */
- 	return num_present_cpus() > 1;
+	/* Assume multi socket systems are not synchronized */
+	return num_present_cpus() > 1;
 }
 
 int __init notsc_setup(char *s)

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 20/25] x86_64: Convert to cleckevents
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (18 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 19/25] x86-64: remove dead code and other janitor work in tsc.c Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 21/25] x86_64: hpet restore vread Thomas Gleixner
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: x86-64-convert-to-clockevents.patch --]
[-- Type: text/plain, Size: 70183 bytes --]

Convert x86_64 to the clockevents code. Share code with i386 for
hpet and PIT.

Build and whitespace fixups from:
 Venki Pallipadi <venkatesh.pallipadi@intel.com>
and
 Chris Wright <chrisw@sous-sol.org>

Based on an initial patch from Chris Wright <chrisw@sous-sol.org>

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Andi Kleen <ak@suse.de>

---
 arch/i386/kernel/hpet.c                  |   50 ++
 arch/i386/kernel/i8253.c                 |    5 
 arch/x86_64/Kconfig                      |   12 
 arch/x86_64/kernel/Makefile              |    4 
 arch/x86_64/kernel/apic.c                |  567 +++++++++++++++++--------------
 arch/x86_64/kernel/hpet.c                |  493 --------------------------
 arch/x86_64/kernel/i8259.c               |   47 --
 arch/x86_64/kernel/mce_amd.c             |    6 
 arch/x86_64/kernel/smpboot.c             |    4 
 arch/x86_64/kernel/time.c                |  253 +------------
 arch/x86_64/kernel/tsc.c                 |   90 ++++
 drivers/acpi/processor_idle.c            |   12 
 include/asm-i386/hpet.h                  |  125 ++----
 include/asm-i386/i8253.h                 |    5 
 include/asm-i386/mach-default/io_ports.h |    5 
 include/asm-i386/tsc.h                   |    4 
 include/asm-x86_64/apic.h                |   10 
 include/asm-x86_64/hpet.h                |   77 ----
 include/asm-x86_64/i8253.h               |    8 
 include/asm-x86_64/proto.h               |    3 
 20 files changed, 569 insertions(+), 1211 deletions(-)

Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/apic.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/apic.c	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/apic.c	2007-06-16 12:10:24.000000000 +0200
@@ -25,6 +25,8 @@
 #include <linux/sysdev.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
+#include <linux/clockchips.h>
+#include <linux/acpi_pmtmr.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -38,10 +40,10 @@
 #include <asm/timex.h>
 #include <asm/hpet.h>
 #include <asm/apic.h>
+#include <asm/i8253.h>
 
 int apic_mapped;
 int apic_verbosity;
-int apic_runs_main_timer;
 int apic_calibrate_pmtmr __initdata;
 
 int disable_apic_timer __initdata;
@@ -50,20 +52,36 @@ int disable_apic_timer __initdata;
 int local_apic_timer_c2_ok;
 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
 
+/* Local APIC timer verification ok */
+static int local_apic_timer_verify_ok;
+
 static struct resource *ioapic_resources;
 static struct resource lapic_resource = {
 	.name = "Local APIC",
 	.flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-/*
- * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
- * IPIs in place of local APIC timers
- */
-static cpumask_t timer_interrupt_broadcast_ipi_mask;
+static unsigned int calibration_result;
 
-/* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer __read_mostly = 0;
+static int lapic_next_event(unsigned long delta,
+			    struct clock_event_device *evt);
+static void lapic_timer_setup(enum clock_event_mode mode,
+			      struct clock_event_device *evt);
+
+static void lapic_timer_broadcast(cpumask_t mask);
+
+static struct clock_event_device lapic_clockevent = {
+	.name		= "lapic",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
+			| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
+	.shift		= 32,
+	.set_mode	= lapic_timer_setup,
+	.set_next_event	= lapic_next_event,
+	.broadcast	= lapic_timer_broadcast,
+	.rating		= 100,
+	.irq		= -1,
+};
+static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
 
 static void apic_pm_activate(void);
 
@@ -92,8 +110,9 @@ unsigned int safe_apic_wait_icr_idle(voi
 void enable_NMI_through_LVT0 (void * dummy)
 {
 	unsigned int v;
-	
-	v = APIC_DM_NMI;                        /* unmask and set to NMI */
+
+	/* unmask and set to NMI */
+	v = APIC_DM_NMI;
 	apic_write(APIC_LVT0, v);
 }
 
@@ -120,7 +139,7 @@ void ack_bad_irq(unsigned int irq)
 	 * holds up an irq slot - in excessive cases (when multiple
 	 * unexpected vectors occur) that might lock up the APIC
 	 * completely.
-  	 * But don't ack when the APIC is disabled. -AK
+	 * But don't ack when the APIC is disabled. -AK
 	 */
 	if (!disable_apic)
 		ack_APIC_irq();
@@ -616,7 +635,7 @@ early_param("apic", apic_set_verbosity);
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
  * On AMD64 we trust the BIOS - if it says no APIC it is likely
- * not correctly set up (usually the APIC timer won't work etc.) 
+ * not correctly set up (usually the APIC timer won't work etc.)
  */
 
 static int __init detect_init_APIC (void)
@@ -759,14 +778,14 @@ void __init init_apic_mappings(void)
 
 #define APIC_DIVISOR 16
 
-static void __setup_APIC_LVTT(unsigned int clocks)
+static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 {
 	unsigned int lvtt_value, tmp_value;
-	int cpu = smp_processor_id();
-
-	lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
 
-	if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask))
+	lvtt_value = LOCAL_TIMER_VECTOR;
+	if (!oneshot)
+		lvtt_value |= APIC_LVT_TIMER_PERIODIC;
+	if (!irqen)
 		lvtt_value |= APIC_LVT_MASKED;
 
 	apic_write(APIC_LVTT, lvtt_value);
@@ -779,227 +798,313 @@ static void __setup_APIC_LVTT(unsigned i
 				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
 				| APIC_TDR_DIV_16);
 
-	apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
+	if (!oneshot)
+		apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
 }
 
-static void setup_APIC_timer(unsigned int clocks)
+static int lapic_next_event(unsigned long delta,
+			    struct clock_event_device *evt)
+{
+	apic_write(APIC_TMICT, delta);
+	return 0;
+}
+
+static void lapic_timer_setup(enum clock_event_mode mode,
+			      struct clock_event_device *evt)
 {
 	unsigned long flags;
+	unsigned int v;
+
+	/* Lapic used for broadcast ? */
+	if (!local_apic_timer_verify_ok)
+		return;
 
 	local_irq_save(flags);
 
-	/* wait for irq slice */
- 	if (hpet_address && hpet_use_timer) {
- 		int trigger = hpet_readl(HPET_T0_CMP);
- 		while (hpet_readl(HPET_COUNTER) >= trigger)
- 			/* do nothing */ ;
- 		while (hpet_readl(HPET_COUNTER) <  trigger)
- 			/* do nothing */ ;
- 	} else {
-		int c1, c2;
-		outb_p(0x00, 0x43);
-		c2 = inb_p(0x40);
-		c2 |= inb_p(0x40) << 8;
-		do {
-			c1 = c2;
-			outb_p(0x00, 0x43);
-			c2 = inb_p(0x40);
-			c2 |= inb_p(0x40) << 8;
-		} while (c2 - c1 < 300);
-	}
-	__setup_APIC_LVTT(clocks);
-	/* Turn off PIT interrupt if we use APIC timer as main timer.
-	   Only works with the PM timer right now
-	   TBD fix it for HPET too. */
-	if ((pmtmr_ioport != 0) &&
-		smp_processor_id() == boot_cpu_id &&
-		apic_runs_main_timer == 1 &&
-		!cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) {
-		stop_timer_interrupt();
-		apic_runs_main_timer++;
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+	case CLOCK_EVT_MODE_ONESHOT:
+		__setup_APIC_LVTT(calibration_result,
+				  mode != CLOCK_EVT_MODE_PERIODIC, 1);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		v = apic_read(APIC_LVTT);
+		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+		apic_write(APIC_LVTT, v);
+		break;
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here */
+		break;
 	}
+
 	local_irq_restore(flags);
 }
 
 /*
- * In this function we calibrate APIC bus clocks to the external
- * timer. Unfortunately we cannot use jiffies and the timer irq
- * to calibrate, since some later bootup code depends on getting
- * the first irq? Ugh.
- *
- * 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.
- * And we want to have irqs off anyways, no accidental
- * APIC irq that way.
+ * Local APIC timer broadcast function
  */
-
-#define TICK_COUNT 100000000
-
-static int __init calibrate_APIC_clock(void)
+static void lapic_timer_broadcast(cpumask_t mask)
 {
-	unsigned apic, apic_start;
-	unsigned long tsc, tsc_start;
-	int result;
-	/*
-	 * Put whatever arbitrary (but long enough) timeout
-	 * value into the APIC clock, we just want to get the
-	 * counter running for calibration.
-	 */
-	__setup_APIC_LVTT(4000000000);
-
-	apic_start = apic_read(APIC_TMCCT);
-#ifdef CONFIG_X86_PM_TIMER
-	if (apic_calibrate_pmtmr && pmtmr_ioport) {
-		pmtimer_wait(5000);  /* 5ms wait */
-		apic = apic_read(APIC_TMCCT);
-		result = (apic_start - apic) * 1000L / 5;
-	} else
+#ifdef CONFIG_SMP
+	send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
 #endif
-	{
-		rdtscll(tsc_start);
+}
 
-		do {
-			apic = apic_read(APIC_TMCCT);
-			rdtscll(tsc);
-		} while ((tsc - tsc_start) < TICK_COUNT &&
-				(apic_start - apic) < TICK_COUNT);
+static void __devinit setup_APIC_timer(void)
+{
+	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 
-		result = (apic_start - apic) * 1000L * tsc_khz /
-					(tsc - tsc_start);
-	}
-	printk("result %d\n", result);
+	memcpy(levt, &lapic_clockevent, sizeof(*levt));
+	levt->cpumask = cpumask_of_cpu(smp_processor_id());
+
+	clockevents_register_device(levt);
+}
+
+/*
+ * In this functions we calibrate APIC bus clocks to the external timer.
+ *
+ * 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.
+ *
+ * This was previously done by reading the PIT/HPET and waiting for a wrap
+ * around to find out, that a tick has elapsed. I have a box, where the PIT
+ * readout is broken, so it never gets out of the wait loop again. This was
+ * also reported by others.
+ *
+ * Monitoring the jiffies value is inaccurate and the clockevents
+ * infrastructure allows us to do a simple substitution of the interrupt
+ * handler.
+ *
+ * The calibration routine also uses the pm_timer when possible, as the PIT
+ * happens to run way too slow (factor 2.3 on my VAIO CoreDuo, which goes
+ * back to normal later in the boot process).
+ */
 
+#define LAPIC_CAL_LOOPS		(HZ/10)
 
-	printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
-		result / 1000 / 1000, result / 1000 % 1000);
+static __initdata volatile int lapic_cal_loops = -1;
+static __initdata long lapic_cal_t1, lapic_cal_t2;
+static __initdata unsigned long long lapic_cal_tsc1, lapic_cal_tsc2;
+static __initdata unsigned long lapic_cal_pm1, lapic_cal_pm2;
+static __initdata unsigned long lapic_cal_j1, lapic_cal_j2;
 
-	return result * APIC_DIVISOR / HZ;
+/*
+ * Temporary interrupt handler.
+ */
+static void __init lapic_cal_handler(struct clock_event_device *dev)
+{
+	unsigned long long tsc = 0;
+	long tapic = apic_read(APIC_TMCCT);
+	unsigned long pm = acpi_pm_read_early();
+
+	if (cpu_has_tsc)
+		rdtscll(tsc);
+
+	switch (lapic_cal_loops++) {
+	case 0:
+		lapic_cal_t1 = tapic;
+		lapic_cal_tsc1 = tsc;
+		lapic_cal_pm1 = pm;
+		lapic_cal_j1 = jiffies;
+		break;
+
+	case LAPIC_CAL_LOOPS:
+		lapic_cal_t2 = tapic;
+		lapic_cal_tsc2 = tsc;
+		if (pm < lapic_cal_pm1)
+			pm += ACPI_PM_OVRRUN;
+		lapic_cal_pm2 = pm;
+		lapic_cal_j2 = jiffies;
+		break;
+	}
 }
 
-static unsigned int calibration_result;
-
 void __init setup_boot_APIC_clock (void)
 {
-	if (disable_apic_timer) { 
-		printk(KERN_INFO "Disabling APIC timer\n"); 
-		return; 
-	} 
+	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
+	const long pm_100ms = PMTMR_TICKS_PER_SEC/10;
+	const long pm_thresh = pm_100ms/100;
+	void (*real_handler)(struct clock_event_device *dev);
+	unsigned long deltaj;
+	long delta, deltapm;
+	int pm_referenced = 0;
+
+	/*
+	 * The local apic timer can be disabled via the kernel
+	 * commandline or from the test above. Register the lapic
+	 * timer as a dummy clock event source on SMP systems, so the
+	 * broadcast mechanism is used. On UP systems simply ignore it.
+	 */
+	if (disable_apic_timer) {
+		printk(KERN_INFO "Disabling APIC timer\n");
+		/* No broadcast on UP ! */
+		if (num_possible_cpus() > 1)
+			setup_APIC_timer();
+		return;
+	}
 
 	printk(KERN_INFO "Using local APIC timer interrupts.\n");
-	using_apic_timer = 1;
 
-	local_irq_disable();
+	/* Replace the global interrupt handler */
+	real_handler = global_clock_event->event_handler;
+	global_clock_event->event_handler = lapic_cal_handler;
 
-	calibration_result = calibrate_APIC_clock();
 	/*
-	 * Now set up the timer for real.
+	 * Setup the APIC counter to 1e9. There is no way the lapic
+	 * can underflow in the 100ms detection time frame
 	 */
-	setup_APIC_timer(calibration_result);
+	__setup_APIC_LVTT(1000000000, 0, 0);
 
+	/* Let the interrupts run */
 	local_irq_enable();
-}
 
-void __cpuinit setup_secondary_APIC_clock(void)
-{
-	local_irq_disable(); /* FIXME: Do we need this? --RR */
-	setup_APIC_timer(calibration_result);
-	local_irq_enable();
-}
+	while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
+		cpu_relax();
 
-void disable_APIC_timer(void)
-{
-	if (using_apic_timer) {
-		unsigned long v;
+	local_irq_disable();
 
-		v = apic_read(APIC_LVTT);
-		/*
-		 * When an illegal vector value (0-15) is written to an LVT
-		 * entry and delivery mode is Fixed, the APIC may signal an
-		 * illegal vector error, with out regard to whether the mask
-		 * bit is set or whether an interrupt is actually seen on input.
-		 *
-		 * Boot sequence might call this function when the LVTT has
-		 * '0' vector value. So make sure vector field is set to
-		 * valid value.
-		 */
-		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-		apic_write(APIC_LVTT, v);
+	/* Restore the real event handler */
+	global_clock_event->event_handler = real_handler;
+
+	/* Build delta t1-t2 as apic timer counts down */
+	delta = lapic_cal_t1 - lapic_cal_t2;
+	apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
+
+	/* Check, if the PM timer is available */
+	deltapm = lapic_cal_pm2 - lapic_cal_pm1;
+	apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+
+	if (deltapm) {
+		unsigned long mult;
+		u64 res;
+
+		mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, 22);
+
+		if (deltapm > (pm_100ms - pm_thresh) &&
+		    deltapm < (pm_100ms + pm_thresh)) {
+			apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
+		} else {
+			res = (((u64) deltapm) *  mult) >> 22;
+			do_div(res, 1000000);
+			printk(KERN_WARNING "APIC calibration not consistent "
+			       "with PM Timer: %ldms instead of 100ms\n",
+			       (long)res);
+			/* Correct the lapic counter value */
+			res = (((u64) delta ) * pm_100ms);
+			do_div(res, deltapm);
+			printk(KERN_INFO "APIC delta adjusted to PM-Timer: "
+			       "%lu (%ld)\n", (unsigned long) res, delta);
+			delta = (long) res;
+		}
+		pm_referenced = 1;
 	}
-}
 
-void enable_APIC_timer(void)
-{
-	int cpu = smp_processor_id();
+	/* Calculate the scaled math multiplication factor */
+	lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 32);
+	lapic_clockevent.max_delta_ns =
+		clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+	lapic_clockevent.min_delta_ns =
+		clockevent_delta2ns(0xF, &lapic_clockevent);
 
-	if (using_apic_timer &&
-	    !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) {
-		unsigned long v;
+	calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
-		v = apic_read(APIC_LVTT);
-		apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED);
+	apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
+	apic_printk(APIC_VERBOSE, "..... mult: %ld\n", lapic_clockevent.mult);
+	apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
+		    calibration_result);
+
+	if (cpu_has_tsc) {
+		delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
+		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
+			    "%ld.%04ld MHz.\n",
+			    (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ),
+			    (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ));
 	}
-}
 
-void switch_APIC_timer_to_ipi(void *cpumask)
-{
-	cpumask_t mask = *(cpumask_t *)cpumask;
-	int cpu = smp_processor_id();
+	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
+		    "%u.%04u MHz.\n",
+		    calibration_result / (1000000 / HZ),
+		    calibration_result % (1000000 / HZ));
 
-	if (cpu_isset(cpu, mask) &&
-	    !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) {
-		disable_APIC_timer();
-		cpu_set(cpu, timer_interrupt_broadcast_ipi_mask);
-	}
-}
-EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
+	local_apic_timer_verify_ok = 1;
 
-void smp_send_timer_broadcast_ipi(void)
-{
-	int cpu = smp_processor_id();
-	cpumask_t mask;
+	/* We trust the pm timer based calibration */
+	if (!pm_referenced) {
+		apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
 
-	cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask);
+		/*
+		 * Setup the apic timer manually
+		 */
+		levt->event_handler = lapic_cal_handler;
+		lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
+		lapic_cal_loops = -1;
 
-	if (cpu_isset(cpu, mask)) {
-		cpu_clear(cpu, mask);
-		add_pda(apic_timer_irqs, 1);
-		smp_local_timer_interrupt();
-	}
+		/* Let the interrupts run */
+		local_irq_enable();
+
+		while(lapic_cal_loops <= LAPIC_CAL_LOOPS)
+			cpu_relax();
+
+		local_irq_disable();
+
+		/* Stop the lapic timer */
+		lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
+
+		local_irq_enable();
 
-	if (!cpus_empty(mask)) {
-		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+		/* Jiffies delta */
+		deltaj = lapic_cal_j2 - lapic_cal_j1;
+		apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
+
+		/* Check, if the jiffies result is consistent */
+		if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2)
+			apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
+		else
+			local_apic_timer_verify_ok = 0;
+	} else
+		local_irq_enable();
+
+	if (!local_apic_timer_verify_ok) {
+		printk(KERN_WARNING
+		       "APIC timer disabled due to verification failure.\n");
+		/* No broadcast on UP ! */
+		if (num_possible_cpus() == 1)
+			return;
+	} else {
+		/*
+		 * If nmi_watchdog is set to IO_APIC, we need the
+		 * PIT/HPET going.  Otherwise register lapic as a dummy
+		 * device.
+		 */
+		if (nmi_watchdog != NMI_IO_APIC)
+			lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
 	}
+
+	/* Setup the lapic or request the broadcast */
+	setup_APIC_timer();
 }
 
-void switch_ipi_to_APIC_timer(void *cpumask)
+void __cpuinit setup_secondary_APIC_clock(void)
 {
-	cpumask_t mask = *(cpumask_t *)cpumask;
-	int cpu = smp_processor_id();
-
-	if (cpu_isset(cpu, mask) &&
-	    cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) {
-		cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask);
-		enable_APIC_timer();
-	}
+	setup_APIC_timer();
 }
-EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
 
 int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
 
-void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
-			    unsigned char msg_type, unsigned char mask)
+void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector,
+			     unsigned char msg_type, unsigned char mask)
 {
 	unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE;
 	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
+
 	apic_write(reg, v);
 }
 
-#undef APIC_DIVISOR
-
 /*
  * Local timer interrupt handler. It does both profiling and
  * process statistics/rescheduling.
@@ -1010,24 +1115,36 @@ void setup_APIC_extened_lvt(unsigned cha
  * value into /proc/profile.
  */
 
-void smp_local_timer_interrupt(void)
+void local_apic_timer_interrupt(void)
 {
-	profile_tick(CPU_PROFILING);
-#ifdef CONFIG_SMP
-	update_process_times(user_mode(get_irq_regs()));
-#endif
-	if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id)
-		main_timer_handler();
+	int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
+
 	/*
-	 * We take the 'long' return path, and there every subsystem
-	 * grabs the appropriate locks (kernel lock/ irq lock).
-	 *
-	 * We might want to decouple profiling from the 'long path',
-	 * and do the profiling totally in assembly.
+	 * Normally we should not be here till LAPIC has been initialized but
+	 * in some cases like kdump, its possible that there is a pending LAPIC
+	 * timer interrupt from previous kernel's context and is delivered in
+	 * new kernel the moment interrupts are enabled.
 	 *
-	 * Currently this isn't too much of an issue (performance wise),
-	 * we can take more than 100K local irqs per second on a 100 MHz P5.
+	 * Interrupts are enabled early and LAPIC is setup much later, hence
+	 * its possible that when we get here evt->event_handler is NULL.
+	 * Check for event_handler being NULL and discard the interrupt as
+	 * spurious.
+	 */
+	if (!evt->event_handler) {
+		printk(KERN_WARNING
+		       "Spurious LAPIC timer interrupt on cpu %d\n", cpu);
+		/* Switch it off */
+		lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt);
+		return;
+	}
+
+	/*
+	 * the NMI deadlock-detector uses this.
 	 */
+	add_pda(apic_timer_irqs, 1);
+
+	evt->event_handler(evt);
 }
 
 /*
@@ -1043,11 +1160,6 @@ void smp_apic_timer_interrupt(struct pt_
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
 	/*
-	 * the NMI deadlock-detector uses this.
-	 */
-	add_pda(apic_timer_irqs, 1);
-
-	/*
 	 * NOTE! We'd better ACK the irq immediately,
 	 * because timer handling can be slow.
 	 */
@@ -1059,7 +1171,7 @@ void smp_apic_timer_interrupt(struct pt_
 	 */
 	exit_idle();
 	irq_enter();
-	smp_local_timer_interrupt();
+	local_apic_timer_interrupt();
 	irq_exit();
 	set_irq_regs(old_regs);
 }
@@ -1127,21 +1239,6 @@ asmlinkage void smp_spurious_interrupt(v
 	v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
 	if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
 		ack_APIC_irq();
-
-#if 0
-	static unsigned long last_warning; 
-	static unsigned long skipped; 
-
-	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
-	if (time_before(last_warning+30*HZ,jiffies)) { 
-		printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
-		       smp_processor_id(), skipped);
-		last_warning = jiffies; 
-		skipped = 0;
-	} else { 
-		skipped++; 
-	} 
-#endif 
 	irq_exit();
 }
 
@@ -1173,11 +1270,11 @@ asmlinkage void smp_error_interrupt(void
 	   7: Illegal register address
 	*/
 	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
-	        smp_processor_id(), v , v1);
+		smp_processor_id(), v , v1);
 	irq_exit();
 }
 
-int disable_apic; 
+int disable_apic;
 
 /*
  * This initializes the IO-APIC and APIC hardware if this is
@@ -1185,11 +1282,11 @@ int disable_apic; 
  */
 int __init APIC_init_uniprocessor (void)
 {
-	if (disable_apic) { 
+	if (disable_apic) {
 		printk(KERN_INFO "Apic disabled\n");
-		return -1; 
+		return -1;
 	}
-	if (!cpu_has_apic) { 
+	if (!cpu_has_apic) {
 		disable_apic = 1;
 		printk(KERN_INFO "Apic disabled by BIOS\n");
 		return -1;
@@ -1211,8 +1308,8 @@ int __init APIC_init_uniprocessor (void)
 	return 0;
 }
 
-static __init int setup_disableapic(char *str) 
-{ 
+static __init int setup_disableapic(char *str)
+{
 	disable_apic = 1;
 	clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
 	return 0;
@@ -1220,10 +1317,10 @@ static __init int setup_disableapic(char
 early_param("disableapic", setup_disableapic);
 
 /* same as disableapic, for compatibility */
-static __init int setup_nolapic(char *str) 
-{ 
+static __init int setup_nolapic(char *str)
+{
 	return setup_disableapic(str);
-} 
+}
 early_param("nolapic", setup_nolapic);
 
 static int __init parse_lapic_timer_c2_ok(char *arg)
@@ -1233,36 +1330,12 @@ static int __init parse_lapic_timer_c2_o
 }
 early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok);
 
-static __init int setup_noapictimer(char *str) 
-{ 
+static __init int setup_noapictimer(char *str)
+{
 	if (str[0] != ' ' && str[0] != 0)
 		return 0;
 	disable_apic_timer = 1;
 	return 1;
-} 
-
-static __init int setup_apicmaintimer(char *str)
-{
-	apic_runs_main_timer = 1;
-	nohpet = 1;
-	return 1;
 }
-__setup("apicmaintimer", setup_apicmaintimer);
-
-static __init int setup_noapicmaintimer(char *str)
-{
-	apic_runs_main_timer = -1;
-	return 1;
-}
-__setup("noapicmaintimer", setup_noapicmaintimer);
-
-static __init int setup_apicpmtimer(char *s)
-{
-	apic_calibrate_pmtmr = 1;
-	notsc_setup(NULL);
-	return setup_apicmaintimer(NULL);
-}
-__setup("apicpmtimer", setup_apicpmtimer);
-
-__setup("noapictimer", setup_noapictimer); 
+__setup("noapictimer", setup_noapictimer);
 
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/time.c	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-16 12:10:24.000000000 +0200
@@ -28,11 +28,11 @@
 #include <linux/cpu.h>
 #include <linux/kallsyms.h>
 #include <linux/acpi.h>
+#include <linux/clockchips.h>
 #ifdef CONFIG_ACPI
 #include <acpi/achware.h>	/* for PM timer frequency */
 #include <acpi/acpi_bus.h>
 #endif
-#include <asm/8253pit.h>
 #include <asm/i8253.h>
 #include <asm/pgtable.h>
 #include <asm/vsyscall.h>
@@ -47,12 +47,8 @@
 #include <asm/nmi.h>
 #include <asm/vgtod.h>
 
-static char *timename = NULL;
-
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
-DEFINE_SPINLOCK(i8253_lock);
-EXPORT_SYMBOL(i8253_lock);
 
 volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
 
@@ -153,49 +149,14 @@ int update_persistent_clock(struct times
 	return set_rtc_mmss(now.tv_sec);
 }
 
-void main_timer_handler(void)
-{
-/*
- * Here we are in the timer irq handler. We have irqs locally disabled (so we
- * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
- * on the other CPU, so we need a lock. We also need to lock the vsyscall
- * variables, because both do_timer() and us change them -arca+vojtech
- */
-
-	write_seqlock(&xtime_lock);
-
-/*
- * Do the timer stuff.
- */
-
-	do_timer(1);
-#ifndef CONFIG_SMP
-	update_process_times(user_mode(get_irq_regs()));
-#endif
-
-/*
- * In the SMP case we use the local APIC timer interrupt to do the profiling,
- * except when we simulate SMP mode on a uniprocessor system, in that case we
- * have to call the local interrupt handler.
- */
-
-	if (!using_apic_timer)
-		smp_local_timer_interrupt();
-
-	write_sequnlock(&xtime_lock);
-}
-
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-	if (apic_runs_main_timer > 1)
-		return IRQ_HANDLED;
-	main_timer_handler();
-	if (using_apic_timer)
-		smp_send_timer_broadcast_ipi();
+	global_clock_event->event_handler(global_clock_event);
+
 	return IRQ_HANDLED;
 }
 
-static unsigned long get_cmos_time(void)
+unsigned long read_persistent_clock(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 	unsigned long flags;
@@ -222,7 +183,7 @@ static unsigned long get_cmos_time(void)
 	/*
 	 * We know that x86-64 always uses BCD format, no need to check the
 	 * config register.
- 	 */
+	 */
 
 	BCD_TO_BIN(sec);
 	BCD_TO_BIN(min);
@@ -235,11 +196,11 @@ static unsigned long get_cmos_time(void)
 		BCD_TO_BIN(century);
 		year += century * 100;
 		printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
-	} else { 
+	} else {
 		/*
 		 * x86-64 systems only exists since 2002.
 		 * This will work up to Dec 31, 2100
-	 	 */
+		 */
 		year += 2000;
 	}
 
@@ -257,17 +218,17 @@ static unsigned int __init tsc_calibrate
        unsigned long flags;
 
        for (i = 0; i < 4; i++)
-               if (avail_to_resrv_perfctr_nmi_bit(i))
-                       break;
+	       if (avail_to_resrv_perfctr_nmi_bit(i))
+		       break;
        no_ctr_free = (i == 4);
        if (no_ctr_free) {
-               i = 3;
-               rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
-               wrmsrl(MSR_K7_EVNTSEL3, 0);
-               rdmsrl(MSR_K7_PERFCTR3, pmc3);
+	       i = 3;
+	       rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
+	       wrmsrl(MSR_K7_EVNTSEL3, 0);
+	       rdmsrl(MSR_K7_PERFCTR3, pmc3);
        } else {
-               reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-               reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+	       reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+	       reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
        }
        local_irq_save(flags);
        /* start meauring cycles, incrementing from 0 */
@@ -275,119 +236,38 @@ static unsigned int __init tsc_calibrate
        wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
        rdtscl(tsc_start);
        do {
-               rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
-               tsc_now = get_cycles_sync();
+	       rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
+	       tsc_now = get_cycles_sync();
        } while ((tsc_now - tsc_start) < TICK_COUNT);
 
        local_irq_restore(flags);
        if (no_ctr_free) {
-               wrmsrl(MSR_K7_EVNTSEL3, 0);
-               wrmsrl(MSR_K7_PERFCTR3, pmc3);
-               wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
+	       wrmsrl(MSR_K7_EVNTSEL3, 0);
+	       wrmsrl(MSR_K7_PERFCTR3, pmc3);
+	       wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
        } else {
-               release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
-               release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+	       release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+	       release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
        }
 
        return pmc_now * tsc_khz / (tsc_now - tsc_start);
 }
 
-/*
- * pit_calibrate_tsc() uses the speaker output (channel 2) of
- * the PIT. This is better than using the timer interrupt output,
- * because we can read the value of the speaker with just one inb(),
- * where we need three i/o operations for the interrupt channel.
- * We count how many ticks the TSC does in 50 ms.
- */
-
-static unsigned int __init pit_calibrate_tsc(void)
-{
-	unsigned long start, end;
-	unsigned long flags;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-
-	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
-
-	outb(0xb0, 0x43);
-	outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
-	outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42);
-	start = get_cycles_sync();
-	while ((inb(0x61) & 0x20) == 0);
-	end = get_cycles_sync();
-
-	spin_unlock_irqrestore(&i8253_lock, flags);
-	
-	return (end - start) / 50;
-}
-
-#define PIT_MODE 0x43
-#define PIT_CH0  0x40
-
-static void __pit_init(int val, u8 mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-	outb_p(mode, PIT_MODE);
-	outb_p(val & 0xff, PIT_CH0);	/* LSB */
-	outb_p(val >> 8, PIT_CH0);	/* MSB */
-	spin_unlock_irqrestore(&i8253_lock, flags);
-}
-
-void __init pit_init(void)
-{
-	__pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
-}
-
-void pit_stop_interrupt(void)
-{
-	__pit_init(0, 0x30); /* mode 0 */
-}
-
-void stop_timer_interrupt(void)
-{
-	char *name;
-	if (hpet_address) {
-		name = "HPET";
-		hpet_timer_stop_set_go(0);
-	} else {
-		name = "PIT";
-		pit_stop_interrupt();
-	}
-	printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
-}
-
 static struct irqaction irq0 = {
 	.handler	= timer_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_IRQPOLL,
 	.mask		= CPU_MASK_NONE,
-	.name 		= "timer"
+	.name		= "timer"
 };
 
 void __init time_init(void)
 {
-	if (nohpet)
-		hpet_address = 0;
-	xtime.tv_sec = get_cmos_time();
-	xtime.tv_nsec = 0;
-
-	set_normalized_timespec(&wall_to_monotonic,
-	                        -xtime.tv_sec, -xtime.tv_nsec);
-
-	if (hpet_arch_init())
-		hpet_address = 0;
-
-	if (hpet_use_timer) {
-		/* set tick_nsec to use the proper rate for HPET */
-	  	tick_nsec = TICK_NSEC_HPET;
-		tsc_khz = hpet_calibrate_tsc();
-		timename = "HPET";
-	} else {
-		pit_init();
-		tsc_khz = pit_calibrate_tsc();
-		timename = "PIT";
-	}
+	if (!hpet_enable())
+		setup_pit_timer();
+
+	setup_irq(0, &irq0);
+
+	tsc_calibrate();
 
 	cpu_khz = tsc_khz;
 	if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
@@ -406,79 +286,4 @@ void __init time_init(void)
 	printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
 		cpu_khz / 1000, cpu_khz % 1000);
 	init_tsc_clocksource();
-
-	setup_irq(0, &irq0);
 }
-
-
-static long clock_cmos_diff;
-static unsigned long sleep_start;
-
-/*
- * sysfs support for the timer.
- */
-
-static int timer_suspend(struct sys_device *dev, pm_message_t state)
-{
-	/*
-	 * Estimate time zone so that set_time can update the clock
-	 */
-	long cmos_time =  get_cmos_time();
-
-	clock_cmos_diff = -cmos_time;
-	clock_cmos_diff += get_seconds();
-	sleep_start = cmos_time;
-	return 0;
-}
-
-static int timer_resume(struct sys_device *dev)
-{
-	unsigned long flags;
-	unsigned long sec;
-	unsigned long ctime = get_cmos_time();
-	long sleep_length = (ctime - sleep_start) * HZ;
-
-	if (sleep_length < 0) {
-		printk(KERN_WARNING "Time skew detected in timer resume!\n");
-		/* The time after the resume must not be earlier than the time
-		 * before the suspend or some nasty things will happen
-		 */
-		sleep_length = 0;
-		ctime = sleep_start;
-	}
-	if (hpet_address)
-		hpet_reenable();
-	else
-		i8254_timer_resume();
-
-	sec = ctime + clock_cmos_diff;
-	write_seqlock_irqsave(&xtime_lock,flags);
-	xtime.tv_sec = sec;
-	xtime.tv_nsec = 0;
-	jiffies += sleep_length;
-	write_sequnlock_irqrestore(&xtime_lock,flags);
-	touch_softlockup_watchdog();
-	return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
-	.resume = timer_resume,
-	.suspend = timer_suspend,
-	set_kset_name("timer"),
-};
-
-/* XXX this sysfs stuff should probably go elsewhere later -john */
-static struct sys_device device_timer = {
-	.id	= 0,
-	.cls	= &timer_sysclass,
-};
-
-static int time_init_device(void)
-{
-	int error = sysdev_class_register(&timer_sysclass);
-	if (!error)
-		error = sysdev_register(&device_timer);
-	return error;
-}
-
-device_initcall(time_init_device);
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/hpet.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/hpet.c	2007-06-16 12:10:20.000000000 +0200
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,493 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/mc146818rtc.h>
-#include <linux/time.h>
-#include <linux/clocksource.h>
-#include <linux/ioport.h>
-#include <linux/acpi.h>
-#include <linux/hpet.h>
-#include <asm/pgtable.h>
-#include <asm/vsyscall.h>
-#include <asm/timex.h>
-#include <asm/hpet.h>
-
-#define HPET_MASK	0xFFFFFFFF
-#define HPET_SHIFT	22
-
-/* FSEC = 10^-15 NSEC = 10^-9 */
-#define FSEC_PER_NSEC	1000000
-
-int nohpet __initdata;
-
-unsigned long hpet_address;
-unsigned long hpet_period;	/* fsecs / HPET clock */
-unsigned long hpet_tick;	/* HPET clocks / interrupt */
-
-int hpet_use_timer;		/* Use counter of hpet for time keeping,
-				 * otherwise PIT
-				 */
-
-#ifdef	CONFIG_HPET
-static __init int late_hpet_init(void)
-{
-	struct hpet_data	hd;
-	unsigned int 		ntimer;
-
-	if (!hpet_address)
-        	return 0;
-
-	memset(&hd, 0, sizeof(hd));
-
-	ntimer = hpet_readl(HPET_ID);
-	ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
-	ntimer++;
-
-	/*
-	 * Register with driver.
-	 * Timer0 and Timer1 is used by platform.
-	 */
-	hd.hd_phys_address = hpet_address;
-	hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
-	hd.hd_nirqs = ntimer;
-	hd.hd_flags = HPET_DATA_PLATFORM;
-	hpet_reserve_timer(&hd, 0);
-#ifdef	CONFIG_HPET_EMULATE_RTC
-	hpet_reserve_timer(&hd, 1);
-#endif
-	hd.hd_irq[0] = HPET_LEGACY_8254;
-	hd.hd_irq[1] = HPET_LEGACY_RTC;
-	if (ntimer > 2) {
-		struct hpet		*hpet;
-		struct hpet_timer	*timer;
-		int			i;
-
-		hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
-		timer = &hpet->hpet_timers[2];
-		for (i = 2; i < ntimer; timer++, i++)
-			hd.hd_irq[i] = (timer->hpet_config &
-					Tn_INT_ROUTE_CNF_MASK) >>
-				Tn_INT_ROUTE_CNF_SHIFT;
-
-	}
-
-	hpet_alloc(&hd);
-	return 0;
-}
-fs_initcall(late_hpet_init);
-#endif
-
-int hpet_timer_stop_set_go(unsigned long tick)
-{
-	unsigned int cfg;
-
-/*
- * Stop the timers and reset the main counter.
- */
-
-	cfg = hpet_readl(HPET_CFG);
-	cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
-	hpet_writel(cfg, HPET_CFG);
-	hpet_writel(0, HPET_COUNTER);
-	hpet_writel(0, HPET_COUNTER + 4);
-
-/*
- * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
- * and period also hpet_tick.
- */
-	if (hpet_use_timer) {
-		hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
-		    HPET_TN_32BIT, HPET_T0_CFG);
-		hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
-		hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
-		cfg |= HPET_CFG_LEGACY;
-	}
-/*
- * Go!
- */
-
-	cfg |= HPET_CFG_ENABLE;
-	hpet_writel(cfg, HPET_CFG);
-
-	return 0;
-}
-
-static cycle_t read_hpet(void)
-{
-	return (cycle_t)hpet_readl(HPET_COUNTER);
-}
-
-static cycle_t __vsyscall_fn vread_hpet(void)
-{
-	return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
-}
-
-struct clocksource clocksource_hpet = {
-	.name		= "hpet",
-	.rating		= 250,
-	.read		= read_hpet,
-	.mask		= (cycle_t)HPET_MASK,
-	.mult		= 0, /* set below */
-	.shift		= HPET_SHIFT,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-	.vread		= vread_hpet,
-};
-
-int hpet_arch_init(void)
-{
-	unsigned int id;
-	u64 tmp;
-
-	if (!hpet_address)
-		return -1;
-	set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
-	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
-
-/*
- * Read the period, compute tick and quotient.
- */
-
-	id = hpet_readl(HPET_ID);
-
-	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
-		return -1;
-
-	hpet_period = hpet_readl(HPET_PERIOD);
-	if (hpet_period < 100000 || hpet_period > 100000000)
-		return -1;
-
-	hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
-
-	hpet_use_timer = (id & HPET_ID_LEGSUP);
-
-	/*
-	 * hpet period is in femto seconds per cycle
-	 * so we need to convert this to ns/cyc units
-	 * aproximated by mult/2^shift
-	 *
-	 *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
-	 *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
-	 *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
-	 *  (fsec/cyc << shift)/1000000 = mult
-	 *  (hpet_period << shift)/FSEC_PER_NSEC = mult
-	 */
-	tmp = (u64)hpet_period << HPET_SHIFT;
-	do_div(tmp, FSEC_PER_NSEC);
-	clocksource_hpet.mult = (u32)tmp;
-	clocksource_register(&clocksource_hpet);
-
-	return hpet_timer_stop_set_go(hpet_tick);
-}
-
-int hpet_reenable(void)
-{
-	return hpet_timer_stop_set_go(hpet_tick);
-}
-
-/*
- * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
- * it to the HPET timer of known frequency.
- */
-
-#define TICK_COUNT 100000000
-#define TICK_MIN   5000
-#define MAX_TRIES  5
-
-/*
- * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
- * occurs between the reads of the hpet & TSC.
- */
-static void __init read_hpet_tsc(int *hpet, int *tsc)
-{
-	int tsc1, tsc2, hpet1, i;
-
-	for (i = 0; i < MAX_TRIES; i++) {
-		tsc1 = get_cycles_sync();
-		hpet1 = hpet_readl(HPET_COUNTER);
-		tsc2 = get_cycles_sync();
-		if (tsc2 - tsc1 > TICK_MIN)
-			break;
-	}
-	*hpet = hpet1;
-	*tsc = tsc2;
-}
-
-unsigned int __init hpet_calibrate_tsc(void)
-{
-	int tsc_start, hpet_start;
-	int tsc_now, hpet_now;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	read_hpet_tsc(&hpet_start, &tsc_start);
-
-	do {
-		local_irq_disable();
-		read_hpet_tsc(&hpet_now, &tsc_now);
-		local_irq_restore(flags);
-	} while ((tsc_now - tsc_start) < TICK_COUNT &&
-		(hpet_now - hpet_start) < TICK_COUNT);
-
-	return (tsc_now - tsc_start) * 1000000000L
-		/ ((hpet_now - hpet_start) * hpet_period / 1000);
-}
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
- * is enabled, we support RTC interrupt functionality in software.
- * RTC has 3 kinds of interrupts:
- * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
- *    is updated
- * 2) Alarm Interrupt - generate an interrupt at a specific time of day
- * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
- *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
- * (1) and (2) above are implemented using polling at a frequency of
- * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
- * overhead. (DEFAULT_RTC_INT_FREQ)
- * For (3), we use interrupts at 64Hz or user specified periodic
- * frequency, whichever is higher.
- */
-#include <linux/rtc.h>
-
-#define DEFAULT_RTC_INT_FREQ 	64
-#define RTC_NUM_INTS 		1
-
-static unsigned long UIE_on;
-static unsigned long prev_update_sec;
-
-static unsigned long AIE_on;
-static struct rtc_time alarm_time;
-
-static unsigned long PIE_on;
-static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
-static unsigned long PIE_count;
-
-static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
-static unsigned int hpet_t1_cmp; /* cached comparator register */
-
-int is_hpet_enabled(void)
-{
-	return hpet_address != 0;
-}
-
-/*
- * Timer 1 for RTC, we do not use periodic interrupt feature,
- * even if HPET supports periodic interrupts on Timer 1.
- * The reason being, to set up a periodic interrupt in HPET, we need to
- * stop the main counter. And if we do that everytime someone diables/enables
- * RTC, we will have adverse effect on main kernel timer running on Timer 0.
- * So, for the time being, simulate the periodic interrupt in software.
- *
- * hpet_rtc_timer_init() is called for the first time and during subsequent
- * interuppts reinit happens through hpet_rtc_timer_reinit().
- */
-int hpet_rtc_timer_init(void)
-{
-	unsigned int cfg, cnt;
-	unsigned long flags;
-
-	if (!is_hpet_enabled())
-		return 0;
-	/*
-	 * Set the counter 1 and enable the interrupts.
-	 */
-	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-		hpet_rtc_int_freq = PIE_freq;
-	else
-		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-	local_irq_save(flags);
-
-	cnt = hpet_readl(HPET_COUNTER);
-	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
-	hpet_writel(cnt, HPET_T1_CMP);
-	hpet_t1_cmp = cnt;
-
-	cfg = hpet_readl(HPET_T1_CFG);
-	cfg &= ~HPET_TN_PERIODIC;
-	cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T1_CFG);
-
-	local_irq_restore(flags);
-
-	return 1;
-}
-
-static void hpet_rtc_timer_reinit(void)
-{
-	unsigned int cfg, cnt, ticks_per_int, lost_ints;
-
-	if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
-		cfg = hpet_readl(HPET_T1_CFG);
-		cfg &= ~HPET_TN_ENABLE;
-		hpet_writel(cfg, HPET_T1_CFG);
-		return;
-	}
-
-	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
-		hpet_rtc_int_freq = PIE_freq;
-	else
-		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
-
-	/* It is more accurate to use the comparator value than current count.*/
-	ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
-	hpet_t1_cmp += ticks_per_int;
-	hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-	/*
-	 * If the interrupt handler was delayed too long, the write above tries
-	 * to schedule the next interrupt in the past and the hardware would
-	 * not interrupt until the counter had wrapped around.
-	 * So we have to check that the comparator wasn't set to a past time.
-	 */
-	cnt = hpet_readl(HPET_COUNTER);
-	if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
-		lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
-		/* Make sure that, even with the time needed to execute
-		 * this code, the next scheduled interrupt has been moved
-		 * back to the future: */
-		lost_ints++;
-
-		hpet_t1_cmp += lost_ints * ticks_per_int;
-		hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
-
-		if (PIE_on)
-			PIE_count += lost_ints;
-
-		if (printk_ratelimit())
-			printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-			       hpet_rtc_int_freq);
-	}
-}
-
-/*
- * The functions below are called from rtc driver.
- * Return 0 if HPET is not being used.
- * Otherwise do the necessary changes and return 1.
- */
-int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	if (bit_mask & RTC_UIE)
-		UIE_on = 0;
-	if (bit_mask & RTC_PIE)
-		PIE_on = 0;
-	if (bit_mask & RTC_AIE)
-		AIE_on = 0;
-
-	return 1;
-}
-
-int hpet_set_rtc_irq_bit(unsigned long bit_mask)
-{
-	int timer_init_reqd = 0;
-
-	if (!is_hpet_enabled())
-		return 0;
-
-	if (!(PIE_on | AIE_on | UIE_on))
-		timer_init_reqd = 1;
-
-	if (bit_mask & RTC_UIE) {
-		UIE_on = 1;
-	}
-	if (bit_mask & RTC_PIE) {
-		PIE_on = 1;
-		PIE_count = 0;
-	}
-	if (bit_mask & RTC_AIE) {
-		AIE_on = 1;
-	}
-
-	if (timer_init_reqd)
-		hpet_rtc_timer_init();
-
-	return 1;
-}
-
-int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	alarm_time.tm_hour = hrs;
-	alarm_time.tm_min = min;
-	alarm_time.tm_sec = sec;
-
-	return 1;
-}
-
-int hpet_set_periodic_freq(unsigned long freq)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	PIE_freq = freq;
-	PIE_count = 0;
-
-	return 1;
-}
-
-int hpet_rtc_dropped_irq(void)
-{
-	if (!is_hpet_enabled())
-		return 0;
-
-	return 1;
-}
-
-irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct rtc_time curr_time;
-	unsigned long rtc_int_flag = 0;
-	int call_rtc_interrupt = 0;
-
-	hpet_rtc_timer_reinit();
-
-	if (UIE_on | AIE_on) {
-		rtc_get_rtc_time(&curr_time);
-	}
-	if (UIE_on) {
-		if (curr_time.tm_sec != prev_update_sec) {
-			/* Set update int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag = RTC_UF;
-			prev_update_sec = curr_time.tm_sec;
-		}
-	}
-	if (PIE_on) {
-		PIE_count++;
-		if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
-			/* Set periodic int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag |= RTC_PF;
-			PIE_count = 0;
-		}
-	}
-	if (AIE_on) {
-		if ((curr_time.tm_sec == alarm_time.tm_sec) &&
-		    (curr_time.tm_min == alarm_time.tm_min) &&
-		    (curr_time.tm_hour == alarm_time.tm_hour)) {
-			/* Set alarm int info, call real rtc int routine */
-			call_rtc_interrupt = 1;
-			rtc_int_flag |= RTC_AF;
-		}
-	}
-	if (call_rtc_interrupt) {
-		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
-		rtc_interrupt(rtc_int_flag, dev_id);
-	}
-	return IRQ_HANDLED;
-}
-#endif
-
-static int __init nohpet_setup(char *s)
-{
-	nohpet = 1;
-	return 1;
-}
-
-__setup("nohpet", nohpet_setup);
Index: linux-2.6.22-rc4-mm/arch/x86_64/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/Kconfig	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/Kconfig	2007-06-16 12:10:24.000000000 +0200
@@ -28,6 +28,18 @@ config GENERIC_TIME
 	bool
 	default y
 
+config GENERIC_CLOCKEVENTS
+	bool
+	default y
+
+config GENERIC_CLOCKEVENTS_BROADCAST
+	bool
+	default y
+
+config NONIRQ_WAKEUP
+	bool
+	default y
+
 config GENERIC_TIME_VSYSCALL
 	bool
 	default y
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/hpet.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/hpet.h	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/hpet.h	2007-06-16 12:10:24.000000000 +0200
@@ -1,77 +1,2 @@
-#ifndef _ASM_X8664_HPET_H
-#define _ASM_X8664_HPET_H 1
 
-/*
- * Documentation on HPET can be found at:
- *      http://www.intel.com/ial/home/sp/pcmmspec.htm
- *      ftp://download.intel.com/ial/home/sp/mmts098.pdf
- */
-
-#define HPET_MMAP_SIZE	1024
-
-#define HPET_ID		0x000
-#define HPET_PERIOD	0x004
-#define HPET_CFG	0x010
-#define HPET_STATUS	0x020
-#define HPET_COUNTER	0x0f0
-#define HPET_Tn_OFFSET	0x20
-#define HPET_Tn_CFG(n)	 (0x100 + (n) * HPET_Tn_OFFSET)
-#define HPET_Tn_ROUTE(n) (0x104 + (n) * HPET_Tn_OFFSET)
-#define HPET_Tn_CMP(n)	 (0x108 + (n) * HPET_Tn_OFFSET)
-#define HPET_T0_CFG	HPET_Tn_CFG(0)
-#define HPET_T0_CMP	HPET_Tn_CMP(0)
-#define HPET_T1_CFG	HPET_Tn_CFG(1)
-#define HPET_T1_CMP	HPET_Tn_CMP(1)
-
-#define HPET_ID_VENDOR	0xffff0000
-#define HPET_ID_LEGSUP	0x00008000
-#define HPET_ID_64BIT	0x00002000
-#define HPET_ID_NUMBER	0x00001f00
-#define HPET_ID_REV	0x000000ff
-#define	HPET_ID_NUMBER_SHIFT	8
-
-#define HPET_ID_VENDOR_SHIFT	16
-#define HPET_ID_VENDOR_8086	0x8086
-
-#define HPET_CFG_ENABLE	0x001
-#define HPET_CFG_LEGACY	0x002
-#define	HPET_LEGACY_8254	2
-#define	HPET_LEGACY_RTC		8
-
-#define HPET_TN_LEVEL		0x0002
-#define HPET_TN_ENABLE		0x0004
-#define HPET_TN_PERIODIC	0x0008
-#define HPET_TN_PERIODIC_CAP	0x0010
-#define HPET_TN_64BIT_CAP	0x0020
-#define HPET_TN_SETVAL		0x0040
-#define HPET_TN_32BIT		0x0100
-#define HPET_TN_ROUTE		0x3e00
-#define HPET_TN_FSB		0x4000
-#define HPET_TN_FSB_CAP		0x8000
-
-#define HPET_TN_ROUTE_SHIFT	9
-
-#define HPET_TICK_RATE (HZ * 100000UL)
-
-extern int is_hpet_enabled(void);
-extern int hpet_rtc_timer_init(void);
-extern int hpet_arch_init(void);
-extern int hpet_timer_stop_set_go(unsigned long tick);
-extern int hpet_reenable(void);
-extern unsigned int hpet_calibrate_tsc(void);
-
-extern int hpet_use_timer;
-extern unsigned long hpet_address;
-extern unsigned long hpet_period;
-extern unsigned long hpet_tick;
-
-#ifdef CONFIG_HPET_EMULATE_RTC
-extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
-extern int hpet_set_rtc_irq_bit(unsigned long bit_mask);
-extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec);
-extern int hpet_set_periodic_freq(unsigned long freq);
-extern int hpet_rtc_dropped_irq(void);
-extern int hpet_rtc_timer_init(void);
-#endif /* CONFIG_HPET_EMULATE_RTC */
-
-#endif
+#include <asm-i386/hpet.h>
Index: linux-2.6.22-rc4-mm/include/asm-i386/hpet.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/hpet.h	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/hpet.h	2007-06-16 12:10:24.000000000 +0200
@@ -4,112 +4,87 @@
 
 #ifdef CONFIG_HPET_TIMER
 
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/irq.h>
-#include <asm/msr.h>
-#include <asm/delay.h>
-#include <asm/mpspec.h>
-#include <asm/uaccess.h>
-#include <asm/processor.h>
-
-#include <linux/timex.h>
-
 /*
  * Documentation on HPET can be found at:
  *      http://www.intel.com/ial/home/sp/pcmmspec.htm
  *      ftp://download.intel.com/ial/home/sp/mmts098.pdf
  */
 
-#define HPET_MMAP_SIZE	1024
+#define HPET_MMAP_SIZE		1024
 
-#define HPET_ID		0x000
-#define HPET_PERIOD	0x004
-#define HPET_CFG	0x010
-#define HPET_STATUS	0x020
-#define HPET_COUNTER	0x0f0
-#define HPET_T0_CFG	0x100
-#define HPET_T0_CMP	0x108
-#define HPET_T0_ROUTE	0x110
-#define HPET_T1_CFG	0x120
-#define HPET_T1_CMP	0x128
-#define HPET_T1_ROUTE	0x130
-#define HPET_T2_CFG	0x140
-#define HPET_T2_CMP	0x148
-#define HPET_T2_ROUTE	0x150
-
-#define HPET_ID_LEGSUP	0x00008000
-#define HPET_ID_NUMBER	0x00001f00
-#define HPET_ID_REV	0x000000ff
+#define HPET_ID			0x000
+#define HPET_PERIOD		0x004
+#define HPET_CFG		0x010
+#define HPET_STATUS		0x020
+#define HPET_COUNTER		0x0f0
+#define HPET_T0_CFG		0x100
+#define HPET_T0_CMP		0x108
+#define HPET_T0_ROUTE		0x110
+#define HPET_T1_CFG		0x120
+#define HPET_T1_CMP		0x128
+#define HPET_T1_ROUTE		0x130
+#define HPET_T2_CFG		0x140
+#define HPET_T2_CMP		0x148
+#define HPET_T2_ROUTE		0x150
+
+#define HPET_ID_REV		0x000000ff
+#define HPET_ID_NUMBER		0x00001f00
+#define HPET_ID_64BIT		0x00002000
+#define HPET_ID_LEGSUP		0x00008000
+#define HPET_ID_VENDOR		0xffff0000
 #define	HPET_ID_NUMBER_SHIFT	8
+#define HPET_ID_VENDOR_SHIFT	16
+
+#define HPET_ID_VENDOR_8086	0x8086
 
-#define HPET_CFG_ENABLE	0x001
-#define HPET_CFG_LEGACY	0x002
+#define HPET_CFG_ENABLE		0x001
+#define HPET_CFG_LEGACY		0x002
 #define	HPET_LEGACY_8254	2
 #define	HPET_LEGACY_RTC		8
 
-#define HPET_TN_ENABLE		0x004
-#define HPET_TN_PERIODIC	0x008
-#define HPET_TN_PERIODIC_CAP	0x010
-#define HPET_TN_SETVAL		0x040
-#define HPET_TN_32BIT		0x100
-
-/* Use our own asm for 64 bit multiply/divide */
-#define ASM_MUL64_REG(eax_out,edx_out,reg_in,eax_in) 			\
-		__asm__ __volatile__("mull %2" 				\
-				:"=a" (eax_out), "=d" (edx_out) 	\
-				:"r" (reg_in), "0" (eax_in))
-
-#define ASM_DIV64_REG(eax_out,edx_out,reg_in,eax_in,edx_in) 		\
-		__asm__ __volatile__("divl %2" 				\
-				:"=a" (eax_out), "=d" (edx_out) 	\
-				:"r" (reg_in), "0" (eax_in), "1" (edx_in))
+#define HPET_TN_LEVEL		0x0002
+#define HPET_TN_ENABLE		0x0004
+#define HPET_TN_PERIODIC	0x0008
+#define HPET_TN_PERIODIC_CAP	0x0010
+#define HPET_TN_64BIT_CAP	0x0020
+#define HPET_TN_SETVAL		0x0040
+#define HPET_TN_32BIT		0x0100
+#define HPET_TN_ROUTE		0x3e00
+#define HPET_TN_FSB		0x4000
+#define HPET_TN_FSB_CAP		0x8000
+#define HPET_TN_ROUTE_SHIFT	9
 
-#define KERNEL_TICK_USEC 	(1000000UL/HZ)	/* tick value in microsec */
 /* Max HPET Period is 10^8 femto sec as in HPET spec */
-#define HPET_MAX_PERIOD (100000000UL)
+#define HPET_MAX_PERIOD		100000000UL
 /*
  * Min HPET period is 10^5 femto sec just for safety. If it is less than this,
  * then 32 bit HPET counter wrapsaround in less than 0.5 sec.
  */
-#define HPET_MIN_PERIOD (100000UL)
-#define HPET_TICK_RATE  (HZ * 100000UL)
+#define HPET_MIN_PERIOD		100000UL
 
-extern unsigned long hpet_address;	/* hpet memory map physical address */
+/* hpet memory map physical address */
+extern unsigned long hpet_address;
 extern int is_hpet_enabled(void);
+extern int hpet_enable(void);
 
 #ifdef CONFIG_X86_64
-extern unsigned long hpet_tick;	/* hpet clks count per tick */
-extern int hpet_use_timer;
-extern int hpet_rtc_timer_init(void);
-extern int hpet_enable(void);
-extern int is_hpet_capable(void);
-extern int hpet_readl(unsigned long a);
-#else
-extern int hpet_enable(void);
+/* hpet_readl/writel defines */
+#include <asm/vsyscall.h>
 #endif
 
 #ifdef CONFIG_HPET_EMULATE_RTC
+
+#include <linux/interrupt.h>
+
 extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
 extern int hpet_set_rtc_irq_bit(unsigned long bit_mask);
-extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec);
+extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min,
+			       unsigned char sec);
 extern int hpet_set_periodic_freq(unsigned long freq);
 extern int hpet_rtc_dropped_irq(void);
 extern int hpet_rtc_timer_init(void);
 extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
+
 #endif /* CONFIG_HPET_EMULATE_RTC */
 
 #else
Index: linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/hpet.c	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-16 12:10:24.000000000 +0200
@@ -1,11 +1,14 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/hpet.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/sysdev.h>
 #include <linux/pm.h>
 
+#include <asm/fixmap.h>
 #include <asm/hpet.h>
 #include <asm/io.h>
 
@@ -21,6 +24,27 @@ extern struct clock_event_device *global
  * HPET address is set in acpi/boot.c, when an ACPI entry exists
  */
 unsigned long hpet_address;
+
+#ifdef CONFIG_X86_64
+
+#include <asm/pgtable.h>
+#include <asm/vsyscall.h>
+
+static inline void hpet_set_mapping(void)
+{
+	set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
+	__set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
+}
+
+static inline void __iomem *hpet_get_virt_address(void)
+{
+	return (void __iomem *)fix_to_virt(FIX_HPET_BASE);
+}
+
+static inline void hpet_clear_mapping(void) { }
+
+#else
+
 static void __iomem * hpet_virt_address;
 
 static inline unsigned long hpet_readl(unsigned long a)
@@ -33,6 +57,23 @@ static inline void hpet_writel(unsigned 
 	writel(d, hpet_virt_address + a);
 }
 
+static inline void hpet_set_mapping(void)
+{
+	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+}
+
+static inline void __iomem *hpet_get_virt_address(void)
+{
+	return hpet_virt_address;
+}
+
+static inline void hpet_clear_mapping(void)
+{
+	iounmap(hpet_virt_address);
+	hpet_virt_address = NULL;
+}
+#endif
+
 /*
  * HPET command line enable / disable
  */
@@ -73,7 +114,7 @@ int is_hpet_enabled(void)
 #ifdef CONFIG_HPET
 static void hpet_reserve_platform_timers(unsigned long id)
 {
-	struct hpet __iomem *hpet = hpet_virt_address;
+	struct hpet __iomem *hpet = hpet_get_virt_address();
 	struct hpet_timer __iomem *timer = &hpet->hpet_timers[2];
 	unsigned int nrtimers, i;
 	struct hpet_data hd;
@@ -82,7 +123,7 @@ static void hpet_reserve_platform_timers
 
 	memset(&hd, 0, sizeof (hd));
 	hd.hd_phys_address = hpet_address;
-	hd.hd_address = hpet_virt_address;
+	hd.hd_address = hpet;
 	hd.hd_nirqs = nrtimers;
 	hd.hd_flags = HPET_DATA_PLATFORM;
 	hpet_reserve_timer(&hd, 0);
@@ -237,7 +278,7 @@ int __init hpet_enable(void)
 	if (!is_hpet_capable())
 		return 0;
 
-	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+	hpet_set_mapping();
 
 	/*
 	 * Read the period and check for a sane value:
@@ -333,8 +374,7 @@ int __init hpet_enable(void)
 	return 0;
 
 out_nohpet:
-	iounmap(hpet_virt_address);
-	hpet_virt_address = NULL;
+	hpet_clear_mapping();
 	boot_hpet_disable = 1;
 	return 0;
 }
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/mce_amd.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/mce_amd.c	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/mce_amd.c	2007-06-16 12:10:24.000000000 +0200
@@ -157,9 +157,9 @@ void __cpuinit mce_amd_feature_init(stru
 			high |= K8_APIC_EXT_LVT_ENTRY_THRESHOLD << 20;
 			wrmsr(address, low, high);
 
-			setup_APIC_extened_lvt(K8_APIC_EXT_LVT_ENTRY_THRESHOLD,
-					       THRESHOLD_APIC_VECTOR,
-					       K8_APIC_EXT_INT_MSG_FIX, 0);
+			setup_APIC_extended_lvt(K8_APIC_EXT_LVT_ENTRY_THRESHOLD,
+						THRESHOLD_APIC_VECTOR,
+						K8_APIC_EXT_INT_MSG_FIX, 0);
 
 			threshold_defaults.address = address;
 			threshold_restart_bank(&threshold_defaults, 0, 0);
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/smpboot.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/smpboot.c	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/smpboot.c	2007-06-16 12:10:24.000000000 +0200
@@ -223,8 +223,6 @@ void __cpuinit smp_callin(void)
 	local_irq_disable();
 	Dprintk("Stack at about %p\n",&cpuid);
 
-	disable_APIC_timer();
-
 	/*
 	 * Save our processor parameters
 	 */
@@ -348,8 +346,6 @@ void __cpuinit start_secondary(void)
 		enable_8259A_irq(0);
 	}
 
-	enable_APIC_timer();
-
 	/*
 	 * The sibling maps must be set before turing the online map on for
 	 * this cpu
Index: linux-2.6.22-rc4-mm/drivers/acpi/processor_idle.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/drivers/acpi/processor_idle.c	2007-06-16 12:10:22.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/acpi/processor_idle.c	2007-06-16 12:10:24.000000000 +0200
@@ -203,21 +203,12 @@ static void acpi_timer_check_state(int s
 
 static void acpi_propagate_timer_broadcast(struct acpi_processor *pr)
 {
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 	unsigned long reason;
 
 	reason = pr->power.timer_broadcast_on_state < INT_MAX ?
 		CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
 
 	clockevents_notify(reason, &pr->id);
-#else
-	cpumask_t mask = cpumask_of_cpu(pr->id);
-
-	if (pr->power.timer_broadcast_on_state < INT_MAX)
-		on_each_cpu(switch_APIC_timer_to_ipi, &mask, 1, 1);
-	else
-		on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
-#endif
 }
 
 /* Power(C) State timer broadcast control */
@@ -225,8 +216,6 @@ static void acpi_state_timer_broadcast(s
 				       struct acpi_processor_cx *cx,
 				       int broadcast)
 {
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-
 	int state = cx - pr->power.states;
 
 	if (state >= pr->power.timer_broadcast_on_state) {
@@ -236,7 +225,6 @@ static void acpi_state_timer_broadcast(s
 			CLOCK_EVT_NOTIFY_BROADCAST_EXIT;
 		clockevents_notify(reason, &pr->id);
 	}
-#endif
 }
 
 #else
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/i8253.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/i8253.h	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/i8253.h	2007-06-16 12:10:24.000000000 +0200
@@ -1,6 +1,2 @@
-#ifndef __ASM_I8253_H__
-#define __ASM_I8253_H__
-
-extern spinlock_t i8253_lock;
-
-#endif	/* __ASM_I8253_H__ */
+#include <asm-i386/i8253.h>
+#include <asm/8253pit.h>
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/proto.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/proto.h	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/proto.h	2007-06-16 12:10:24.000000000 +0200
@@ -51,9 +51,6 @@ extern void reserve_bootmem_generic(unsi
 
 extern void load_gs_index(unsigned gs);
 
-extern void stop_timer_interrupt(void);
-extern void main_timer_handler(void);
-
 extern unsigned long end_pfn_map; 
 
 extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long * rsp);
Index: linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/apic.h	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h	2007-06-16 12:10:24.000000000 +0200
@@ -79,12 +79,10 @@ extern void smp_local_timer_interrupt (v
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
-extern void disable_APIC_timer(void);
-extern void enable_APIC_timer(void);
 extern void setup_apic_routing(void);
 
-extern void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
-				   unsigned char msg_type, unsigned char mask);
+extern void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector,
+				    unsigned char msg_type, unsigned char mask);
 
 extern int apic_is_clustered_box(void);
 
@@ -95,10 +93,6 @@ extern int apic_is_clustered_box(void);
 #define K8_APIC_EXT_INT_MSG_EXT 0x7
 #define K8_APIC_EXT_LVT_ENTRY_THRESHOLD    0
 
-void smp_send_timer_broadcast_ipi(void);
-void switch_APIC_timer_to_ipi(void *cpumask);
-void switch_ipi_to_APIC_timer(void *cpumask);
-
 #define ARCH_APICTIMER_STOPS_ON_C3	1
 
 extern unsigned boot_cpu_id;
Index: linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/i8253.c	2007-06-16 12:10:23.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-16 12:10:24.000000000 +0200
@@ -15,8 +15,6 @@
 #include <asm/io.h>
 #include <asm/timer.h>
 
-#include "io_ports.h"
-
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
 
@@ -122,6 +120,7 @@ void __init setup_pit_timer(void)
 	global_clock_event = &pit_clockevent;
 }
 
+#ifndef CONFIG_X86_64
 /*
  * Since the PIT overflows every tick, its not very useful
  * to just read by itself. So use jiffies to emulate a free
@@ -206,3 +205,5 @@ static int __init init_pit_clocksource(v
 	return clocksource_register(&clocksource_pit);
 }
 arch_initcall(init_pit_clocksource);
+
+#endif
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/tsc.c	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/tsc.c	2007-06-16 12:10:24.000000000 +0200
@@ -6,7 +6,9 @@
 #include <linux/time.h>
 #include <linux/acpi.h>
 #include <linux/cpufreq.h>
+#include <linux/acpi_pmtmr.h>
 
+#include <asm/hpet.h>
 #include <asm/timex.h>
 
 static int notsc __initdata = 0;
@@ -90,6 +92,94 @@ core_initcall(cpufreq_tsc);
 
 #endif
 
+#define MAX_RETRIES	5
+#define SMI_TRESHOLD	50000
+
+/*
+ * Read TSC and the reference counters. Take care of SMI disturbance
+ */
+static unsigned long __init tsc_read_refs(unsigned long *pm,
+					  unsigned long *hpet)
+{
+	unsigned long t1, t2;
+	int i;
+
+	for (i = 0; i < MAX_RETRIES; i++) {
+		t1 = get_cycles_sync();
+		if (hpet)
+			*hpet = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF;
+		else
+			*pm = acpi_pm_read_early();
+		t2 = get_cycles_sync();
+		if ((t2 - t1) < SMI_TRESHOLD)
+			return t2;
+	}
+	return ULONG_MAX;
+}
+
+/**
+ * tsc_calibrate - calibrate the tsc on boot
+ */
+void __init tsc_calibrate(void)
+{
+	unsigned long flags, tsc1, tsc2, tr1, tr2, pm1, pm2, hpet1, hpet2;
+	int hpet = is_hpet_enabled();
+
+	local_irq_save(flags);
+
+	tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
+
+	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+	outb(0xb0, 0x43);
+	outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
+	outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42);
+	tr1 = get_cycles_sync();
+	while ((inb(0x61) & 0x20) == 0);
+	tr2 = get_cycles_sync();
+
+	tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
+
+	local_irq_restore(flags);
+
+	/*
+	 * Preset the result with the raw and inaccurate PIT
+	 * calibration value
+	 */
+	tsc_khz = (tr2 - tr1) / 50;
+
+	/* hpet or pmtimer available ? */
+	if (!hpet && !pm1 && !pm2) {
+		printk(KERN_INFO "TSC calibrated against PIT\n");
+		return;
+	}
+
+	/* Check, whether the sampling was disturbed by an SMI */
+	if (tsc1 == ULONG_MAX || tsc2 == ULONG_MAX) {
+		printk(KERN_WARNING "TSC calibration disturbed by SMI, "
+		       "using PIT calibration result\n");
+		return;
+	}
+
+	tsc2 = (tsc2 - tsc1) * 1000000L;
+
+	if (hpet) {
+		printk(KERN_INFO "TSC calibrated against HPET\n");
+		if (hpet2 < hpet1)
+			hpet2 += 0x100000000;
+		hpet2 -= hpet1;
+		tsc1 = (hpet2 * hpet_readl(HPET_PERIOD)) / 1000000;
+	} else {
+		printk(KERN_INFO "TSC calibrated against PM_TIMER\n");
+		if (pm2 < pm1)
+			pm2 += ACPI_PM_OVRRUN;
+		pm2 -= pm1;
+		tsc1 = (pm2 * 1000000000) / PMTMR_TICKS_PER_SEC;
+	}
+
+	tsc_khz = tsc2 / tsc1;
+}
+
 /*
  * Make an educated guess if the TSC is trustworthy and synchronized
  * over all CPUs.
Index: linux-2.6.22-rc4-mm/include/asm-i386/tsc.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/tsc.h	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/tsc.h	2007-06-16 12:10:24.000000000 +0200
@@ -71,4 +71,8 @@ extern void init_tsc_clocksource(void);
 extern void check_tsc_sync_source(int cpu);
 extern void check_tsc_sync_target(void);
 
+#ifdef CONFIG_X86_64
+extern void tsc_calibrate(void);
+#endif
+
 #endif
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/i8259.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/i8259.c	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/i8259.c	2007-06-16 12:10:24.000000000 +0200
@@ -460,47 +460,6 @@ void invalidate_interrupt6(void);
 void invalidate_interrupt7(void);
 void thermal_interrupt(void);
 void threshold_interrupt(void);
-void i8254_timer_resume(void);
-
-static void setup_timer_hardware(void)
-{
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	udelay(10);
-	outb(LATCH >> 8 , 0x40);	/* MSB */
-}
-
-static int timer_resume(struct sys_device *dev)
-{
-	setup_timer_hardware();
-	return 0;
-}
-
-void i8254_timer_resume(void)
-{
-	setup_timer_hardware();
-}
-
-static struct sysdev_class timer_sysclass = {
-	set_kset_name("timer_pit"),
-	.resume		= timer_resume,
-};
-
-static struct sys_device device_timer = {
-	.id		= 0,
-	.cls		= &timer_sysclass,
-};
-
-static int __init init_timer_sysfs(void)
-{
-	int error = sysdev_class_register(&timer_sysclass);
-	if (!error)
-		error = sysdev_register(&device_timer);
-	return error;
-}
-
-device_initcall(init_timer_sysfs);
 
 void __init init_IRQ(void)
 {
@@ -551,12 +510,6 @@ void __init init_IRQ(void)
 	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
 
-	/*
-	 * Set the clock to HZ Hz, we already have a valid
-	 * vector now:
-	 */
-	setup_timer_hardware();
-
 	if (!acpi_ioapic)
 		setup_irq(2, &irq2);
 }
Index: linux-2.6.22-rc4-mm/include/asm-i386/mach-default/io_ports.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/mach-default/io_ports.h	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/mach-default/io_ports.h	2007-06-16 12:10:24.000000000 +0200
@@ -7,11 +7,6 @@
 #ifndef _MACH_IO_PORTS_H
 #define _MACH_IO_PORTS_H
 
-/* i8253A PIT registers */
-#define PIT_MODE		0x43
-#define PIT_CH0			0x40
-#define PIT_CH2			0x42
-
 /* i8259A PIC registers */
 #define PIC_MASTER_CMD		0x20
 #define PIC_MASTER_IMR		0x21
Index: linux-2.6.22-rc4-mm/include/asm-i386/i8253.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-i386/i8253.h	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/i8253.h	2007-06-16 12:10:24.000000000 +0200
@@ -3,6 +3,11 @@
 
 #include <linux/clockchips.h>
 
+/* i8253A PIT registers */
+#define PIT_MODE		0x43
+#define PIT_CH0			0x40
+#define PIT_CH2			0x42
+
 extern spinlock_t i8253_lock;
 
 extern struct clock_event_device *global_clock_event;
Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/Makefile
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/Makefile	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/Makefile	2007-06-16 12:10:24.000000000 +0200
@@ -9,7 +9,7 @@ obj-y	:= process.o signal.o entry.o trap
 		x8664_ksyms.o i387.o syscall.o vsyscall.o \
 		setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
 		pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o bugs.o \
-		perfctr-watchdog.o sched-clock.o
+		perfctr-watchdog.o sched-clock.o i8253.o
 
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_X86_MCE)		+= mce.o therm_throt.o
@@ -49,6 +49,8 @@ obj-y				+= pcspeaker.o
 
 CFLAGS_vsyscall.o		:= $(PROFILING) -g0
 
+i8253-y				+= ../../i386/kernel/i8253.o
+hpet-y				+= ../../i386/kernel/hpet.o
 therm_throt-y                   += ../../i386/kernel/cpu/mcheck/therm_throt.o
 bootflag-y			+= ../../i386/kernel/bootflag.o
 legacy_serial-y			+= ../../i386/kernel/legacy_serial.o

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 21/25] x86_64: hpet restore vread
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (19 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 20/25] x86_64: Convert to cleckevents Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 22/25] x86_64: restore restore nohpet cmdline Thomas Gleixner
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Sébastien Dugué

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: x86-64-hpet-restore-vread.patch --]
[-- Type: text/plain, Size: 1198 bytes --]

>From sebastien.dugue@bull.net

It seems the hpet clocksource's vread method was lost in the x86_64 conversion
to clockevents. So here it is.

Signed-off-by: Sébastien Dugué <sebastien.dugue@bull.net>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

 arch/i386/kernel/hpet.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

Index: linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/hpet.c	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-16 12:10:24.000000000 +0200
@@ -255,6 +255,13 @@ static cycle_t read_hpet(void)
 	return (cycle_t)hpet_readl(HPET_COUNTER);
 }
 
+#ifdef CONFIG_X86_64
+static cycle_t __vsyscall_fn vread_hpet(void)
+{
+	return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
+}
+#endif
+
 static struct clocksource clocksource_hpet = {
 	.name		= "hpet",
 	.rating		= 250,
@@ -263,6 +270,9 @@ static struct clocksource clocksource_hp
 	.shift		= HPET_SHIFT,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.resume		= hpet_start_counter,
+#ifdef CONFIG_X86_64
+	.vread		= vread_hpet,
+#endif
 };
 
 /*

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 22/25] x86_64: restore restore nohpet cmdline
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (20 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 21/25] x86_64: hpet restore vread Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 23/25] x86-64 block irq balancing for timer Thomas Gleixner
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: x86_64-restore-nohpet-cmdline.patch --]
[-- Type: text/plain, Size: 1049 bytes --]

From: Chris Wright <chrisw@sous-sol.org>

Lost when merged with i386.  Happy to drop, but I suspect Andi would
rather not break existing users (I noticed because it was part of my
testing).  If dropped, Documentation needs updating.

Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andi Kleen <ak@suse.de>

---
 arch/i386/kernel/hpet.c |    7 +++++++
 1 file changed, 7 insertions(+)

Index: linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/hpet.c	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-16 12:10:25.000000000 +0200
@@ -89,6 +89,13 @@ static int __init hpet_setup(char* str)
 }
 __setup("hpet=", hpet_setup);
 
+static int __init disable_hpet(char *str)
+{
+	boot_hpet_disable = 1;
+	return 1;
+}
+__setup("nohpet", disable_hpet);
+
 static inline int is_hpet_capable(void)
 {
 	return (!boot_hpet_disable && hpet_address);

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 23/25] x86-64 block irq balancing for timer
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (21 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 22/25] x86_64: restore restore nohpet cmdline Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 24/25] x86_64: prep idle loop for dynticks Thomas Gleixner
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: x86-64-clockevents-irq-balancing.patch --]
[-- Type: text/plain, Size: 907 bytes --]

From: Venki Pallipadi <venkatesh.pallipadi@intel.com>

Disable irq balancing on IRQ0.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andi Kleen <ak@suse.de>

---
 arch/x86_64/kernel/time.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/time.c	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-16 12:10:25.000000000 +0200
@@ -255,7 +255,7 @@ static unsigned int __init tsc_calibrate
 
 static struct irqaction irq0 = {
 	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_IRQPOLL,
+	.flags		= IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
 	.mask		= CPU_MASK_NONE,
 	.name		= "timer"
 };

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 24/25] x86_64: prep idle loop for dynticks
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (22 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 23/25] x86-64 block irq balancing for timer Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 10:36 ` [patch-mm 25/25] x86_64: enable high resolution timers and dynticks Thomas Gleixner
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: x86-64-prepare-idle-for-dyntick.patch --]
[-- Type: text/plain, Size: 1282 bytes --]

From:	Chris Wright <chrisw@sous-sol.org>

Add tick_nohz_{stop,restart}_sched_tick to idle
loop in prepartion for turning on dynticks.  These
are just noops until NO_HZ is enabled in next patch.

Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andi Kleen <ak@suse.de>

---
 arch/x86_64/kernel/process.c |    4 ++++
 1 file changed, 4 insertions(+)

Index: linux-2.6.22-rc4-mm/arch/x86_64/kernel/process.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/process.c	2007-06-16 12:10:20.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/process.c	2007-06-16 12:10:25.000000000 +0200
@@ -37,6 +37,7 @@
 #include <linux/notifier.h>
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
+#include <linux/tick.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -207,6 +208,8 @@ void cpu_idle (void)
 			if (__get_cpu_var(cpu_idle_state))
 				__get_cpu_var(cpu_idle_state) = 0;
 
+			tick_nohz_stop_sched_tick();
+
 			check_pgt_cache();
 			rmb();
 			idle = pm_idle;
@@ -228,6 +231,7 @@ void cpu_idle (void)
 			__exit_idle();
 		}
 
+		tick_nohz_restart_sched_tick();
 		preempt_enable_no_resched();
 		schedule();
 		preempt_disable();

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [patch-mm 25/25] x86_64: enable high resolution timers and dynticks
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (23 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 24/25] x86_64: prep idle loop for dynticks Thomas Gleixner
@ 2007-06-16 10:36 ` Thomas Gleixner
  2007-06-16 14:41 ` [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Alistair John Strachan
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 10:36 UTC (permalink / raw)
  To: LKML
  Cc: Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: x86-64-enable-highres-dyntick.patch --]
[-- Type: text/plain, Size: 802 bytes --]

From:	Chris Wright <chrisw@sous-sol.org>

Everything is in place, enable the HIGHRES andf NO_HZ config options.

Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andi Kleen <ak@suse.de>

---
 arch/x86_64/Kconfig |    2 ++
 1 file changed, 2 insertions(+)

Index: linux-2.6.22-rc4-mm/arch/x86_64/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/Kconfig	2007-06-16 12:10:24.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/Kconfig	2007-06-16 12:10:25.000000000 +0200
@@ -150,6 +150,8 @@ source "init/Kconfig"
 
 menu "Processor type and features"
 
+source "kernel/time/Kconfig"
+
 choice
 	prompt "Subarchitecture Type"
 	default X86_PC

-- 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling
  2007-06-16 10:36 ` [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
@ 2007-06-16 14:36   ` Bernhard Rosenkraenzer
  2007-06-16 14:54     ` Thomas Gleixner
  0 siblings, 1 reply; 52+ messages in thread
From: Bernhard Rosenkraenzer @ 2007-06-16 14:36 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Adam Belay, Len Brown,
	Dave Miller, Paul Mundt, Russell King

On Saturday 16 June 2007, Thomas Gleixner wrote:

> +#if defined(CONFIG_NO_HZ) && !defined(CONFIG_NONIRQ_WAKEUP)
> +	/* Make sure that timer wheel updates are propagated */
> +	if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
> +		tick_nohz_stop_sched_tick();a
> +#endif
>  	preempt_enable_no_resched();
>  }

The bit above breaks the build for a CONFIG_NO_HZ build without 
CONFIG_NONIRQ_WAKEUP -- please remove the extra "a" after 
tick_nohz_stop_sched_tick(); before applying this.

Regards,
bero

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (24 preceding siblings ...)
  2007-06-16 10:36 ` [patch-mm 25/25] x86_64: enable high resolution timers and dynticks Thomas Gleixner
@ 2007-06-16 14:41 ` Alistair John Strachan
  2007-06-16 19:06   ` Thomas Gleixner
  2007-06-16 23:04 ` Nigel Cunningham
  2007-06-18 20:06 ` Valdis.Kletnieks
  27 siblings, 1 reply; 52+ messages in thread
From: Alistair John Strachan @ 2007-06-16 14:41 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Mikko Tiihonen

On Saturday 16 June 2007 11:36:00 Thomas Gleixner wrote:
> The -hrt tree at http://www.tglx.de/projects/hrtimers/2.6.22-rc4/ contains
> also an hpet force patch series from Venki Pallipadi, but I leave this up
> to Venki to send it mainline wards.

What's the status on the nForce "hpet force fix" (Subject: "Enable hidden HPET 
on NVidia motherboards") that also exists? I think if one board can have its 
HPET forced, so can another.

Last I heard we were waiting on NVIDIA to confirm whether Mikko's logic was 
supported by specifications? Any update on this?

-- 
Cheers,
Alistair.

Final year Computer Science undergraduate.
1F2 55 South Clerk Street, Edinburgh, UK.

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling
  2007-06-16 14:36   ` Bernhard Rosenkraenzer
@ 2007-06-16 14:54     ` Thomas Gleixner
  0 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 14:54 UTC (permalink / raw)
  To: Bernhard Rosenkraenzer
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Adam Belay, Len Brown,
	Dave Miller, Paul Mundt, Russell King

On Sat, 2007-06-16 at 16:36 +0200, Bernhard Rosenkraenzer wrote:
> On Saturday 16 June 2007, Thomas Gleixner wrote:
> 
> > +#if defined(CONFIG_NO_HZ) && !defined(CONFIG_NONIRQ_WAKEUP)
> > +	/* Make sure that timer wheel updates are propagated */
> > +	if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
> > +		tick_nohz_stop_sched_tick();a
> > +#endif
> >  	preempt_enable_no_resched();
> >  }
> 
> The bit above breaks the build for a CONFIG_NO_HZ build without 
> CONFIG_NONIRQ_WAKEUP -- please remove the extra "a" after 
> tick_nohz_stop_sched_tick(); before applying this.

Oops. Must have happened when I edited the mailbox. Replacement patch
below:

	tglx

--------------------->

Subject: NOHZ: Fix nox x86 dyntick idle handling

The cpuidle patches moved the tick nohz handling from irq_exit into
the inner idle loop. The change is correct as it covers non interrupt
based wakeups (e.g DMA) on x86 as well, but the move breaks ARM, SH
and SPARC64. 

Keep the original implementation and deselet the irq exit code for
those architectures which have no irq idle wakeups.

This way the non affected architectures are not burdened with the
extra changes in the idle implementation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Adam Belay <abelay@novell.com>
Cc: Len Brown <lenb@kernel.org>
Cc: Dave Miller <davem@davemloft.net>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>

---
 arch/i386/Kconfig |    4 ++++
 kernel/softirq.c  |    5 +++++
 2 files changed, 9 insertions(+)

Index: linux-2.6.22-rc4-mm/arch/i386/Kconfig
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/Kconfig	2007-06-16 17:04:14.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/Kconfig	2007-06-16 17:04:18.000000000 +0200
@@ -31,6 +31,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST
 	default y
 	depends on X86_LOCAL_APIC
 
+config NONIRQ_WAKEUP
+	bool
+	default y
+
 config LOCKDEP_SUPPORT
 	bool
 	default y
Index: linux-2.6.22-rc4-mm/kernel/softirq.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/kernel/softirq.c	2007-06-16 17:04:14.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/softirq.c	2007-06-16 17:04:39.000000000 +0200
@@ -304,6 +304,11 @@ void irq_exit(void)
 	if (!in_interrupt() && local_softirq_pending())
 		invoke_softirq();
 
+#if defined(CONFIG_NO_HZ) && !defined(CONFIG_NONIRQ_WAKEUP)
+	/* Make sure that timer wheel updates are propagated */
+	if (!in_interrupt() && idle_cpu(smp_processor_id()) && !need_resched())
+		tick_nohz_stop_sched_tick();
+#endif
 	preempt_enable_no_resched();
 }
 



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 15/25] clocksource: add settimeofday hook for PPC
  2007-06-16 10:36 ` [patch-mm 15/25] clocksource: add settimeofday hook for PPC Thomas Gleixner
@ 2007-06-16 15:51   ` Daniel Walker
  2007-06-20  6:57     ` [RFC] clocksouce implementation for powerpc Tony Breeds
  0 siblings, 1 reply; 52+ messages in thread
From: Daniel Walker @ 2007-06-16 15:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Tony Breeds, john stultz

On Sat, 2007-06-16 at 10:36 +0000, Thomas Gleixner wrote:
> plain text document attachment
> (clocksource-add-settimeofday-hook.patch)
> From: Tony Breeds <tony@bakeyournoodle.com >
> 
> I'm working on a clocksource implementation for all powerpc platforms.
> some of these platforms needs to do a little work as part of the
> settimeofday() syscall and I can't see a way to do that without adding
> this hook to clocksource.
> 


I'd like to see how this is used? If the code that uses this API change
isn't ready yet, then this patch should really wait..

Daniel


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic)
  2007-06-16 10:36 ` [patch-mm 06/25] clockevents: Fix resume logic Thomas Gleixner
@ 2007-06-16 18:51   ` Oleg Verych
  2007-06-16 19:04     ` Thomas Gleixner
  0 siblings, 1 reply; 52+ messages in thread
From: Oleg Verych @ 2007-06-16 18:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Andrew Morton, Linus Torvalds, Ingo Molnar, Andi Kleen,
	Chris Wright, Arjan van de Ven, Venkatesh Pallipadi, LKML

* From: Thomas Gleixner

[]
> Fixup the existing users.
>
> This removes the sysfs entry for the HPET, which is now controlled by
> the clockevents resume code.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>
> ---
>  arch/arm/mach-davinci/time.c      |    2 +
>  arch/arm/mach-imx/time.c          |    1 
>  arch/arm/mach-ixp4xx/common.c     |    2 +
>  arch/arm/mach-omap1/time.c        |    1 
>  arch/arm/plat-omap/timer32k.c     |    2 +

Testers and users are most likely to run one particular arch on
one particular test bench. If individual patches are arch
separated, i think bisecting will be a little bit easier.

Thus, i would like to propose separate arch patching (x86_64/i386 mainly).

Is it possible to do that? (And even set such check in ``checkpatch''?)

You would say, why? Because current kbuild/kconfig support of builds for
whole tree.

That's because to make download, build, test and debug particular arch
more easily, i'm trying to re-think and re-do some kbuild parts. With
minimum set of files, downloaded with git one can spend less
time/bandwidth for starting testing.

>  arch/i386/kernel/apic.c           |    3 +
>  arch/i386/kernel/hpet.c           |   71 ++------------------------------------
>  arch/i386/kernel/i8253.c          |   26 ++++++-------
>  arch/i386/kernel/vmiclock.c       |    1 
>  arch/i386/xen/time.c              |    1 

Opinions?

>  arch/sh/kernel/timers/timer-tmu.c |    1 
>  arch/sparc64/kernel/time.c        |    1 
____

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic)
  2007-06-16 18:51   ` Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic) Oleg Verych
@ 2007-06-16 19:04     ` Thomas Gleixner
  0 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 19:04 UTC (permalink / raw)
  To: Oleg Verych
  Cc: Andrew Morton, Linus Torvalds, Ingo Molnar, Andi Kleen,
	Chris Wright, Arjan van de Ven, Venkatesh Pallipadi, LKML

Oleg,

On Sat, 2007-06-16 at 20:51 +0200, Oleg Verych wrote:
> >  arch/arm/plat-omap/timer32k.c     |    2 +
> 
> Testers and users are most likely to run one particular arch on
> one particular test bench. If individual patches are arch
> separated, i think bisecting will be a little bit easier.

No it is not. See below.

> Thus, i would like to propose separate arch patching (x86_64/i386 mainly).

This change adds an enum entry in a generic header file. _ALL_ users of
clock events have a switch(this_changed_enum) in the set_mode()
function. _ALL_ of them will spit warnings and some of them will even
break, when the fix up is not done in one go.

> Is it possible to do that? (And even set such check in ``checkpatch''?)

It's possible, but results in an commit which will affect bisecting. I'm
not going to send a patch which knowingly breaks bisecting either at
compile or at run time.

> You would say, why? Because current kbuild/kconfig support of builds
> for whole tree.
> 
> That's because to make download, build, test and debug particular arch
> more easily, i'm trying to re-think and re-do some kbuild parts. With
> minimum set of files, downloaded with git one can spend less
> time/bandwidth for starting testing.

Oh, well. That's going to be an interesting feature for git and the
result will be published kernel trees with a total delta of 40MB against
mainline, because someone tweaked the stuff in a way that it contains
only the relevant files for a particular sub architecture. Embedded
folks do this already and it makes it extremely hard to do efficient
trouble shooting on such crippled trees. No thanks.

If we would still have 9600 Baud modem connections I would understand
that, but git is really effective since packing was added, so this
argument is more or less an academic exercise.

	tglx



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-16 14:41 ` [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Alistair John Strachan
@ 2007-06-16 19:06   ` Thomas Gleixner
  0 siblings, 0 replies; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-16 19:06 UTC (permalink / raw)
  To: Alistair John Strachan
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, Mikko Tiihonen

On Sat, 2007-06-16 at 15:41 +0100, Alistair John Strachan wrote:
> On Saturday 16 June 2007 11:36:00 Thomas Gleixner wrote:
> > The -hrt tree at http://www.tglx.de/projects/hrtimers/2.6.22-rc4/ contains
> > also an hpet force patch series from Venki Pallipadi, but I leave this up
> > to Venki to send it mainline wards.
> 
> What's the status on the nForce "hpet force fix" (Subject: "Enable hidden HPET 
> on NVidia motherboards") that also exists? I think if one board can have its 
> HPET forced, so can another.
> 
> Last I heard we were waiting on NVIDIA to confirm whether Mikko's logic was 
> supported by specifications? Any update on this?

The full hpet force enable series is maintained by Venki and updates
should go to him. I can add the patch to my -hrt queue for testing.

	tglx



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (25 preceding siblings ...)
  2007-06-16 14:41 ` [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Alistair John Strachan
@ 2007-06-16 23:04 ` Nigel Cunningham
  2007-06-18 20:06 ` Valdis.Kletnieks
  27 siblings, 0 replies; 52+ messages in thread
From: Nigel Cunningham @ 2007-06-16 23:04 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: Type: text/plain, Size: 268 bytes --]

Hi all.

I'm currently running with the combined patch applied all the time, and it 
seems to be working fine here, including with hibernation.

Regards,

Nigel
-- 
Nigel, Michelle and Alisdair Cunningham
5 Mitchell Street
Cobden 3266
Victoria, Australia

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
                   ` (26 preceding siblings ...)
  2007-06-16 23:04 ` Nigel Cunningham
@ 2007-06-18 20:06 ` Valdis.Kletnieks
  2007-06-18 20:24   ` Pallipadi, Venkatesh
  2007-06-19  1:52   ` Arjan van de Ven
  27 siblings, 2 replies; 52+ messages in thread
From: Valdis.Kletnieks @ 2007-06-18 20:06 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi

[-- Attachment #1: Type: text/plain, Size: 1266 bytes --]

On Sat, 16 Jun 2007 10:36:00 -0000, Thomas Gleixner said:
> The following patch series contains:
> 
> - dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
> 
> - updates and improvements to high resolution timer / dynticks 
> 
> - high resolution timer / dynticks support for x86_64

Am running with the 22-rc4-mm2-hrt4 patch on my Latitude D820.  Mostly seems
to work, but for some reason the Intel 'powertop' util thinks it's 100% busy:

     PowerTOP version 1.7       (C) 2007 Intel Corporation

Cn          Avg residency (5s)          P-states (frequencies)
C0 (cpu running)        (100.0%)
C1                0.0ms ( 0.0%)         2.00 Ghz     0.0%
C2                0.0ms ( 0.0%)         1.67 Ghz     0.0%
C3                0.0ms ( 0.0%)         1333 Mhz     0.0%
                                        1000 Mhz   100.0%

In reality:

[/sys/devices/system/cpu/cpu0/cpuidle] for i in */*; do echo -n "$i: "; cat $i; done
state0/latency: 1
state0/power: 1000
state0/time: 0
state0/usage: 3
state1/latency: 1
state1/power: 500
state1/time: 1756017623
state1/usage: 1837402
state2/latency: 57
state2/power: 100
state2/time: -159524787
state2/usage: 15007443

I think we have a 32/64 bit issue on state2/time which is probably borking
things up....


[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

^ permalink raw reply	[flat|nested] 52+ messages in thread

* RE: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-18 20:06 ` Valdis.Kletnieks
@ 2007-06-18 20:24   ` Pallipadi, Venkatesh
  2007-06-18 21:49     ` Valdis.Kletnieks
  2007-06-19  1:52   ` Arjan van de Ven
  1 sibling, 1 reply; 52+ messages in thread
From: Pallipadi, Venkatesh @ 2007-06-18 20:24 UTC (permalink / raw)
  To: Valdis.Kletnieks, Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven

 

>-----Original Message-----
>From: Valdis.Kletnieks@vt.edu [mailto:Valdis.Kletnieks@vt.edu] 
>Sent: Monday, June 18, 2007 1:07 PM
>To: Thomas Gleixner
>Cc: LKML; Andrew Morton; Ingo Molnar; Andi Kleen; Chris 
>Wright; Arjan van de Ven; Pallipadi, Venkatesh
>Subject: Re: [patch-mm 00/25] High resolution timer updates 
>and x86_64 support - V2
>
>On Sat, 16 Jun 2007 10:36:00 -0000, Thomas Gleixner said:
>> The following patch series contains:
>> 
>> - dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
>> 
>> - updates and improvements to high resolution timer / dynticks 
>> 
>> - high resolution timer / dynticks support for x86_64
>
>Am running with the 22-rc4-mm2-hrt4 patch on my Latitude D820. 
> Mostly seems
>to work, but for some reason the Intel 'powertop' util thinks 
>it's 100% busy:
>
>     PowerTOP version 1.7       (C) 2007 Intel Corporation
>
>Cn          Avg residency (5s)          P-states (frequencies)
>C0 (cpu running)        (100.0%)
>C1                0.0ms ( 0.0%)         2.00 Ghz     0.0%
>C2                0.0ms ( 0.0%)         1.67 Ghz     0.0%
>C3                0.0ms ( 0.0%)         1333 Mhz     0.0%
>                                        1000 Mhz   100.0%
>
>In reality:
>
>[/sys/devices/system/cpu/cpu0/cpuidle] for i in */*; do echo 
>-n "$i: "; cat $i; done
>state0/latency: 1
>state0/power: 1000
>state0/time: 0
>state0/usage: 3
>state1/latency: 1
>state1/power: 500
>state1/time: 1756017623
>state1/usage: 1837402
>state2/latency: 57
>state2/power: 100
>state2/time: -159524787
>state2/usage: 15007443
>

The problem is powertop only understands /proc/acpi/processor/CPU*/power
for
and not /sys..cpuidle for the moment.

I had a patch in recent cpuidle fixes series that makes /proc interface
active
again with cpuidle which should correct this. Those patches are not in
rc4-mm2-hrt4, but are there in latest rc4-hrt and rc5-hrt series.

Thanks,
Venki 

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-18 20:24   ` Pallipadi, Venkatesh
@ 2007-06-18 21:49     ` Valdis.Kletnieks
  2007-06-18 22:10       ` Pallipadi, Venkatesh
  2007-06-19 11:28       ` Valdis.Kletnieks
  0 siblings, 2 replies; 52+ messages in thread
From: Valdis.Kletnieks @ 2007-06-18 21:49 UTC (permalink / raw)
  To: Pallipadi, Venkatesh
  Cc: Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar, Andi Kleen,
	Chris Wright, Arjan van de Ven

[-- Attachment #1: Type: text/plain, Size: 748 bytes --]

On Mon, 18 Jun 2007 13:24:33 PDT, "Pallipadi, Venkatesh" said:

> >state2/time: -159524787
> >state2/usage: 15007443
> >
> 
> The problem is powertop only understands /proc/acpi/processor/CPU*/power
> for
> and not /sys..cpuidle for the moment.
> 
> I had a patch in recent cpuidle fixes series that makes /proc interface
> active
> again with cpuidle which should correct this. Those patches are not in
> rc4-mm2-hrt4, but are there in latest rc4-hrt and rc5-hrt series.

OK, so I've got a 32/64 bug that isn't the cause of *this* issue because
powertop isn't looking at the broken value.

A quick check shows that the keep_proc_acpi_power_around_001.patch from
rc5-hrt will apply to rc4-mm2-hrt - I'll give that a try tonight and report
back...


[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

^ permalink raw reply	[flat|nested] 52+ messages in thread

* RE: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-18 21:49     ` Valdis.Kletnieks
@ 2007-06-18 22:10       ` Pallipadi, Venkatesh
  2007-06-19 11:28       ` Valdis.Kletnieks
  1 sibling, 0 replies; 52+ messages in thread
From: Pallipadi, Venkatesh @ 2007-06-18 22:10 UTC (permalink / raw)
  To: Valdis.Kletnieks
  Cc: Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar, Andi Kleen,
	Chris Wright, Arjan van de Ven

 

>-----Original Message-----
>From: Valdis.Kletnieks@vt.edu [mailto:Valdis.Kletnieks@vt.edu] 
>Sent: Monday, June 18, 2007 2:50 PM
>To: Pallipadi, Venkatesh
>Cc: Thomas Gleixner; LKML; Andrew Morton; Ingo Molnar; Andi 
>Kleen; Chris Wright; Arjan van de Ven
>Subject: Re: [patch-mm 00/25] High resolution timer updates 
>and x86_64 support - V2
>
>On Mon, 18 Jun 2007 13:24:33 PDT, "Pallipadi, Venkatesh" said:
>
>> >state2/time: -159524787
>> >state2/usage: 15007443
>> >
>> 
>> The problem is powertop only understands 
>/proc/acpi/processor/CPU*/power
>> for
>> and not /sys..cpuidle for the moment.
>> 
>> I had a patch in recent cpuidle fixes series that makes 
>/proc interface
>> active
>> again with cpuidle which should correct this. Those patches 
>are not in
>> rc4-mm2-hrt4, but are there in latest rc4-hrt and rc5-hrt series.
>
>OK, so I've got a 32/64 bug that isn't the cause of *this* 
>issue because
>powertop isn't looking at the broken value.
>

Yes. The output does indicate a bug in cpuidle /sysfs part. Will look at
sysfs output of cpuidle and fix those issues soon.

Thanks,
Venki

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-18 20:06 ` Valdis.Kletnieks
  2007-06-18 20:24   ` Pallipadi, Venkatesh
@ 2007-06-19  1:52   ` Arjan van de Ven
  1 sibling, 0 replies; 52+ messages in thread
From: Arjan van de Ven @ 2007-06-19  1:52 UTC (permalink / raw)
  To: Valdis.Kletnieks
  Cc: Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar, Andi Kleen,
	Chris Wright, Venkatesh Pallipadi

On Mon, 2007-06-18 at 16:06 -0400, Valdis.Kletnieks@vt.edu wrote:
> On Sat, 16 Jun 2007 10:36:00 -0000, Thomas Gleixner said:
> > The following patch series contains:
> > 
> > - dyntick bugfixes for -mm (caused by the cpuidle changes in ACPI)
> > 
> > - updates and improvements to high resolution timer / dynticks 
> > 
> > - high resolution timer / dynticks support for x86_64
> 
> Am running with the 22-rc4-mm2-hrt4 patch on my Latitude D820.  Mostly seems
> to work, but for some reason the Intel 'powertop' util thinks it's 100% busy:
> 
>      PowerTOP version 1.7       (C) 2007 Intel Corporation
> 
> Cn          Avg residency (5s)          P-states (frequencies)
> C0 (cpu running)        (100.0%)
> C1                0.0ms ( 0.0%)         2.00 Ghz     0.0%
> C2                0.0ms ( 0.0%)         1.67 Ghz     0.0%
> C3                0.0ms ( 0.0%)         1333 Mhz     0.0%
>                                         1000 Mhz   100.0%
> 
> In reality:


looks like something broke the /proc/acpi/processor/*/power file
data....

can you check in that file to see if there is actual C-state time
accounting going on?
(it is in mainline, so if it's not then it's an -mm or -hrt bug)

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 14/25] NTP: Move the cmos update code into ntp.c
  2007-06-16 10:36 ` [patch-mm 14/25] NTP: Move the cmos update code into ntp.c Thomas Gleixner
@ 2007-06-19  8:26   ` Franck Bui-Huu
  0 siblings, 0 replies; 52+ messages in thread
From: Franck Bui-Huu @ 2007-06-19  8:26 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Andrew Morton, Ingo Molnar, Andi Kleen, Chris Wright,
	Arjan van de Ven, Venkatesh Pallipadi, john stultz, David Miller

Hi Thomas,

Thomas Gleixner wrote:
> i386 and sparc64 have the identical code to update the cmos clock.
> Move it into kernel/time/ntp.c as there are other architectures
> coming along with the same requirements.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Chris Wright <chrisw@sous-sol.org>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: john stultz <johnstul@us.ibm.com>
> Cc: David Miller <davem@davemloft.net>
> 
> ---
>  arch/i386/Kconfig          |    4 +++
>  arch/i386/kernel/time.c    |   50 +-------------------------------------
>  arch/sparc64/Kconfig       |    4 +++
>  arch/sparc64/kernel/time.c |   53 +---------------------------------------
>  include/asm-i386/timer.h   |    1 
>  include/linux/time.h       |    2 +
>  kernel/time/ntp.c          |   59 ++++++++++++++++++++++++++++++++++++++++++---
>  7 files changed, 70 insertions(+), 103 deletions(-)
> 

[snip]

>  /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
> Index: linux-2.6.22-rc4-mm/include/linux/time.h
> ===================================================================
> --- linux-2.6.22-rc4-mm.orig/include/linux/time.h	2007-06-16 12:10:21.000000000 +0200
> +++ linux-2.6.22-rc4-mm/include/linux/time.h	2007-06-16 12:10:24.000000000 +0200
> @@ -93,6 +93,8 @@ extern struct timespec wall_to_monotonic
>  extern seqlock_t xtime_lock __attribute__((weak));
>  
>  extern unsigned long read_persistent_clock(void);
> +extern int update_persistent_clock(struct timespec now);

I'm wondering if update_persistent_clock shouldn't be part of
"drivers/rtc/*" framework. Do you have any idea on how this
is going to be implemented on platforms that use this framework ?

> +extern int no_sync_cmos_clock __read_mostly;
>  void timekeeping_init(void);
>  
>  static inline unsigned long get_seconds(void)
> Index: linux-2.6.22-rc4-mm/kernel/time/ntp.c
> ===================================================================
> --- linux-2.6.22-rc4-mm.orig/kernel/time/ntp.c	2007-06-16 12:10:21.000000000 +0200
> +++ linux-2.6.22-rc4-mm/kernel/time/ntp.c	2007-06-16 12:10:24.000000000 +0200
> @@ -10,6 +10,7 @@
>  
>  #include <linux/mm.h>
>  #include <linux/time.h>
> +#include <linux/timer.h>
>  #include <linux/timex.h>
>  #include <linux/jiffies.h>
>  #include <linux/hrtimer.h>
> @@ -187,12 +188,64 @@ u64 current_tick_length(void)
>  	return tick_length;
>  }
>  
> +#ifdef CONFIG_GENERIC_CMOS_UPDATE
>  
> -void __attribute__ ((weak)) notify_arch_cmos_timer(void)
> +/* Disable the cmos update - used by virtualization and embedded */
> +int no_sync_cmos_clock  __read_mostly;
> +

[snip]

>  
> +static void notify_cmos_timer(void)
> +{
> +	if (no_sync_cmos_clock)
> +		mod_timer(&sync_cmos_timer, jiffies + 1);
> +}

Isn't the test condition wrong ? Shouldn't it be:

	if (!no_sync_cmos_clock)
		mod_timer(&sync_cmos_timer, jiffies + 1);

Thanks,

		Franck

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [patch-mm 00/25] High resolution timer updates and x86_64 support - V2
  2007-06-18 21:49     ` Valdis.Kletnieks
  2007-06-18 22:10       ` Pallipadi, Venkatesh
@ 2007-06-19 11:28       ` Valdis.Kletnieks
  1 sibling, 0 replies; 52+ messages in thread
From: Valdis.Kletnieks @ 2007-06-19 11:28 UTC (permalink / raw)
  Cc: Pallipadi, Venkatesh, Thomas Gleixner, LKML, Andrew Morton,
	Ingo Molnar, Andi Kleen, Chris Wright, Arjan van de Ven

[-- Attachment #1: Type: text/plain, Size: 733 bytes --]

On Mon, 18 Jun 2007 17:49:44 EDT, Valdis.Kletnieks@vt.edu said:

> A quick check shows that the keep_proc_acpi_power_around_001.patch from
> rc5-hrt will apply to rc4-mm2-hrt - I'll give that a try tonight and report
> back...

Confirming - I backported that patch from rc5-hrt to rc4-mm2-hrt, and
now powertop is reporting sane values again:

     PowerTOP version 1.7       (C) 2007 Intel Corporation

Cn          Avg residency (5s)          P-states (frequencies)
C0 (cpu running)        (15.8%)
C1                0.0ms ( 0.0%)         2.00 Ghz     0.0%
C2                0.6ms ( 7.9%)         1.67 Ghz     0.0%
C3                0.7ms (76.3%)         1333 Mhz     0.0%
                                        1000 Mhz   100.0%



[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]

^ permalink raw reply	[flat|nested] 52+ messages in thread

* [RFC] clocksouce implementation for powerpc
  2007-06-16 15:51   ` Daniel Walker
@ 2007-06-20  6:57     ` Tony Breeds
  2007-06-20 14:57       ` Daniel Walker
                         ` (2 more replies)
  0 siblings, 3 replies; 52+ messages in thread
From: Tony Breeds @ 2007-06-20  6:57 UTC (permalink / raw)
  To: Daniel Walker
  Cc: Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar, john stultz,
	LinuxPPC-dev

On Sat, Jun 16, 2007 at 08:51:23AM -0700, Daniel Walker wrote:
> On Sat, 2007-06-16 at 10:36 +0000, Thomas Gleixner wrote:
> > plain text document attachment
> > (clocksource-add-settimeofday-hook.patch)
> > From: Tony Breeds <tony@bakeyournoodle.com >
> > 
> > I'm working on a clocksource implementation for all powerpc platforms.
> > some of these platforms needs to do a little work as part of the
> > settimeofday() syscall and I can't see a way to do that without adding
> > this hook to clocksource.
> > 
> 
> 
> I'd like to see how this is used? If the code that uses this API change
> isn't ready yet, then this patch should really wait..

This is my current patch to rework arch/powerpc/kernel/time.c to create
a clocksource.  It's not ready for inclusion.

powerpc needs to keep the vdso in sync whenener settimeodfay() is
called.  Adding the hook the to the clocksource structure was my way of
allowing this to happen.  There are other approaches, but this seemed to
best allow for runtime.  Initially I considered using update_vsyscall()
but this is called from do_timer(), and I don't need this code run then
:(

This has been booted on pSeries and iSeries (I'm using glibc 2.5, which
uses the vdso gettimeoday())

All comments appreiated.

Index: working/arch/powerpc/Kconfig
===================================================================
--- working.orig/arch/powerpc/Kconfig
+++ working/arch/powerpc/Kconfig
@@ -31,6 +31,12 @@ config MMU
 	bool
 	default y
 
+config GENERIC_TIME
+	def_bool y
+
+config GENERIC_TIME_VSYSCALL
+	def_bool y
+
 config GENERIC_HARDIRQS
 	bool
 	default y
Index: working/arch/powerpc/kernel/time.c
===================================================================
--- working.orig/arch/powerpc/kernel/time.c
+++ working/arch/powerpc/kernel/time.c
@@ -74,6 +74,30 @@
 #endif
 #include <asm/smp.h>
 
+/* powerpc clocksource/clockevent code */
+
+/* TODO:
+ *  o Code style
+ *    * Variable names ... be consistent.
+ *
+ * TODO: Clocksource
+ *  o Need a _USE_RTC() clocksource impelementation
+ *  o xtime:  Either time.c manages it, or clocksource does, not both
+ */
+
+#include <linux/clocksource.h>
+
+static struct clocksource clocksource_timebase = {
+	.name         = "timebase",
+	.rating       = 200,
+	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,
+	.mask         = CLOCKSOURCE_MASK(64),
+	.shift        = 22,
+	.mult         = 0,	/* To be filled in */
+	.read         = NULL,   /* To be filled in */
+	.settimeofday = NULL,   /* To be filled in */
+};
+
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
 #ifdef CONFIG_PPC_ISERIES
@@ -376,65 +400,6 @@ static __inline__ void timer_check_rtc(v
         }
 }
 
-/*
- * This version of gettimeofday has microsecond resolution.
- */
-static inline void __do_gettimeofday(struct timeval *tv)
-{
-	unsigned long sec, usec;
-	u64 tb_ticks, xsec;
-	struct gettimeofday_vars *temp_varp;
-	u64 temp_tb_to_xs, temp_stamp_xsec;
-
-	/*
-	 * These calculations are faster (gets rid of divides)
-	 * if done in units of 1/2^20 rather than microseconds.
-	 * The conversion to microseconds at the end is done
-	 * without a divide (and in fact, without a multiply)
-	 */
-	temp_varp = do_gtod.varp;
-
-	/* Sampling the time base must be done after loading
-	 * do_gtod.varp in order to avoid racing with update_gtod.
-	 */
-	data_barrier(temp_varp);
-	tb_ticks = get_tb() - temp_varp->tb_orig_stamp;
-	temp_tb_to_xs = temp_varp->tb_to_xs;
-	temp_stamp_xsec = temp_varp->stamp_xsec;
-	xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
-	sec = xsec / XSEC_PER_SEC;
-	usec = (unsigned long)xsec & (XSEC_PER_SEC - 1);
-	usec = SCALE_XSEC(usec, 1000000);
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-void do_gettimeofday(struct timeval *tv)
-{
-	if (__USE_RTC()) {
-		/* do this the old way */
-		unsigned long flags, seq;
-		unsigned int sec, nsec, usec;
-
-		do {
-			seq = read_seqbegin_irqsave(&xtime_lock, flags);
-			sec = xtime.tv_sec;
-			nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
-		} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-		usec = nsec / 1000;
-		while (usec >= 1000000) {
-			usec -= 1000000;
-			++sec;
-		}
-		tv->tv_sec = sec;
-		tv->tv_usec = usec;
-		return;
-	}
-	__do_gettimeofday(tv);
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
 
 /*
  * There are two copies of tb_to_xs and stamp_xsec so that no
@@ -666,8 +631,8 @@ void timer_interrupt(struct pt_regs * re
 		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
 			tb_last_jiffy = tb_next_jiffy;
 			do_timer(1);
-			timer_recalc_offset(tb_last_jiffy);
-			timer_check_rtc();
+			/* timer_recalc_offset() && timer_check_rtc()
+			 * are now called from update_vsyscall() */
 		}
 		write_sequnlock(&xtime_lock);
 	}
@@ -739,77 +704,6 @@ unsigned long long sched_clock(void)
 	return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
 }
 
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, new_sec = tv->tv_sec;
-	long wtm_nsec, new_nsec = tv->tv_nsec;
-	unsigned long flags;
-	u64 new_xsec;
-	unsigned long tb_delta;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-
-	/*
-	 * Updating the RTC is not the job of this code. If the time is
-	 * stepped under NTP, the RTC will be updated after STA_UNSYNC
-	 * is cleared.  Tools like clock/hwclock either copy the RTC
-	 * to the system time, in which case there is no point in writing
-	 * to the RTC again, or write to the RTC but then they don't call
-	 * settimeofday to perform this operation.
-	 */
-#ifdef CONFIG_PPC_ISERIES
-	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
-		iSeries_tb_recal();
-		first_settimeofday = 0;
-	}
-#endif
-
-	/* Make userspace gettimeofday spin until we're done. */
-	++vdso_data->tb_update_count;
-	smp_mb();
-
-	/*
-	 * Subtract off the number of nanoseconds since the
-	 * beginning of the last tick.
-	 */
-	tb_delta = tb_ticks_since(tb_last_jiffy);
-	tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
-	new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
-
- 	set_normalized_timespec(&xtime, new_sec, new_nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	/* In case of a large backwards jump in time with NTP, we want the 
-	 * clock to be updated as soon as the PLL is again in lock.
-	 */
-	last_rtc_update = new_sec - 658;
-
-	ntp_clear();
-
-	new_xsec = xtime.tv_nsec;
-	if (new_xsec != 0) {
-		new_xsec *= XSEC_PER_SEC;
-		do_div(new_xsec, NSEC_PER_SEC);
-	}
-	new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
-	update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
-
-	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
-	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
-
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
 static int __init get_freq(char *name, int cells, unsigned long *val)
 {
 	struct device_node *cpu;
@@ -878,6 +772,78 @@ unsigned long get_boot_time(void)
 		      tm.tm_hour, tm.tm_min, tm.tm_sec);
 }
 
+/* clocksource code */
+static cycle_t timebase_read(void)
+{
+	return (cycle_t)get_tb();
+}
+
+static void clocksource_settimeofday(struct clocksource *cs,
+                                     struct timespec *ts)
+{
+	u64 new_xsec;
+
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
+		iSeries_tb_recal();
+		first_settimeofday = 0;
+	}
+#endif
+
+	/* Make userspace gettimeofday spin until we're done. */
+	++vdso_data->tb_update_count;
+	smp_mb();
+
+	/* In case of a large backwards jump in time with NTP, we want the
+	 * clock to be updated as soon as the PLL is again in lock.
+	 */
+	last_rtc_update = xtime.tv_sec - 658;
+
+	new_xsec = xtime.tv_nsec;
+	if (new_xsec != 0) {
+		new_xsec *= XSEC_PER_SEC;
+		do_div(new_xsec, NSEC_PER_SEC);
+	}
+
+	new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
+
+	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
+	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
+
+	update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
+}
+
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
+{
+	timer_recalc_offset(tb_last_jiffy);
+	timer_check_rtc();
+}
+
+void __init clocksource_init(void)
+{
+	int mult;
+
+	if (__USE_RTC())
+		return;
+
+	mult = clocksource_hz2mult(tb_ticks_per_sec,
+	                           clocksource_timebase.shift);
+	clocksource_timebase.mult = mult;
+
+	clocksource_timebase.read = timebase_read;
+	clocksource_timebase.settimeofday = clocksource_settimeofday;
+
+	if (clocksource_register(&clocksource_timebase)) {
+		printk(KERN_ERR "clocksource: %s is already registered\n",
+		       clocksource_timebase.name);
+		return;
+	}
+
+	printk(KERN_INFO "clocksource: %s mult[%x] shift[%d] registered\n",
+	       clocksource_timebase.name,
+	       clocksource_timebase.mult, clocksource_timebase.shift);
+}
+
 /* This function is only called on the boot processor */
 void __init time_init(void)
 {
@@ -999,6 +965,9 @@ void __init time_init(void)
 	                        -xtime.tv_sec, -xtime.tv_nsec);
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
+	/* Register the clocksource */
+	clocksource_init();
+
 	/* Not exact, but the timer interrupt takes care of this */
 	set_dec(tb_ticks_per_jiffy);
 }
Yours Tony

  linux.conf.au        http://linux.conf.au/ || http://lca2008.linux.org.au/
  Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20  6:57     ` [RFC] clocksouce implementation for powerpc Tony Breeds
@ 2007-06-20 14:57       ` Daniel Walker
  2007-06-20 17:20         ` Sergei Shtylyov
  2007-06-22  6:23         ` Tony Breeds
  2007-06-20 16:53       ` Sergei Shtylyov
  2007-06-20 21:06       ` john stultz
  2 siblings, 2 replies; 52+ messages in thread
From: Daniel Walker @ 2007-06-20 14:57 UTC (permalink / raw)
  To: Tony Breeds
  Cc: Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar, john stultz,
	LinuxPPC-dev

On Wed, 2007-06-20 at 16:57 +1000, Tony Breeds wrote:
> On Sat, Jun 16, 2007 at 08:51:23AM -0700, Daniel Walker wrote:
> > On Sat, 2007-06-16 at 10:36 +0000, Thomas Gleixner wrote:
> > > plain text document attachment
> > > (clocksource-add-settimeofday-hook.patch)
> > > From: Tony Breeds <tony@bakeyournoodle.com >
> > > 
> > > I'm working on a clocksource implementation for all powerpc platforms.
> > > some of these platforms needs to do a little work as part of the
> > > settimeofday() syscall and I can't see a way to do that without adding
> > > this hook to clocksource.
> > > 
> > 
> > 
> > I'd like to see how this is used? If the code that uses this API change
> > isn't ready yet, then this patch should really wait..
> 
> This is my current patch to rework arch/powerpc/kernel/time.c to create
> a clocksource.  It's not ready for inclusion.
> 
> powerpc needs to keep the vdso in sync whenener settimeodfay() is
> called.  Adding the hook the to the clocksource structure was my way of
> allowing this to happen.  There are other approaches, but this seemed to
> best allow for runtime.  Initially I considered using update_vsyscall()
> but this is called from do_timer(), and I don't need this code run then
> :(

As I said in our private thread, I do think you should be using
update_vsyscall() .. update_vsyscall() is just called when the time is
set, usually that happens in the timer interrupt and sometimes that
happens in settimeofday() ..

> This has been booted on pSeries and iSeries (I'm using glibc 2.5, which
> uses the vdso gettimeoday())
> 
> All comments appreiated.

At least some of your code is duplications over what is already being
worked on inside the powerpc community.. For instance, I know there is
already a timebase clocksource,

http://people.redhat.com/~mingo/realtime-preempt/patch-2.6.21.5-rt17


> Index: working/arch/powerpc/Kconfig
> ===================================================================
> --- working.orig/arch/powerpc/Kconfig
> +++ working/arch/powerpc/Kconfig
> @@ -31,6 +31,12 @@ config MMU
>  	bool
>  	default y
>  
> +config GENERIC_TIME
> +	def_bool y
> +
> +config GENERIC_TIME_VSYSCALL
> +	def_bool y
> +
>  config GENERIC_HARDIRQS
>  	bool
>  	default y
> Index: working/arch/powerpc/kernel/time.c
> ===================================================================
> --- working.orig/arch/powerpc/kernel/time.c
> +++ working/arch/powerpc/kernel/time.c
> @@ -74,6 +74,30 @@
>  #endif
>  #include <asm/smp.h>
>  
> +/* powerpc clocksource/clockevent code */
> +
> +/* TODO:
> + *  o Code style
> + *    * Variable names ... be consistent.
> + *
> + * TODO: Clocksource
> + *  o Need a _USE_RTC() clocksource impelementation
> + *  o xtime:  Either time.c manages it, or clocksource does, not both
> + */
> +
> +#include <linux/clocksource.h>
> +
> +static struct clocksource clocksource_timebase = {
> +	.name         = "timebase",
> +	.rating       = 200,
> +	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,
> +	.mask         = CLOCKSOURCE_MASK(64),
> +	.shift        = 22,
> +	.mult         = 0,	/* To be filled in */
> +	.read         = NULL,   /* To be filled in */
> +	.settimeofday = NULL,   /* To be filled in */
> +};
> +
>  /* keep track of when we need to update the rtc */
>  time_t last_rtc_update;
>  #ifdef CONFIG_PPC_ISERIES
> @@ -376,65 +400,6 @@ static __inline__ void timer_check_rtc(v
>          }
>  }
>  
> -/*
> - * This version of gettimeofday has microsecond resolution.
> - */
> -static inline void __do_gettimeofday(struct timeval *tv)
> -{
> -	unsigned long sec, usec;
> -	u64 tb_ticks, xsec;
> -	struct gettimeofday_vars *temp_varp;
> -	u64 temp_tb_to_xs, temp_stamp_xsec;
> -
> -	/*
> -	 * These calculations are faster (gets rid of divides)
> -	 * if done in units of 1/2^20 rather than microseconds.
> -	 * The conversion to microseconds at the end is done
> -	 * without a divide (and in fact, without a multiply)
> -	 */
> -	temp_varp = do_gtod.varp;
> -
> -	/* Sampling the time base must be done after loading
> -	 * do_gtod.varp in order to avoid racing with update_gtod.
> -	 */
> -	data_barrier(temp_varp);
> -	tb_ticks = get_tb() - temp_varp->tb_orig_stamp;
> -	temp_tb_to_xs = temp_varp->tb_to_xs;
> -	temp_stamp_xsec = temp_varp->stamp_xsec;
> -	xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
> -	sec = xsec / XSEC_PER_SEC;
> -	usec = (unsigned long)xsec & (XSEC_PER_SEC - 1);
> -	usec = SCALE_XSEC(usec, 1000000);
> -
> -	tv->tv_sec = sec;
> -	tv->tv_usec = usec;
> -}
> -
> -void do_gettimeofday(struct timeval *tv)
> -{
> -	if (__USE_RTC()) {
> -		/* do this the old way */
> -		unsigned long flags, seq;
> -		unsigned int sec, nsec, usec;
> -
> -		do {
> -			seq = read_seqbegin_irqsave(&xtime_lock, flags);
> -			sec = xtime.tv_sec;
> -			nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
> -		} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
> -		usec = nsec / 1000;
> -		while (usec >= 1000000) {
> -			usec -= 1000000;
> -			++sec;
> -		}
> -		tv->tv_sec = sec;
> -		tv->tv_usec = usec;
> -		return;
> -	}
> -	__do_gettimeofday(tv);
> -}
> -
> -EXPORT_SYMBOL(do_gettimeofday);
>  
>  /*
>   * There are two copies of tb_to_xs and stamp_xsec so that no
> @@ -666,8 +631,8 @@ void timer_interrupt(struct pt_regs * re
>  		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
>  			tb_last_jiffy = tb_next_jiffy;
>  			do_timer(1);
> -			timer_recalc_offset(tb_last_jiffy);
> -			timer_check_rtc();
> +			/* timer_recalc_offset() && timer_check_rtc()
> +			 * are now called from update_vsyscall() */
>  		}
>  		write_sequnlock(&xtime_lock);
>  	}
> @@ -739,77 +704,6 @@ unsigned long long sched_clock(void)
>  	return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
>  }
>  
> -int do_settimeofday(struct timespec *tv)
> -{
> -	time_t wtm_sec, new_sec = tv->tv_sec;
> -	long wtm_nsec, new_nsec = tv->tv_nsec;
> -	unsigned long flags;
> -	u64 new_xsec;
> -	unsigned long tb_delta;
> -
> -	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
> -		return -EINVAL;
> -
> -	write_seqlock_irqsave(&xtime_lock, flags);
> -
> -	/*
> -	 * Updating the RTC is not the job of this code. If the time is
> -	 * stepped under NTP, the RTC will be updated after STA_UNSYNC
> -	 * is cleared.  Tools like clock/hwclock either copy the RTC
> -	 * to the system time, in which case there is no point in writing
> -	 * to the RTC again, or write to the RTC but then they don't call
> -	 * settimeofday to perform this operation.
> -	 */
> -#ifdef CONFIG_PPC_ISERIES
> -	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
> -		iSeries_tb_recal();
> -		first_settimeofday = 0;
> -	}
> -#endif
> -
> -	/* Make userspace gettimeofday spin until we're done. */
> -	++vdso_data->tb_update_count;
> -	smp_mb();
> -
> -	/*
> -	 * Subtract off the number of nanoseconds since the
> -	 * beginning of the last tick.
> -	 */
> -	tb_delta = tb_ticks_since(tb_last_jiffy);
> -	tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
> -	new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
> -
> -	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
> -	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
> -
> - 	set_normalized_timespec(&xtime, new_sec, new_nsec);
> -	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
> -
> -	/* In case of a large backwards jump in time with NTP, we want the 
> -	 * clock to be updated as soon as the PLL is again in lock.
> -	 */
> -	last_rtc_update = new_sec - 658;
> -
> -	ntp_clear();
> -
> -	new_xsec = xtime.tv_nsec;
> -	if (new_xsec != 0) {
> -		new_xsec *= XSEC_PER_SEC;
> -		do_div(new_xsec, NSEC_PER_SEC);
> -	}
> -	new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
> -	update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
> -
> -	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
> -	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
> -
> -	write_sequnlock_irqrestore(&xtime_lock, flags);
> -	clock_was_set();
> -	return 0;
> -}
> -
> -EXPORT_SYMBOL(do_settimeofday);
> -
>  static int __init get_freq(char *name, int cells, unsigned long *val)
>  {
>  	struct device_node *cpu;
> @@ -878,6 +772,78 @@ unsigned long get_boot_time(void)
>  		      tm.tm_hour, tm.tm_min, tm.tm_sec);
>  }
>  
> +/* clocksource code */
> +static cycle_t timebase_read(void)
> +{
> +	return (cycle_t)get_tb();
> +}
> +
> +static void clocksource_settimeofday(struct clocksource *cs,
> +                                     struct timespec *ts)
> +{
> +	u64 new_xsec;
> +
> +#ifdef CONFIG_PPC_ISERIES
> +	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
> +		iSeries_tb_recal();
> +		first_settimeofday = 0;
> +	}
> +#endif
> +
> +	/* Make userspace gettimeofday spin until we're done. */
> +	++vdso_data->tb_update_count;
> +	smp_mb();
> +
> +	/* In case of a large backwards jump in time with NTP, we want the
> +	 * clock to be updated as soon as the PLL is again in lock.
> +	 */
> +	last_rtc_update = xtime.tv_sec - 658;
> +
> +	new_xsec = xtime.tv_nsec;
> +	if (new_xsec != 0) {
> +		new_xsec *= XSEC_PER_SEC;
> +		do_div(new_xsec, NSEC_PER_SEC);
> +	}
> +
> +	new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
> +
> +	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
> +	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
> +
> +	update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
> +}

It does look too large to run from interrupt context, but it also looks
like it could get cleaned out more ..

> +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
> +{
> +	timer_recalc_offset(tb_last_jiffy);
> +	timer_check_rtc();
> +}

Hmm .. This doesn't look like it's taking into account that the time has
changed .. Your time has effectively incremented by one jiffie .. The
vdso_data doesn't appear to be updated ..

> +void __init clocksource_init(void)
> +{
> +	int mult;
> +
> +	if (__USE_RTC())
> +		return;
> +
> +	mult = clocksource_hz2mult(tb_ticks_per_sec,
> +	                           clocksource_timebase.shift);
> +	clocksource_timebase.mult = mult;
> +
> +	clocksource_timebase.read = timebase_read;
> +	clocksource_timebase.settimeofday = clocksource_settimeofday;
> +
> +	if (clocksource_register(&clocksource_timebase)) {
> +		printk(KERN_ERR "clocksource: %s is already registered\n",
> +		       clocksource_timebase.name);
> +		return;
> +	}
> +
> +	printk(KERN_INFO "clocksource: %s mult[%x] shift[%d] registered\n",
> +	       clocksource_timebase.name,
> +	       clocksource_timebase.mult, clocksource_timebase.shift);
> +}
> +
>  /* This function is only called on the boot processor */
>  void __init time_init(void)
>  {
> @@ -999,6 +965,9 @@ void __init time_init(void)
>  	                        -xtime.tv_sec, -xtime.tv_nsec);
>  	write_sequnlock_irqrestore(&xtime_lock, flags);
>  
> +	/* Register the clocksource */
> +	clocksource_init();
> +
>  	/* Not exact, but the timer interrupt takes care of this */
>  	set_dec(tb_ticks_per_jiffy);
>  }
> Yours Tony
> 
>   linux.conf.au        http://linux.conf.au/ || http://lca2008.linux.org.au/
>   Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!
> 


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20  6:57     ` [RFC] clocksouce implementation for powerpc Tony Breeds
  2007-06-20 14:57       ` Daniel Walker
@ 2007-06-20 16:53       ` Sergei Shtylyov
  2007-06-22  6:10         ` Tony Breeds
  2007-06-20 21:06       ` john stultz
  2 siblings, 1 reply; 52+ messages in thread
From: Sergei Shtylyov @ 2007-06-20 16:53 UTC (permalink / raw)
  To: Tony Breeds
  Cc: Daniel Walker, Andrew Morton, john stultz, LKML, LinuxPPC-dev,
	Thomas Gleixner, Ingo Molnar

Hello.

Tony Breeds wrote:

>>>plain text document attachment
>>>(clocksource-add-settimeofday-hook.patch)
>>>From: Tony Breeds <tony@bakeyournoodle.com >

>>>I'm working on a clocksource implementation for all powerpc platforms.
>>>some of these platforms needs to do a little work as part of the
>>>settimeofday() syscall and I can't see a way to do that without adding
>>>this hook to clocksource.

>>I'd like to see how this is used? If the code that uses this API change
>>isn't ready yet, then this patch should really wait..

> This is my current patch to rework arch/powerpc/kernel/time.c to create
> a clocksource.  It's not ready for inclusion.

    I guess it's been based on the prior work by John Stultz (and me too :-)?

> powerpc needs to keep the vdso in sync whenener settimeodfay() is
> called.  Adding the hook the to the clocksource structure was my way of
> allowing this to happen.  There are other approaches, but this seemed to
> best allow for runtime.  Initially I considered using update_vsyscall()
> but this is called from do_timer(), and I don't need this code run then
> :(

> This has been booted on pSeries and iSeries (I'm using glibc 2.5, which
> uses the vdso gettimeoday())

[...]
> Index: working/arch/powerpc/kernel/time.c
> ===================================================================
> --- working.orig/arch/powerpc/kernel/time.c
> +++ working/arch/powerpc/kernel/time.c
> @@ -74,6 +74,30 @@
>  #endif
>  #include <asm/smp.h>
>  
> +/* powerpc clocksource/clockevent code */
> +
> +/* TODO:
> + *  o Code style
> + *    * Variable names ... be consistent.
> + *
> + * TODO: Clocksource
> + *  o Need a _USE_RTC() clocksource impelementation
> + *  o xtime:  Either time.c manages it, or clocksource does, not both

    If you mean the init. part, this has been already done by me -- I've 
implemented read_persistent_clock() and got rid of xtime setting. What's left 
is to implemet update_persistent_clock() and get rid of timer_check_rtc()...

> + */
> +
> +#include <linux/clocksource.h>
> +
> +static struct clocksource clocksource_timebase = {
> +	.name         = "timebase",
> +	.rating       = 200,

    Perhaps we even need to raise the rating to 300 or 400 -- according to 
what <linux/clocksource.h> says?

> +	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,
> +	.mask         = CLOCKSOURCE_MASK(64),
> +	.shift        = 22,

    PPC64 has issues with the fixed shift value, see:

http://patchwork.ozlabs.org/linuxppc/patch?id=11125

> +	.mult         = 0,	/* To be filled in */
> +	.read         = NULL,   /* To be filled in */
> +	.settimeofday = NULL,   /* To be filled in */

    I don't quite understand why not just init them right away?  The values 
are fixed anyways.

> +};
> +
>  /* keep track of when we need to update the rtc */
>  time_t last_rtc_update;
>  #ifdef CONFIG_PPC_ISERIES
[...]
> @@ -666,8 +631,8 @@ void timer_interrupt(struct pt_regs * re
>  		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
>  			tb_last_jiffy = tb_next_jiffy;
>  			do_timer(1);
> -			timer_recalc_offset(tb_last_jiffy);
> -			timer_check_rtc();
> +			/* timer_recalc_offset() && timer_check_rtc()
> +			 * are now called from update_vsyscall() */

    I.e. in the softirq context...

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20 14:57       ` Daniel Walker
@ 2007-06-20 17:20         ` Sergei Shtylyov
  2007-06-20 17:31           ` Thomas Gleixner
  2007-06-22  6:23         ` Tony Breeds
  1 sibling, 1 reply; 52+ messages in thread
From: Sergei Shtylyov @ 2007-06-20 17:20 UTC (permalink / raw)
  To: Tony Breeds
  Cc: Daniel Walker, Andrew Morton, john stultz, LKML, LinuxPPC-dev,
	Thomas Gleixner, Ingo Molnar

Daniel Walker wrote:
>>+static void clocksource_settimeofday(struct clocksource *cs,
>>+                                     struct timespec *ts)
>>+{
>>+	u64 new_xsec;
>>+
>>+#ifdef CONFIG_PPC_ISERIES
>>+	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
>>+		iSeries_tb_recal();
>>+		first_settimeofday = 0;
>>+	}
>>+#endif
>>+
>>+	/* Make userspace gettimeofday spin until we're done. */
>>+	++vdso_data->tb_update_count;
>>+	smp_mb();
>>+
>>+	/* In case of a large backwards jump in time with NTP, we want the
>>+	 * clock to be updated as soon as the PLL is again in lock.
>>+	 */
>>+	last_rtc_update = xtime.tv_sec - 658;
>>+
>>+	new_xsec = xtime.tv_nsec;
>>+	if (new_xsec != 0) {
>>+		new_xsec *= XSEC_PER_SEC;
>>+		do_div(new_xsec, NSEC_PER_SEC);
>>+	}
>>+
>>+	new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
>>+
>>+	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
>>+	vdso_data->tz_dsttime = sys_tz.tz_dsttime;

    I'm not sure why these are copied *only* here. Shouldn't they be copied 
only once, at init. time?

>>+
>>+	update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
>>+}

> It does look too large to run from interrupt context,

    You mean if this would have been "included" into update_vsyscall()?

> but it also looks
> like it could get cleaned out more ..

    Yeah, at least new_xsec calculation is duplicated in timer_recalc_offset()..

>>+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
>>+{
>>+	timer_recalc_offset(tb_last_jiffy);
>>+	timer_check_rtc();
>>+}

> Hmm .. This doesn't look like it's taking into account that the time has
> changed ..

    Why? By the time it gets called (form the timer softirq context) 
tb_last_jiffy should've been incremented. Well, this won't happen wither in or 
right after the timer interrupt... since timer has no IRQ on PowerPC -- it 
signals "exception". Well, HRT works somehow anyway. :-)

> Your time has effectively incremented by one jiffie .. The
> vdso_data doesn't appear to be updated ..

    Moreover, it will get called for settimeofday() as well which would seem 
to double the overhead since your clocksource hook will get called beforehand.

WBR, Sergei

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20 17:20         ` Sergei Shtylyov
@ 2007-06-20 17:31           ` Thomas Gleixner
  2007-06-20 18:11             ` Sergei Shtylyov
  0 siblings, 1 reply; 52+ messages in thread
From: Thomas Gleixner @ 2007-06-20 17:31 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Tony Breeds, Daniel Walker, Andrew Morton, john stultz, LKML,
	LinuxPPC-dev, Ingo Molnar

On Wed, 2007-06-20 at 21:20 +0400, Sergei Shtylyov wrote:
> >>+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
> >>+{
> >>+	timer_recalc_offset(tb_last_jiffy);
> >>+	timer_check_rtc();
> >>+}
> 
> > Hmm .. This doesn't look like it's taking into account that the time has
> > changed ..
> 
>     Why? By the time it gets called (form the timer softirq context) 

It is called from interrupt context at least in mainline. Only the -rt
patch moves this to the softirq.

	tglx



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20 17:31           ` Thomas Gleixner
@ 2007-06-20 18:11             ` Sergei Shtylyov
  0 siblings, 0 replies; 52+ messages in thread
From: Sergei Shtylyov @ 2007-06-20 18:11 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Tony Breeds, Daniel Walker, Andrew Morton, john stultz, LKML,
	LinuxPPC-dev, Ingo Molnar

Hello.

Thomas Gleixner wrote:

>>>>+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
>>>>+{
>>>>+	timer_recalc_offset(tb_last_jiffy);
>>>>+	timer_check_rtc();
>>>>+}
>>
>>>Hmm .. This doesn't look like it's taking into account that the time has
>>>changed ..
>>
>>    Why? By the time it gets called (form the timer softirq context) 
> 
> 
> It is called from interrupt context at least in mainline. Only the -rt
> patch moves this to the softirq.

    Anyway, by the time it gets called, tb_last_jiffy gets updated.

> 	tglx

WBR, Sergei

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20  6:57     ` [RFC] clocksouce implementation for powerpc Tony Breeds
  2007-06-20 14:57       ` Daniel Walker
  2007-06-20 16:53       ` Sergei Shtylyov
@ 2007-06-20 21:06       ` john stultz
  2007-06-22  6:28         ` Tony Breeds
  2 siblings, 1 reply; 52+ messages in thread
From: john stultz @ 2007-06-20 21:06 UTC (permalink / raw)
  To: Tony Breeds
  Cc: Daniel Walker, Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar,
	LinuxPPC-dev

On Wed, 2007-06-20 at 16:57 +1000, Tony Breeds wrote:
> On Sat, Jun 16, 2007 at 08:51:23AM -0700, Daniel Walker wrote:
> > On Sat, 2007-06-16 at 10:36 +0000, Thomas Gleixner wrote:
> > > plain text document attachment
> > > (clocksource-add-settimeofday-hook.patch)
> > > From: Tony Breeds <tony@bakeyournoodle.com >
> > > 
> > > I'm working on a clocksource implementation for all powerpc platforms.
> > > some of these platforms needs to do a little work as part of the
> > > settimeofday() syscall and I can't see a way to do that without adding
> > > this hook to clocksource.
> > > 
> > 
> > 
> > I'd like to see how this is used? If the code that uses this API change
> > isn't ready yet, then this patch should really wait..
> 
> This is my current patch to rework arch/powerpc/kernel/time.c to create
> a clocksource.  It's not ready for inclusion.

Hey Tony,
	Thanks for sending this out! I really appreciate this work, as its been
on my todo forever, and I've just not been able to focus on it.
Currently it seems a bit minimal of a conversion (ideally there should
be very little time code left), but It looks like a great start!

More comments below.

> powerpc needs to keep the vdso in sync whenener settimeodfay() is
> called.  Adding the hook the to the clocksource structure was my way of
> allowing this to happen.  There are other approaches, but this seemed to
> best allow for runtime.  Initially I considered using update_vsyscall()
> but this is called from do_timer(), and I don't need this code run then
> :(

I might be missing a subtlety in the ppc code, but I'm still not sure if
I see the need for the clocksource settimeofday hook.

update_vsyscall() is intended to provide a hook that allows the generic
time code to provide all the needed timekeeping state to the arch
specific vsyscall implementation. It is called any time the base
timekeeping variables are changed.

You're already calling timer_recalc_offset from there which looks almost
as expensive as the settime hook, so I'm not sure I understand the
division.

But to your credit, the patch Sergei and I have been slowly working on
(I believe I've sent that to you already, but if not let me know) never
got the VDSO code working, so good show!

> +static void clocksource_settimeofday(struct clocksource *cs,
> +                                     struct timespec *ts)
> +{
> +	u64 new_xsec;
> +
> +#ifdef CONFIG_PPC_ISERIES
> +	if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) {
> +		iSeries_tb_recal();
> +		first_settimeofday = 0;
> +	}
> +#endif
> +
> +	/* Make userspace gettimeofday spin until we're done. */
> +	++vdso_data->tb_update_count;
> +	smp_mb();
> +
> +	/* In case of a large backwards jump in time with NTP, we want the
> +	 * clock to be updated as soon as the PLL is again in lock.
> +	 */
> +	last_rtc_update = xtime.tv_sec - 658;
> +
> +	new_xsec = xtime.tv_nsec;
> +	if (new_xsec != 0) {
> +		new_xsec *= XSEC_PER_SEC;
> +		do_div(new_xsec, NSEC_PER_SEC);
> +	}
> +
> +	new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC;
> +
> +	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
> +	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
> +
> +	update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs);
> +}
> +
> +void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
> +{
> +	timer_recalc_offset(tb_last_jiffy);
> +	timer_check_rtc();
> +}

I think it would be enlightening to flatten this out a bit. Putting both
the timer_recalc_offset and clocksource_settime code in the same
function. It might illustrate where some optimizations could be done and
where it might make more sense to split things up.

Also I'd leave timer_check_rtc() in the timer_interrupt for now (later
moving it to tglx's generic rtc update).

thanks
-john


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20 16:53       ` Sergei Shtylyov
@ 2007-06-22  6:10         ` Tony Breeds
  2007-06-22 12:42           ` Sergei Shtylyov
  0 siblings, 1 reply; 52+ messages in thread
From: Tony Breeds @ 2007-06-22  6:10 UTC (permalink / raw)
  To: Sergei Shtylyov
  Cc: Daniel Walker, Andrew Morton, john stultz, LKML, LinuxPPC-dev,
	Thomas Gleixner, Ingo Molnar

On Wed, Jun 20, 2007 at 08:53:47PM +0400, Sergei Shtylyov wrote:

Hi Sergei,
	Thanks for taking the time to look over my patch.

>    I guess it's been based on the prior work by John Stultz (and me too :-)?

At some level I guess so.  John did send me a patch a while ago.
 
>    If you mean the init. part, this has been already done by me -- I've 
> implemented read_persistent_clock() and got rid of xtime setting. What's 
> left is to implemet update_persistent_clock() and get rid of 
> timer_check_rtc()...

Actually I think that comment is redundant.  and should be removed
sorry.

>    Perhaps we even need to raise the rating to 300 or 400 -- according to 
> what <linux/clocksource.h> says?

Sure.
 
> >+	.flags        = CLOCK_SOURCE_IS_CONTINUOUS,
> >+	.mask         = CLOCKSOURCE_MASK(64),
> >+	.shift        = 22,
> 
>    PPC64 has issues with the fixed shift value, see:
> 
> http://patchwork.ozlabs.org/linuxppc/patch?id=11125

Thanks!
 
> >+	.mult         = 0,	/* To be filled in */
> >+	.read         = NULL,   /* To be filled in */
> >+	.settimeofday = NULL,   /* To be filled in */
> 
>    I don't quite understand why not just init them right away?  The values 
> are fixed anyways.

Well at least mult needs to be calculated at runtime, and I prefer to
have the structure near the top of the file at which stage the
read/settimeofday functions aren't defined.

Yours Tony

  linux.conf.au        http://linux.conf.au/ || http://lca2008.linux.org.au/
  Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20 14:57       ` Daniel Walker
  2007-06-20 17:20         ` Sergei Shtylyov
@ 2007-06-22  6:23         ` Tony Breeds
  1 sibling, 0 replies; 52+ messages in thread
From: Tony Breeds @ 2007-06-22  6:23 UTC (permalink / raw)
  To: Daniel Walker
  Cc: Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar, john stultz,
	LinuxPPC-dev

On Wed, Jun 20, 2007 at 07:57:19AM -0700, Daniel Walker wrote:

Hi Daniel.

> As I said in our private thread, I do think you should be using
> update_vsyscall() .. update_vsyscall() is just called when the time is
> set, usually that happens in the timer interrupt and sometimes that
> happens in settimeofday() ..

Well I've taken another look at the code and I think I can probably
restructure my code to use update_vsyscall().  I thought I needed a
hook that was called /only/ from settimeofday() (which as you say
doesn't match update_vsyscall()'s usage).

I'll try again and see what problems I hit.
 
> At least some of your code is duplications over what is already being
> worked on inside the powerpc community.. For instance, I know there is
> already a timebase clocksource,
> 
> http://people.redhat.com/~mingo/realtime-preempt/patch-2.6.21.5-rt17

Thanks. The one in -rt doesn't seem to support the VDSO.  however I see
that there is duplication of effort there.
 
> Hmm .. This doesn't look like it's taking into account that the time has
> changed .. Your time has effectively incremented by one jiffie .. The
> vdso_data doesn't appear to be updated ..

Unless I miss your meaning, the vdso is updated in
timer_recalc_offset()/update_gtod() when needed.

Yours Tony

  linux.conf.au        http://linux.conf.au/ || http://lca2008.linux.org.au/
  Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-20 21:06       ` john stultz
@ 2007-06-22  6:28         ` Tony Breeds
  0 siblings, 0 replies; 52+ messages in thread
From: Tony Breeds @ 2007-06-22  6:28 UTC (permalink / raw)
  To: john stultz
  Cc: Daniel Walker, Thomas Gleixner, LKML, Andrew Morton, Ingo Molnar,
	LinuxPPC-dev

On Wed, Jun 20, 2007 at 02:06:01PM -0700, john stultz wrote:

Hi John.

> Hey Tony,
> 	Thanks for sending this out! I really appreciate this work, as its been
> on my todo forever, and I've just not been able to focus on it.
> Currently it seems a bit minimal of a conversion (ideally there should
> be very little time code left), but It looks like a great start!

Thanks.

> I might be missing a subtlety in the ppc code, but I'm still not sure if
> I see the need for the clocksource settimeofday hook.
> 
> update_vsyscall() is intended to provide a hook that allows the generic
> time code to provide all the needed timekeeping state to the arch
> specific vsyscall implementation. It is called any time the base
> timekeeping variables are changed.

Well as I just said the Daniel, I was under the impression I needed a
hook that was only called from settimeofday().  The comments I've
recieved from everyone has given me good cause to re-evaluate.

I think I can make it work without the hook, that started this
discussion.  Thomas, I think it's probably best to axe it now.  If I
/really/ need it then I'll start the discussion again :)  Thanks.
 
> I think it would be enlightening to flatten this out a bit. Putting both
> the timer_recalc_offset and clocksource_settime code in the same
> function. It might illustrate where some optimizations could be done and
> where it might make more sense to split things up.
> 
> Also I'd leave timer_check_rtc() in the timer_interrupt for now (later
> moving it to tglx's generic rtc update).

Yes you're rigth I don't need to move the timer_check_rtc() call.

Yours Tony

  linux.conf.au        http://linux.conf.au/ || http://lca2008.linux.org.au/
  Jan 28 - Feb 02 2008 The Australian Linux Technical Conference!


^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [RFC] clocksouce implementation for powerpc
  2007-06-22  6:10         ` Tony Breeds
@ 2007-06-22 12:42           ` Sergei Shtylyov
  0 siblings, 0 replies; 52+ messages in thread
From: Sergei Shtylyov @ 2007-06-22 12:42 UTC (permalink / raw)
  To: Tony Breeds
  Cc: Daniel Walker, Andrew Morton, john stultz, LKML, LinuxPPC-dev,
	Thomas Gleixner, Ingo Molnar

Tony Breeds wrote:

> 	Thanks for taking the time to look over my patch.

>>   I guess it's been based on the prior work by John Stultz (and me too :-)?

> At some level I guess so.  John did send me a patch a while ago.

>>   If you mean the init. part, this has been already done by me -- I've 
>>implemented read_persistent_clock() and got rid of xtime setting. What's 
>>left is to implemet update_persistent_clock() and get rid of 
>>timer_check_rtc()...

> Actually I think that comment is redundant.  and should be removed
> sorry.

    I guess you haven't looked thru the -rt patch? There's much more than 
John's initial patch there now, including the clockevents driver.

>>>+	.mult         = 0,	/* To be filled in */
>>>+	.read         = NULL,   /* To be filled in */
>>>+	.settimeofday = NULL,   /* To be filled in */
>>
>>   I don't quite understand why not just init them right away?  The values 
>>are fixed anyways.

> Well at least mult needs to be calculated at runtime, and I prefer to

    I was talking about the method intializers specifically.

> have the structure near the top of the file at which stage the
> read/settimeofday functions aren't defined.

    I don't think it's justified anyway.

> Yours Tony

WBR, Sergei

^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2007-06-22 12:40 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-16 10:36 [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 01/25] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
2007-06-16 14:36   ` Bernhard Rosenkraenzer
2007-06-16 14:54     ` Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 02/25] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 03/25] Clockevents remove prototypes of removed functions Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 04/25] Timekeeping: Fixup shadow variable argument Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 05/25] timer.c cleanup recently introduced whitespace damage Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 06/25] clockevents: Fix resume logic Thomas Gleixner
2007-06-16 18:51   ` Separate arch patching (Re: [patch-mm 06/25] clockevents: Fix resume logic) Oleg Verych
2007-06-16 19:04     ` Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 07/25] Tick management: spread timer interrupt Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 08/25] i386: PIT stop only, when in periodic or oneshot mode Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 09/25] clockevents: Fix device replacement Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 10/25] highres: Improve debug output Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 11/25] hrtimer: speedup hrtimer_enqueue Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 12/25] pcspkr: use the global PIT lock Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 13/25] i386: hpet assumes boot cpu is 0 Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 14/25] NTP: Move the cmos update code into ntp.c Thomas Gleixner
2007-06-19  8:26   ` Franck Bui-Huu
2007-06-16 10:36 ` [patch-mm 15/25] clocksource: add settimeofday hook for PPC Thomas Gleixner
2007-06-16 15:51   ` Daniel Walker
2007-06-20  6:57     ` [RFC] clocksouce implementation for powerpc Tony Breeds
2007-06-20 14:57       ` Daniel Walker
2007-06-20 17:20         ` Sergei Shtylyov
2007-06-20 17:31           ` Thomas Gleixner
2007-06-20 18:11             ` Sergei Shtylyov
2007-06-22  6:23         ` Tony Breeds
2007-06-20 16:53       ` Sergei Shtylyov
2007-06-22  6:10         ` Tony Breeds
2007-06-22 12:42           ` Sergei Shtylyov
2007-06-20 21:06       ` john stultz
2007-06-22  6:28         ` Tony Breeds
2007-06-16 10:36 ` [patch-mm 16/25] x86_64: untangle asm/hpet.h from asm/timex.h Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 17/25] x86_64: Use generic cmos update Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 18/25] i386: move setup_pit_timer to the correct header file Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 19/25] x86-64: remove dead code and other janitor work in tsc.c Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 20/25] x86_64: Convert to cleckevents Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 21/25] x86_64: hpet restore vread Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 22/25] x86_64: restore restore nohpet cmdline Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 23/25] x86-64 block irq balancing for timer Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 24/25] x86_64: prep idle loop for dynticks Thomas Gleixner
2007-06-16 10:36 ` [patch-mm 25/25] x86_64: enable high resolution timers and dynticks Thomas Gleixner
2007-06-16 14:41 ` [patch-mm 00/25] High resolution timer updates and x86_64 support - V2 Alistair John Strachan
2007-06-16 19:06   ` Thomas Gleixner
2007-06-16 23:04 ` Nigel Cunningham
2007-06-18 20:06 ` Valdis.Kletnieks
2007-06-18 20:24   ` Pallipadi, Venkatesh
2007-06-18 21:49     ` Valdis.Kletnieks
2007-06-18 22:10       ` Pallipadi, Venkatesh
2007-06-19 11:28       ` Valdis.Kletnieks
2007-06-19  1:52   ` Arjan van de Ven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).