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

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 overall diffstat of the patchset is:
 50 files changed, 843 insertions(+), 1477 deletions(-)

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.

Changes since V2:

- dropped clocksource settimeofday hook for PPC
- fixed compile breakage of vmiclock
- coding style fixups
- better patch split


The patch series is also available from the hrtimers project site:

http://www.tglx.de/projects/hrtimers/2.6.22-rc4-mm2/patch-2.6.22-rc4-mm2-hrt6.patch
http://www.tglx.de/projects/hrtimers/2.6.22-rc4-mm2/patch-2.6.22-rc4-mm2-hrt6.patches.tar.bz2

Note: these patches also contain the recently posted HPET force enable
series from Venki.

Thanks,

	tglx
-- 


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

* [patch -mm 01/28] NOHZ: Fix nox x86 dyntick idle handling
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 02/28] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown Thomas Gleixner
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML, Adam Belay, Len Brown,
	Dave Miller, Paul Mundt, Russell King

[-- Attachment #1: cpuidle-fix-sparc-arm-sh-idle.patch --]
[-- Type: text/plain, Size: 1924 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 idle wakeups without interrupts.

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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/Kconfig	2007-06-23 14:38:57.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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/softirq.c	2007-06-23 14:38:57.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] 39+ messages in thread

* [patch -mm 02/28] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 01/28] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 03/28] clockevents: fix typo in acpi_pm.c Thomas Gleixner
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML, 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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/acpi/processor_idle.c	2007-06-23 14:38:57.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] 39+ messages in thread

* [patch -mm 03/28] clockevents: fix typo in acpi_pm.c
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 01/28] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 02/28] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 04/28] Timekeeping: Fixup shadow variable argument Thomas Gleixner
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML, Alessio Igor Bogani

[-- Attachment #1: fix-typo-in-acpi-pm-c.patch --]
[-- Type: text/plain, Size: 816 bytes --]

From:	Alessio Igor Bogani <abogani@texware.it>

Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
Cc: john stultz <johnstul@us.ibm.com>

---
 drivers/clocksource/acpi_pm.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6.22-rc4-mm/drivers/clocksource/acpi_pm.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/drivers/clocksource/acpi_pm.c	2007-06-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/clocksource/acpi_pm.c	2007-06-23 14:38:57.000000000 +0200
@@ -71,7 +71,7 @@ static struct clocksource clocksource_ac
 	.rating		= 200,
 	.read		= acpi_pm_read,
 	.mask		= (cycle_t)ACPI_PM_MASK,
-	.mult		= 0, /*to be caluclated*/
+	.mult		= 0, /*to be calculated*/
 	.shift		= 22,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 

-- 


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

* [patch -mm 04/28] Timekeeping: Fixup shadow variable argument
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (2 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 03/28] clockevents: fix typo in acpi_pm.c Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 05/28] timer.c cleanup recently introduced whitespace damage Thomas Gleixner
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/timekeeping.c	2007-06-23 14:38:57.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] 39+ messages in thread

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

[-- 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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/timer.c	2007-06-23 14:38:57.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] 39+ messages in thread

* [patch -mm 06/28] Clockevents remove prototypes of removed functions
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (4 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 05/28] timer.c cleanup recently introduced whitespace damage Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 07/28] clockevents: Fix resume logic Thomas Gleixner
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/clockchips.h	2007-06-23 14:38:58.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] 39+ messages in thread

* [patch -mm 07/28] clockevents: Fix resume logic
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (5 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 06/28] Clockevents remove prototypes of removed functions Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 08/28] clockevents: Fix device replacement Thomas Gleixner
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: clockevents-fix-resume-logic.patch --]
[-- Type: text/plain, Size: 12500 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.

Thanks to Nigel Cunningham for tracking down a long standing thinko,
which affected the jinxed VAIO.

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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-23 14:38:58.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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/clockchips.h	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-broadcast.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-common.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-davinci/time.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-imx/time.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-ixp4xx/common.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/mach-omap1/time.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/arm/plat-omap/timer32k.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/vmiclock.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/xen/time.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sh/kernel/timers/timer-tmu.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sparc64/kernel/time.c	2007-06-23 14:38:58.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] 39+ messages in thread

* [patch -mm 08/28] clockevents: Fix device replacement
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (6 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 07/28] clockevents: Fix resume logic Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 09/28] Tick management: spread timer interrupt Thomas Gleixner
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-broadcast.c	2007-06-23 14:38:58.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] 39+ messages in thread

* [patch -mm 09/28] Tick management: spread timer interrupt
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (7 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 08/28] clockevents: Fix device replacement Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-26  0:11   ` Andrew Morton
  2007-06-23 13:32 ` [patch -mm 10/28] highres: Improve debug output Thomas Gleixner
                   ` (19 subsequent siblings)
  28 siblings, 1 reply; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: tick-spread-timer-interrupts.patch --]
[-- Type: text/plain, Size: 1575 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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-sched.c	2007-06-23 14:38:58.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] 39+ messages in thread

* [patch -mm 10/28] highres: Improve debug output
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (8 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 09/28] Tick management: spread timer interrupt Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-26  0:14   ` Andrew Morton
  2007-06-23 13:32 ` [patch -mm 11/28] hrtimer: speedup hrtimer_enqueue Thomas Gleixner
                   ` (18 subsequent siblings)
  28 siblings, 1 reply; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/hrtimer.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/tick-oneshot.c	2007-06-23 14:38:58.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] 39+ messages in thread

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

[-- 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/hrtimer.c	2007-06-23 14:38:58.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] 39+ messages in thread

* [patch -mm 12/28] pcspkr: use the global PIT lock
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (10 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 11/28] hrtimer: speedup hrtimer_enqueue Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 13/28] NTP: Move the cmos update code into ntp.c Thomas Gleixner
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-23 14:38:58.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-23 14:38:56.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/input/misc/pcspkr.c	2007-06-23 14:38:58.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-23 14:38:58.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] 39+ messages in thread

* [patch -mm 13/28] NTP: Move the cmos update code into ntp.c
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (11 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 12/28] pcspkr: use the global PIT lock Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 14/28] i386: PIT stop only, when in periodic or oneshot mode Thomas Gleixner
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML, 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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/Kconfig	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/time.c	2007-06-23 14:38:59.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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sparc64/kernel/time.c	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/linux/time.h	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/kernel/time/ntp.c	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/sparc64/Kconfig	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/timer.h	2007-06-23 14:38:59.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] 39+ messages in thread

* [patch -mm 14/28] i386: PIT stop only, when in periodic or oneshot mode
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (12 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 13/28] NTP: Move the cmos update code into ntp.c Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 15/28] i386: remove volatile in apic.c Thomas Gleixner
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-23 14:38:59.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] 39+ messages in thread

* [patch -mm 15/28] i386: remove volatile in apic.c
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (13 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 14/28] i386: PIT stop only, when in periodic or oneshot mode Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 16/28] i386: hpet assumes boot cpu is 0 Thomas Gleixner
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: i386-apic-remove-bogus-volatile.patch --]
[-- Type: text/plain, Size: 1184 bytes --]

Remove the volatile in apic. We have a cpu_relax() in the wait loop.
Fix a coding style issue while at it.

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

---
 arch/i386/kernel/apic.c |    4 ++--
 1 file changed, 2 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/apic.c	2007-06-23 14:38:59.000000000 +0200
@@ -318,7 +318,7 @@ static void __devinit setup_APIC_timer(v
 
 #define LAPIC_CAL_LOOPS		(HZ/10)
 
-static __initdata volatile int lapic_cal_loops = -1;
+static __initdata 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;
@@ -488,7 +488,7 @@ void __init setup_boot_APIC_clock(void)
 		/* Let the interrupts run */
 		local_irq_enable();
 
-		while(lapic_cal_loops <= LAPIC_CAL_LOOPS)
+		while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
 			cpu_relax();
 
 		local_irq_disable();

-- 


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

* [patch -mm 16/28] i386: hpet assumes boot cpu is 0
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (14 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 15/28] i386: remove volatile in apic.c Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 17/28] i386: move PIT function declarations and constants to correct header file Thomas Gleixner
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-23 14:38:59.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] 39+ messages in thread

* [patch -mm 17/28] i386: move PIT function declarations and constants to correct header file
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (15 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 16/28] i386: hpet assumes boot cpu is 0 Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 18/28] x86_64: untangle asm/hpet.h from asm/timex.h Thomas Gleixner
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: i386-move-pit-related-functions-and-constants-to-i8253-h.patch --]
[-- Type: text/plain, Size: 3279 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.

Move also the PIT constants.

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

---
 arch/i386/kernel/i8253.c                 |    2 --
 arch/i386/kernel/vmiclock.c              |    1 +
 include/asm-i386/i8253.h                 |    7 +++++++
 include/asm-i386/mach-default/io_ports.h |    5 -----
 include/asm-i386/timer.h                 |    1 -
 5 files changed, 8 insertions(+), 8 deletions(-)

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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/i8253.h	2007-06-23 14:38:59.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;
@@ -18,4 +23,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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/timer.h	2007-06-23 14:38:59.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);
 
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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-23 14:38:59.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);
 
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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/vmiclock.c	2007-06-23 14:38:59.000000000 +0200
@@ -32,6 +32,7 @@
 #include <asm/apicdef.h>
 #include <asm/apic.h>
 #include <asm/timer.h>
+#include <asm/i8253.h>
 
 #include <irq_vectors.h>
 #include "io_ports.h"
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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/mach-default/io_ports.h	2007-06-23 14:38:59.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

-- 


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

* [patch -mm 18/28] x86_64: untangle asm/hpet.h from asm/timex.h
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (16 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 17/28] i386: move PIT function declarations and constants to correct header file Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 19/28] x86_64: Use generic cmos update Thomas Gleixner
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: x86-64-untangle-hpet-headers.patch --]
[-- Type: text/plain, Size: 2714 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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/char/rtc.c	2007-06-23 14:38:59.000000000 +0200
@@ -82,7 +82,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#if defined(__i386__)
+#ifdef CONFIG_X86
 #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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/timex.h	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/hpet.h	2007-06-23 14:38:59.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] 39+ messages in thread

* [patch -mm 19/28] x86_64: Use generic cmos update
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (17 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 18/28] x86_64: untangle asm/hpet.h from asm/timex.h Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 20/28] x86-64: remove dead code and other janitor work in tsc.c Thomas Gleixner
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-23 14:38:59.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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/Kconfig	2007-06-23 14:38:59.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] 39+ messages in thread

* [patch -mm 20/28] x86-64: remove dead code and other janitor work in tsc.c
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (18 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 19/28] x86_64: Use generic cmos update Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 21/28] x86-64: Fix APIC typo Thomas Gleixner
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:55.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/tsc.c	2007-06-23 14:38:59.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] 39+ messages in thread

* [patch -mm 21/28] x86-64: Fix APIC typo
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (19 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 20/28] x86-64: remove dead code and other janitor work in tsc.c Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 22/28] x86_64: Convert to cleckevents Thomas Gleixner
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: x86-64-fix-apic-typo.patch --]
[-- Type: text/plain, Size: 2569 bytes --]

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

---
 arch/x86_64/kernel/apic.c    |    4 ++--
 arch/x86_64/kernel/mce_amd.c |    6 +++---
 include/asm-x86_64/apic.h    |    4 ++--
 3 files changed, 7 insertions(+), 7 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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/apic.c	2007-06-23 14:39:00.000000000 +0200
@@ -990,8 +990,8 @@ int setup_profiling_timer(unsigned int m
 	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;
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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/mce_amd.c	2007-06-23 14:39:00.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/include/asm-x86_64/apic.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/apic.h	2007-06-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h	2007-06-23 14:39:00.000000000 +0200
@@ -83,8 +83,8 @@ 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);
 

-- 


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

* [patch -mm 22/28] x86_64: Convert to cleckevents
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (20 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 21/28] x86-64: Fix APIC typo Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-26  0:27   ` Andrew Morton
  2007-06-23 13:32 ` [patch -mm 23/28] ACPI: Remove the useless ifdef code Thomas Gleixner
                   ` (6 subsequent siblings)
  28 siblings, 1 reply; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: x86-64-convert-to-clockevents.patch --]
[-- Type: text/plain, Size: 65885 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     |    3 
 arch/x86_64/Kconfig          |   12 
 arch/x86_64/kernel/Makefile  |    4 
 arch/x86_64/kernel/apic.c    |  563 ++++++++++++++++++++++++-------------------
 arch/x86_64/kernel/hpet.c    |  493 -------------------------------------
 arch/x86_64/kernel/i8259.c   |   47 ---
 arch/x86_64/kernel/smpboot.c |    4 
 arch/x86_64/kernel/time.c    |  253 ++-----------------
 arch/x86_64/kernel/tsc.c     |   90 ++++++
 include/asm-i386/hpet.h      |  125 +++------
 include/asm-i386/tsc.h       |    4 
 include/asm-x86_64/apic.h    |    6 
 include/asm-x86_64/hpet.h    |   77 -----
 include/asm-x86_64/i8253.h   |    8 
 include/asm-x86_64/proto.h   |    3 
 16 files changed, 557 insertions(+), 1185 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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-23 14:39:00.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-23 14:38:54.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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/Kconfig	2007-06-23 14:39:00.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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/hpet.h	2007-06-23 14:39:00.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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/hpet.h	2007-06-23 14:39:00.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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-23 14:39:00.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/smpboot.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/smpboot.c	2007-06-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/smpboot.c	2007-06-23 14:39:00.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/include/asm-x86_64/i8253.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/i8253.h	2007-06-23 14:38:58.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/i8253.h	2007-06-23 14:39:00.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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/proto.h	2007-06-23 14:39:00.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/arch/i386/kernel/i8253.c
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/i386/kernel/i8253.c	2007-06-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/i8253.c	2007-06-23 14:39:00.000000000 +0200
@@ -120,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
@@ -204,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-23 14:38:59.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/tsc.c	2007-06-23 14:39:00.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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-i386/tsc.h	2007-06-23 14:39:00.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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/i8259.c	2007-06-23 14:39:00.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/arch/x86_64/kernel/Makefile
===================================================================
--- linux-2.6.22-rc4-mm.orig/arch/x86_64/kernel/Makefile	2007-06-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/Makefile	2007-06-23 14:39:00.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
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-23 14:39:00.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/apic.c	2007-06-23 14:39:00.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,211 +798,298 @@ 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 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)
 {
@@ -995,11 +1101,10 @@ void setup_APIC_extended_lvt(unsigned ch
 {
 	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_extended_lvt(unsigned ch
  * 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/include/asm-x86_64/apic.h
===================================================================
--- linux-2.6.22-rc4-mm.orig/include/asm-x86_64/apic.h	2007-06-23 14:39:00.000000000 +0200
+++ linux-2.6.22-rc4-mm/include/asm-x86_64/apic.h	2007-06-23 14:39:00.000000000 +0200
@@ -79,8 +79,6 @@ 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_extended_lvt(unsigned char lvt_off, unsigned char vector,
@@ -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;

-- 


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

* [patch -mm 23/28] ACPI: Remove the useless ifdef code
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (21 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 22/28] x86_64: Convert to cleckevents Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 24/28] x86_64: hpet restore vread Thomas Gleixner
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- Attachment #1: acpi-remove-now-useless-ifdef-code.patch --]
[-- Type: text/plain, Size: 1669 bytes --]

The conversion of x86-64 to clock events makes the 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 n the timer broadcast functions useless. Remove it.

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

---
 drivers/acpi/processor_idle.c |   12 ------------
 1 file changed, 12 deletions(-)

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-23 14:38:57.000000000 +0200
+++ linux-2.6.22-rc4-mm/drivers/acpi/processor_idle.c	2007-06-23 14:39:00.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

-- 


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

* [patch -mm 24/28] x86_64: hpet restore vread
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (22 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 23/28] ACPI: Remove the useless ifdef code Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 25/28] x86_64: restore restore nohpet cmdline Thomas Gleixner
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML, 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-23 14:39:00.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-23 14:39:00.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] 39+ messages in thread

* [patch -mm 25/28] x86_64: restore restore nohpet cmdline
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (23 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 24/28] x86_64: hpet restore vread Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 26/28] x86-64 block irq balancing for timer Thomas Gleixner
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:39:00.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/i386/kernel/hpet.c	2007-06-23 14:39:00.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] 39+ messages in thread

* [patch -mm 26/28] x86-64 block irq balancing for timer
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (24 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 25/28] x86_64: restore restore nohpet cmdline Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 21:27   ` Arjan van de Ven
  2007-06-23 13:32 ` [patch -mm 27/28] x86_64: prep idle loop for dynticks Thomas Gleixner
                   ` (2 subsequent siblings)
  28 siblings, 1 reply; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:39:00.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/time.c	2007-06-23 14:39:00.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] 39+ messages in thread

* [patch -mm 27/28] x86_64: prep idle loop for dynticks
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (25 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 26/28] x86-64 block irq balancing for timer Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-23 13:32 ` [patch -mm 28/28] x86_64: enable high resolution timers and dynticks Thomas Gleixner
  2007-06-28  9:42 ` [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Andrew Morton
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:38:54.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/kernel/process.c	2007-06-23 14:39:00.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] 39+ messages in thread

* [patch -mm 28/28] x86_64: enable high resolution timers and dynticks
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (26 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 27/28] x86_64: prep idle loop for dynticks Thomas Gleixner
@ 2007-06-23 13:32 ` Thomas Gleixner
  2007-06-28  9:42 ` [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Andrew Morton
  28 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-23 13:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

[-- 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-23 14:39:00.000000000 +0200
+++ linux-2.6.22-rc4-mm/arch/x86_64/Kconfig	2007-06-23 14:39:01.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] 39+ messages in thread

* Re: [patch -mm 26/28] x86-64 block irq balancing for timer
  2007-06-23 13:32 ` [patch -mm 26/28] x86-64 block irq balancing for timer Thomas Gleixner
@ 2007-06-23 21:27   ` Arjan van de Ven
  2007-06-24  0:04     ` Andreas Kleen
  0 siblings, 1 reply; 39+ messages in thread
From: Arjan van de Ven @ 2007-06-23 21:27 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Andrew Morton, Andi Kleen, Ingo Molnar, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Sat, 2007-06-23 at 13:32 +0000, Thomas Gleixner wrote:
> plain text document attachment
> (x86-64-clockevents-irq-balancing.patch)
> From: Venki Pallipadi <venkatesh.pallipadi@intel.com>
> 
> Disable irq balancing on IRQ0.


this patch is missing some rationale....

-- 
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] 39+ messages in thread

* Re: [patch -mm 26/28] x86-64 block irq balancing for timer
  2007-06-23 21:27   ` Arjan van de Ven
@ 2007-06-24  0:04     ` Andreas Kleen
  2007-06-24  1:20       ` Arjan van de Ven
  0 siblings, 1 reply; 39+ messages in thread
From: Andreas Kleen @ 2007-06-24  0:04 UTC (permalink / raw)
  To: Arjan van de Ven
  Cc: Thomas Gleixner, Andrew Morton, Ingo Molnar, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

Am Sat 23 Jun 2007 11:27:20 PM CEST schrieb Arjan van de Ven  
<arjan@infradead.org>:

> On Sat, 2007-06-23 at 13:32 +0000, Thomas Gleixner wrote:
>> plain text document attachment
>> (x86-64-clockevents-irq-balancing.patch)
>> From: Venki Pallipadi <venkatesh.pallipadi@intel.com>
>>
>> Disable irq balancing on IRQ0.
>
>
> this patch is missing some rationale....

Several SIS chipsets lock up when you try to change affinity of IRQ #0

-Andi


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

* Re: [patch -mm 26/28] x86-64 block irq balancing for timer
  2007-06-24  0:04     ` Andreas Kleen
@ 2007-06-24  1:20       ` Arjan van de Ven
  0 siblings, 0 replies; 39+ messages in thread
From: Arjan van de Ven @ 2007-06-24  1:20 UTC (permalink / raw)
  To: Andreas Kleen
  Cc: Thomas Gleixner, Andrew Morton, Ingo Molnar, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Sun, 2007-06-24 at 02:04 +0200, Andreas Kleen wrote:
> Am Sat 23 Jun 2007 11:27:20 PM CEST schrieb Arjan van de Ven  
> <arjan@infradead.org>:
> 
> > On Sat, 2007-06-23 at 13:32 +0000, Thomas Gleixner wrote:
> >> plain text document attachment
> >> (x86-64-clockevents-irq-balancing.patch)
> >> From: Venki Pallipadi <venkatesh.pallipadi@intel.com>
> >>
> >> Disable irq balancing on IRQ0.
> >
> >
> > this patch is missing some rationale....
> 
> Several SIS chipsets lock up when you try to change affinity of IRQ #0

so we're protecting root against himself.. fair enough.
probably wants a comment in the code 
-- 
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] 39+ messages in thread

* Re: [patch -mm 09/28] Tick management: spread timer interrupt
  2007-06-23 13:32 ` [patch -mm 09/28] Tick management: spread timer interrupt Thomas Gleixner
@ 2007-06-26  0:11   ` Andrew Morton
  0 siblings, 0 replies; 39+ messages in thread
From: Andrew Morton @ 2007-06-26  0:11 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Sat, 23 Jun 2007 13:32:34 -0000
Thomas Gleixner <tglx@linutronix.de> wrote:

> 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-23 14:38:56.000000000 +0200
> +++ linux-2.6.22-rc4-mm/kernel/time/tick-sched.c	2007-06-23 14:38:58.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);

With CONFIG_NR_CPUS=128 on a 2-way this'll be a pretty lumpy spreading? 
Perhaps it woud be better to use num_possible_cpus() here?


> +	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] 39+ messages in thread

* Re: [patch -mm 10/28] highres: Improve debug output
  2007-06-23 13:32 ` [patch -mm 10/28] highres: Improve debug output Thomas Gleixner
@ 2007-06-26  0:14   ` Andrew Morton
  2007-06-26 12:16     ` Thomas Gleixner
  0 siblings, 1 reply; 39+ messages in thread
From: Andrew Morton @ 2007-06-26  0:14 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Sat, 23 Jun 2007 13:32:35 -0000
Thomas Gleixner <tglx@linutronix.de> wrote:

>  	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);
> +		}

There is a logic path through here where the printk doesn't get its \n
termination?  And it will fail to print the reason for the failure, too.

Maybe that's a can't-happen, in which case the CLOCK_EVT_FEAT_ONESHOT test
is superfluous?


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

* Re: [patch -mm 22/28] x86_64: Convert to cleckevents
  2007-06-23 13:32 ` [patch -mm 22/28] x86_64: Convert to cleckevents Thomas Gleixner
@ 2007-06-26  0:27   ` Andrew Morton
  0 siblings, 0 replies; 39+ messages in thread
From: Andrew Morton @ 2007-06-26  0:27 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Sat, 23 Jun 2007 13:32:47 -0000
Thomas Gleixner <tglx@linutronix.de> wrote:

> 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>

semi-fixes.

>         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);
>         }

There's still bulk whitespace bustage in here.

(However checkpatch only says

Use #include <linux/hpet.h> instead of <asm/hpet.h>
#1913: FILE: arch/x86_64/kernel/tsc.c:11:
+#include <asm/hpet.h>
)

<edits the diff, fixes it>

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

* Re: [patch -mm 10/28] highres: Improve debug output
  2007-06-26  0:14   ` Andrew Morton
@ 2007-06-26 12:16     ` Thomas Gleixner
  0 siblings, 0 replies; 39+ messages in thread
From: Thomas Gleixner @ 2007-06-26 12:16 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Mon, 2007-06-25 at 17:14 -0700, Andrew Morton wrote:
> On Sat, 23 Jun 2007 13:32:35 -0000
> Thomas Gleixner <tglx@linutronix.de> wrote:
> 
> >  	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);
> > +		}
> 
> There is a logic path through here where the printk doesn't get its \n
> termination?  And it will fail to print the reason for the failure, too.
> 
> Maybe that's a can't-happen, in which case the CLOCK_EVT_FEAT_ONESHOT test
> is superfluous?

Right, the "else if (...)" test is bogus. A simple "else" is sufficient.

	tglx



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

* Re: [patch-mm 00/28] High resolution timer updates and x86_64 support - V3
  2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
                   ` (27 preceding siblings ...)
  2007-06-23 13:32 ` [patch -mm 28/28] x86_64: enable high resolution timers and dynticks Thomas Gleixner
@ 2007-06-28  9:42 ` Andrew Morton
  2007-06-28  9:47   ` Andi Kleen
  28 siblings, 1 reply; 39+ messages in thread
From: Andrew Morton @ 2007-06-28  9:42 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Andi Kleen, Ingo Molnar, Arjan van de Ven, Venkatesh Pallipadi,
	John Stultz, Chris Wright, LKML

On Sat, 23 Jun 2007 13:32:25 -0000 Thomas Gleixner <tglx@linutronix.de> wrote:

> 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

Blam.  http://userweb.kernel.org/~akpm/hpet-crash.jpg

time_init() is called before slab is set up.  We cannot do memory
allocations inside time_init().

> 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.

hrm.  Looks like none of your testers have HPET_ID_LEGSUP hardware.  This:

--- a/arch/i386/kernel/hpet.c~a
+++ a/arch/i386/kernel/hpet.c
@@ -376,7 +376,7 @@ int __init hpet_enable(void)
 
 	clocksource_register(&clocksource_hpet);
 
-	if (id & HPET_ID_LEGSUP) {
+	if (0 && (id & HPET_ID_LEGSUP)) {
 		hpet_enable_int();
 		hpet_reserve_platform_timers(id);
 		/*
_

gets it working.  It basically nobbles the hpet and the kernel chose the
TSC clocksource instead.


btw, if you want to know why I go on and on about crappy commenting, try to
work out from the kernel source code what HPET_ID_LEGSUP is, and why it
gets special treatment.  It is not possible.  This is not maintainable
code.


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

* Re: [patch-mm 00/28] High resolution timer updates and x86_64 support - V3
  2007-06-28  9:42 ` [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Andrew Morton
@ 2007-06-28  9:47   ` Andi Kleen
  2007-06-28 10:39     ` Andrew Morton
  0 siblings, 1 reply; 39+ messages in thread
From: Andi Kleen @ 2007-06-28  9:47 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Thomas Gleixner, Ingo Molnar, Arjan van de Ven,
	Venkatesh Pallipadi, John Stultz, Chris Wright, LKML

On Thursday 28 June 2007 11:42:33 Andrew Morton wrote:

> > 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.
> 
> hrm.  Looks like none of your testers have HPET_ID_LEGSUP hardware.  

AFAIK it's only on IBM Summit. You have such a box?

> btw, if you want to know why I go on and on about crappy commenting, try to
> work out from the kernel source code what HPET_ID_LEGSUP is, and why it
> gets special treatment.  It is not possible.  This is not maintainable
> code.

We have a reference somewhere to the HPET spec.

-Andi

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

* Re: [patch-mm 00/28] High resolution timer updates and x86_64 support - V3
  2007-06-28  9:47   ` Andi Kleen
@ 2007-06-28 10:39     ` Andrew Morton
  0 siblings, 0 replies; 39+ messages in thread
From: Andrew Morton @ 2007-06-28 10:39 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Thomas Gleixner, Ingo Molnar, Arjan van de Ven,
	Venkatesh Pallipadi, John Stultz, Chris Wright, LKML

On Thu, 28 Jun 2007 11:47:04 +0200 Andi Kleen <ak@suse.de> wrote:

> On Thursday 28 June 2007 11:42:33 Andrew Morton wrote:
> 
> > > 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.
> > 
> > hrm.  Looks like none of your testers have HPET_ID_LEGSUP hardware.  
> 
> AFAIK it's only on IBM Summit. You have such a box?

Intel Nocona SDV thing.  Old.

> > btw, if you want to know why I go on and on about crappy commenting, try to
> > work out from the kernel source code what HPET_ID_LEGSUP is, and why it
> > gets special treatment.  It is not possible.  This is not maintainable
> > code.
> 
> We have a reference somewhere to the HPET spec.

The HPET spec won't tell me why HPET_ID_LEGSUP hpets get a kmalloc in Linux
but the !HPET_ID_LEGSUP ones don't.


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

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

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-23 13:32 [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 01/28] NOHZ: Fix nox x86 dyntick idle handling Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 02/28] ACPI: Move timer broadcast and pmtimer access before C3 arbiter shutdown Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 03/28] clockevents: fix typo in acpi_pm.c Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 04/28] Timekeeping: Fixup shadow variable argument Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 05/28] timer.c cleanup recently introduced whitespace damage Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 06/28] Clockevents remove prototypes of removed functions Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 07/28] clockevents: Fix resume logic Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 08/28] clockevents: Fix device replacement Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 09/28] Tick management: spread timer interrupt Thomas Gleixner
2007-06-26  0:11   ` Andrew Morton
2007-06-23 13:32 ` [patch -mm 10/28] highres: Improve debug output Thomas Gleixner
2007-06-26  0:14   ` Andrew Morton
2007-06-26 12:16     ` Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 11/28] hrtimer: speedup hrtimer_enqueue Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 12/28] pcspkr: use the global PIT lock Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 13/28] NTP: Move the cmos update code into ntp.c Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 14/28] i386: PIT stop only, when in periodic or oneshot mode Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 15/28] i386: remove volatile in apic.c Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 16/28] i386: hpet assumes boot cpu is 0 Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 17/28] i386: move PIT function declarations and constants to correct header file Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 18/28] x86_64: untangle asm/hpet.h from asm/timex.h Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 19/28] x86_64: Use generic cmos update Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 20/28] x86-64: remove dead code and other janitor work in tsc.c Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 21/28] x86-64: Fix APIC typo Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 22/28] x86_64: Convert to cleckevents Thomas Gleixner
2007-06-26  0:27   ` Andrew Morton
2007-06-23 13:32 ` [patch -mm 23/28] ACPI: Remove the useless ifdef code Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 24/28] x86_64: hpet restore vread Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 25/28] x86_64: restore restore nohpet cmdline Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 26/28] x86-64 block irq balancing for timer Thomas Gleixner
2007-06-23 21:27   ` Arjan van de Ven
2007-06-24  0:04     ` Andreas Kleen
2007-06-24  1:20       ` Arjan van de Ven
2007-06-23 13:32 ` [patch -mm 27/28] x86_64: prep idle loop for dynticks Thomas Gleixner
2007-06-23 13:32 ` [patch -mm 28/28] x86_64: enable high resolution timers and dynticks Thomas Gleixner
2007-06-28  9:42 ` [patch-mm 00/28] High resolution timer updates and x86_64 support - V3 Andrew Morton
2007-06-28  9:47   ` Andi Kleen
2007-06-28 10:39     ` Andrew Morton

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).