All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/23] clocksource update v12
@ 2007-01-31  3:37 Daniel Walker
  2007-01-31  3:37 ` [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch Daniel Walker
                   ` (22 more replies)
  0 siblings, 23 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

This tree is mostly cleanups . I move timekeeping code into it's own 
file, and I modify the clocksource interface to provide a more robust
API.

I've dropped some duplication off the hrt/dynamic tick patch set which
is all new to that tree and new to -mm. This is an -mm patch set , it's
not meant to go on 2.6.20-rc6 at all .. I'm modifying code only
included in -mm.

I boot tested x86_64 smp, and i386 smp, and compile tested for ARM
(!GENERIC_TIME). This set should be bisect-able for at least i386 and
likely x86_64.

It's also available at,

ftp://source.mvista.com/pub/dwalker/clocksource/clocksource-v12/

Daniel
-- 

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

* [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 12:47   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 02/23] clocksource: drop clocksource-add-verification-watchdog-helper.patch Daniel Walker
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul, tglx, mingo

[-- Attachment #1: drop-clocksource-add-verification-watchdog-helper-fix.patch --]
[-- Type: text/plain, Size: 1245 bytes --]

Drop.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 kernel/time/clocksource.c |   11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -28,7 +28,6 @@
 #include <linux/sysdev.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/tick.h>
 
 /* XXX - Would like a better way for initializing curr_clocksource */
 extern struct clocksource clocksource_jiffies;
@@ -107,16 +106,8 @@ static void clocksource_watchdog(unsigne
 		/* Initialized ? */
 		if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
 			if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
-			    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) {
+			    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS))
 				cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-				/*
-				 * We just marked the clocksource as
-				 * highres-capable, notify the rest of the
-				 * system as well so that we transition
-				 * into high-res mode:
-				 */
-				tick_clock_notify();
-			}
 			cs->flags |= CLOCK_SOURCE_WATCHDOG;
 			cs->wd_last = csnow;
 		} else {

-- 

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

* [PATCH 02/23] clocksource: drop clocksource-add-verification-watchdog-helper.patch
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
  2007-01-31  3:37 ` [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 03/23] clocksource: drop clocksource-remove-the-update-callback.patch Daniel Walker
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul, tglx, mingo

[-- Attachment #1: drop-clocksource-add-verification-watchdog-helper.patch --]
[-- Type: text/plain, Size: 10594 bytes --]

Drop.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/Kconfig           |    4 -
 arch/i386/kernel/tsc.c      |   49 +++++++++++++++++
 include/linux/clocksource.h |   15 -----
 kernel/time/clocksource.c   |  125 +-------------------------------------------
 kernel/timer.c              |   48 ++++++++--------
 5 files changed, 79 insertions(+), 162 deletions(-)

Index: linux-2.6.19/arch/i386/Kconfig
===================================================================
--- linux-2.6.19.orig/arch/i386/Kconfig
+++ linux-2.6.19/arch/i386/Kconfig
@@ -18,10 +18,6 @@ config GENERIC_TIME
 	bool
 	default y
 
-config CLOCKSOURCE_WATCHDOG
-	bool
-	default y
-
 config GENERIC_CLOCKEVENTS
 	bool
 	default y
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -344,6 +344,49 @@ static struct dmi_system_id __initdata b
 	 {}
 };
 
+#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
+static struct timer_list verify_tsc_freq_timer;
+
+/* XXX - Probably should add locking */
+static void verify_tsc_freq(unsigned long unused)
+{
+	static u64 last_tsc;
+	static unsigned long last_jiffies;
+
+	u64 now_tsc, interval_tsc;
+	unsigned long now_jiffies, interval_jiffies;
+
+
+	if (check_tsc_unstable())
+		return;
+
+	rdtscll(now_tsc);
+	now_jiffies = jiffies;
+
+	if (!last_jiffies) {
+		goto out;
+	}
+
+	interval_jiffies = now_jiffies - last_jiffies;
+	interval_tsc = now_tsc - last_tsc;
+	interval_tsc *= HZ;
+	do_div(interval_tsc, cpu_khz*1000);
+
+	if (interval_tsc < (interval_jiffies * 3 / 4)) {
+		printk("TSC appears to be running slowly. "
+			"Marking it as unstable\n");
+		mark_tsc_unstable();
+		return;
+	}
+
+out:
+	last_tsc = now_tsc;
+	last_jiffies = now_jiffies;
+	/* set us up to go off on the next interval: */
+	mod_timer(&verify_tsc_freq_timer,
+		jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
+}
+
 /*
  * Make an educated guess if the TSC is trustworthy and synchronized
  * over all CPUs.
@@ -401,6 +444,12 @@ static int __init init_tsc_clocksource(v
 			clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
 		}
 
+		init_timer(&verify_tsc_freq_timer);
+		verify_tsc_freq_timer.function = verify_tsc_freq;
+		verify_tsc_freq_timer.expires =
+			jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL);
+		add_timer(&verify_tsc_freq_timer);
+
 		return clocksource_register(&clocksource_tsc);
 	}
 
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -12,13 +12,11 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
-#include <linux/timer.h>
 #include <asm/div64.h>
 #include <asm/io.h>
 
 /* clocksource cycle base type */
 typedef u64 cycle_t;
-struct clocksource;
 
 /**
  * struct clocksource - hardware abstraction for a free running counter
@@ -66,22 +64,13 @@ struct clocksource {
 	cycle_t cycle_last, cycle_interval;
 	u64 xtime_nsec, xtime_interval;
 	s64 error;
-
-#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
-	/* Watchdog related data, used by the framework */
-	struct list_head wd_list;
-	cycle_t wd_last;
-#endif
 };
 
 /*
  * Clock source flags bits::
  */
-#define CLOCK_SOURCE_IS_CONTINUOUS		0x01
-#define CLOCK_SOURCE_MUST_VERIFY		0x02
-
-#define CLOCK_SOURCE_WATCHDOG			0x10
-#define CLOCK_SOURCE_VALID_FOR_HRES		0x20
+#define CLOCK_SOURCE_IS_CONTINUOUS	0x01
+#define CLOCK_SOURCE_MUST_VERIFY	0x02
 
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -62,114 +62,8 @@ static int __init clocksource_done_booti
 	finished_booting = 1;
 	return 0;
 }
-late_initcall(clocksource_done_booting);
-
-#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
-static LIST_HEAD(watchdog_list);
-static struct clocksource *watchdog;
-static struct timer_list watchdog_timer;
-static DEFINE_SPINLOCK(watchdog_lock);
-static cycle_t watchdog_last;
-/*
- * Interval: 0.5sec Treshold: 0.0625s
- */
-#define WATCHDOG_INTERVAL (HZ >> 1)
-#define WATCHDOG_TRESHOLD (NSEC_PER_SEC >> 4)
-
-static void clocksource_ratewd(struct clocksource *cs, int64_t delta)
-{
-	if (delta > -WATCHDOG_TRESHOLD && delta < WATCHDOG_TRESHOLD)
-		return;
-
-	printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n",
-	       cs->name, delta);
-	cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
-	clocksource_change_rating(cs, 0);
-	cs->flags &= ~CLOCK_SOURCE_WATCHDOG;
-	list_del(&cs->wd_list);
-}
-
-static void clocksource_watchdog(unsigned long data)
-{
-	struct clocksource *cs, *tmp;
-	cycle_t csnow, wdnow;
-	int64_t wd_nsec, cs_nsec;
-
-	spin_lock(&watchdog_lock);
-
-	wdnow = watchdog->read();
-	wd_nsec = cyc2ns(watchdog, (wdnow - watchdog_last) & watchdog->mask);
-	watchdog_last = wdnow;
-
-	list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
-		csnow = cs->read();
-		/* Initialized ? */
-		if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
-			if ((cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) &&
-			    (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS))
-				cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-			cs->flags |= CLOCK_SOURCE_WATCHDOG;
-			cs->wd_last = csnow;
-		} else {
-			cs_nsec = cyc2ns(cs, (csnow - cs->wd_last) & cs->mask);
-			cs->wd_last = csnow;
-			/* Check the delta. Might remove from the list ! */
-			clocksource_ratewd(cs, cs_nsec - wd_nsec);
-		}
-	}
-
-	if (!list_empty(&watchdog_list)) {
-		__mod_timer(&watchdog_timer,
-			    watchdog_timer.expires + WATCHDOG_INTERVAL);
-	}
-	spin_unlock(&watchdog_lock);
-}
-static void clocksource_check_watchdog(struct clocksource *cs)
-{
-	struct clocksource *cse;
-	unsigned long flags;
 
-	spin_lock_irqsave(&watchdog_lock, flags);
-	if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
-		int started = !list_empty(&watchdog_list);
-
-		list_add(&cs->wd_list, &watchdog_list);
-		if (!started && watchdog) {
-			watchdog_last = watchdog->read();
-			watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
-			add_timer(&watchdog_timer);
-		}
-	} else if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) {
-			cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-
-		if (!watchdog || cs->rating > watchdog->rating) {
-			if (watchdog)
-				del_timer(&watchdog_timer);
-			watchdog = cs;
-			init_timer(&watchdog_timer);
-			watchdog_timer.function = clocksource_watchdog;
-
-			/* Reset watchdog cycles */
-			list_for_each_entry(cse, &watchdog_list, wd_list)
-				cse->flags &= ~CLOCK_SOURCE_WATCHDOG;
-			/* Start if list is not empty */
-			if (!list_empty(&watchdog_list)) {
-				watchdog_last = watchdog->read();
-				watchdog_timer.expires =
-					jiffies + WATCHDOG_INTERVAL;
-				add_timer(&watchdog_timer);
-			}
-		}
-	}
-	spin_unlock_irqrestore(&watchdog_lock, flags);
-}
-#else
-static void clocksource_check_watchdog(struct clocksource *cs)
-{
-	if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
-		cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
-}
-#endif
+late_initcall(clocksource_done_booting);
 
 /**
  * clocksource_get_next - Returns the selected clocksource
@@ -199,21 +93,13 @@ struct clocksource *clocksource_get_next
  */
 static struct clocksource *select_clocksource(void)
 {
-	struct clocksource *next;
-
 	if (list_empty(&clocksource_list))
 		return NULL;
 
 	if (clocksource_override)
-		next = clocksource_override;
-	else
-		next = list_entry(clocksource_list.next, struct clocksource,
-				  list);
+		return clocksource_override;
 
-	if (next == curr_clocksource)
-		return NULL;
-
-	return next;
+	return list_entry(clocksource_list.next, struct clocksource, list);
 }
 
 /*
@@ -251,15 +137,13 @@ static int clocksource_enqueue(struct cl
 int clocksource_register(struct clocksource *c)
 {
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
 	ret = clocksource_enqueue(c);
 	if (!ret)
 		next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
-	if (!ret)
-		clocksource_check_watchdog(c);
 	return ret;
 }
 EXPORT_SYMBOL(clocksource_register);
@@ -274,7 +158,6 @@ void clocksource_change_rating(struct cl
 
 	spin_lock_irqsave(&clocksource_lock, flags);
 	list_del(&cs->list);
-	cs->rating = rating;
 	clocksource_enqueue(cs);
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
Index: linux-2.6.19/kernel/timer.c
===================================================================
--- linux-2.6.19.orig/kernel/timer.c
+++ linux-2.6.19/kernel/timer.c
@@ -876,35 +876,31 @@ EXPORT_SYMBOL(do_settimeofday);
  *
  * Accumulates current time interval and initializes new clocksource
  */
-static void change_clocksource(void)
+static int change_clocksource(void)
 {
 	struct clocksource *new;
 	cycle_t now;
 	u64 nsec;
-
 	new = clocksource_get_next();
-
-	if (clock == new)
-		return;
-
-	now = clocksource_read(new);
-	nsec =  __get_nsec_offset();
-	timespec_add_ns(&xtime, nsec);
-
-	clock = new;
-	clock->cycle_last = now;
-
-	clock->error = 0;
-	clock->xtime_nsec = 0;
-	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-
-	tick_clock_notify();
-
-	printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-	       clock->name);
+	if (clock != new) {
+		now = clocksource_read(new);
+		nsec =  __get_nsec_offset();
+		timespec_add_ns(&xtime, nsec);
+
+		clock = new;
+		clock->cycle_last = now;
+		tick_clock_notify();
+		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+		       clock->name);
+		return 1;
+	}
+	return 0;
 }
 #else
-static inline void change_clocksource(void) { }
+static inline int change_clocksource(void)
+{
+	return 0;
+}
 #endif
 
 /**
@@ -918,7 +914,7 @@ int timekeeping_is_continuous(void)
 	do {
 		seq = read_seqbegin(&xtime_lock);
 
-		ret = clock->flags & CLOCK_SOURCE_VALID_FOR_HRES;
+		ret = clock->flags & CLOCK_SOURCE_IS_CONTINUOUS;
 
 	} while (read_seqretry(&xtime_lock, seq));
 
@@ -1172,7 +1168,11 @@ static void update_wall_time(void)
 	clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
 
 	/* check to see if there is a new clocksource to use */
-	change_clocksource();
+	if (change_clocksource()) {
+		clock->error = 0;
+		clock->xtime_nsec = 0;
+		clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+	}
 	update_vsyscall(&xtime, clock);
 }
 

-- 

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

* [PATCH 03/23] clocksource: drop clocksource-remove-the-update-callback.patch
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
  2007-01-31  3:37 ` [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch Daniel Walker
  2007-01-31  3:37 ` [PATCH 02/23] clocksource: drop clocksource-add-verification-watchdog-helper.patch Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 04/23] clocksource: drop time-x86_64-tsc-fixup-clocksource-changes.patch Daniel Walker
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul, tglx, mingo

[-- Attachment #1: drop-clocksource-remove-the-update-callback.patch --]
[-- Type: text/plain, Size: 5390 bytes --]

Drop.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/kernel/tsc.c      |   51 +++++++++++++++++++++++++++++---------------
 include/linux/clocksource.h |   11 ++++++---
 kernel/timer.c              |    3 ++
 3 files changed, 45 insertions(+), 20 deletions(-)

Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -60,6 +60,12 @@ static inline int check_tsc_unstable(voi
 	return tsc_unstable;
 }
 
+void mark_tsc_unstable(void)
+{
+	tsc_unstable = 1;
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
 /* Accellerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -289,6 +295,7 @@ core_initcall(cpufreq_tsc);
 /* clock source code */
 
 static unsigned long current_tsc_khz = 0;
+static int tsc_update_callback(void);
 
 static cycle_t read_tsc(void)
 {
@@ -306,28 +313,38 @@ static struct clocksource clocksource_ts
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
+	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-void mark_tsc_unstable(void)
+static int tsc_update_callback(void)
 {
-	if (!tsc_unstable) {
-		tsc_unstable = 1;
-		/* Can be called before registration */
-		if (clocksource_tsc.mult)
-			clocksource_change_rating(&clocksource_tsc, 0);
-		else
-			clocksource_tsc.rating = 0;
+	int change = 0;
+
+	/* check to see if we should switch to the safe clocksource: */
+	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
+		clocksource_tsc.rating = 0;
+		clocksource_reselect();
+		change = 1;
+	}
+
+	/* only update if tsc_khz has changed: */
+	if (current_tsc_khz != tsc_khz) {
+		current_tsc_khz = tsc_khz;
+		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+							clocksource_tsc.shift);
+		change = 1;
 	}
+
+	return change;
 }
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
 {
 	printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
 		       d->ident);
-	tsc_unstable = 1;
+	mark_tsc_unstable();
 	return 0;
 }
 
@@ -399,12 +416,11 @@ __cpuinit int unsynchronized_tsc(void)
 	 * Intel systems are normally all synchronized.
 	 * Exceptions must mark TSC as unstable:
 	 */
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
-		/* assume multi socket systems are not synchronized: */
-		if (num_possible_cpus() > 1)
-			tsc_unstable = 1;
-	}
-	return tsc_unstable;
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ 		return 0;
+
+	/* assume multi socket systems are not synchronized: */
+ 	return num_possible_cpus() > 1;
 }
 
 /*
@@ -433,7 +449,8 @@ static int __init init_tsc_clocksource(v
 		/* check blacklist */
 		dmi_check_system(bad_tsc_dmi_table);
 
-		unsynchronized_tsc();
+		if (unsynchronized_tsc()) /* mark unstable if unsynced */
+			mark_tsc_unstable();
 		check_geode_tsc_reliable();
 		current_tsc_khz = tsc_khz;
 		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -44,6 +44,7 @@ typedef u64 cycle_t;
  *			subtraction of non 64 bit counters
  * @mult:		cycle to nanosecond multiplier
  * @shift:		cycle to nanosecond divisor (power of two)
+ * @update_callback:	called when safe to alter clocksource values
  * @flags:		flags describing special properties
  * @vread:		vsyscall based read
  * @cycle_interval:	Used internally by timekeeping core, please ignore.
@@ -57,6 +58,7 @@ struct clocksource {
 	cycle_t mask;
 	u32 mult;
 	u32 shift;
+	int (*update_callback)(void);
 	unsigned long flags;
 	cycle_t (*vread)(void);
 
@@ -184,9 +186,9 @@ static inline void clocksource_calculate
 
 
 /* used to install a new clocksource */
-extern int clocksource_register(struct clocksource*);
-extern struct clocksource* clocksource_get_next(void);
-extern void clocksource_change_rating(struct clocksource *cs, int rating);
+int clocksource_register(struct clocksource*);
+void clocksource_reselect(void);
+struct clocksource* clocksource_get_next(void);
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
@@ -196,4 +198,7 @@ static inline void update_vsyscall(struc
 }
 #endif
 
+#define clocksource_reselect()	clocksource_change_rating(&clocksource_tsc, clocksource_tsc.rating)
+extern void clocksource_change_rating(struct clocksource *cs, int rating);
+
 #endif /* _LINUX_CLOCKSOURCE_H */
Index: linux-2.6.19/kernel/timer.c
===================================================================
--- linux-2.6.19.orig/kernel/timer.c
+++ linux-2.6.19/kernel/timer.c
@@ -893,6 +893,8 @@ static int change_clocksource(void)
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
 		return 1;
+	} else if (clock->update_callback) {
+		return clock->update_callback();
 	}
 	return 0;
 }
@@ -959,6 +961,7 @@ void __init timekeeping_init(void)
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 }
 
+
 /* flag for if timekeeping is suspended */
 static int timekeeping_suspended;
 /* time in seconds when suspend began */

-- 

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

* [PATCH 04/23] clocksource: drop time-x86_64-tsc-fixup-clocksource-changes.patch
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (2 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 03/23] clocksource: drop clocksource-remove-the-update-callback.patch Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 05/23] clocksource: drop simplify-the-registration-of-clocksources.patch Daniel Walker
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul, tglx, mingo

[-- Attachment #1: drop-time-x86_64-tsc-fixup-clocksource-changes.patch --]
[-- Type: text/plain, Size: 2090 bytes --]

Drop.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/x86_64/kernel/tsc.c |   31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/tsc.c
+++ linux-2.6.19/arch/x86_64/kernel/tsc.c
@@ -46,6 +46,13 @@ static inline int check_tsc_unstable(voi
 {
 	return tsc_unstable;
 }
+
+void mark_tsc_unstable(void)
+{
+	tsc_unstable = 1;
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
 #ifdef CONFIG_CPU_FREQ
 
 /* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
@@ -174,6 +181,9 @@ __setup("notsc", notsc_setup);
 
 
 /* clock source code: */
+
+static int tsc_update_callback(void);
+
 static cycle_t read_tsc(void)
 {
 	cycle_t ret = (cycle_t)get_cycles_sync();
@@ -192,23 +202,24 @@ static struct clocksource clocksource_ts
 	.read			= read_tsc,
 	.mask			= CLOCKSOURCE_MASK(64),
 	.shift			= 22,
+	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 	.vread			= vread_tsc,
 };
 
-void mark_tsc_unstable(void)
+static int tsc_update_callback(void)
 {
-	if (!tsc_unstable) {
-		tsc_unstable = 1;
-		/* Change only the rating, when not registered */
-		if (clocksource_tsc.mult)
-			clocksource_change_rating(&clocksource_tsc, 0);
-		else
-			clocksource_tsc.rating = 0;
+	int change = 0;
+
+	/* check to see if we should switch to the safe clocksource: */
+	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
+		clocksource_tsc.rating = 50;
+		clocksource_reselect();
+		change = 1;
 	}
+	return change;
 }
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init init_tsc_clocksource(void)
 {
@@ -216,7 +227,7 @@ static int __init init_tsc_clocksource(v
 		clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
 							clocksource_tsc.shift);
 		if (check_tsc_unstable())
-			clocksource_tsc.rating = 0;
+			clocksource_tsc.rating = 50;
 
 		return clocksource_register(&clocksource_tsc);
 	}

-- 

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

* [PATCH 05/23] clocksource: drop simplify-the-registration-of-clocksources.patch
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (3 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 04/23] clocksource: drop time-x86_64-tsc-fixup-clocksource-changes.patch Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c Daniel Walker
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul, tglx, mingo

[-- Attachment #1: drop-simplify-the-registration-of-clocksources.patch --]
[-- Type: text/plain, Size: 6525 bytes --]

Drop.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |    3 -
 kernel/time/clocksource.c   |  118 ++++++++++++++++++++++----------------------
 2 files changed, 61 insertions(+), 60 deletions(-)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -198,7 +198,4 @@ static inline void update_vsyscall(struc
 }
 #endif
 
-#define clocksource_reselect()	clocksource_change_rating(&clocksource_tsc, clocksource_tsc.rating)
-extern void clocksource_change_rating(struct clocksource *cs, int rating);
-
 #endif /* _LINUX_CLOCKSOURCE_H */
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -47,7 +47,6 @@ extern struct clocksource clocksource_ji
  */
 static struct clocksource *curr_clocksource = &clocksource_jiffies;
 static struct clocksource *next_clocksource;
-static struct clocksource *clocksource_override;
 static LIST_HEAD(clocksource_list);
 static DEFINE_SPINLOCK(clocksource_lock);
 static char override_name[32];
@@ -84,46 +83,60 @@ struct clocksource *clocksource_get_next
 }
 
 /**
- * select_clocksource - Selects the best registered clocksource.
+ * select_clocksource - Finds the best registered clocksource.
  *
  * Private function. Must hold clocksource_lock when called.
  *
- * Select the clocksource with the best rating, or the clocksource,
- * which is selected by userspace override.
+ * Looks through the list of registered clocksources, returning
+ * the one with the highest rating value. If there is a clocksource
+ * name that matches the override string, it returns that clocksource.
  */
 static struct clocksource *select_clocksource(void)
 {
-	if (list_empty(&clocksource_list))
-		return NULL;
+	struct clocksource *best = NULL;
+	struct list_head *tmp;
+
+	list_for_each(tmp, &clocksource_list) {
+		struct clocksource *src;
 
-	if (clocksource_override)
-		return clocksource_override;
+		src = list_entry(tmp, struct clocksource, list);
+		if (!best)
+			best = src;
+
+		/* check for override: */
+		if (strlen(src->name) == strlen(override_name) &&
+		    !strcmp(src->name, override_name)) {
+			best = src;
+			break;
+		}
+		/* pick the highest rating: */
+		if (src->rating > best->rating)
+		 	best = src;
+	}
 
-	return list_entry(clocksource_list.next, struct clocksource, list);
+	return best;
 }
 
-/*
- * Enqueue the clocksource sorted by rating
+/**
+ * is_registered_source - Checks if clocksource is registered
+ * @c:		pointer to a clocksource
+ *
+ * Private helper function. Must hold clocksource_lock when called.
+ *
+ * Returns one if the clocksource is already registered, zero otherwise.
  */
-static int clocksource_enqueue(struct clocksource *c)
+static int is_registered_source(struct clocksource *c)
 {
-	struct list_head *tmp, *entry = &clocksource_list;
+	int len = strlen(c->name);
+	struct list_head *tmp;
 
 	list_for_each(tmp, &clocksource_list) {
-		struct clocksource *cs;
+		struct clocksource *src;
 
-		cs = list_entry(tmp, struct clocksource, list);
-		if (cs == c)
-			return -EBUSY;
-		/* Keep track of the place, where to insert */
-		if (cs->rating >= c->rating)
-			entry = tmp;
+		src = list_entry(tmp, struct clocksource, list);
+		if (strlen(src->name) == len &&	!strcmp(src->name, c->name))
+			return 1;
 	}
-	list_add(&c->list, entry);
-
-	if (strlen(c->name) == strlen(override_name) &&
-	    !strcmp(c->name, override_name))
-		clocksource_override = c;
 
 	return 0;
 }
@@ -136,32 +149,42 @@ static int clocksource_enqueue(struct cl
  */
 int clocksource_register(struct clocksource *c)
 {
-	unsigned long flags;
 	int ret = 0;
+	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	ret = clocksource_enqueue(c);
-	if (!ret)
+	/* check if clocksource is already registered */
+	if (is_registered_source(c)) {
+		printk("register_clocksource: Cannot register %s. "
+		       "Already registered!", c->name);
+		ret = -EBUSY;
+	} else {
+		/* register it */
+ 		list_add(&c->list, &clocksource_list);
+		/* scan the registered clocksources, and pick the best one */
 		next_clocksource = select_clocksource();
+	}
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(clocksource_register);
 
 /**
- * clocksource_change_rating - Change the rating of a registered clocksource
+ * clocksource_reselect - Rescan list for next clocksource
  *
+ * A quick helper function to be used if a clocksource changes its
+ * rating. Forces the clocksource list to be re-scanned for the best
+ * clocksource.
  */
-void clocksource_change_rating(struct clocksource *cs, int rating)
+void clocksource_reselect(void)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	list_del(&cs->list);
-	clocksource_enqueue(cs);
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 }
+EXPORT_SYMBOL(clocksource_reselect);
 
 #ifdef CONFIG_SYSFS
 /**
@@ -197,11 +220,7 @@ sysfs_show_current_clocksources(struct s
 static ssize_t sysfs_override_clocksource(struct sys_device *dev,
 					  const char *buf, size_t count)
 {
-	struct clocksource *ovr = NULL;
-	struct list_head *tmp;
 	size_t ret = count;
-	int len;
-
 	/* strings from sysfs write are not 0 terminated! */
 	if (count >= sizeof(override_name))
 		return -EINVAL;
@@ -209,32 +228,17 @@ static ssize_t sysfs_override_clocksourc
 	/* strip of \n: */
 	if (buf[count-1] == '\n')
 		count--;
+	if (count < 1)
+		return -EINVAL;
 
 	spin_lock_irq(&clocksource_lock);
 
-	if (count > 0)
-		memcpy(override_name, buf, count);
+	/* copy the name given: */
+	memcpy(override_name, buf, count);
 	override_name[count] = 0;
 
-	len = strlen(override_name);
-	if (len) {
-		ovr = clocksource_override;
-		/* try to select it: */
-		list_for_each(tmp, &clocksource_list) {
-			struct clocksource *cs;
-
-			cs = list_entry(tmp, struct clocksource, list);
-			if (strlen(cs->name) == len &&
-			    !strcmp(cs->name, override_name))
-				ovr = cs;
-		}
-	}
-
-	/* Reselect, when the override name has changed */
-	if (ovr != clocksource_override) {
-		clocksource_override = ovr;
-		next_clocksource = select_clocksource();
-	}
+	/* try to select it: */
+	next_clocksource = select_clocksource();
 
 	spin_unlock_irq(&clocksource_lock);
 

-- 

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

* [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (4 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 05/23] clocksource: drop simplify-the-registration-of-clocksources.patch Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  8:59   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 07/23] clocksource: rating sorted list Daniel Walker
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: timekeeping_move_out_of_timer_c.patch --]
[-- Type: text/plain, Size: 42371 bytes --]

Move the generic timekeeping code from kernel/timer.c to
kernel/time/timekeeping.c . This requires some glue code which is
added to the include/linux/timekeeping.h header.

I tried to be as careful as possible in picking up recent changes to
the timekeeping code. This patches is on top of -mm , and moves all
the changes included in -mm.

This is also moving do_timer and the load calculation code which was
connect to the timekeeping code. Moving it provided for slightly better
compiler optimization.

Signed-Off-By: Daniel Walker <dwalker@mvista.com> 

---
 include/linux/clocksource.h |    3 
 include/linux/timekeeping.h |   13 
 kernel/time/Makefile        |    2 
 kernel/time/clocksource.c   |    3 
 kernel/time/timekeeping.c   |  711 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/timer.c              |  694 ------------------------------------------
 6 files changed, 729 insertions(+), 697 deletions(-)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -18,6 +18,9 @@
 /* clocksource cycle base type */
 typedef u64 cycle_t;
 
+/* XXX - Would like a better way for initializing curr_clocksource */
+extern struct clocksource clocksource_jiffies;
+
 /**
  * struct clocksource - hardware abstraction for a free running counter
  *	Provides mostly state-free accessors to the underlying hardware.
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
--- /dev/null
+++ linux-2.6.19/include/linux/timekeeping.h
@@ -0,0 +1,13 @@
+#ifndef _LINUX_TIMEKEEPING_H
+#define _LINUX_TIMEKEEPING_H
+
+#include <linux/clocksource.h>
+
+#ifndef CONFIG_GENERIC_TIME
+static inline int change_clocksource(void)
+{
+	return 0;
+}
+#endif /* !CONFIG_GENERIC_TIME */
+
+#endif /* _LINUX_TIMEKEEPING_H */
Index: linux-2.6.19/kernel/time/Makefile
===================================================================
--- linux-2.6.19.orig/kernel/time/Makefile
+++ linux-2.6.19/kernel/time/Makefile
@@ -1,4 +1,4 @@
-obj-y += ntp.o clocksource.o jiffies.o timer_list.o
+obj-y += ntp.o clocksource.o jiffies.o timer_list.o timekeeping.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= clockevents.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -29,9 +29,6 @@
 #include <linux/init.h>
 #include <linux/module.h>
 
-/* XXX - Would like a better way for initializing curr_clocksource */
-extern struct clocksource clocksource_jiffies;
-
 /*[Clocksource internal variables]---------
  * curr_clocksource:
  *	currently selected clocksource. Initialized to clocksource_jiffies.
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
--- /dev/null
+++ linux-2.6.19/kernel/time/timekeeping.c
@@ -0,0 +1,711 @@
+/*
+ *  linux/kernel/time/timekeeping.c
+ *
+ *  timekeeping functions
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/timekeeping.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+
+/*
+ * The current time
+ * wall_to_monotonic is what we need to add to xtime (or xtime corrected
+ * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
+ * at zero at system boot time, so wall_to_monotonic will be negative,
+ * however, we will ALWAYS keep the tv_nsec part positive so we can use
+ * the usual normalization.
+ */
+struct timespec xtime __attribute__ ((aligned (16)));
+struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+
+EXPORT_SYMBOL(xtime);
+
+/*
+ * flag for if timekeeping is suspended
+ */
+static int timekeeping_suspended;
+
+/*
+ * time in seconds when suspend began
+ */
+static unsigned long timekeeping_suspend_time;
+
+/*
+ * Clock used for timekeeping
+ */
+struct clocksource *clock = &clocksource_jiffies;
+
+#ifdef CONFIG_GENERIC_TIME
+/**
+ * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
+ *
+ * private function, must hold xtime_lock lock when being
+ * called. Returns the number of nanoseconds since the
+ * last call to update_wall_time() (adjusted by NTP scaling)
+ */
+static inline s64 __get_nsec_offset(void)
+{
+	cycle_t cycle_now, cycle_delta;
+	s64 ns_offset;
+
+	/* read clocksource: */
+	cycle_now = clocksource_read(clock);
+
+	/* calculate the delta since the last update_wall_time: */
+	cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
+
+	/* convert to nanoseconds: */
+	ns_offset = cyc2ns(clock, cycle_delta);
+
+	return ns_offset;
+}
+
+/**
+ * __get_realtime_clock_ts - Returns the time of day in a timespec
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec. Used by
+ * do_gettimeofday() and get_realtime_clock_ts().
+ */
+static inline void __get_realtime_clock_ts(struct timespec *ts)
+{
+	unsigned long seq;
+	s64 nsecs;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+
+		*ts = xtime;
+		nsecs = __get_nsec_offset();
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	timespec_add_ns(ts, nsecs);
+}
+
+/**
+ * getnstimeofday - Returns the time of day in a timespec
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ */
+void getnstimeofday(struct timespec *ts)
+{
+	__get_realtime_clock_ts(ts);
+}
+
+EXPORT_SYMBOL(getnstimeofday);
+
+/**
+ * do_gettimeofday - Returns the time of day in a timeval
+ * @tv:		pointer to the timeval to be set
+ *
+ * NOTE: Users should be converted to using get_realtime_clock_ts()
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	struct timespec now;
+
+	__get_realtime_clock_ts(&now);
+	tv->tv_sec = now.tv_sec;
+	tv->tv_usec = now.tv_nsec/1000;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+/**
+ * do_settimeofday - Sets the time of day
+ * @tv:		pointer to the timespec variable containing the new time
+ *
+ * Sets the time of day to the new time and update NTP and notify hrtimers
+ */
+int do_settimeofday(struct timespec *tv)
+{
+	unsigned long flags;
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
+	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	nsec -= __get_nsec_offset();
+
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+	clock->error = 0;
+	ntp_clear();
+
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	/* signal hrtimers about time change */
+	clock_was_set();
+
+	return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/**
+ * change_clocksource - Swaps clocksources if a new one is available
+ *
+ * Accumulates current time interval and initializes new clocksource
+ */
+static int change_clocksource(void)
+{
+	struct clocksource *new;
+	cycle_t now;
+	u64 nsec;
+	new = clocksource_get_next();
+	if (clock != new) {
+		now = clocksource_read(new);
+		nsec =  __get_nsec_offset();
+		timespec_add_ns(&xtime, nsec);
+
+		clock = new;
+		clock->cycle_last = now;
+		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+		       clock->name);
+		return 1;
+	} else if (clock->update_callback) {
+		return clock->update_callback();
+	}
+	return 0;
+}
+
+/**
+ * timeofday_is_continuous - check to see if timekeeping is free running
+ */
+int timekeeping_is_continuous(void)
+{
+	unsigned long seq;
+	int ret;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+
+		ret = clock->flags & CLOCK_SOURCE_IS_CONTINUOUS;
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	return ret;
+}
+#endif /* CONFIG_GENERIC_TIME */
+
+/**
+ * read_persistent_clock -  Return time in seconds from the persistent clock.
+ *
+ * Weak dummy function for arches that do not yet support it.
+ * Returns seconds from epoch using the battery backed persistent clock.
+ * Returns zero if unsupported.
+ *
+ *  XXX - Do be sure to remove it once all arches implement it.
+ */
+unsigned long __attribute__((weak)) read_persistent_clock(void)
+{
+	return 0;
+}
+
+/*
+ * timekeeping_init - Initializes the clocksource and common timekeeping values
+ */
+void __init timekeeping_init(void)
+{
+	unsigned long flags;
+	unsigned long sec = read_persistent_clock();
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	ntp_clear();
+
+	clock = clocksource_get_next();
+	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+	clock->cycle_last = clocksource_read(clock);
+
+	xtime.tv_sec = sec;
+	xtime.tv_nsec = 0;
+	set_normalized_timespec(&wall_to_monotonic,
+		-xtime.tv_sec, -xtime.tv_nsec);
+
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+}
+
+
+/* flag for if timekeeping is suspended */
+static int timekeeping_suspended;
+/* time in seconds when suspend began */
+static unsigned long timekeeping_suspend_time;
+
+/**
+ * timekeeping_resume - Resumes the generic timekeeping subsystem.
+ * @dev:	unused
+ *
+ * This is for the generic clocksource timekeeping.
+ * xtime/wall_to_monotonic/jiffies/etc are
+ * still managed by arch specific suspend/resume code.
+ */
+static int timekeeping_resume(struct sys_device *dev)
+{
+	unsigned long flags;
+	unsigned long now = read_persistent_clock();
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	if (now && (now > timekeeping_suspend_time)) {
+		unsigned long sleep_length = now - timekeeping_suspend_time;
+		xtime.tv_sec += sleep_length;
+		jiffies_64 += (u64)sleep_length * HZ;
+	}
+	/* re-base the last cycle value */
+	clock->cycle_last = clocksource_read(clock);
+	clock->error = 0;
+	timekeeping_suspended = 0;
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
+	/* Resume hrtimers */
+	clock_was_set();
+
+	return 0;
+}
+
+static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
+{
+	unsigned long flags;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	timekeeping_suspended = 1;
+	timekeeping_suspend_time = read_persistent_clock();
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+	return 0;
+}
+
+/* sysfs resume/suspend bits for timekeeping */
+static struct sysdev_class timekeeping_sysclass = {
+	.resume		= timekeeping_resume,
+	.suspend	= timekeeping_suspend,
+	set_kset_name("timekeeping"),
+};
+
+static struct sys_device device_timer = {
+	.id		= 0,
+	.cls		= &timekeeping_sysclass,
+};
+
+static int __init timekeeping_init_device(void)
+{
+	int error = sysdev_class_register(&timekeeping_sysclass);
+	if (!error)
+		error = sysdev_register(&device_timer);
+	return error;
+}
+
+device_initcall(timekeeping_init_device);
+
+/*
+ * If the error is already larger, we look ahead even further
+ * to compensate for late or lost adjustments.
+ */
+static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
+						 s64 *offset)
+{
+	s64 tick_error, i;
+	u32 look_ahead, adj;
+	s32 error2, mult;
+
+	/*
+	 * Use the current error value to determine how much to look ahead.
+	 * The larger the error the slower we adjust for it to avoid problems
+	 * with losing too many ticks, otherwise we would overadjust and
+	 * produce an even larger error.  The smaller the adjustment the
+	 * faster we try to adjust for it, as lost ticks can do less harm
+	 * here.  This is tuned so that an error of about 1 msec is adusted
+	 * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
+	 */
+	error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
+	error2 = abs(error2);
+	for (look_ahead = 0; error2 > 0; look_ahead++)
+		error2 >>= 2;
+
+	/*
+	 * Now calculate the error in (1 << look_ahead) ticks, but first
+	 * remove the single look ahead already included in the error.
+	 */
+	tick_error = current_tick_length() >>
+		(TICK_LENGTH_SHIFT - clock->shift + 1);
+	tick_error -= clock->xtime_interval >> 1;
+	error = ((error - tick_error) >> look_ahead) + tick_error;
+
+	/* Finally calculate the adjustment shift value.  */
+	i = *interval;
+	mult = 1;
+	if (error < 0) {
+		error = -error;
+		*interval = -*interval;
+		*offset = -*offset;
+		mult = -1;
+	}
+	for (adj = 0; error > i; adj++)
+		error >>= 1;
+
+	*interval <<= adj;
+	*offset <<= adj;
+	return mult << adj;
+}
+
+/*
+ * Adjust the multiplier to reduce the error value,
+ * 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)
+{
+	s64 error, interval = clock->cycle_interval;
+	int adj;
+
+	error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
+	if (error > interval) {
+		error >>= 2;
+		if (likely(error <= interval))
+			adj = 1;
+		else
+			adj = clocksource_bigadjust(error, &interval, &offset);
+	} else if (error < -interval) {
+		error >>= 2;
+		if (likely(error >= -interval)) {
+			adj = -1;
+			interval = -interval;
+			offset = -offset;
+		} else
+			adj = clocksource_bigadjust(error, &interval, &offset);
+	} else
+		return;
+
+	clock->mult += adj;
+	clock->xtime_interval += interval;
+	clock->xtime_nsec -= offset;
+	clock->error -= (interval - offset) <<
+			(TICK_LENGTH_SHIFT - clock->shift);
+}
+
+/**
+ * update_wall_time - Uses the current clocksource to increment the wall time
+ *
+ * Called from the timer interrupt, must hold a write on xtime_lock.
+ */
+static inline void update_wall_time(void)
+{
+	cycle_t offset;
+
+	/* Make sure we're fully resumed: */
+	if (unlikely(timekeeping_suspended))
+		return;
+
+#ifdef CONFIG_GENERIC_TIME
+	offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
+#else
+	offset = clock->cycle_interval;
+#endif
+	clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
+
+	/* normally this loop will run just once, however in the
+	 * case of lost or late ticks, it will accumulate correctly.
+	 */
+	while (offset >= clock->cycle_interval) {
+		/* accumulate one interval */
+		clock->xtime_nsec += clock->xtime_interval;
+		clock->cycle_last += clock->cycle_interval;
+		offset -= clock->cycle_interval;
+
+		if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
+			clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
+			xtime.tv_sec++;
+			second_overflow();
+		}
+
+		/* interpolator bits */
+		time_interpolator_update(clock->xtime_interval
+						>> clock->shift);
+
+		/* accumulate error between NTP and clock interval */
+		clock->error += current_tick_length();
+		clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
+	}
+
+	/* correct the clock when NTP error is too big */
+	clocksource_adjust(clock, offset);
+
+	/* store full nanoseconds into xtime */
+	xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
+	clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
+
+	/* check to see if there is a new clocksource to use */
+	if (change_clocksource()) {
+		clock->error = 0;
+		clock->xtime_nsec = 0;
+		tick_clock_notify();
+		clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+	}
+	update_vsyscall(&xtime, clock);
+}
+
+/*
+ * Nr of active tasks - counted in fixed-point numbers
+ */
+static unsigned long count_active_tasks(void)
+{
+	return nr_active() * FIXED_1;
+}
+
+/*
+ * Hmm.. Changed this, as the GNU make sources (load.c) seems to
+ * imply that avenrun[] is the standard name for this kind of thing.
+ * Nothing else seems to be standardized: the fractional size etc
+ * all seem to differ on different machines.
+ *
+ * Requires xtime_lock to access.
+ */
+unsigned long avenrun[3];
+
+EXPORT_SYMBOL(avenrun);
+
+/*
+ * calc_load - given tick count, update the avenrun load estimates.
+ * This is called while holding a write_lock on xtime_lock.
+ */
+static inline void calc_load(unsigned long ticks)
+{
+	unsigned long active_tasks; /* fixed-point */
+	static int count = LOAD_FREQ;
+
+	count -= ticks;
+	if (unlikely(count < 0)) {
+		active_tasks = count_active_tasks();
+		do {
+			CALC_LOAD(avenrun[0], EXP_1, active_tasks);
+			CALC_LOAD(avenrun[1], EXP_5, active_tasks);
+			CALC_LOAD(avenrun[2], EXP_15, active_tasks);
+			count += LOAD_FREQ;
+		} while (count < 0);
+	}
+}
+
+/*
+ * Called by the timer interrupt. xtime_lock must already be taken
+ * by the timer IRQ!
+ */
+static inline void update_times(unsigned long ticks)
+{
+	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.
+ * jiffies is defined in the linker script...
+ */
+
+void do_timer(unsigned long ticks)
+{
+	jiffies_64 += ticks;
+	update_times(ticks);
+}
+
+#ifdef CONFIG_TIME_INTERPOLATION
+
+struct time_interpolator *time_interpolator __read_mostly;
+static struct time_interpolator *time_interpolator_list __read_mostly;
+static DEFINE_SPINLOCK(time_interpolator_lock);
+
+static inline cycles_t time_interpolator_get_cycles(unsigned int src)
+{
+	unsigned long (*x)(void);
+
+	switch (src)
+	{
+		case TIME_SOURCE_FUNCTION:
+			x = time_interpolator->addr;
+			return x();
+
+		case TIME_SOURCE_MMIO64	:
+			return readq_relaxed((void __iomem *)time_interpolator->addr);
+
+		case TIME_SOURCE_MMIO32	:
+			return readl_relaxed((void __iomem *)time_interpolator->addr);
+
+		default: return get_cycles();
+	}
+}
+
+static inline u64 time_interpolator_get_counter(int writelock)
+{
+	unsigned int src = time_interpolator->source;
+
+	if (time_interpolator->jitter)
+	{
+		cycles_t lcycle;
+		cycles_t now;
+
+		do {
+			lcycle = time_interpolator->last_cycle;
+			now = time_interpolator_get_cycles(src);
+			if (lcycle && time_after(lcycle, now))
+				return lcycle;
+
+			/* When holding the xtime write lock, there's no need
+			 * to add the overhead of the cmpxchg.  Readers are
+			 * force to retry until the write lock is released.
+			 */
+			if (writelock) {
+				time_interpolator->last_cycle = now;
+				return now;
+			}
+			/* Keep track of the last timer value returned. The use of cmpxchg here
+			 * will cause contention in an SMP environment.
+			 */
+		} while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle));
+		return now;
+	}
+	else
+		return time_interpolator_get_cycles(src);
+}
+
+void time_interpolator_reset(void)
+{
+	time_interpolator->offset = 0;
+	time_interpolator->last_counter = time_interpolator_get_counter(1);
+}
+
+#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
+
+unsigned long time_interpolator_get_offset(void)
+{
+	/* If we do not have a time interpolator set up then just return zero */
+	if (!time_interpolator)
+		return 0;
+
+	return time_interpolator->offset +
+		GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
+}
+
+#define INTERPOLATOR_ADJUST 65536
+#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
+
+void time_interpolator_update(long delta_nsec)
+{
+	u64 counter;
+	unsigned long offset;
+
+	/* If there is no time interpolator set up then do nothing */
+	if (!time_interpolator)
+		return;
+
+	/*
+	 * The interpolator compensates for late ticks by accumulating the late
+	 * time in time_interpolator->offset. A tick earlier than expected will
+	 * lead to a reset of the offset and a corresponding jump of the clock
+	 * forward. Again this only works if the interpolator clock is running
+	 * slightly slower than the regular clock and the tuning logic insures
+	 * that.
+	 */
+
+	counter = time_interpolator_get_counter(1);
+	offset = time_interpolator->offset +
+			GET_TI_NSECS(counter, time_interpolator);
+
+	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
+		time_interpolator->offset = offset - delta_nsec;
+	else {
+		time_interpolator->skips++;
+		time_interpolator->ns_skipped += delta_nsec - offset;
+		time_interpolator->offset = 0;
+	}
+	time_interpolator->last_counter = counter;
+
+	/* Tuning logic for time interpolator invoked every minute or so.
+	 * Decrease interpolator clock speed if no skips occurred and an offset is carried.
+	 * Increase interpolator clock speed if we skip too much time.
+	 */
+	if (jiffies % INTERPOLATOR_ADJUST == 0)
+	{
+		if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
+			time_interpolator->nsec_per_cyc--;
+		if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
+			time_interpolator->nsec_per_cyc++;
+		time_interpolator->skips = 0;
+		time_interpolator->ns_skipped = 0;
+	}
+}
+
+static inline int
+is_better_time_interpolator(struct time_interpolator *new)
+{
+	if (!time_interpolator)
+		return 1;
+	return new->frequency > 2*time_interpolator->frequency ||
+	    (unsigned long)new->drift < (unsigned long)time_interpolator->drift;
+}
+
+void
+register_time_interpolator(struct time_interpolator *ti)
+{
+	unsigned long flags;
+
+	/* Sanity check */
+	BUG_ON(ti->frequency == 0 || ti->mask == 0);
+
+	ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
+	spin_lock(&time_interpolator_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
+	if (is_better_time_interpolator(ti)) {
+		time_interpolator = ti;
+		time_interpolator_reset();
+	}
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	ti->next = time_interpolator_list;
+	time_interpolator_list = ti;
+	spin_unlock(&time_interpolator_lock);
+}
+
+void
+unregister_time_interpolator(struct time_interpolator *ti)
+{
+	struct time_interpolator *curr, **prev;
+	unsigned long flags;
+
+	spin_lock(&time_interpolator_lock);
+	prev = &time_interpolator_list;
+	for (curr = *prev; curr; curr = curr->next) {
+		if (curr == ti) {
+			*prev = curr->next;
+			break;
+		}
+		prev = &curr->next;
+	}
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	if (ti == time_interpolator) {
+		/* we lost the best time-interpolator: */
+		time_interpolator = NULL;
+		/* find the next-best interpolator */
+		for (curr = time_interpolator_list; curr; curr = curr->next)
+			if (is_better_time_interpolator(curr))
+				time_interpolator = curr;
+		time_interpolator_reset();
+	}
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+	spin_unlock(&time_interpolator_lock);
+}
+#endif /* CONFIG_TIME_INTERPOLATION */
+
Index: linux-2.6.19/kernel/timer.c
===================================================================
--- linux-2.6.19.orig/kernel/timer.c
+++ linux-2.6.19/kernel/timer.c
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/tick.h>
 #include <linux/kallsyms.h>
+#include <linux/timekeeping.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -736,449 +737,6 @@ unsigned long next_timer_interrupt(void)
 
 #endif
 
-/******************************************************************/
-
-/* 
- * The current time 
- * wall_to_monotonic is what we need to add to xtime (or xtime corrected 
- * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
- * at zero at system boot time, so wall_to_monotonic will be negative,
- * however, we will ALWAYS keep the tv_nsec part positive so we can use
- * the usual normalization.
- */
-struct timespec xtime __attribute__ ((aligned (16)));
-struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
-
-EXPORT_SYMBOL(xtime);
-
-
-/* XXX - all of this timekeeping code should be later moved to time.c */
-#include <linux/clocksource.h>
-static struct clocksource *clock; /* pointer to current clocksource */
-
-#ifdef CONFIG_GENERIC_TIME
-/**
- * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
- *
- * private function, must hold xtime_lock lock when being
- * called. Returns the number of nanoseconds since the
- * last call to update_wall_time() (adjusted by NTP scaling)
- */
-static inline s64 __get_nsec_offset(void)
-{
-	cycle_t cycle_now, cycle_delta;
-	s64 ns_offset;
-
-	/* read clocksource: */
-	cycle_now = clocksource_read(clock);
-
-	/* calculate the delta since the last update_wall_time: */
-	cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
-
-	/* convert to nanoseconds: */
-	ns_offset = cyc2ns(clock, cycle_delta);
-
-	return ns_offset;
-}
-
-/**
- * __get_realtime_clock_ts - Returns the time of day in a timespec
- * @ts:		pointer to the timespec to be set
- *
- * Returns the time of day in a timespec. Used by
- * do_gettimeofday() and get_realtime_clock_ts().
- */
-static inline void __get_realtime_clock_ts(struct timespec *ts)
-{
-	unsigned long seq;
-	s64 nsecs;
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-
-		*ts = xtime;
-		nsecs = __get_nsec_offset();
-
-	} while (read_seqretry(&xtime_lock, seq));
-
-	timespec_add_ns(ts, nsecs);
-}
-
-/**
- * getnstimeofday - Returns the time of day in a timespec
- * @ts:		pointer to the timespec to be set
- *
- * Returns the time of day in a timespec.
- */
-void getnstimeofday(struct timespec *ts)
-{
-	__get_realtime_clock_ts(ts);
-}
-
-EXPORT_SYMBOL(getnstimeofday);
-
-/**
- * do_gettimeofday - Returns the time of day in a timeval
- * @tv:		pointer to the timeval to be set
- *
- * NOTE: Users should be converted to using get_realtime_clock_ts()
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	struct timespec now;
-
-	__get_realtime_clock_ts(&now);
-	tv->tv_sec = now.tv_sec;
-	tv->tv_usec = now.tv_nsec/1000;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-/**
- * do_settimeofday - Sets the time of day
- * @tv:		pointer to the timespec variable containing the new time
- *
- * Sets the time of day to the new time and update NTP and notify hrtimers
- */
-int do_settimeofday(struct timespec *tv)
-{
-	unsigned long flags;
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-
-	nsec -= __get_nsec_offset();
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	clock->error = 0;
-	ntp_clear();
-
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-
-	/* signal hrtimers about time change */
-	clock_was_set();
-
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/**
- * change_clocksource - Swaps clocksources if a new one is available
- *
- * Accumulates current time interval and initializes new clocksource
- */
-static int change_clocksource(void)
-{
-	struct clocksource *new;
-	cycle_t now;
-	u64 nsec;
-	new = clocksource_get_next();
-	if (clock != new) {
-		now = clocksource_read(new);
-		nsec =  __get_nsec_offset();
-		timespec_add_ns(&xtime, nsec);
-
-		clock = new;
-		clock->cycle_last = now;
-		tick_clock_notify();
-		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
-		       clock->name);
-		return 1;
-	} else if (clock->update_callback) {
-		return clock->update_callback();
-	}
-	return 0;
-}
-#else
-static inline int change_clocksource(void)
-{
-	return 0;
-}
-#endif
-
-/**
- * timeofday_is_continuous - check to see if timekeeping is free running
- */
-int timekeeping_is_continuous(void)
-{
-	unsigned long seq;
-	int ret;
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-
-		ret = clock->flags & CLOCK_SOURCE_IS_CONTINUOUS;
-
-	} while (read_seqretry(&xtime_lock, seq));
-
-	return ret;
-}
-
-/**
- * read_persistent_clock -  Return time in seconds from the persistent clock.
- *
- * Weak dummy function for arches that do not yet support it.
- * Returns seconds from epoch using the battery backed persistent clock.
- * Returns zero if unsupported.
- *
- *  XXX - Do be sure to remove it once all arches implement it.
- */
-unsigned long __attribute__((weak)) read_persistent_clock(void)
-{
-	return 0;
-}
-
-/*
- * timekeeping_init - Initializes the clocksource and common timekeeping values
- */
-void __init timekeeping_init(void)
-{
-	unsigned long flags;
-	unsigned long sec = read_persistent_clock();
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-
-	ntp_clear();
-
-	clock = clocksource_get_next();
-	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-	clock->cycle_last = clocksource_read(clock);
-
-	xtime.tv_sec = sec;
-	xtime.tv_nsec = 0;
-	set_normalized_timespec(&wall_to_monotonic,
-		-xtime.tv_sec, -xtime.tv_nsec);
-
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-}
-
-
-/* flag for if timekeeping is suspended */
-static int timekeeping_suspended;
-/* time in seconds when suspend began */
-static unsigned long timekeeping_suspend_time;
-
-/**
- * timekeeping_resume - Resumes the generic timekeeping subsystem.
- * @dev:	unused
- *
- * This is for the generic clocksource timekeeping.
- * xtime/wall_to_monotonic/jiffies/etc are
- * still managed by arch specific suspend/resume code.
- */
-static int timekeeping_resume(struct sys_device *dev)
-{
-	unsigned long flags;
-	unsigned long now = read_persistent_clock();
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-
-	if (now && (now > timekeeping_suspend_time)) {
-		unsigned long sleep_length = now - timekeeping_suspend_time;
-		xtime.tv_sec += sleep_length;
-		jiffies_64 += (u64)sleep_length * HZ;
-	}
-	/* re-base the last cycle value */
-	clock->cycle_last = clocksource_read(clock);
-	clock->error = 0;
-	timekeeping_suspended = 0;
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-
-	clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
-	/* Resume hrtimers */
-	clock_was_set();
-
-	return 0;
-}
-
-static int timekeeping_suspend(struct sys_device *dev, pm_message_t state)
-{
-	unsigned long flags;
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-	timekeeping_suspended = 1;
-	timekeeping_suspend_time = read_persistent_clock();
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-	return 0;
-}
-
-/* sysfs resume/suspend bits for timekeeping */
-static struct sysdev_class timekeeping_sysclass = {
-	.resume		= timekeeping_resume,
-	.suspend	= timekeeping_suspend,
-	set_kset_name("timekeeping"),
-};
-
-static struct sys_device device_timer = {
-	.id		= 0,
-	.cls		= &timekeeping_sysclass,
-};
-
-static int __init timekeeping_init_device(void)
-{
-	int error = sysdev_class_register(&timekeeping_sysclass);
-	if (!error)
-		error = sysdev_register(&device_timer);
-	return error;
-}
-
-device_initcall(timekeeping_init_device);
-
-/*
- * If the error is already larger, we look ahead even further
- * to compensate for late or lost adjustments.
- */
-static __always_inline int clocksource_bigadjust(s64 error, s64 *interval,
-						 s64 *offset)
-{
-	s64 tick_error, i;
-	u32 look_ahead, adj;
-	s32 error2, mult;
-
-	/*
-	 * Use the current error value to determine how much to look ahead.
-	 * The larger the error the slower we adjust for it to avoid problems
-	 * with losing too many ticks, otherwise we would overadjust and
-	 * produce an even larger error.  The smaller the adjustment the
-	 * faster we try to adjust for it, as lost ticks can do less harm
-	 * here.  This is tuned so that an error of about 1 msec is adusted
-	 * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
-	 */
-	error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
-	error2 = abs(error2);
-	for (look_ahead = 0; error2 > 0; look_ahead++)
-		error2 >>= 2;
-
-	/*
-	 * Now calculate the error in (1 << look_ahead) ticks, but first
-	 * remove the single look ahead already included in the error.
-	 */
-	tick_error = current_tick_length() >>
-		(TICK_LENGTH_SHIFT - clock->shift + 1);
-	tick_error -= clock->xtime_interval >> 1;
-	error = ((error - tick_error) >> look_ahead) + tick_error;
-
-	/* Finally calculate the adjustment shift value.  */
-	i = *interval;
-	mult = 1;
-	if (error < 0) {
-		error = -error;
-		*interval = -*interval;
-		*offset = -*offset;
-		mult = -1;
-	}
-	for (adj = 0; error > i; adj++)
-		error >>= 1;
-
-	*interval <<= adj;
-	*offset <<= adj;
-	return mult << adj;
-}
-
-/*
- * Adjust the multiplier to reduce the error value,
- * 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)
-{
-	s64 error, interval = clock->cycle_interval;
-	int adj;
-
-	error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
-	if (error > interval) {
-		error >>= 2;
-		if (likely(error <= interval))
-			adj = 1;
-		else
-			adj = clocksource_bigadjust(error, &interval, &offset);
-	} else if (error < -interval) {
-		error >>= 2;
-		if (likely(error >= -interval)) {
-			adj = -1;
-			interval = -interval;
-			offset = -offset;
-		} else
-			adj = clocksource_bigadjust(error, &interval, &offset);
-	} else
-		return;
-
-	clock->mult += adj;
-	clock->xtime_interval += interval;
-	clock->xtime_nsec -= offset;
-	clock->error -= (interval - offset) <<
-			(TICK_LENGTH_SHIFT - clock->shift);
-}
-
-/**
- * update_wall_time - Uses the current clocksource to increment the wall time
- *
- * Called from the timer interrupt, must hold a write on xtime_lock.
- */
-static void update_wall_time(void)
-{
-	cycle_t offset;
-
-	/* Make sure we're fully resumed: */
-	if (unlikely(timekeeping_suspended))
-		return;
-
-#ifdef CONFIG_GENERIC_TIME
-	offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
-#else
-	offset = clock->cycle_interval;
-#endif
-	clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
-
-	/* normally this loop will run just once, however in the
-	 * case of lost or late ticks, it will accumulate correctly.
-	 */
-	while (offset >= clock->cycle_interval) {
-		/* accumulate one interval */
-		clock->xtime_nsec += clock->xtime_interval;
-		clock->cycle_last += clock->cycle_interval;
-		offset -= clock->cycle_interval;
-
-		if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
-			clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
-			xtime.tv_sec++;
-			second_overflow();
-		}
-
-		/* interpolator bits */
-		time_interpolator_update(clock->xtime_interval
-						>> clock->shift);
-
-		/* accumulate error between NTP and clock interval */
-		clock->error += current_tick_length();
-		clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
-	}
-
-	/* correct the clock when NTP error is too big */
-	clocksource_adjust(clock, offset);
-
-	/* store full nanoseconds into xtime */
-	xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
-	clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
-
-	/* check to see if there is a new clocksource to use */
-	if (change_clocksource()) {
-		clock->error = 0;
-		clock->xtime_nsec = 0;
-		clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
-	}
-	update_vsyscall(&xtime, clock);
-}
-
 /*
  * Called from the timer interrupt handler to charge one tick to the current 
  * process.  user_tick is 1 if the tick is user time, 0 for system.
@@ -1201,47 +759,6 @@ void update_process_times(int user_tick)
 }
 
 /*
- * Nr of active tasks - counted in fixed-point numbers
- */
-static unsigned long count_active_tasks(void)
-{
-	return nr_active() * FIXED_1;
-}
-
-/*
- * Hmm.. Changed this, as the GNU make sources (load.c) seems to
- * imply that avenrun[] is the standard name for this kind of thing.
- * Nothing else seems to be standardized: the fractional size etc
- * all seem to differ on different machines.
- *
- * Requires xtime_lock to access.
- */
-unsigned long avenrun[3];
-
-EXPORT_SYMBOL(avenrun);
-
-/*
- * calc_load - given tick count, update the avenrun load estimates.
- * This is called while holding a write_lock on xtime_lock.
- */
-static inline void calc_load(unsigned long ticks)
-{
-	unsigned long active_tasks; /* fixed-point */
-	static int count = LOAD_FREQ;
-
-	count -= ticks;
-	if (unlikely(count < 0)) {
-		active_tasks = count_active_tasks();
-		do {
-			CALC_LOAD(avenrun[0], EXP_1, active_tasks);
-			CALC_LOAD(avenrun[1], EXP_5, active_tasks);
-			CALC_LOAD(avenrun[2], EXP_15, active_tasks);
-			count += LOAD_FREQ;
-		} while (count < 0);
-	}
-}
-
-/*
  * This read-write spinlock protects us from races in SMP while
  * playing with xtime and avenrun.
  */
@@ -1271,27 +788,6 @@ void run_local_timers(void)
 	softlockup_tick();
 }
 
-/*
- * Called by the timer interrupt. xtime_lock must already be taken
- * by the timer IRQ!
- */
-static inline void update_times(unsigned long ticks)
-{
-	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.
- * jiffies is defined in the linker script...
- */
-
-void do_timer(unsigned long ticks)
-{
-	jiffies_64 += ticks;
-	update_times(ticks);
-}
 
 #ifdef __ARCH_WANT_SYS_ALARM
 
@@ -1710,194 +1206,6 @@ void __init init_timers(void)
 	open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
 }
 
-#ifdef CONFIG_TIME_INTERPOLATION
-
-struct time_interpolator *time_interpolator __read_mostly;
-static struct time_interpolator *time_interpolator_list __read_mostly;
-static DEFINE_SPINLOCK(time_interpolator_lock);
-
-static inline cycles_t time_interpolator_get_cycles(unsigned int src)
-{
-	unsigned long (*x)(void);
-
-	switch (src)
-	{
-		case TIME_SOURCE_FUNCTION:
-			x = time_interpolator->addr;
-			return x();
-
-		case TIME_SOURCE_MMIO64	:
-			return readq_relaxed((void __iomem *)time_interpolator->addr);
-
-		case TIME_SOURCE_MMIO32	:
-			return readl_relaxed((void __iomem *)time_interpolator->addr);
-
-		default: return get_cycles();
-	}
-}
-
-static inline u64 time_interpolator_get_counter(int writelock)
-{
-	unsigned int src = time_interpolator->source;
-
-	if (time_interpolator->jitter)
-	{
-		cycles_t lcycle;
-		cycles_t now;
-
-		do {
-			lcycle = time_interpolator->last_cycle;
-			now = time_interpolator_get_cycles(src);
-			if (lcycle && time_after(lcycle, now))
-				return lcycle;
-
-			/* When holding the xtime write lock, there's no need
-			 * to add the overhead of the cmpxchg.  Readers are
-			 * force to retry until the write lock is released.
-			 */
-			if (writelock) {
-				time_interpolator->last_cycle = now;
-				return now;
-			}
-			/* Keep track of the last timer value returned. The use of cmpxchg here
-			 * will cause contention in an SMP environment.
-			 */
-		} while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle));
-		return now;
-	}
-	else
-		return time_interpolator_get_cycles(src);
-}
-
-void time_interpolator_reset(void)
-{
-	time_interpolator->offset = 0;
-	time_interpolator->last_counter = time_interpolator_get_counter(1);
-}
-
-#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
-
-unsigned long time_interpolator_get_offset(void)
-{
-	/* If we do not have a time interpolator set up then just return zero */
-	if (!time_interpolator)
-		return 0;
-
-	return time_interpolator->offset +
-		GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
-}
-
-#define INTERPOLATOR_ADJUST 65536
-#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
-
-void time_interpolator_update(long delta_nsec)
-{
-	u64 counter;
-	unsigned long offset;
-
-	/* If there is no time interpolator set up then do nothing */
-	if (!time_interpolator)
-		return;
-
-	/*
-	 * The interpolator compensates for late ticks by accumulating the late
-	 * time in time_interpolator->offset. A tick earlier than expected will
-	 * lead to a reset of the offset and a corresponding jump of the clock
-	 * forward. Again this only works if the interpolator clock is running
-	 * slightly slower than the regular clock and the tuning logic insures
-	 * that.
-	 */
-
-	counter = time_interpolator_get_counter(1);
-	offset = time_interpolator->offset +
-			GET_TI_NSECS(counter, time_interpolator);
-
-	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-		time_interpolator->offset = offset - delta_nsec;
-	else {
-		time_interpolator->skips++;
-		time_interpolator->ns_skipped += delta_nsec - offset;
-		time_interpolator->offset = 0;
-	}
-	time_interpolator->last_counter = counter;
-
-	/* Tuning logic for time interpolator invoked every minute or so.
-	 * Decrease interpolator clock speed if no skips occurred and an offset is carried.
-	 * Increase interpolator clock speed if we skip too much time.
-	 */
-	if (jiffies % INTERPOLATOR_ADJUST == 0)
-	{
-		if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
-			time_interpolator->nsec_per_cyc--;
-		if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
-			time_interpolator->nsec_per_cyc++;
-		time_interpolator->skips = 0;
-		time_interpolator->ns_skipped = 0;
-	}
-}
-
-static inline int
-is_better_time_interpolator(struct time_interpolator *new)
-{
-	if (!time_interpolator)
-		return 1;
-	return new->frequency > 2*time_interpolator->frequency ||
-	    (unsigned long)new->drift < (unsigned long)time_interpolator->drift;
-}
-
-void
-register_time_interpolator(struct time_interpolator *ti)
-{
-	unsigned long flags;
-
-	/* Sanity check */
-	BUG_ON(ti->frequency == 0 || ti->mask == 0);
-
-	ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
-	spin_lock(&time_interpolator_lock);
-	write_seqlock_irqsave(&xtime_lock, flags);
-	if (is_better_time_interpolator(ti)) {
-		time_interpolator = ti;
-		time_interpolator_reset();
-	}
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-
-	ti->next = time_interpolator_list;
-	time_interpolator_list = ti;
-	spin_unlock(&time_interpolator_lock);
-}
-
-void
-unregister_time_interpolator(struct time_interpolator *ti)
-{
-	struct time_interpolator *curr, **prev;
-	unsigned long flags;
-
-	spin_lock(&time_interpolator_lock);
-	prev = &time_interpolator_list;
-	for (curr = *prev; curr; curr = curr->next) {
-		if (curr == ti) {
-			*prev = curr->next;
-			break;
-		}
-		prev = &curr->next;
-	}
-
-	write_seqlock_irqsave(&xtime_lock, flags);
-	if (ti == time_interpolator) {
-		/* we lost the best time-interpolator: */
-		time_interpolator = NULL;
-		/* find the next-best interpolator */
-		for (curr = time_interpolator_list; curr; curr = curr->next)
-			if (is_better_time_interpolator(curr))
-				time_interpolator = curr;
-		time_interpolator_reset();
-	}
-	write_sequnlock_irqrestore(&xtime_lock, flags);
-	spin_unlock(&time_interpolator_lock);
-}
-#endif /* CONFIG_TIME_INTERPOLATION */
-
 /**
  * msleep - sleep safely even with waitqueue interruptions
  * @msecs: Time in milliseconds to sleep for

-- 

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

* [PATCH 07/23] clocksource: rating sorted list
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (5 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  9:34   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 08/23] clocksource: drop duplicate register checking Daniel Walker
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_priority_sorted_list.patch --]
[-- Type: text/plain, Size: 9221 bytes --]

Converts the original plain list into a sorted list based on the clock rating.
Later in my tree this allows some of the variables to be dropped since the
highest rated clock is always at the front of the list. This also does some
other nice things like allow the sysfs files to print the clocks in a more
interesting order. It's forward looking.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/kernel/tsc.c      |    2 
 arch/x86_64/kernel/tsc.c    |    2 
 include/linux/clocksource.h |    8 +-
 kernel/time/clocksource.c   |  132 +++++++++++++++++++++++++++++---------------
 4 files changed, 96 insertions(+), 48 deletions(-)

Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -325,7 +325,7 @@ static int tsc_update_callback(void)
 	/* check to see if we should switch to the safe clocksource: */
 	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
 		clocksource_tsc.rating = 0;
-		clocksource_reselect();
+		clocksource_rating_change(&clocksource_tsc);
 		change = 1;
 	}
 
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/tsc.c
+++ linux-2.6.19/arch/x86_64/kernel/tsc.c
@@ -229,7 +229,7 @@ static int tsc_update_callback(void)
 	/* check to see if we should switch to the safe clocksource: */
 	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
 		clocksource_tsc.rating = 50;
-		clocksource_reselect();
+		clocksource_rating_change(&clocksource_tsc);
 		change = 1;
 	}
 	return change;
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -12,6 +12,8 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/sysdev.h>
+
 #include <asm/div64.h>
 #include <asm/io.h>
 
@@ -189,9 +191,9 @@ static inline void clocksource_calculate
 
 
 /* used to install a new clocksource */
-int clocksource_register(struct clocksource*);
-void clocksource_reselect(void);
-struct clocksource* clocksource_get_next(void);
+extern struct clocksource *clocksource_get_next(void);
+extern int clocksource_register(struct clocksource*);
+extern void clocksource_rating_change(struct clocksource*);
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -35,7 +35,7 @@
  * next_clocksource:
  *	pending next selected clocksource.
  * clocksource_list:
- *	linked list with the registered clocksources
+ *	rating sorted linked list with the registered clocksources
  * clocksource_lock:
  *	protects manipulations to curr_clocksource and next_clocksource
  *	and the clocksource_list
@@ -80,69 +80,105 @@ struct clocksource *clocksource_get_next
 }
 
 /**
- * select_clocksource - Finds the best registered clocksource.
+ * __is_registered - Returns a clocksource if it's registered
+ * @name:		name of the clocksource to return
  *
  * Private function. Must hold clocksource_lock when called.
  *
- * Looks through the list of registered clocksources, returning
- * the one with the highest rating value. If there is a clocksource
- * name that matches the override string, it returns that clocksource.
+ * Returns the clocksource if registered, zero otherwise.
+ * If no clocksources are registered the jiffies clock is
+ * returned.
  */
-static struct clocksource *select_clocksource(void)
+static struct clocksource * __is_registered(char * name)
 {
-	struct clocksource *best = NULL;
 	struct list_head *tmp;
 
 	list_for_each(tmp, &clocksource_list) {
 		struct clocksource *src;
 
 		src = list_entry(tmp, struct clocksource, list);
-		if (!best)
-			best = src;
-
-		/* check for override: */
-		if (strlen(src->name) == strlen(override_name) &&
-		    !strcmp(src->name, override_name)) {
-			best = src;
-			break;
-		}
-		/* pick the highest rating: */
-		if (src->rating > best->rating)
-		 	best = src;
+		if (!strcmp(src->name, name))
+			return src;
 	}
 
-	return best;
+	return 0;
 }
 
 /**
- * is_registered_source - Checks if clocksource is registered
- * @c:		pointer to a clocksource
+ * __get_clock - Finds a specific clocksource
+ * @name:		name of the clocksource to return
  *
- * Private helper function. Must hold clocksource_lock when called.
+ * Private function. Must hold clocksource_lock when called.
  *
- * Returns one if the clocksource is already registered, zero otherwise.
+ * Returns the clocksource if registered, zero otherwise.
+ * If the @name is null the highest rated clock is returned.
  */
-static int is_registered_source(struct clocksource *c)
+static inline struct clocksource * __get_clock(char * name)
+{
+
+	if (unlikely(list_empty(&clocksource_list)))
+		return &clocksource_jiffies;
+
+	if (!name)
+		return list_entry(clocksource_list.next,
+				  struct clocksource, list);
+
+	return __is_registered(name);
+}
+
+/**
+ * select_clocksource - Finds the best registered clocksource.
+ *
+ * Private function. Must hold clocksource_lock when called.
+ *
+ * Looks through the list of registered clocksources, returning
+ * the one with the highest rating value. If there is a clocksource
+ * name that matches the override string, it returns that clocksource.
+ */
+static struct clocksource *select_clocksource(void)
+{
+	if (!*override_name)
+		return list_entry(clocksource_list.next,
+				  struct clocksource, list);
+
+	return __get_clock(override_name);
+}
+
+/*
+ * __sorted_list_add - Sorted clocksource add
+ * @c:			clocksource to add
+ *
+ * Adds a clocksource to the clocksource_list in sorted order.
+ */
+static void __sorted_list_add(struct clocksource *c)
 {
-	int len = strlen(c->name);
 	struct list_head *tmp;
 
 	list_for_each(tmp, &clocksource_list) {
 		struct clocksource *src;
 
 		src = list_entry(tmp, struct clocksource, list);
-		if (strlen(src->name) == len &&	!strcmp(src->name, c->name))
-			return 1;
+
+		if (c->rating > src->rating) {
+			list_add_tail(&c->list, &src->list);
+			return;
+		}
 	}
 
-	return 0;
+	/*
+	 * If it's bigger/smaller than all the other entries put it
+	 * at the end.
+	 */
+	list_add_tail(&c->list, &clocksource_list);
 }
 
 /**
  * clocksource_register - Used to install new clocksources
  * @t:		clocksource to be registered
  *
- * Returns -EBUSY if registration fails, zero otherwise.
+ * Returns -EBUSY clock is already registered,
+ * Returns -EINVAL if clocksource is invalid,
+ * Return zero otherwise.
  */
 int clocksource_register(struct clocksource *c)
 {
@@ -150,14 +186,13 @@ int clocksource_register(struct clocksou
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	/* check if clocksource is already registered */
-	if (is_registered_source(c)) {
-		printk("register_clocksource: Cannot register %s. "
+	if (unlikely(!list_empty(&c->list) && __is_registered(c->name))) {
+		printk("register_clocksource: Cannot register %s clocksource. "
 		       "Already registered!", c->name);
 		ret = -EBUSY;
 	} else {
-		/* register it */
- 		list_add(&c->list, &clocksource_list);
+		INIT_LIST_HEAD(&c->list);
+ 		__sorted_list_add(c);
 		/* scan the registered clocksources, and pick the best one */
 		next_clocksource = select_clocksource();
 	}
@@ -167,21 +202,31 @@ int clocksource_register(struct clocksou
 EXPORT_SYMBOL(clocksource_register);
 
 /**
- * clocksource_reselect - Rescan list for next clocksource
+ * clocksource_rating_change - Allows dynamic rating changes for register
+ *                           clocksources.
  *
- * A quick helper function to be used if a clocksource changes its
- * rating. Forces the clocksource list to be re-scanned for the best
- * clocksource.
+ * Signals that a clocksource is dynamically changing it's rating.
+ * This could happen if a clocksource becomes more/less stable.
  */
-void clocksource_reselect(void)
+void clocksource_rating_change(struct clocksource *c)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&clocksource_lock, flags);
+	if (unlikely(list_empty(&c->list)))
+		return;
+
+  	spin_lock_irqsave(&clocksource_lock, flags);
+
+	/*
+	 * Re-register the clocksource with it's new rating.
+	 */
+	list_del_init(&c->list);
+	__sorted_list_add(c);
+
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 }
-EXPORT_SYMBOL(clocksource_reselect);
+EXPORT_SYMBOL(clocksource_rating_change);
 
 #ifdef CONFIG_SYSFS
 /**
@@ -247,7 +292,8 @@ static ssize_t sysfs_override_clocksourc
  * @dev:	unused
  * @buf:	char buffer to be filled with clocksource list
  *
- * Provides sysfs interface for listing registered clocksources
+ * Provides sysfs interface for listing registered clocksources.
+ * Output in priority sorted order.
  */
 static ssize_t
 sysfs_show_available_clocksources(struct sys_device *dev, char *buf)

-- 

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

* [PATCH 08/23] clocksource: drop duplicate register checking
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (6 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 07/23] clocksource: rating sorted list Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  9:59   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 09/23] clocksource: add block notifier Daniel Walker
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_list_init.patch --]
[-- Type: text/plain, Size: 1468 bytes --]

This is something Thomas already dropped, and I'm just sticking
with that .. If you register your clocksource _twice_ your kernel will
likely not work correctly (and might crash).

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 kernel/time/clocksource.c |   19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -186,16 +186,12 @@ int clocksource_register(struct clocksou
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	if (unlikely(!list_empty(&c->list) && __is_registered(c->name))) {
-		printk("register_clocksource: Cannot register %s clocksource. "
-		       "Already registered!", c->name);
-		ret = -EBUSY;
-	} else {
-		INIT_LIST_HEAD(&c->list);
- 		__sorted_list_add(c);
-		/* scan the registered clocksources, and pick the best one */
-		next_clocksource = select_clocksource();
-	}
+ 	__sorted_list_add(c);
+
+	/*
+	 * scan the registered clocksources, and pick the best one
+	 */
+	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 	return ret;
 }
@@ -212,9 +208,6 @@ void clocksource_rating_change(struct cl
 {
 	unsigned long flags;
 
-	if (unlikely(list_empty(&c->list)))
-		return;
-
   	spin_lock_irqsave(&clocksource_lock, flags);
 
 	/*

-- 

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

* [PATCH 09/23] clocksource: add block notifier
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (7 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 08/23] clocksource: drop duplicate register checking Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 10:17   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 10/23] clocksource: remove update_callback Daniel Walker
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_add_block_notify_on_new_clock.patch --]
[-- Type: text/plain, Size: 3603 bytes --]

Adds a call back interface for register/rating change events. This is also used
later in this series to signal other interesting events.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |   37 +++++++++++++++++++++++++++++++++++++
 include/linux/timekeeping.h |    3 +++
 kernel/time/clocksource.c   |   10 ++++++++++
 3 files changed, 50 insertions(+)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -13,6 +13,7 @@
 #include <linux/time.h>
 #include <linux/list.h>
 #include <linux/sysdev.h>
+#include <linux/notifier.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -23,6 +24,42 @@ typedef u64 cycle_t;
 /* XXX - Would like a better way for initializing curr_clocksource */
 extern struct clocksource clocksource_jiffies;
 
+/*
+ * Allows inlined calling for notifier routines.
+ */
+extern struct atomic_notifier_head clocksource_list_notifier;
+
+/*
+ * Block notifier flags.
+ */
+#define CLOCKSOURCE_NOTIFY_REGISTER	1
+#define CLOCKSOURCE_NOTIFY_RATING	2
+#define CLOCKSOURCE_NOTIFY_FREQ		4
+
+/**
+ * clocksource_notifier_register - Registers a list change notifier
+ * @nb:		pointer to a notifier block
+ *
+ * Returns zero always.
+ */
+static inline int clocksource_notifier_register(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&clocksource_list_notifier, nb);
+}
+
+/**
+ * clocksource_freq_change - Allows notification of dynamic frequency changes.
+ *
+ * Signals that a clocksource is dynamically changing it's frequency.
+ * This could happen if a clocksource becomes more/less stable.
+ */
+static inline void clocksource_freq_change(struct clocksource *c)
+{
+	atomic_notifier_call_chain(&clocksource_list_notifier,
+				   CLOCKSOURCE_NOTIFY_FREQ, c);
+}
+
+
 /**
  * struct clocksource - hardware abstraction for a free running counter
  *	Provides mostly state-free accessors to the underlying hardware.
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
--- linux-2.6.19.orig/include/linux/timekeeping.h
+++ linux-2.6.19/include/linux/timekeeping.h
@@ -8,6 +8,9 @@ static inline int change_clocksource(voi
 {
 	return 0;
 }
+
+static inline void change_clocksource(void) { }
+
 #endif /* !CONFIG_GENERIC_TIME */
 
 #endif /* _LINUX_TIMEKEEPING_H */
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -49,6 +49,8 @@ static DEFINE_SPINLOCK(clocksource_lock)
 static char override_name[32];
 static int finished_booting;
 
+ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
+
 /* clocksource_done_booting - Called near the end of bootup
  *
  * Hack to avoid lots of clocksource churn at boot time
@@ -193,6 +195,10 @@ int clocksource_register(struct clocksou
 	 */
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
+
+	atomic_notifier_call_chain(&clocksource_list_notifier,
+ 				   CLOCKSOURCE_NOTIFY_REGISTER, c);
+
 	return ret;
 }
 EXPORT_SYMBOL(clocksource_register);
@@ -218,6 +224,10 @@ void clocksource_rating_change(struct cl
 
 	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
+
+	atomic_notifier_call_chain(&clocksource_list_notifier,
+				   CLOCKSOURCE_NOTIFY_RATING, c);
+
 }
 EXPORT_SYMBOL(clocksource_rating_change);
 

-- 

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

* [PATCH 10/23] clocksource: remove update_callback
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (8 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 09/23] clocksource: add block notifier Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 10:46   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 11/23] clocksource: atomic signals Daniel Walker
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_remove_update_callback.patch --]
[-- Type: text/plain, Size: 7209 bytes --]

Uses the block notifier to replace the functionality of update_callback().
update_callback() was a special case specifically for the tsc, but including
it in the clocksource structure duplicated it needlessly for other clocks.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/kernel/tsc.c      |   33 +++++++++------------------------
 arch/x86_64/kernel/tsc.c    |   19 +++++--------------
 include/linux/clocksource.h |    2 --
 include/linux/timekeeping.h |    1 +
 kernel/time/timekeeping.c   |   32 ++++++++++++++++++++++++++++++--
 5 files changed, 45 insertions(+), 42 deletions(-)

Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -50,8 +50,7 @@ static int __init tsc_setup(char *str)
 __setup("notsc", tsc_setup);
 
 /*
- * code to mark and check if the TSC is unstable
- * due to cpufreq or due to unsynced TSCs
+ * Flag that denotes an unstable tsc and check function.
  */
 static int tsc_unstable;
 
@@ -60,12 +59,6 @@ static inline int check_tsc_unstable(voi
 	return tsc_unstable;
 }
 
-void mark_tsc_unstable(void)
-{
-	tsc_unstable = 1;
-}
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
-
 /* Accellerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -179,6 +172,7 @@ int recalibrate_cpu_khz(void)
 	if (cpu_has_tsc) {
 		cpu_khz = calculate_cpu_khz();
 		tsc_khz = cpu_khz;
+		mark_tsc_unstable();
 		cpu_data[0].loops_per_jiffy =
 			cpufreq_scale(cpu_data[0].loops_per_jiffy,
 					cpu_khz_old, cpu_khz);
@@ -295,7 +289,6 @@ core_initcall(cpufreq_tsc);
 /* clock source code */
 
 static unsigned long current_tsc_khz = 0;
-static int tsc_update_callback(void);
 
 static cycle_t read_tsc(void)
 {
@@ -313,32 +306,24 @@ static struct clocksource clocksource_ts
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-static int tsc_update_callback(void)
+/*
+ * Code to mark if the TSC is unstable due to cpufreq or due to unsynced TSCs
+ */
+void mark_tsc_unstable(void)
 {
-	int change = 0;
-
 	/* check to see if we should switch to the safe clocksource: */
-	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
+	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 0)) {
 		clocksource_tsc.rating = 0;
 		clocksource_rating_change(&clocksource_tsc);
-		change = 1;
 	}
 
-	/* only update if tsc_khz has changed: */
-	if (current_tsc_khz != tsc_khz) {
-		current_tsc_khz = tsc_khz;
-		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
-							clocksource_tsc.shift);
-		change = 1;
-	}
-
-	return change;
+	tsc_unstable = 1;
 }
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
 {
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/tsc.c
+++ linux-2.6.19/arch/x86_64/kernel/tsc.c
@@ -47,11 +47,6 @@ static inline int check_tsc_unstable(voi
 	return tsc_unstable;
 }
 
-void mark_tsc_unstable(void)
-{
-	tsc_unstable = 1;
-}
-EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 #ifdef CONFIG_CPU_FREQ
 
@@ -182,8 +177,6 @@ __setup("notsc", notsc_setup);
 
 /* clock source code: */
 
-static int tsc_update_callback(void);
-
 static cycle_t read_tsc(void)
 {
 	cycle_t ret = (cycle_t)get_cycles_sync();
@@ -202,24 +195,22 @@ static struct clocksource clocksource_ts
 	.read			= read_tsc,
 	.mask			= CLOCKSOURCE_MASK(64),
 	.shift			= 22,
-	.update_callback	= tsc_update_callback,
 	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 	.vread			= vread_tsc,
 };
 
-static int tsc_update_callback(void)
+void mark_tsc_unstable(void)
 {
-	int change = 0;
-
 	/* check to see if we should switch to the safe clocksource: */
-	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
+	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 50)) {
 		clocksource_tsc.rating = 50;
 		clocksource_rating_change(&clocksource_tsc);
-		change = 1;
 	}
-	return change;
+
+	tsc_unstable = 1;
 }
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static int __init init_tsc_clocksource(void)
 {
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -86,7 +86,6 @@ static inline void clocksource_freq_chan
  *			subtraction of non 64 bit counters
  * @mult:		cycle to nanosecond multiplier
  * @shift:		cycle to nanosecond divisor (power of two)
- * @update_callback:	called when safe to alter clocksource values
  * @flags:		flags describing special properties
  * @vread:		vsyscall based read
  * @cycle_interval:	Used internally by timekeeping core, please ignore.
@@ -100,7 +99,6 @@ struct clocksource {
 	cycle_t mask;
 	u32 mult;
 	u32 shift;
-	int (*update_callback)(void);
 	unsigned long flags;
 	cycle_t (*vread)(void);
 
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
--- linux-2.6.19.orig/include/linux/timekeeping.h
+++ linux-2.6.19/include/linux/timekeeping.h
@@ -10,6 +10,7 @@ static inline int change_clocksource(voi
 }
 
 static inline void change_clocksource(void) { }
+static inline void timekeeping_init_notifier(void) { }
 
 #endif /* !CONFIG_GENERIC_TIME */
 
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.19.orig/kernel/time/timekeeping.c
+++ linux-2.6.19/kernel/time/timekeeping.c
@@ -39,6 +39,7 @@ static unsigned long timekeeping_suspend
  * Clock used for timekeeping
  */
 struct clocksource *clock = &clocksource_jiffies;
+atomic_t clock_recalc_interval = ATOMIC_INIT(0);
 
 #ifdef CONFIG_GENERIC_TIME
 /**
@@ -176,8 +177,9 @@ static int change_clocksource(void)
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
 		return 1;
-	} else if (clock->update_callback) {
-		return clock->update_callback();
+	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
+		atomic_set(&clock_recalc_interval, 0);
+		return 1;
 	}
 	return 0;
 }
@@ -199,6 +201,29 @@ int timekeeping_is_continuous(void)
 
 	return ret;
 }
+
+static int
+clocksource_callback(struct notifier_block *nb, unsigned long op, void *c)
+{
+	if (c == clock && op == CLOCKSOURCE_NOTIFY_FREQ &&
+	    !atomic_read(&clock_recalc_interval))
+		atomic_inc(&clock_recalc_interval);
+
+	return 0;
+}
+
+static struct notifier_block clocksource_nb = {
+	.notifier_call = clocksource_callback,
+};
+
+void __init timekeeping_init_notifier(void)
+{
+	/*
+	 * Needs to be done early, incase a clock is unstable
+	 * early.
+	 */
+	clocksource_notifier_register(&clocksource_nb);
+}
 #endif /* CONFIG_GENERIC_TIME */
 
 /**
@@ -237,6 +262,9 @@ void __init timekeeping_init(void)
 		-xtime.tv_sec, -xtime.tv_nsec);
 
 	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	timekeeping_init_notifier();
+
 }
 
 

-- 

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

* [PATCH 11/23] clocksource: atomic signals
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (9 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 10/23] clocksource: remove update_callback Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 11:07   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 12/23] clocksource: add clocksource_get_clock() Daniel Walker
                   ` (11 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_add_atomic_singals.patch --]
[-- Type: text/plain, Size: 5656 bytes --]

Modifies the way clocks are switched to in the timekeeping code. The original
code would constantly monitor the clocksource list checking for newly added
clocksources. I modified this by using atomic types to signal when a new clock
is added. This allows the operation to be used only when it's needed.

The fast path is also reduced to checking a single atomic value.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |    5 ++++
 include/linux/timekeeping.h |    4 ---
 kernel/time/clocksource.c   |    6 +++++
 kernel/time/timekeeping.c   |   49 ++++++++++++++++++++++++++++----------------
 4 files changed, 43 insertions(+), 21 deletions(-)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -25,6 +25,11 @@ typedef u64 cycle_t;
 extern struct clocksource clocksource_jiffies;
 
 /*
+ * Atomic signal that is specific to timekeeping.
+ */
+extern atomic_t clock_check;
+
+/*
  * Allows inlined calling for notifier routines.
  */
 extern struct atomic_notifier_head clocksource_list_notifier;
Index: linux-2.6.19/include/linux/timekeeping.h
===================================================================
--- linux-2.6.19.orig/include/linux/timekeeping.h
+++ linux-2.6.19/include/linux/timekeeping.h
@@ -4,10 +4,6 @@
 #include <linux/clocksource.h>
 
 #ifndef CONFIG_GENERIC_TIME
-static inline int change_clocksource(void)
-{
-	return 0;
-}
 
 static inline void change_clocksource(void) { }
 static inline void timekeeping_init_notifier(void) { }
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -50,6 +50,7 @@ static char override_name[32];
 static int finished_booting;
 
 ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
+atomic_t clock_check = ATOMIC_INIT(0);
 
 /* clocksource_done_booting - Called near the end of bootup
  *
@@ -58,6 +59,8 @@ ATOMIC_NOTIFIER_HEAD(clocksource_list_no
 static int __init clocksource_done_booting(void)
 {
 	finished_booting = 1;
+	/* Check for a new clock now */
+	atomic_inc(&clock_check);
 	return 0;
 }
 
@@ -285,6 +288,9 @@ static ssize_t sysfs_override_clocksourc
 	/* try to select it: */
 	next_clocksource = select_clocksource();
 
+	/* Signal that there is a new clocksource */
+	atomic_inc(&clock_check);
+
 	spin_unlock_irq(&clocksource_lock);
 
 	return ret;
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.19.orig/kernel/time/timekeeping.c
+++ linux-2.6.19/kernel/time/timekeeping.c
@@ -9,6 +9,7 @@
 #include <linux/sched.h>
 #include <linux/timekeeping.h>
 #include <linux/time.h>
+#include <linux/timex.h>
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
 
@@ -39,7 +40,6 @@ static unsigned long timekeeping_suspend
  * Clock used for timekeeping
  */
 struct clocksource *clock = &clocksource_jiffies;
-atomic_t clock_recalc_interval = ATOMIC_INIT(0);
 
 #ifdef CONFIG_GENERIC_TIME
 /**
@@ -157,11 +157,12 @@ int do_settimeofday(struct timespec *tv)
 EXPORT_SYMBOL(do_settimeofday);
 
 /**
- * change_clocksource - Swaps clocksources if a new one is available
+ * timkeeping_change_clocksource - Swaps clocksources if a new one is available
  *
  * Accumulates current time interval and initializes new clocksource
+ * Needs to be called with the xtime_lock held.
  */
-static int change_clocksource(void)
+static void timekeeping_change_clocksource(void)
 {
 	struct clocksource *new;
 	cycle_t now;
@@ -176,12 +177,15 @@ static int change_clocksource(void)
 		clock->cycle_last = now;
 		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
 		       clock->name);
-		return 1;
-	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
-		atomic_set(&clock_recalc_interval, 0);
-		return 1;
+		tick_clock_notify();
+		clock->error = 0;
+		clock->xtime_nsec = 0;
+		clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+	} else {
+		clock->error = 0;
+		clock->xtime_nsec = 0;
+		clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
 	}
-	return 0;
 }
 
 /**
@@ -205,9 +209,14 @@ int timekeeping_is_continuous(void)
 static int
 clocksource_callback(struct notifier_block *nb, unsigned long op, void *c)
 {
-	if (c == clock && op == CLOCKSOURCE_NOTIFY_FREQ &&
-	    !atomic_read(&clock_recalc_interval))
-		atomic_inc(&clock_recalc_interval);
+	if (likely(c != clock))
+		return 0;
+
+	switch (op) {
+		case CLOCKSOURCE_NOTIFY_FREQ:
+		case CLOCKSOURCE_NOTIFY_RATING:
+			atomic_inc(&clock_check);
+	}
 
 	return 0;
 }
@@ -334,6 +343,7 @@ static int __init timekeeping_init_devic
 	int error = sysdev_class_register(&timekeeping_sysclass);
 	if (!error)
 		error = sysdev_register(&device_timer);
+
 	return error;
 }
 
@@ -476,13 +486,18 @@ static inline void update_wall_time(void
 	xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
 	clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
 
-	/* check to see if there is a new clocksource to use */
-	if (change_clocksource()) {
-		clock->error = 0;
-		clock->xtime_nsec = 0;
-		tick_clock_notify();
-		clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
+#ifdef CONFIG_GENERIC_TIME
+	/*
+	 * check to see if there is a new clocksource to use
+	 */
+	if (unlikely(atomic_read(&clock_check))) {
+
+		timekeeping_change_clocksource();
+
+		atomic_set(&clock_check, 0);
 	}
+#endif /* CONFIG_GENERIC_TIME */
+
 	update_vsyscall(&xtime, clock);
 }
 

-- 

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

* [PATCH 12/23] clocksource: add clocksource_get_clock()
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (10 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 11/23] clocksource: atomic signals Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 11:46   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 13/23] timekeeping: move sysfs layer/drop API calls Daniel Walker
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_add_get_clock.patch --]
[-- Type: text/plain, Size: 2111 bytes --]

One new API call clocksource_get_clock() which allows clocks to be selected
based on their name, or if the name is null the highest rated clock is returned.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |   12 ++++++++++++
 kernel/time/clocksource.c   |   18 ++++++++++++++++++
 2 files changed, 30 insertions(+)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -234,6 +234,18 @@ static inline void clocksource_calculate
 extern struct clocksource *clocksource_get_next(void);
 extern int clocksource_register(struct clocksource*);
 extern void clocksource_rating_change(struct clocksource*);
+extern struct clocksource * clocksource_get_clock(char*);
+
+/**
+ * clocksource_get_best_clock - Finds highest rated clocksource
+ *
+ * Returns the highest rated clocksource. If none are register the
+ * jiffies clock is returned.
+ */
+static inline struct clocksource * clocksource_get_best_clock(void)
+{
+	return clocksource_get_clock(NULL);
+}
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
 extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -132,6 +132,24 @@ static inline struct clocksource * __get
 }
 
 /**
+ * clocksource_get_clock - Finds a specific clocksource
+ * @name:		name of the clocksource to return
+ *
+ * Returns the clocksource if registered, zero otherwise.
+ */
+struct clocksource * clocksource_get_clock(char * name)
+{
+	struct clocksource * ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocksource_lock, flags);
+	ret = __get_clock(name);
+	spin_unlock_irqrestore(&clocksource_lock, flags);
+	return ret;
+}
+
+
+/**
  * select_clocksource - Finds the best registered clocksource.
  *
  * Private function. Must hold clocksource_lock when called.

-- 

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

* [PATCH 13/23] timekeeping: move sysfs layer/drop API calls
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (11 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 12/23] clocksource: add clocksource_get_clock() Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 11:49   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 14/23] clocksource: increase initcall priority Daniel Walker
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: timekeeping_move_sysfs_layer.patch --]
[-- Type: text/plain, Size: 12956 bytes --]

This moves the timekeeping sysfs override layer into timekeeping.c and
removes the get_next_clocksource and select_clocksource functions, and 
their component variables, since they are no longer used.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |    5 -
 kernel/time/clocksource.c   |  169 --------------------------------------------
 kernel/time/timekeeping.c   |  131 +++++++++++++++++++++++++++++++++-
 3 files changed, 134 insertions(+), 171 deletions(-)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -25,9 +25,9 @@ typedef u64 cycle_t;
 extern struct clocksource clocksource_jiffies;
 
 /*
- * Atomic signal that is specific to timekeeping.
+ * Sysfs device extern, for registering clocksources under the same sysfs dir.
  */
-extern atomic_t clock_check;
+extern struct sys_device clocksource_sys_device;
 
 /*
  * Allows inlined calling for notifier routines.
@@ -231,7 +231,6 @@ static inline void clocksource_calculate
 
 
 /* used to install a new clocksource */
-extern struct clocksource *clocksource_get_next(void);
 extern int clocksource_register(struct clocksource*);
 extern void clocksource_rating_change(struct clocksource*);
 extern struct clocksource * clocksource_get_clock(char*);
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -30,27 +30,17 @@
 #include <linux/module.h>
 
 /*[Clocksource internal variables]---------
- * curr_clocksource:
- *	currently selected clocksource. Initialized to clocksource_jiffies.
- * next_clocksource:
- *	pending next selected clocksource.
  * clocksource_list:
  *	rating sorted linked list with the registered clocksources
  * clocksource_lock:
  *	protects manipulations to curr_clocksource and next_clocksource
  *	and the clocksource_list
- * override_name:
- *	Name of the user-specified clocksource.
  */
-static struct clocksource *curr_clocksource = &clocksource_jiffies;
-static struct clocksource *next_clocksource;
 static LIST_HEAD(clocksource_list);
 static DEFINE_SPINLOCK(clocksource_lock);
-static char override_name[32];
 static int finished_booting;
 
 ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
-atomic_t clock_check = ATOMIC_INIT(0);
 
 /* clocksource_done_booting - Called near the end of bootup
  *
@@ -59,32 +49,12 @@ atomic_t clock_check = ATOMIC_INIT(0);
 static int __init clocksource_done_booting(void)
 {
 	finished_booting = 1;
-	/* Check for a new clock now */
-	atomic_inc(&clock_check);
 	return 0;
 }
 
 late_initcall(clocksource_done_booting);
 
 /**
- * clocksource_get_next - Returns the selected clocksource
- *
- */
-struct clocksource *clocksource_get_next(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocksource_lock, flags);
-	if (next_clocksource && finished_booting) {
-		curr_clocksource = next_clocksource;
-		next_clocksource = NULL;
-	}
-	spin_unlock_irqrestore(&clocksource_lock, flags);
-
-	return curr_clocksource;
-}
-
-/**
  * __is_registered - Returns a clocksource if it's registered
  * @name:		name of the clocksource to return
  *
@@ -148,25 +118,6 @@ struct clocksource * clocksource_get_clo
 	return ret;
 }
 
-
-/**
- * select_clocksource - Finds the best registered clocksource.
- *
- * Private function. Must hold clocksource_lock when called.
- *
- * Looks through the list of registered clocksources, returning
- * the one with the highest rating value. If there is a clocksource
- * name that matches the override string, it returns that clocksource.
- */
-static struct clocksource *select_clocksource(void)
-{
-	if (!*override_name)
-		return list_entry(clocksource_list.next,
-				  struct clocksource, list);
-
-	return __get_clock(override_name);
-}
-
 /*
  * __sorted_list_add - Sorted clocksource add
  * @c:			clocksource to add
@@ -210,11 +161,6 @@ int clocksource_register(struct clocksou
 
 	spin_lock_irqsave(&clocksource_lock, flags);
  	__sorted_list_add(c);
-
-	/*
-	 * scan the registered clocksources, and pick the best one
-	 */
-	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 
 	atomic_notifier_call_chain(&clocksource_list_notifier,
@@ -243,7 +189,6 @@ void clocksource_rating_change(struct cl
 	list_del_init(&c->list);
 	__sorted_list_add(c);
 
-	next_clocksource = select_clocksource();
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 
 	atomic_notifier_call_chain(&clocksource_list_notifier,
@@ -254,67 +199,6 @@ EXPORT_SYMBOL(clocksource_rating_change)
 
 #ifdef CONFIG_SYSFS
 /**
- * sysfs_show_current_clocksources - sysfs interface for current clocksource
- * @dev:	unused
- * @buf:	char buffer to be filled with clocksource list
- *
- * Provides sysfs interface for listing current clocksource.
- */
-static ssize_t
-sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
-{
-	char *curr = buf;
-
-	spin_lock_irq(&clocksource_lock);
-	curr += sprintf(curr, "%s ", curr_clocksource->name);
-	spin_unlock_irq(&clocksource_lock);
-
-	curr += sprintf(curr, "\n");
-
-	return curr - buf;
-}
-
-/**
- * sysfs_override_clocksource - interface for manually overriding clocksource
- * @dev:	unused
- * @buf:	name of override clocksource
- * @count:	length of buffer
- *
- * Takes input from sysfs interface for manually overriding the default
- * clocksource selction.
- */
-static ssize_t sysfs_override_clocksource(struct sys_device *dev,
-					  const char *buf, size_t count)
-{
-	size_t ret = count;
-	/* strings from sysfs write are not 0 terminated! */
-	if (count >= sizeof(override_name))
-		return -EINVAL;
-
-	/* strip of \n: */
-	if (buf[count-1] == '\n')
-		count--;
-	if (count < 1)
-		return -EINVAL;
-
-	spin_lock_irq(&clocksource_lock);
-
-	/* copy the name given: */
-	memcpy(override_name, buf, count);
-	override_name[count] = 0;
-
-	/* try to select it: */
-	next_clocksource = select_clocksource();
-
-	/* Signal that there is a new clocksource */
-	atomic_inc(&clock_check);
-
-	spin_unlock_irq(&clocksource_lock);
-
-	return ret;
-}
-
-/**
  * sysfs_show_available_clocksources - sysfs interface for listing clocksource
  * @dev:	unused
  * @buf:	char buffer to be filled with clocksource list
@@ -345,9 +229,6 @@ sysfs_show_available_clocksources(struct
 /*
  * Sysfs setup bits:
  */
-static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources,
-		   sysfs_override_clocksource);
-
 static SYSDEV_ATTR(available_clocksource, 0600,
 		   sysfs_show_available_clocksources, NULL);
 
@@ -355,7 +236,7 @@ static struct sysdev_class clocksource_s
 	set_kset_name("clocksource"),
 };
 
-static struct sys_device device_clocksource = {
+struct sys_device clocksource_sys_device = {
 	.id	= 0,
 	.cls	= &clocksource_sysclass,
 };
@@ -365,57 +246,13 @@ static int __init init_clocksource_sysfs
 	int error = sysdev_class_register(&clocksource_sysclass);
 
 	if (!error)
-		error = sysdev_register(&device_clocksource);
+		error = sysdev_register(&clocksource_sys_device);
 	if (!error)
 		error = sysdev_create_file(
-				&device_clocksource,
-				&attr_current_clocksource);
-	if (!error)
-		error = sysdev_create_file(
-				&device_clocksource,
+				&clocksource_sys_device,
 				&attr_available_clocksource);
 	return error;
 }
 
 device_initcall(init_clocksource_sysfs);
 #endif /* CONFIG_SYSFS */
-
-/**
- * boot_override_clocksource - boot clock override
- * @str:	override name
- *
- * Takes a clocksource= boot argument and uses it
- * as the clocksource override name.
- */
-static int __init boot_override_clocksource(char* str)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&clocksource_lock, flags);
-	if (str)
-		strlcpy(override_name, str, sizeof(override_name));
-	spin_unlock_irqrestore(&clocksource_lock, flags);
-	return 1;
-}
-
-__setup("clocksource=", boot_override_clocksource);
-
-/**
- * boot_override_clock - Compatibility layer for deprecated boot option
- * @str:	override name
- *
- * DEPRECATED! Takes a clock= boot argument and uses it
- * as the clocksource override name
- */
-static int __init boot_override_clock(char* str)
-{
-	if (!strcmp(str, "pmtmr")) {
-		printk("Warning: clock=pmtmr is deprecated. "
-			"Use clocksource=acpi_pm.\n");
-		return boot_override_clocksource("acpi_pm");
-	}
-	printk("Warning! clock= boot option is deprecated. "
-		"Use clocksource=xyz\n");
-	return boot_override_clocksource(str);
-}
-
-__setup("clock=", boot_override_clock);
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.19.orig/kernel/time/timekeeping.c
+++ linux-2.6.19/kernel/time/timekeeping.c
@@ -12,6 +12,7 @@
 #include <linux/timex.h>
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
+#include <linux/sysdev.h>
 
 /*
  * The current time
@@ -42,6 +43,17 @@ static unsigned long timekeeping_suspend
 struct clocksource *clock = &clocksource_jiffies;
 
 #ifdef CONFIG_GENERIC_TIME
+
+/*
+ * Signals to check the current clock in the timer interrupt.
+ */
+static atomic_t clock_check = ATOMIC_INIT(0);
+
+/*
+ * Holds the override name if one is given
+ */
+static char override_name[32];
+
 /**
  * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
  *
@@ -167,7 +179,12 @@ static void timekeeping_change_clocksour
 	struct clocksource *new;
 	cycle_t now;
 	u64 nsec;
-	new = clocksource_get_next();
+
+	if (!*override_name)
+		new = clocksource_get_clock(NULL);
+	else
+		new = clocksource_get_clock(override_name);
+
 	if (clock != new) {
 		now = clocksource_read(new);
 		nsec =  __get_nsec_offset();
@@ -233,6 +250,117 @@ void __init timekeeping_init_notifier(vo
 	 */
 	clocksource_notifier_register(&clocksource_nb);
 }
+
+#ifdef CONFIG_SYSFS
+/**
+ * sysfs_show_current_clocksources - sysfs interface for current clocksource
+ * @dev:	unused
+ * @buf:	char buffer to be filled with clocksource list
+ *
+ * Provides sysfs interface for listing current clocksource.
+ */
+static ssize_t
+timekeeping_sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
+{
+	char *curr = buf;
+
+	curr += sprintf(curr, "%s \n", clock->name);
+
+	return curr - buf;
+}
+
+/**
+ * sysfs_override_clocksource - interface for manually overriding clocksource
+ * @dev:	unused
+ * @buf:	name of override clocksource
+ * @count:	length of buffer
+ *
+ * Takes input from sysfs interface for manually overriding the default
+ * clocksource selction.
+ */
+static ssize_t
+timekeeping_sysfs_override_clocksource(struct sys_device *dev,
+				       const char *buf, size_t count)
+{
+	size_t ret = count;
+	/* strings from sysfs write are not 0 terminated! */
+	if (count >= sizeof(override_name))
+		return -EINVAL;
+
+	/* strip of \n: */
+	if (buf[count-1] == '\n')
+		count--;
+	if (count < 1)
+		return -EINVAL;
+
+	/* copy the name given: */
+	memcpy(override_name, buf, count);
+	override_name[count] = 0;
+
+	/* Signal that there is a new clocksource */
+	atomic_inc(&clock_check);
+
+	return ret;
+}
+
+static SYSDEV_ATTR(current_clocksource, 0600,
+		   timekeeping_sysfs_show_current_clocksources,
+		   timekeeping_sysfs_override_clocksource);
+
+static __init int timekeeping_init_sysfs(void)
+{
+	int error;
+
+	error = sysdev_create_file(&clocksource_sys_device,
+				   &attr_current_clocksource);
+	return error;
+}
+device_initcall(timekeeping_init_sysfs);
+#endif /* CONFIG_SYSFS */
+
+static int __init timekeeping_early_clockswitch(void)
+{
+	atomic_inc(&clock_check);
+	return 0;
+}
+
+late_initcall(timekeeping_early_clockswitch);
+
+/**
+ * boot_override_clocksource - boot clock override
+ * @str:	override name
+ *
+ * Takes a clocksource= boot argument and uses it
+ * as the clocksource override name.
+ */
+static int __init boot_override_clocksource(char* str)
+{
+	if (str)
+		strlcpy(override_name, str, sizeof(override_name));
+	return 1;
+}
+__setup("clocksource=", boot_override_clocksource);
+
+/**
+ * boot_override_clock - Compatibility layer for deprecated boot option
+ * @str:	override name
+ *
+ * DEPRECATED! Takes a clock= boot argument and uses it
+ * as the clocksource override name
+ */
+static int __init boot_override_clock(char* str)
+{
+	if (!strcmp(str, "pmtmr")) {
+		printk("Warning: clock=pmtmr is deprecated. "
+			"Use clocksource=acpi_pm.\n");
+		return boot_override_clocksource("acpi_pm");
+	}
+	printk("Warning! clock= boot option is deprecated. "
+		"Use clocksource=xyz\n");
+	return boot_override_clocksource(str);
+}
+__setup("clock=", boot_override_clock);
+
 #endif /* CONFIG_GENERIC_TIME */
 
 /**
@@ -261,7 +389,6 @@ void __init timekeeping_init(void)
 
 	ntp_clear();
 
-	clock = clocksource_get_next();
 	clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
 	clock->cycle_last = clocksource_read(clock);
 

-- 

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

* [PATCH 14/23] clocksource: increase initcall priority
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (12 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 13/23] timekeeping: move sysfs layer/drop API calls Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 11:50   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 15/23] clocksource: add new flags Daniel Walker
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_init_call.patch --]
[-- Type: text/plain, Size: 9439 bytes --]


Normal systems often have almost everything registered in
device_initcall() . Most drivers are registered there, and usually if
people add code that needs an initcall they will either use
device_initcall() or module_init() which both result in the same
initcall..

When John created the clocksource interface he did what most people
would do , and he made the clocksource registration happen in  
device_initcall with most everything else .. The effect of doing this
was the addition of the following code,

/* clocksource_done_booting - Called near the end of bootup
 *
 * Hack to avoid lots of clocksource churn at boot time
 */
static int __init clocksource_done_booting(void)
{
        finished_booting = 1;
        return 0;
}

late_initcall(clocksource_done_booting);

This is one of two initcalls in the clocksource interface , the other
one is device_initcall(init_clocksource_sysfs); ..

If I leave the clocksource initcall alone then anything that uses a
clocksource in the future would need at least one late_initcall().
Since the clocksources aren't all fully register until after 
device_initcall. 

The reason behind changing that is because it doesn't fit the usually
development flow of initialization functions which , as I said earlier,
almost always end up into device_initcall .

This change certainly isn't mandatory . I feel it would reduce the
likely hood of developers that use the clocksource interface from adding
multiple initcalls (one late_initcall, and one device_initcall). It also
better fits developers tendencies to put almost everything into
device_initcall() ..

In addition,

This patch removes a small amount of code in time keeping which existed to
detect the end of the initcall sequence then selected a clock.

As a note, arm and mips both register their clocksources during time_init()
instead of using initcalls.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/kernel/hpet.c          |    2 +-
 arch/i386/kernel/i8253.c         |    2 +-
 arch/i386/kernel/tsc.c           |    2 +-
 arch/x86_64/kernel/hpet.c        |    2 +-
 arch/x86_64/kernel/tsc.c         |    3 +--
 drivers/clocksource/acpi_pm.c    |    8 +++++++-
 drivers/clocksource/cyclone.c    |    2 +-
 drivers/clocksource/scx200_hrt.c |    2 +-
 include/linux/clocksource.h      |    6 ++++++
 kernel/time/clocksource.c        |   13 -------------
 kernel/time/jiffies.c            |    2 +-
 kernel/time/tick-sched.c         |    8 ++++++++
 kernel/time/timekeeping.c        |   15 +++++++--------
 13 files changed, 36 insertions(+), 31 deletions(-)

Index: linux-2.6.19/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/hpet.c
+++ linux-2.6.19/arch/i386/kernel/hpet.c
@@ -315,7 +315,7 @@ static int __init init_hpet_clocksource(
 	return clocksource_register(&clocksource_hpet);
 }
 
-module_init(init_hpet_clocksource);
+clocksource_initcall(init_hpet_clocksource);
 
 #ifdef CONFIG_HPET_EMULATE_RTC
 
Index: linux-2.6.19/arch/i386/kernel/i8253.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/i8253.c
+++ linux-2.6.19/arch/i386/kernel/i8253.c
@@ -195,4 +195,4 @@ static int __init init_pit_clocksource(v
 	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
 	return clocksource_register(&clocksource_pit);
 }
-module_init(init_pit_clocksource);
+clocksource_initcall(init_pit_clocksource);
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -458,4 +458,4 @@ static int __init init_tsc_clocksource(v
 	return 0;
 }
 
-module_init(init_tsc_clocksource);
+clocksource_initcall(init_tsc_clocksource);
Index: linux-2.6.19/arch/x86_64/kernel/hpet.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/hpet.c
+++ linux-2.6.19/arch/x86_64/kernel/hpet.c
@@ -508,4 +508,4 @@ static int __init init_hpet_clocksource(
 	return clocksource_register(&clocksource_hpet);
 }
 
-module_init(init_hpet_clocksource);
+clocksource_initcall(init_hpet_clocksource);
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/tsc.c
+++ linux-2.6.19/arch/x86_64/kernel/tsc.c
@@ -224,5 +224,4 @@ static int __init init_tsc_clocksource(v
 	}
 	return 0;
 }
-
-module_init(init_tsc_clocksource);
+clocksource_initcall(init_tsc_clocksource);
Index: linux-2.6.19/drivers/clocksource/acpi_pm.c
===================================================================
--- linux-2.6.19.orig/drivers/clocksource/acpi_pm.c
+++ linux-2.6.19/drivers/clocksource/acpi_pm.c
@@ -214,4 +214,10 @@ pm_good:
 	return clocksource_register(&clocksource_acpi_pm);
 }
 
-module_init(init_acpi_pm_clocksource);
+/*
+ * This clocksource is removed from the clocksource_initcall
+ * macro since it's mandatory for it to be in fs_initcall as the
+ * highest initcall level, or else it doesn't work properly with
+ * it's PCI fix ups.
+ */
+fs_initcall(init_acpi_pm_clocksource);
Index: linux-2.6.19/drivers/clocksource/cyclone.c
===================================================================
--- linux-2.6.19.orig/drivers/clocksource/cyclone.c
+++ linux-2.6.19/drivers/clocksource/cyclone.c
@@ -116,4 +116,4 @@ static int __init init_cyclone_clocksour
 	return clocksource_register(&clocksource_cyclone);
 }
 
-module_init(init_cyclone_clocksource);
+clocksource_initcall(init_cyclone_clocksource);
Index: linux-2.6.19/drivers/clocksource/scx200_hrt.c
===================================================================
--- linux-2.6.19.orig/drivers/clocksource/scx200_hrt.c
+++ linux-2.6.19/drivers/clocksource/scx200_hrt.c
@@ -94,7 +94,7 @@ static int __init init_hrt_clocksource(v
 	return clocksource_register(&cs_hrt);
 }
 
-module_init(init_hrt_clocksource);
+clocksource_initcall(init_hrt_clocksource);
 
 MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
 MODULE_DESCRIPTION("clocksource on SCx200 HiRes Timer");
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -41,6 +41,12 @@ extern struct atomic_notifier_head clock
 #define CLOCKSOURCE_NOTIFY_RATING	2
 #define CLOCKSOURCE_NOTIFY_FREQ		4
 
+/*
+ * Defined so the initcall can be changes without touching
+ * every clocksource in the system.
+ */
+#define clocksource_initcall(x)		fs_initcall(x)
+
 /**
  * clocksource_notifier_register - Registers a list change notifier
  * @nb:		pointer to a notifier block
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -38,22 +38,9 @@
  */
 static LIST_HEAD(clocksource_list);
 static DEFINE_SPINLOCK(clocksource_lock);
-static int finished_booting;
 
 ATOMIC_NOTIFIER_HEAD(clocksource_list_notifier);
 
-/* clocksource_done_booting - Called near the end of bootup
- *
- * Hack to avoid lots of clocksource churn at boot time
- */
-static int __init clocksource_done_booting(void)
-{
-	finished_booting = 1;
-	return 0;
-}
-
-late_initcall(clocksource_done_booting);
-
 /**
  * __is_registered - Returns a clocksource if it's registered
  * @name:		name of the clocksource to return
Index: linux-2.6.19/kernel/time/jiffies.c
===================================================================
--- linux-2.6.19.orig/kernel/time/jiffies.c
+++ linux-2.6.19/kernel/time/jiffies.c
@@ -69,4 +69,4 @@ static int __init init_jiffies_clocksour
 	return clocksource_register(&clocksource_jiffies);
 }
 
-module_init(init_jiffies_clocksource);
+clocksource_initcall(init_jiffies_clocksource);
Index: linux-2.6.19/kernel/time/tick-sched.c
===================================================================
--- linux-2.6.19.orig/kernel/time/tick-sched.c
+++ linux-2.6.19/kernel/time/tick-sched.c
@@ -540,6 +540,14 @@ int tick_check_oneshot_change(int allow_
 {
 	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
 
+	/*
+	 * HRT or Dynamic tick can't be started during init, but it's possible
+	 * for generic time to switch to a good clock during init. So
+	 * explicitly check that we are't still booting here.
+	 */
+	if (system_state == SYSTEM_BOOTING)
+		return 0;
+
 	if (!test_and_clear_bit(0, &ts->check_clocks))
 		return 0;
 
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.19.orig/kernel/time/timekeeping.c
+++ linux-2.6.19/kernel/time/timekeeping.c
@@ -318,14 +318,6 @@ static __init int timekeeping_init_sysfs
 device_initcall(timekeeping_init_sysfs);
 #endif /* CONFIG_SYSFS */
 
-static int __init timekeeping_early_clockswitch(void)
-{
-	atomic_inc(&clock_check);
-	return 0;
-}
-
-late_initcall(timekeeping_early_clockswitch);
-
 /**
  * boot_override_clocksource - boot clock override
  * @str:	override name
@@ -471,6 +463,13 @@ static int __init timekeeping_init_devic
 	if (!error)
 		error = sysdev_register(&device_timer);
 
+#ifdef CONFIG_GENERIC_TIME
+	/*
+	 * Now we signal to switch to a high-res clock.
+	 */
+	atomic_inc(&clock_check);
+#endif
+
 	return error;
 }
 

-- 

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

* [PATCH 15/23] clocksource: add new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (13 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 14/23] clocksource: increase initcall priority Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 16/23] clocksource: arm update for " Daniel Walker
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_add_flag_values.patch --]
[-- Type: text/plain, Size: 861 bytes --]

Compile patch .. This just adds some code so the next few patches will compile.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |    6 ++++++
 1 file changed, 6 insertions(+)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -235,6 +235,12 @@ static inline void clocksource_calculate
 	c->xtime_interval = (u64)c->cycle_interval * c->mult;
 }
 
+#define CLOCKSOURCE_NOT_CONTINUOUS	1
+#define CLOCKSOURCE_UNSTABLE		2
+#define CLOCKSOURCE_NOT_ATOMIC		4
+#define CLOCKSOURCE_UNDER_32BITS	8
+#define CLOCKSOURCE_64BITS		16
+#define CLOCKSOURCE_PM_AFFECTED		32
 
 /* used to install a new clocksource */
 extern int clocksource_register(struct clocksource*);

-- 

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

* [PATCH 16/23] clocksource: arm update for new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (14 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 15/23] clocksource: add new flags Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 12:27   ` Ingo Molnar
  2007-01-31  3:37 ` [PATCH 17/23] clocksource: avr32 " Daniel Walker
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource-arm-add-flags.patch --]
[-- Type: text/plain, Size: 1990 bytes --]

Update ARM for new flags.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/arm/mach-imx/time.c      |    1 -
 arch/arm/mach-ixp4xx/common.c |    1 -
 arch/arm/mach-netx/time.c     |    1 -
 arch/arm/mach-pxa/time.c      |    1 -
 4 files changed, 4 deletions(-)

Index: linux-2.6.19/arch/arm/mach-imx/time.c
===================================================================
--- linux-2.6.19.orig/arch/arm/mach-imx/time.c
+++ linux-2.6.19/arch/arm/mach-imx/time.c
@@ -87,7 +87,6 @@ static struct clocksource clocksource_im
 	.read		= imx_get_cycles,
 	.mask		= 0xFFFFFFFF,
 	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init imx_clocksource_init(void)
Index: linux-2.6.19/arch/arm/mach-ixp4xx/common.c
===================================================================
--- linux-2.6.19.orig/arch/arm/mach-ixp4xx/common.c
+++ linux-2.6.19/arch/arm/mach-ixp4xx/common.c
@@ -395,7 +395,6 @@ static struct clocksource clocksource_ix
 	.read		= ixp4xx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 unsigned long ixp4xx_timer_freq = FREQ;
Index: linux-2.6.19/arch/arm/mach-netx/time.c
===================================================================
--- linux-2.6.19.orig/arch/arm/mach-netx/time.c
+++ linux-2.6.19/arch/arm/mach-netx/time.c
@@ -62,7 +62,6 @@ static struct clocksource clocksource_ne
 	.read		= netx_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift 		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*
Index: linux-2.6.19/arch/arm/mach-pxa/time.c
===================================================================
--- linux-2.6.19.orig/arch/arm/mach-pxa/time.c
+++ linux-2.6.19/arch/arm/mach-pxa/time.c
@@ -112,7 +112,6 @@ static struct clocksource clocksource_px
 	.read           = pxa_get_cycles,
 	.mask           = CLOCKSOURCE_MASK(32),
 	.shift          = 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init pxa_timer_init(void)

-- 

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

* [PATCH 17/23] clocksource: avr32 update for new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (15 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 16/23] clocksource: arm update for " Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 18/23] clocksource: i386 " Daniel Walker
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource-avr32-add-flags.patch --]
[-- Type: text/plain, Size: 545 bytes --]

Update avr32 for new flags.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/avr32/kernel/time.c |    1 -
 1 file changed, 1 deletion(-)

Index: linux-2.6.19/arch/avr32/kernel/time.c
===================================================================
--- linux-2.6.19.orig/arch/avr32/kernel/time.c
+++ linux-2.6.19/arch/avr32/kernel/time.c
@@ -37,7 +37,6 @@ static struct clocksource clocksource_av
 	.read		= read_cycle_count,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.shift		= 16,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 /*

-- 

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

* [PATCH 18/23] clocksource: i386 update for new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (16 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 17/23] clocksource: avr32 " Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 19/23] clocksource: mips " Daniel Walker
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource-i386-add-flags.patch --]
[-- Type: text/plain, Size: 3410 bytes --]

Update i386 for new flags.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/kernel/hpet.c    |    1 -
 arch/i386/kernel/i8253.c   |    1 +
 arch/i386/kernel/tsc.c     |   23 +++++++++++------------
 arch/i386/kernel/vmitime.c |    2 +-
 4 files changed, 13 insertions(+), 14 deletions(-)

Index: linux-2.6.19/arch/i386/kernel/hpet.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/hpet.c
+++ linux-2.6.19/arch/i386/kernel/hpet.c
@@ -287,7 +287,6 @@ static struct clocksource clocksource_hp
 	.read		= read_hpet,
 	.mask		= HPET_MASK,
 	.shift		= HPET_SHIFT,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_hpet_clocksource(void)
Index: linux-2.6.19/arch/i386/kernel/i8253.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/i8253.c
+++ linux-2.6.19/arch/i386/kernel/i8253.c
@@ -183,6 +183,7 @@ static struct clocksource clocksource_pi
 	.rating = 110,
 	.read	= pit_read,
 	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCKSOURCE_NOT_ATOMIC,
 	.mult	= 0,
 	.shift	= 20,
 };
Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -306,8 +306,7 @@ static struct clocksource clocksource_ts
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
-				  CLOCK_SOURCE_MUST_VERIFY,
+	.flags			= CLOCKSOURCE_64BITS | CLOCKSOURCE_PM_AFFECTED,
 };
 
 /*
@@ -316,10 +315,8 @@ static struct clocksource clocksource_ts
 void mark_tsc_unstable(void)
 {
 	/* check to see if we should switch to the safe clocksource: */
-	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 0)) {
-		clocksource_tsc.rating = 0;
-		clocksource_rating_change(&clocksource_tsc);
-	}
+	if (unlikely(!tsc_unstable))
+		clocksource_mark_unstable(&clocksource_tsc);
 
 	tsc_unstable = 1;
 }
@@ -434,17 +431,19 @@ static int __init init_tsc_clocksource(v
 		/* check blacklist */
 		dmi_check_system(bad_tsc_dmi_table);
 
-		if (unsynchronized_tsc()) /* mark unstable if unsynced */
+		if (unsynchronized_tsc()) { /* mark unstable if unsynced */
 			mark_tsc_unstable();
+			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE;
+		}
 		check_geode_tsc_reliable();
 		current_tsc_khz = tsc_khz;
 		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
 							clocksource_tsc.shift);
-		/* lower the rating if we already know its unstable: */
-		if (check_tsc_unstable()) {
-			clocksource_tsc.rating = 0;
-			clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
-		}
+
+		/* flags as unstable if we already know its unstable: */
+		if (check_tsc_unstable())
+			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE |
+						 CLOCKSOURCE_NOT_CONTINUOUS;
 
 		init_timer(&verify_tsc_freq_timer);
 		verify_tsc_freq_timer.function = verify_tsc_freq;
Index: linux-2.6.19/arch/i386/kernel/vmitime.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/vmitime.c
+++ linux-2.6.19/arch/i386/kernel/vmitime.c
@@ -115,7 +115,7 @@ static struct clocksource clocksource_vm
 	.mask			= CLOCKSOURCE_MASK(64),
 	.mult			= 0, /* to be set */
 	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS,
+	.flags			= CLOCKSOURCE_64BITS,
 };
 
 

-- 

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

* [PATCH 19/23] clocksource: mips update for new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (17 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 18/23] clocksource: i386 " Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 20/23] clocksource: x86_64 " Daniel Walker
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource-mips-add-flags.patch --]
[-- Type: text/plain, Size: 591 bytes --]

Update mips for new flags.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/mips/kernel/time.c |    1 -
 1 file changed, 1 deletion(-)

Index: linux-2.6.19/arch/mips/kernel/time.c
===================================================================
--- linux-2.6.19.orig/arch/mips/kernel/time.c
+++ linux-2.6.19/arch/mips/kernel/time.c
@@ -307,7 +307,6 @@ static unsigned int __init calibrate_hpt
 struct clocksource clocksource_mips = {
 	.name		= "MIPS",
 	.mask		= 0xffffffff,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init init_mips_clocksource(void)

-- 

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

* [PATCH 20/23] clocksource: x86_64 update for new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (18 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 19/23] clocksource: mips " Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 21/23] clocksource: drivers/ " Daniel Walker
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource-x86_64-add-flags.patch --]
[-- Type: text/plain, Size: 1864 bytes --]

Update x86_64 for new flags.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/x86_64/kernel/hpet.c |    1 -
 arch/x86_64/kernel/tsc.c  |   11 ++++-------
 2 files changed, 4 insertions(+), 8 deletions(-)

Index: linux-2.6.19/arch/x86_64/kernel/hpet.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/hpet.c
+++ linux-2.6.19/arch/x86_64/kernel/hpet.c
@@ -470,7 +470,6 @@ struct clocksource clocksource_hpet = {
 	.mask		= (cycle_t)HPET_MASK,
 	.mult		= 0, /* set below */
 	.shift		= HPET_SHIFT,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.vread		= vread_hpet,
 };
 
Index: linux-2.6.19/arch/x86_64/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/x86_64/kernel/tsc.c
+++ linux-2.6.19/arch/x86_64/kernel/tsc.c
@@ -195,18 +195,15 @@ static struct clocksource clocksource_ts
 	.read			= read_tsc,
 	.mask			= CLOCKSOURCE_MASK(64),
 	.shift			= 22,
-	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
-				  CLOCK_SOURCE_MUST_VERIFY,
+	.flags                  = CLOCKSOURCE_64BITS | CLOCKSOURCE_PM_AFFECTED,
 	.vread			= vread_tsc,
 };
 
 void mark_tsc_unstable(void)
 {
 	/* check to see if we should switch to the safe clocksource: */
-	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 50)) {
-		clocksource_tsc.rating = 50;
-		clocksource_rating_change(&clocksource_tsc);
-	}
+	if (unlikely(!tsc_unstable && clocksource_tsc.rating != 50))
+		clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE;
 
 	tsc_unstable = 1;
 }
@@ -218,7 +215,7 @@ static int __init init_tsc_clocksource(v
 		clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
 							clocksource_tsc.shift);
 		if (check_tsc_unstable())
-			clocksource_tsc.rating = 50;
+			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE;
 
 		return clocksource_register(&clocksource_tsc);
 	}

-- 

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

* [PATCH 21/23] clocksource: drivers/ update for new flags
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (19 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 20/23] clocksource: x86_64 " Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31  3:37 ` [PATCH 22/23] clocksource: new clock lookup method Daniel Walker
  2007-01-31  3:37 ` [PATCH 23/23] clocksource tsc: add verify routine Daniel Walker
  22 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource-drivers-add-flags.patch --]
[-- Type: text/plain, Size: 1599 bytes --]

Update drivers/ for new flags.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 drivers/clocksource/acpi_pm.c    |    2 +-
 drivers/clocksource/cyclone.c    |    1 -
 drivers/clocksource/scx200_hrt.c |    1 -
 3 files changed, 1 insertion(+), 3 deletions(-)

Index: linux-2.6.19/drivers/clocksource/acpi_pm.c
===================================================================
--- linux-2.6.19.orig/drivers/clocksource/acpi_pm.c
+++ linux-2.6.19/drivers/clocksource/acpi_pm.c
@@ -73,7 +73,7 @@ static struct clocksource clocksource_ac
 	.mask		= (cycle_t)ACPI_PM_MASK,
 	.mult		= 0, /*to be caluclated*/
 	.shift		= 22,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	.flags		= CLOCKSOURCE_UNDER_32BITS,
 
 };
 
Index: linux-2.6.19/drivers/clocksource/cyclone.c
===================================================================
--- linux-2.6.19.orig/drivers/clocksource/cyclone.c
+++ linux-2.6.19/drivers/clocksource/cyclone.c
@@ -31,7 +31,6 @@ static struct clocksource clocksource_cy
 	.mask		= CYCLONE_TIMER_MASK,
 	.mult		= 10,
 	.shift		= 0,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static int __init init_cyclone_clocksource(void)
Index: linux-2.6.19/drivers/clocksource/scx200_hrt.c
===================================================================
--- linux-2.6.19.orig/drivers/clocksource/scx200_hrt.c
+++ linux-2.6.19/drivers/clocksource/scx200_hrt.c
@@ -57,7 +57,6 @@ static struct clocksource cs_hrt = {
 	.rating		= 250,
 	.read		= read_hrt,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	/* mult, shift are set based on mhz27 flag */
 };
 

-- 

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

* [PATCH 22/23] clocksource: new clock lookup method
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (20 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 21/23] clocksource: drivers/ " Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
       [not found]   ` <20070131122215.GE1847@elte.hu>
  2007-01-31  3:37 ` [PATCH 23/23] clocksource tsc: add verify routine Daniel Walker
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul

[-- Attachment #1: clocksource_unstable_api_calls.patch --]
[-- Type: text/plain, Size: 9048 bytes --]

This patch modifies the current clocksource API so that clocks
can be masked if they have specific negative qualities. For 
instance, if a clock is not atomic you can choose not to include 
it in the list you select from, atomic in this case being lockless. 

The following qualities can be masked off,

#define CLOCKSOURCE_NOT_CONTINUOUS      1
#define CLOCKSOURCE_UNSTABLE            2
#define CLOCKSOURCE_NOT_ATOMIC          4
#define CLOCKSOURCE_UNDER_32BITS        8
#define CLOCKSOURCE_64BITS              16
#define CLOCKSOURCE_PM_AFFECTED         32

I modify the .flags to accomplish this.

The reasoning behind this is that it's not interesting to have a
positive "rating" value, and have a positive flags value. 

For instance, if the clock has a high rating you assume it's continuous.
The selection process isn't helped by stating "continuous" in the flags.

The point is to list all the negative side effects that some clocks have
which the programmer knows in advance that their code can not tolerate.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 include/linux/clocksource.h |   35 +++++++++++++++++++++++++-------
 kernel/time/clocksource.c   |   47 ++++++++++++++++++--------------------------
 kernel/time/jiffies.c       |    1 
 kernel/time/timekeeping.c   |   11 ++++++----
 4 files changed, 55 insertions(+), 39 deletions(-)

Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -30,6 +30,11 @@ extern struct clocksource clocksource_ji
 extern struct sys_device clocksource_sys_device;
 
 /*
+ * Read function type.
+ */
+typedef cycle_t (*clock_read_t)(void);
+
+/*
  * Allows inlined calling for notifier routines.
  */
 extern struct atomic_notifier_head clocksource_list_notifier;
@@ -40,6 +45,7 @@ extern struct atomic_notifier_head clock
 #define CLOCKSOURCE_NOTIFY_REGISTER	1
 #define CLOCKSOURCE_NOTIFY_RATING	2
 #define CLOCKSOURCE_NOTIFY_FREQ		4
+#define CLOCKSOURCE_NOTIFY_UNSTABLE	8
 
 /*
  * Defined so the initcall can be changes without touching
@@ -119,12 +125,6 @@ struct clocksource {
 	s64 error;
 };
 
-/*
- * Clock source flags bits::
- */
-#define CLOCK_SOURCE_IS_CONTINUOUS	0x01
-#define CLOCK_SOURCE_MUST_VERIFY	0x02
-
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
 
@@ -235,6 +235,9 @@ static inline void clocksource_calculate
 	c->xtime_interval = (u64)c->cycle_interval * c->mult;
 }
 
+/*
+ * Clocksource flags
+ */
 #define CLOCKSOURCE_NOT_CONTINUOUS	1
 #define CLOCKSOURCE_UNSTABLE		2
 #define CLOCKSOURCE_NOT_ATOMIC		4
@@ -243,9 +246,25 @@ static inline void clocksource_calculate
 #define CLOCKSOURCE_PM_AFFECTED		32
 
 /* used to install a new clocksource */
+extern void clocksource_mark_unstable(struct clocksource *);
+extern struct clocksource *clocksource_get_unstable(void);
 extern int clocksource_register(struct clocksource*);
 extern void clocksource_rating_change(struct clocksource*);
-extern struct clocksource * clocksource_get_clock(char*);
+extern struct clocksource * clocksource_get_clock(char*, unsigned long);
+
+
+/**
+ * clocksource_get_masked_clock - Finds highest rated clocksource w/o mask
+ * @mask:		Clocksource features that are not wanted.
+ *
+ * Returns the highest rated clocksource that doesn't have any of the bits set
+ * in mask. If none are register the jiffies clock is returned. If all the clocks
+ * have the mask bits set, then NULL is returned.
+ */
+static inline struct clocksource * clocksource_get_masked_clock(unsigned long mask)
+{
+	return clocksource_get_clock(NULL, mask);
+}
 
 /**
  * clocksource_get_best_clock - Finds highest rated clocksource
@@ -255,7 +274,7 @@ extern struct clocksource * clocksource_
  */
 static inline struct clocksource * clocksource_get_best_clock(void)
 {
-	return clocksource_get_clock(NULL);
+	return clocksource_get_clock(NULL, 0);
 }
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL
Index: linux-2.6.19/kernel/time/clocksource.c
===================================================================
--- linux-2.6.19.orig/kernel/time/clocksource.c
+++ linux-2.6.19/kernel/time/clocksource.c
@@ -51,7 +51,8 @@ ATOMIC_NOTIFIER_HEAD(clocksource_list_no
  * If no clocksources are registered the jiffies clock is
  * returned.
  */
-static struct clocksource * __is_registered(char * name)
+static inline
+struct clocksource * __is_registered(char * name, unsigned long mask)
 {
 	struct list_head *tmp;
 
@@ -59,7 +60,11 @@ static struct clocksource * __is_registe
 		struct clocksource *src;
 
 		src = list_entry(tmp, struct clocksource, list);
-		if (!strcmp(src->name, name))
+		if (name) {
+			if (!strcmp(src->name, name))
+				return src;
+
+		} else if (!(src->flags & mask))
 			return src;
 	}
 
@@ -75,32 +80,34 @@ static struct clocksource * __is_registe
  * Returns the clocksource if registered, zero otherwise.
  * If the @name is null the highest rated clock is returned.
  */
-static inline struct clocksource * __get_clock(char * name)
+static inline struct clocksource * __get_clock(char * name, unsigned long mask)
 {
 
 	if (unlikely(list_empty(&clocksource_list)))
 		return &clocksource_jiffies;
 
-	if (!name)
+	if (!name && !mask)
 		return list_entry(clocksource_list.next,
 				  struct clocksource, list);
 
-	return __is_registered(name);
+	return __is_registered(name, mask);
 }
 
 /**
  * clocksource_get_clock - Finds a specific clocksource
  * @name:		name of the clocksource to return
+ * @mask:		Clocks with these flags set will
+ *			be ignored.
  *
  * Returns the clocksource if registered, zero otherwise.
  */
-struct clocksource * clocksource_get_clock(char * name)
+struct clocksource * clocksource_get_clock(char * name, unsigned long mask)
 {
 	struct clocksource * ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocksource_lock, flags);
-	ret = __get_clock(name);
+	ret = __get_clock(name, mask);
 	spin_unlock_irqrestore(&clocksource_lock, flags);
 	return ret;
 }
@@ -111,7 +118,7 @@ struct clocksource * clocksource_get_clo
  *
  * Adds a clocksource to the clocksource_list in sorted order.
  */
-static void __sorted_list_add(struct clocksource *c)
+static inline void __sorted_list_add(struct clocksource *c)
 {
 	struct list_head *tmp;
 
@@ -158,31 +165,17 @@ int clocksource_register(struct clocksou
 EXPORT_SYMBOL(clocksource_register);
 
 /**
- * clocksource_rating_change - Allows dynamic rating changes for register
- *                           clocksources.
+ * clocksource_mark_unstable - Mark the clocks as unstable.
  *
- * Signals that a clocksource is dynamically changing it's rating.
- * This could happen if a clocksource becomes more/less stable.
+ * This signals that this clock has become unstable.
  */
-void clocksource_rating_change(struct clocksource *c)
+void clocksource_mark_unstable(struct clocksource *c)
 {
-	unsigned long flags;
-
-  	spin_lock_irqsave(&clocksource_lock, flags);
-
-	/*
-	 * Re-register the clocksource with it's new rating.
-	 */
-	list_del_init(&c->list);
-	__sorted_list_add(c);
-
-	spin_unlock_irqrestore(&clocksource_lock, flags);
+	c->flags |= CLOCKSOURCE_UNSTABLE;
 
 	atomic_notifier_call_chain(&clocksource_list_notifier,
-				   CLOCKSOURCE_NOTIFY_RATING, c);
-
+				   CLOCKSOURCE_NOTIFY_UNSTABLE, c);
 }
-EXPORT_SYMBOL(clocksource_rating_change);
 
 #ifdef CONFIG_SYSFS
 /**
Index: linux-2.6.19/kernel/time/jiffies.c
===================================================================
--- linux-2.6.19.orig/kernel/time/jiffies.c
+++ linux-2.6.19/kernel/time/jiffies.c
@@ -62,6 +62,7 @@ struct clocksource clocksource_jiffies =
 	.mask		= 0xffffffff, /*32bits*/
 	.mult		= NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
 	.shift		= JIFFIES_SHIFT,
+	.flags		= CLOCKSOURCE_NOT_CONTINUOUS, /* not free running */
 };
 
 static int __init init_jiffies_clocksource(void)
Index: linux-2.6.19/kernel/time/timekeeping.c
===================================================================
--- linux-2.6.19.orig/kernel/time/timekeeping.c
+++ linux-2.6.19/kernel/time/timekeeping.c
@@ -181,9 +181,12 @@ static void timekeeping_change_clocksour
 	u64 nsec;
 
 	if (!*override_name)
-		new = clocksource_get_clock(NULL);
+		/*
+		 * Mask off unstable clocks.
+		 */
+		new = clocksource_get_masked_clock(CLOCKSOURCE_UNSTABLE);
 	else
-		new = clocksource_get_clock(override_name);
+		new = clocksource_get_clock(override_name, 0);
 
 	if (clock != new) {
 		now = clocksource_read(new);
@@ -216,7 +219,7 @@ int timekeeping_is_continuous(void)
 	do {
 		seq = read_seqbegin(&xtime_lock);
 
-		ret = clock->flags & CLOCK_SOURCE_IS_CONTINUOUS;
+		ret = !(clock->flags & CLOCKSOURCE_NOT_CONTINUOUS);
 
 	} while (read_seqretry(&xtime_lock, seq));
 
@@ -231,7 +234,7 @@ clocksource_callback(struct notifier_blo
 
 	switch (op) {
 		case CLOCKSOURCE_NOTIFY_FREQ:
-		case CLOCKSOURCE_NOTIFY_RATING:
+		case CLOCKSOURCE_NOTIFY_UNSTABLE:
 			atomic_inc(&clock_check);
 	}
 

-- 

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

* [PATCH 23/23] clocksource tsc: add verify routine
  2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
                   ` (21 preceding siblings ...)
  2007-01-31  3:37 ` [PATCH 22/23] clocksource: new clock lookup method Daniel Walker
@ 2007-01-31  3:37 ` Daniel Walker
  2007-01-31 12:43   ` Ingo Molnar
  22 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31  3:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, johnstul, tglx, mingo

[-- Attachment #1: generic-tsc-verifiy-clock.patch --]
[-- Type: text/plain, Size: 4242 bytes --]

I've included this as another user of the clocksource interface. I don't see a
usage for this across all achitectures. So a fully generic version isn't needed.

I modified this from the pre 2.6.20-rc6-mm2 release to make the routine smaller
and to make it select a clocksource inside the timer. It should work with an HPET.

Signed-Off-By: Daniel Walker <dwalker@mvista.com>

---
 arch/i386/kernel/tsc.c      |   55 ++++++++++++++++++++++++++++----------------
 include/linux/clocksource.h |   16 ++++++++++++
 2 files changed, 51 insertions(+), 20 deletions(-)

Index: linux-2.6.19/arch/i386/kernel/tsc.c
===================================================================
--- linux-2.6.19.orig/arch/i386/kernel/tsc.c
+++ linux-2.6.19/arch/i386/kernel/tsc.c
@@ -343,47 +343,59 @@ static struct dmi_system_id __initdata b
 	 {}
 };
 
-#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
+#define WATCHDOG_TRESHOLD (NSEC_PER_SEC >> 4)
+#define TSC_FREQ_CHECK_INTERVAL (MSEC_PER_SEC/2)
 static struct timer_list verify_tsc_freq_timer;
+struct clocksource *verify_clock;
 
 /* XXX - Probably should add locking */
 static void verify_tsc_freq(unsigned long unused)
 {
-	static u64 last_tsc;
-	static unsigned long last_jiffies;
-
-	u64 now_tsc, interval_tsc;
-	unsigned long now_jiffies, interval_jiffies;
+	static cycle_t last_tsc, last_verify;
 
+	cycle_t now_tsc, verify_clock_now, interval;
+	s64 nsecs;
 
 	if (check_tsc_unstable())
 		return;
 
-	rdtscll(now_tsc);
-	now_jiffies = jiffies;
+	if (unlikely(system_state != SYSTEM_RUNNING))
+		goto out_timer;
 
-	if (!last_jiffies) {
-		goto out;
+	if (unlikely(!verify_clock)) {
+		verify_clock =
+			clocksource_get_masked_clock(CLOCKSOURCE_PM_AFFECTED);
+		printk("TSC: selected %s clocksource for TSC verification.\n",
+		       verify_clock->name);
 	}
 
-	interval_jiffies = now_jiffies - last_jiffies;
-	interval_tsc = now_tsc - last_tsc;
-	interval_tsc *= HZ;
-	do_div(interval_tsc, cpu_khz*1000);
+	now_tsc = clocksource_read(&clocksource_tsc);
+	verify_clock_now = clocksource_read(verify_clock);
+
+	if (!last_tsc)
+		goto out;
 
-	if (interval_tsc < (interval_jiffies * 3 / 4)) {
+	interval = clocksource_subtract(verify_clock, verify_clock_now,
+					last_verify);
+	nsecs = cyc2ns(verify_clock, interval);
+
+	interval = clocksource_subtract(&clocksource_tsc, now_tsc, last_tsc);
+	nsecs -= cyc2ns(&clocksource_tsc, interval);
+
+	if (nsecs > WATCHDOG_TRESHOLD) {
 		printk("TSC appears to be running slowly. "
-			"Marking it as unstable\n");
+		       "Marking it as unstable");
 		mark_tsc_unstable();
 		return;
 	}
 
 out:
-	last_tsc = now_tsc;
-	last_jiffies = now_jiffies;
+  	last_tsc = now_tsc;
+	last_verify = verify_clock_now;
+out_timer:
 	/* set us up to go off on the next interval: */
 	mod_timer(&verify_tsc_freq_timer,
-		jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
+		  jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
 }
 
 /*
@@ -444,7 +456,10 @@ static int __init init_tsc_clocksource(v
 		if (check_tsc_unstable())
 			clocksource_tsc.flags |= CLOCKSOURCE_UNSTABLE |
 						 CLOCKSOURCE_NOT_CONTINUOUS;
-
+		/*
+		 * The verify routine will select the right clock after the
+		 * system boots fully.
+		 */
 		init_timer(&verify_tsc_freq_timer);
 		verify_tsc_freq_timer.function = verify_tsc_freq;
 		verify_tsc_freq_timer.expires =
Index: linux-2.6.19/include/linux/clocksource.h
===================================================================
--- linux-2.6.19.orig/include/linux/clocksource.h
+++ linux-2.6.19/include/linux/clocksource.h
@@ -207,6 +207,22 @@ static inline s64 cyc2ns(struct clocksou
 }
 
 /**
+ * clocksource_subtract - Subtract two cycle_t timestamps
+ * @cs:		Clocksource the timestamp came from
+ * @stop:	Stop timestamp
+ * @start:	Start timestamp
+ *
+ * This subtract accounts for rollover by using the clocksource mask.
+ * The clock can roll over only once, after that this subtract will not
+ * work properly.
+ */
+static inline s64 clocksource_subtract(struct clocksource* cs, cycle_t stop,
+				       cycle_t start)
+{
+	return ((stop - start) & cs->mask);
+}
+
+/**
  * clocksource_calculate_interval - Calculates a clocksource interval struct
  *
  * @c:		Pointer to clocksource.

-- 

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

* Re: [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c
  2007-01-31  3:37 ` [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c Daniel Walker
@ 2007-01-31  8:59   ` Ingo Molnar
  2007-01-31 15:05     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31  8:59 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul


* Daniel Walker <dwalker@mvista.com> wrote:

> Move the generic timekeeping code from kernel/timer.c to 
> kernel/time/timekeeping.c. [...]

please lets not do this just yet. While i have no problems with the 
change in theory, the time code is in high flux and it's easier to keep 
things sorted if we dont do big code movements. It also makes it harder 
to review things and it acts as a hard merge barrier. We usually do such 
move chunks of code in 'quiet periods', and now is definitely not such a 
period. It's also pretty easy to do.

	Ingo

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

* Re: [PATCH 07/23] clocksource: rating sorted list
  2007-01-31  3:37 ` [PATCH 07/23] clocksource: rating sorted list Daniel Walker
@ 2007-01-31  9:34   ` Ingo Molnar
  2007-01-31 15:07     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31  9:34 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> Converts the original plain list into a sorted list based on the clock 
> rating. Later in my tree this allows some of the variables to be 
> dropped since the highest rated clock is always at the front of the 
> list. This also does some other nice things like allow the sysfs files 
> to print the clocks in a more interesting order. It's forward looking.

Unfortunately this seems to be a step backwards to me. Please consider:

>  	if (clocksource_tsc.rating != 0 && check_tsc_unstable()) {
>  		clocksource_tsc.rating = 0;
> -		clocksource_reselect();
> +		clocksource_rating_change(&clocksource_tsc);
>  		change = 1;

this should be the following API:

	clocksource_rating_change(&clocksource_tsc, 0);

a rating change can occur due to other things as well, not only due to 
'tsc unstable' events. So keeping an API around that changes the rating 
(and propagates all related changes), makes more sense to me.

also, a pure function call is the most natural (and most flexible) API, 
for a centrally registered resource like a clock source driver. And a 
rating change should imply a reselect too, obviously. That way we 
replace 2 lines with 1 line - that's a real API improvement and a real 
cleanup patch.

and that's precisely what Thomas' patch in -mm that your queue undoes 
implements. (see: simplify-the-registration-of-clocksources.patch in 
-mm) Have you considered Thomas' change when you dropped it?

	Ingo

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

* Re: [PATCH 08/23] clocksource: drop duplicate register checking
  2007-01-31  3:37 ` [PATCH 08/23] clocksource: drop duplicate register checking Daniel Walker
@ 2007-01-31  9:59   ` Ingo Molnar
  2007-01-31 15:13     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31  9:59 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> This is something Thomas already dropped, [...]

(i think you forgot to Cc: Thomas here, nor is this something that 
Thomas' change dropped.)

> [...] and I'm just sticking with that .. If you register your 
> clocksource _twice_ your kernel will likely not work correctly (and 
> might crash).

this is a quite bad change. John's original clocksource code protects 
against double registry:

         if (is_registered_source(c)) {
                 printk("register_clocksource: Cannot register %s. "
                        "Already registered!", c->name);
                 ret = -EBUSY;

and Thomas' change keeps that property, but doesnt printk. Your change 
makes double registry possible, potentially crashing the kernel later 
on! (And this isnt theoretical, double registry did happen in practice 
when i debugged suspend problems on my SMP laptop.)

	Ingo

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

* Re: [PATCH 09/23] clocksource: add block notifier
  2007-01-31  3:37 ` [PATCH 09/23] clocksource: add block notifier Daniel Walker
@ 2007-01-31 10:17   ` Ingo Molnar
  2007-01-31 15:25     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 10:17 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> Adds a call back interface for register/rating change events. This is 
> also used later in this series to signal other interesting events.

This patch adds:

> +#define CLOCKSOURCE_NOTIFY_REGISTER	1
> +#define CLOCKSOURCE_NOTIFY_RATING	2
> +#define CLOCKSOURCE_NOTIFY_FREQ		4

and a later patch adds:

> +#define CLOCKSOURCE_NOTIFY_UNSTABLE	8

while i tentatively agree with the introduction of clocksource driver 
notifications in general (given any actual real users of that 
infrastructure), i can see three problems with your notifier changes:

firstly, with the full changes applied, CLOCKSOURCE_NOTIFY_RATING is 
totally unused (and not even driven by the core clocksource code).

secondly, CLOCKSOURCE_NOTIFY_REGISTER is only used by the core 
clocksource code and no register-notifier interface is exposed: this 
makes the whole thing an expensive NOP.

thirdly, CLOCKSOURCE_NOTIFY_FREQ is totally unused as well.

(there are tons of examples in the kernel of how to do driver 
notification APIs properly.)

	Ingo

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

* Re: [PATCH 10/23] clocksource: remove update_callback
  2007-01-31  3:37 ` [PATCH 10/23] clocksource: remove update_callback Daniel Walker
@ 2007-01-31 10:46   ` Ingo Molnar
  2007-01-31 15:42     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 10:46 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> Uses the block notifier to replace the functionality of 
> update_callback(). update_callback() was a special case specifically 
> for the tsc, but including it in the clocksource structure duplicated 
> it needlessly for other clocks.

Firstly, it think it should be mentioned that Thomas' queue already does 
this, in clocksource-remove-the-update-callback.patch (hence he should 
have been Cc:-ed). Your queue 'drops' Thomas' patch then redoes it here 
without mentioning that this is another version of what is in Thomas's 
queue. So we get this situation:

   clocksource-remove-the-update-callback.patch
   drop-clocksource-remove-the-update-callback.patch
   clocksource_remove_update_callback.patch

that all flip-flops the same thing.

Secondly, your patch seems to do other changes as well:

> @@ -179,6 +172,7 @@ int recalibrate_cpu_khz(void)
>  	if (cpu_has_tsc) {
>  		cpu_khz = calculate_cpu_khz();
>  		tsc_khz = cpu_khz;
> +		mark_tsc_unstable();
>  		cpu_data[0].loops_per_jiffy =
>  			cpufreq_scale(cpu_data[0].loops_per_jiffy,
>  					cpu_khz_old, cpu_khz);

this adds a new event to a place that didnt have it before. (If this is 
fixing up an initialization artifact then that needs a comment at 
least.)

plus:

>  struct clocksource *clock = &clocksource_jiffies;
> +atomic_t clock_recalc_interval = ATOMIC_INIT(0);

is not mentioned in the changelog. It's also needlessly global. 
Furthermore, it seems to be a rather unclean method of passing 
information from clocksource_callback() into change_clocksource():

> @@ -176,8 +177,9 @@ static int change_clocksource(void)
>  		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
>  		       clock->name);
>  		return 1;
> -	} else if (clock->update_callback) {
> -		return clock->update_callback();
> +	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
> +		atomic_set(&clock_recalc_interval, 0);
> +		return 1;

that's quite bad: you lost an information passing facility by going to a 
notifier, and you try to work it around via a global atomic variable. 
Which also looks quite racy as well.

The clean solution is i think what Thomas did: he calls straight into 
clocksource_change_rating(). And look at Thomas' patch:

 3 files changed, 17 insertions(+), 37 deletions(-)

versus yours:

 5 files changed, 45 insertions(+), 42 deletions(-)

Thomas' looks definitely simpler to me.

	ingo

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

* Re: [PATCH 11/23] clocksource: atomic signals
  2007-01-31  3:37 ` [PATCH 11/23] clocksource: atomic signals Daniel Walker
@ 2007-01-31 11:07   ` Ingo Molnar
  2007-01-31 15:59     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 11:07 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul


* Daniel Walker <dwalker@mvista.com> wrote:

> Modifies the way clocks are switched to in the timekeeping code. The 
> original code would constantly monitor the clocksource list checking 
> for newly added clocksources. I modified this by using atomic types to 
> signal when a new clock is added. This allows the operation to be used 
> only when it's needed.

I see little difference between your and John's code: both poll 
something - you poll an atomic "did a new clocksource arrive" flag in 
the timer interrupt, John takes the clocksource_lock spinlock and checks 
a "did a new clocksource arrive" variable. Both are global atomic 
variables in essence.

what i'd see as a real cleanup here would be to get away from this 'poll 
whether there's any clocksource update' model, and to just ensure that a 
running timer irq will always see the latest clocksource. I.e. to run 
the change_clocksource() logic (and the following updates) when a new 
clock source is selected - not when the next timer interrupt runs. That 
would propagate all effects of a new clock source immediately.

	Ingo

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

* Re: [PATCH 12/23] clocksource: add clocksource_get_clock()
  2007-01-31  3:37 ` [PATCH 12/23] clocksource: add clocksource_get_clock() Daniel Walker
@ 2007-01-31 11:46   ` Ingo Molnar
  2007-01-31 16:40     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 11:46 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> One new API call clocksource_get_clock() which allows clocks to be 
> selected based on their name, or if the name is null the highest rated 
> clock is returned.

this one (and the dependent APIs utilizations) look a step in the right 
direction to me, but they are not fully consequent and thus a bit 
confusing at the moment:

- the current_clocksource is now something that is conceptually related 
  to timekeeping - while it still resides in the clocksource domain.

- if we do this split there should be a separate sysfs hierarchy for 
  timekeeping, separate of clocksource

- you use struct sys_device clocksource_sys_device from clocksource.c in 
  timekeeping.c, which is inconsistent as well.

so these bits need more work.

	Ingo

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

* Re: [PATCH 13/23] timekeeping: move sysfs layer/drop API calls
  2007-01-31  3:37 ` [PATCH 13/23] timekeeping: move sysfs layer/drop API calls Daniel Walker
@ 2007-01-31 11:49   ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 11:49 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul


* Daniel Walker <dwalker@mvista.com> wrote:

> This moves the timekeeping sysfs override layer into timekeeping.c and 
> removes the get_next_clocksource and select_clocksource functions, and 
> their component variables, since they are no longer used.

please do these two changes in at least two separate phases. Like for 
the timer.c code movement i'd not do the big code shuffling just now, 
and even if it's done, it should be a /pure/ movement, with all 
preparatory and post changes done in separate patches. That way the 
individual changes are much more reviewable.

	Ingo

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

* Re: [PATCH 14/23] clocksource: increase initcall priority
  2007-01-31  3:37 ` [PATCH 14/23] clocksource: increase initcall priority Daniel Walker
@ 2007-01-31 11:50   ` Ingo Molnar
  2007-01-31 16:42     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 11:50 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> -module_init(init_acpi_pm_clocksource);
> +/*
> + * This clocksource is removed from the clocksource_initcall
> + * macro since it's mandatory for it to be in fs_initcall as the
> + * highest initcall level, or else it doesn't work properly with
> + * it's PCI fix ups.
> + */
> +fs_initcall(init_acpi_pm_clocksource);

ugh - this bit looks quite interesting.

what's the purpose of this patch? Switching to high-res timers should be 
done late in the bootup - in case there's a problem it's more 
debuggable, etc.

	Ingo

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

* Re: [PATCH 16/23] clocksource: arm update for new flags
  2007-01-31  3:37 ` [PATCH 16/23] clocksource: arm update for " Daniel Walker
@ 2007-01-31 12:27   ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 12:27 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> Update ARM for new flags.
> 
> Signed-Off-By: Daniel Walker <dwalker@mvista.com>

> -	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,

see my general objection to this change (under the [PATCH 22/23] 
subject), but even looking at the pure patch note that it does the flag 
update incorrectly and in a bisect-boot-unfriendly way: the queue at 
this point changes kernel functionality and has side-effects. The right 
way to do flags updates is to first introduce them, then change things 
over.

	Ingo

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

* Re: [PATCH 23/23] clocksource tsc: add verify routine
  2007-01-31  3:37 ` [PATCH 23/23] clocksource tsc: add verify routine Daniel Walker
@ 2007-01-31 12:43   ` Ingo Molnar
  2007-01-31 17:02     ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 12:43 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> I've included this as another user of the clocksource interface. I 
> don't see a usage for this across all achitectures. So a fully generic 
> version isn't needed.

well, this implementation is buggy in at least two ways:

firstly, it allows a circular verification dependency in highres+dyntick 
mode between the jiffies and tsc clocksources.

secondly, verification is not done while the system is booting up:

>  static void verify_tsc_freq(unsigned long unused)
>  {

[...]
> +	if (unlikely(system_state != SYSTEM_RUNNING))
> +		goto out_timer;

so we should just go with Thomas' patch:

  clocksource-add-verification-watchdog-helper.patch

which has been based on and tested on actual systems affected by these 
problems.

	Ingo

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

* Re: [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch
  2007-01-31  3:37 ` [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch Daniel Walker
@ 2007-01-31 12:47   ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 12:47 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, tglx


* Daniel Walker <dwalker@mvista.com> wrote:

> Drop.

i'm summarily replying to your 4 'Drop' patches: what you didnt explain 
is /why/ you dropped these patches. I.e. why you think they are bad and 
how you think your solution is better. Without doing such analysis you 
shouldnt just be dropping patches of others like this.

	Ingo

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

* Re: [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c
  2007-01-31  8:59   ` Ingo Molnar
@ 2007-01-31 15:05     ` Daniel Walker
  0 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 15:05 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 09:59 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > Move the generic timekeeping code from kernel/timer.c to 
> > kernel/time/timekeeping.c. [...]
> 
> please lets not do this just yet. While i have no problems with the 
> change in theory, the time code is in high flux and it's easier to keep 
> things sorted if we dont do big code movements. It also makes it harder 
> to review things and it acts as a hard merge barrier. We usually do such 
> move chunks of code in 'quiet periods', and now is definitely not such a 
> period. It's also pretty easy to do.

I'm not opposed to waiting .. I do think this needs to go in eventually
tho .. This is a clean up that John requested, and I only added it
because I was making other changes to timekeeping.. So it's really his
call .

Daniel


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

* Re: [PATCH 07/23] clocksource: rating sorted list
  2007-01-31  9:34   ` Ingo Molnar
@ 2007-01-31 15:07     ` Daniel Walker
  0 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 15:07 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 10:34 +0100, Ingo Molnar wrote:

> a rating change can occur due to other things as well, not only due to 
> 'tsc unstable' events. So keeping an API around that changes the rating 
> (and propagates all related changes), makes more sense to me.
> 
> also, a pure function call is the most natural (and most flexible) API, 
> for a centrally registered resource like a clock source driver. And a 
> rating change should imply a reselect too, obviously. That way we 
> replace 2 lines with 1 line - that's a real API improvement and a real 
> cleanup patch.
> 
> and that's precisely what Thomas' patch in -mm that your queue undoes 
> implements. (see: simplify-the-registration-of-clocksources.patch in 
> -mm) Have you considered Thomas' change when you dropped it?

My patch set makes clocksource ratings constant (when fully applied).
That particular function is dropped all together .

Daniel


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

* Re: [PATCH 08/23] clocksource: drop duplicate register checking
  2007-01-31  9:59   ` Ingo Molnar
@ 2007-01-31 15:13     ` Daniel Walker
  2007-01-31 17:19       ` Ingo Molnar
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 15:13 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 10:59 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > This is something Thomas already dropped, [...]
> 
> (i think you forgot to Cc: Thomas here, nor is this something that 
> Thomas' change dropped.)

Yes your right .

> > [...] and I'm just sticking with that .. If you register your 
> > clocksource _twice_ your kernel will likely not work correctly (and 
> > might crash).
> 
> this is a quite bad change. John's original clocksource code protects 
> against double registry:
> 
>          if (is_registered_source(c)) {
>                  printk("register_clocksource: Cannot register %s. "
>                         "Already registered!", c->name);
>                  ret = -EBUSY;
> 
> and Thomas' change keeps that property, but doesnt printk. Your change 
> makes double registry possible, potentially crashing the kernel later 
> on! (And this isnt theoretical, double registry did happen in practice 
> when i debugged suspend problems on my SMP laptop.)

My original patch set makes the duplicate register checking better
(which I dropped) .. I'll be happy to reintroduce that part of it..

Daniel


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

* Re: [PATCH 09/23] clocksource: add block notifier
  2007-01-31 10:17   ` Ingo Molnar
@ 2007-01-31 15:25     ` Daniel Walker
  2007-01-31 17:22       ` Ingo Molnar
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 15:25 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 11:17 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > Adds a call back interface for register/rating change events. This is 
> > also used later in this series to signal other interesting events.
> 
> This patch adds:
> 
> > +#define CLOCKSOURCE_NOTIFY_REGISTER	1
> > +#define CLOCKSOURCE_NOTIFY_RATING	2
> > +#define CLOCKSOURCE_NOTIFY_FREQ		4
> 
> and a later patch adds:
> 
> > +#define CLOCKSOURCE_NOTIFY_UNSTABLE	8
> 
> while i tentatively agree with the introduction of clocksource driver 
> notifications in general (given any actual real users of that 
> infrastructure), i can see three problems with your notifier changes:
> 
> firstly, with the full changes applied, CLOCKSOURCE_NOTIFY_RATING is 
> totally unused (and not even driven by the core clocksource code).

True, ratings are constant so the notification never happens (and never
needs to)

> secondly, CLOCKSOURCE_NOTIFY_REGISTER is only used by the core 
> clocksource code and no register-notifier interface is exposed: this 
> makes the whole thing an expensive NOP.

I don't know what you mean when you say "no register-notifier interface
is exposed" .. The timekeeping code doesn't use this notification , but
it really should. It's not that big of an issue since we don't have many
clocks in modules.. 

> thirdly, CLOCKSOURCE_NOTIFY_FREQ is totally unused as well.

Indeed . Consider it dropped.

> (there are tons of examples in the kernel of how to do driver 
> notification APIs properly.)

Are you referring to the comments above , or something else your seeing
in the code?

Daniel


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

* Re: [PATCH 10/23] clocksource: remove update_callback
  2007-01-31 10:46   ` Ingo Molnar
@ 2007-01-31 15:42     ` Daniel Walker
  2007-01-31 17:18       ` Ingo Molnar
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 15:42 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 11:46 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > Uses the block notifier to replace the functionality of 
> > update_callback(). update_callback() was a special case specifically 
> > for the tsc, but including it in the clocksource structure duplicated 
> > it needlessly for other clocks.
> 
> Firstly, it think it should be mentioned that Thomas' queue already does 
> this, in clocksource-remove-the-update-callback.patch (hence he should 
> have been Cc:-ed). Your queue 'drops' Thomas' patch then redoes it here 
> without mentioning that this is another version of what is in Thomas's 
> queue. So we get this situation:
> 
>    clocksource-remove-the-update-callback.patch
>    drop-clocksource-remove-the-update-callback.patch
>    clocksource_remove_update_callback.patch
> 
> that all flip-flops the same thing.

To be clear this change has exists for a very long time, long before
Thomas implemented it .. 

> Secondly, your patch seems to do other changes as well:
> 
> > @@ -179,6 +172,7 @@ int recalibrate_cpu_khz(void)
> >  	if (cpu_has_tsc) {
> >  		cpu_khz = calculate_cpu_khz();
> >  		tsc_khz = cpu_khz;
> > +		mark_tsc_unstable();
> >  		cpu_data[0].loops_per_jiffy =
> >  			cpufreq_scale(cpu_data[0].loops_per_jiffy,
> >  					cpu_khz_old, cpu_khz);
> 
> this adds a new event to a place that didnt have it before. (If this is 
> fixing up an initialization artifact then that needs a comment at 
> least.)

Alright .. Later on I talk about clock frequency recalculation which
pertains to this change .. 

> plus:
> 
> >  struct clocksource *clock = &clocksource_jiffies;
> > +atomic_t clock_recalc_interval = ATOMIC_INIT(0);
> 
> is not mentioned in the changelog. It's also needlessly global. 
> Furthermore, it seems to be a rather unclean method of passing 
> information from clocksource_callback() into change_clocksource():

It's a bisect artifact .. It's eventually dropped in a latter patch .

> > @@ -176,8 +177,9 @@ static int change_clocksource(void)
> >  		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
> >  		       clock->name);
> >  		return 1;
> > -	} else if (clock->update_callback) {
> > -		return clock->update_callback();
> > +	} else if (unlikely(atomic_read(&clock_recalc_interval))) {
> > +		atomic_set(&clock_recalc_interval, 0);
> > +		return 1;
> 
> that's quite bad: you lost an information passing facility by going to a 
> notifier, and you try to work it around via a global atomic variable. 
> Which also looks quite racy as well.
> 
> The clean solution is i think what Thomas did: he calls straight into 
> clocksource_change_rating(). And look at Thomas' patch:

The information passing was purposefully dropped .. It was used (in
part) to recalculate the frequency of a clock , but after discussing it
with John he suggested we drop the frequency recalculation entirely. So
the information passing should no longer be needed.

Daniel


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

* Re: [PATCH 11/23] clocksource: atomic signals
  2007-01-31 11:07   ` Ingo Molnar
@ 2007-01-31 15:59     ` Daniel Walker
  2007-01-31 17:15       ` Ingo Molnar
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 15:59 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 12:07 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > Modifies the way clocks are switched to in the timekeeping code. The 
> > original code would constantly monitor the clocksource list checking 
> > for newly added clocksources. I modified this by using atomic types to 
> > signal when a new clock is added. This allows the operation to be used 
> > only when it's needed.
> 
> I see little difference between your and John's code: both poll 
> something - you poll an atomic "did a new clocksource arrive" flag in 
> the timer interrupt, John takes the clocksource_lock spinlock and checks 
> a "did a new clocksource arrive" variable. Both are global atomic 
> variables in essence.

The original version has more operations on every timer interrupt. Also
changing the spinlock to an atomic eliminates the possibility of
contention in the timer interrupt ..

> what i'd see as a real cleanup here would be to get away from this 'poll 
> whether there's any clocksource update' model, and to just ensure that a 
> running timer irq will always see the latest clocksource. I.e. to run 
> the change_clocksource() logic (and the following updates) when a new 
> clock source is selected - not when the next timer interrupt runs. That 
> would propagate all effects of a new clock source immediately.

You could reduce the code in the interrupt handler (which is good), but
I think you'll end up with a polling model regardless.. If you add some
locking between the interrupt handler and something else you may as well
add the run time of that new critical section to the timer latency . So
I'm not sure it would be a outright win ..

Daniel


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

* Re: [PATCH 12/23] clocksource: add clocksource_get_clock()
  2007-01-31 11:46   ` Ingo Molnar
@ 2007-01-31 16:40     ` Daniel Walker
  0 siblings, 0 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 16:40 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 12:46 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > One new API call clocksource_get_clock() which allows clocks to be 
> > selected based on their name, or if the name is null the highest rated 
> > clock is returned.
> 
> this one (and the dependent APIs utilizations) look a step in the right 
> direction to me, but they are not fully consequent and thus a bit 
> confusing at the moment:
> 
> - the current_clocksource is now something that is conceptually related 
>   to timekeeping - while it still resides in the clocksource domain.

Yes . The sysfs code gets moved in the next patch so it resides in the
timekeeping code .. 

> - if we do this split there should be a separate sysfs hierarchy for 
>   timekeeping, separate of clocksource

A long time ago I changed "current_clocksource" to
"timekeeping_clocksource" which made sense at the time .. I got push
back on that from John, and I think maybe Thomas ..


> - you use struct sys_device clocksource_sys_device from clocksource.c in 
>   timekeeping.c, which is inconsistent as well.
> 

This was on purpose , because I feel the sysfs organization benefits
when you have the clocksource users all in one place. Along with the
list of available clocksources .. I'm all ears if you have a better
suggestion ..

Daniel


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

* Re: [PATCH 14/23] clocksource: increase initcall priority
  2007-01-31 11:50   ` Ingo Molnar
@ 2007-01-31 16:42     ` Daniel Walker
  2007-01-31 17:10       ` Ingo Molnar
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 16:42 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 12:50 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > -module_init(init_acpi_pm_clocksource);
> > +/*
> > + * This clocksource is removed from the clocksource_initcall
> > + * macro since it's mandatory for it to be in fs_initcall as the
> > + * highest initcall level, or else it doesn't work properly with
> > + * it's PCI fix ups.
> > + */
> > +fs_initcall(init_acpi_pm_clocksource);
> 
> ugh - this bit looks quite interesting.
> 
> what's the purpose of this patch? Switching to high-res timers should be 
> done late in the bootup - in case there's a problem it's more 
> debuggable, etc.

The timekeeping code, and hrt/dynamic tick both wait till after boot up
to switch to high res mode ..

The specific code block you commented on above was added cause acpi_pm
has special pci fixups that don't function properly earlier in boot up.
So it can't be arbitrarily raised to order in the initcall sequence ..

Daniel



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

* Re: [PATCH 23/23] clocksource tsc: add verify routine
  2007-01-31 12:43   ` Ingo Molnar
@ 2007-01-31 17:02     ` Daniel Walker
  2007-01-31 17:22       ` Thomas Gleixner
  2007-01-31 17:33       ` Ingo Molnar
  0 siblings, 2 replies; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 17:02 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 13:43 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > I've included this as another user of the clocksource interface. I 
> > don't see a usage for this across all achitectures. So a fully generic 
> > version isn't needed.
> 
> well, this implementation is buggy in at least two ways:
> 
> firstly, it allows a circular verification dependency in highres+dyntick 
> mode between the jiffies and tsc clocksources.

In the current implementation, it's only happens if the only clocks that
exist are "tsc" and "jiffies" which makes verification impossible
anyway .. It's unlikely, but it is possible , the fix is not that
complex.

> secondly, verification is not done while the system is booting up:

Do you know that this is needed ? The current implementation
(clocksource watchdog) doesn't fully settle until after
device_initcall() .. So boot-up is about 99% complete ..

It's trivial to make my version do verification during most of
device_initcall() ..

Daniel


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

* Re: [PATCH 14/23] clocksource: increase initcall priority
  2007-01-31 16:42     ` Daniel Walker
@ 2007-01-31 17:10       ` Ingo Molnar
  2007-01-31 17:20         ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 17:10 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> On Wed, 2007-01-31 at 12:50 +0100, Ingo Molnar wrote:
> > * Daniel Walker <dwalker@mvista.com> wrote:
> > 
> > > -module_init(init_acpi_pm_clocksource);
> > > +/*
> > > + * This clocksource is removed from the clocksource_initcall
> > > + * macro since it's mandatory for it to be in fs_initcall as the
> > > + * highest initcall level, or else it doesn't work properly with
> > > + * it's PCI fix ups.
> > > + */
> > > +fs_initcall(init_acpi_pm_clocksource);
> > 
> > ugh - this bit looks quite interesting.
> > 
> > what's the purpose of this patch? Switching to high-res timers 
> > should be done late in the bootup - in case there's a problem it's 
> > more debuggable, etc.
> 
> The timekeeping code, and hrt/dynamic tick both wait till after boot 
> up to switch to high res mode ..

again, let me repeat the question: what's the purpose of this (whole!) 
patch. Not just of this chunk - the whole patch. You change around 
initcall levels - why? It makes no sense to me. The explanation in the 
patch header makes no sense to me.

Please if possible try to build clear arguments: first outlining "this 
is how it worked before: <X>", then outlining "this is how it will work 
after my change: <Y>", and then maybe a small blurb about "Y is better 
than X, because: <Z>". That X, Y, Z analysis is what is needed to accept 
a patch.

> The specific code block you commented on above was added cause acpi_pm 
> has special pci fixups that don't function properly earlier in boot 
> up. So it can't be arbitrarily raised to order in the initcall 
> sequence ..

i think you misunderstood my comment. In the chunk above you used 
fs_initcall() initcall instead of clocksource_initcall(). (Which is 
funny even ignoring the bad hack that clocksource_initcall is defined to 
fs_initcall.)

	Ingo

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

* Re: [PATCH 11/23] clocksource: atomic signals
  2007-01-31 15:59     ` Daniel Walker
@ 2007-01-31 17:15       ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 17:15 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul


* Daniel Walker <dwalker@mvista.com> wrote:

> > I see little difference between your and John's code: both poll 
> > something - you poll an atomic "did a new clocksource arrive" flag 
> > in the timer interrupt, John takes the clocksource_lock spinlock and 
> > checks a "did a new clocksource arrive" variable. Both are global 
> > atomic variables in essence.
> 
> The original version has more operations on every timer interrupt. 
> Also changing the spinlock to an atomic eliminates the possibility of 
> contention in the timer interrupt ..

there is precisely /zero/ contention on the clocksource_lock! It is a 
very short-held lock, and it's only held by the timer interrupt and some 
really rare operations like 'clocksource register' or 'show 
clocksources'.

> > what i'd see as a real cleanup here would be to get away from this 
> > 'poll whether there's any clocksource update' model, and to just 
> > ensure that a running timer irq will always see the latest 
> > clocksource. I.e. to run the change_clocksource() logic (and the 
> > following updates) when a new clock source is selected - not when 
> > the next timer interrupt runs. That would propagate all effects of a 
> > new clock source immediately.
> 
> You could reduce the code in the interrupt handler (which is good), 
> but I think you'll end up with a polling model regardless.. If you add 
> some locking between the interrupt handler and something else you may 
> as well add the run time of that new critical section to the timer 
> latency . So I'm not sure it would be a outright win ..

I think you didnt understand what i said: the point is to /remove/ the 
polling, and to replace it with a natural lock that is held anyway: 
xtime_lock or whatever other exclusion mechanism. Again, there is almost 
/never/ any contention on this lock so there's no 'latency to add'. But 
the polling overhead in every timer irq, even if it's just a single 
atomic flag, does add up in every timer tick.

you also didnt seem to understand my other point:

> > I.e. to run the change_clocksource() logic (and the following 
> > updates) when a new clock source is selected - not when the next 
> > timer interrupt runs. That would propagate all effects of a new 
> > clock source immediately.

that is actually more important from a design cleanliness POV than the 
basic avoidance of some polling overhead.

	Ingo

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

* Re: [PATCH 10/23] clocksource: remove update_callback
  2007-01-31 15:42     ` Daniel Walker
@ 2007-01-31 17:18       ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 17:18 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> On Wed, 2007-01-31 at 11:46 +0100, Ingo Molnar wrote:
> > * Daniel Walker <dwalker@mvista.com> wrote:
> > 
> > > Uses the block notifier to replace the functionality of 
> > > update_callback(). update_callback() was a special case specifically 
> > > for the tsc, but including it in the clocksource structure duplicated 
> > > it needlessly for other clocks.
> > 
> > Firstly, it think it should be mentioned that Thomas' queue already 
> > does this, in clocksource-remove-the-update-callback.patch (hence he 
> > should have been Cc:-ed). Your queue 'drops' Thomas' patch then 
> > redoes it here without mentioning that this is another version of 
> > what is in Thomas's queue. So we get this situation:
> > 
> >    clocksource-remove-the-update-callback.patch
> >    drop-clocksource-remove-the-update-callback.patch
> >    clocksource_remove_update_callback.patch
> > 
> > that all flip-flops the same thing.
> 
> To be clear this change has exists for a very long time, long before 
> Thomas implemented it ..

it doesnt matter who invented the wheel first, what matters is a clean 
channel of communication so that we end up with the best code - and 
leaving out Cc:s doesnt really help that.

	Ingo

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

* Re: [PATCH 08/23] clocksource: drop duplicate register checking
  2007-01-31 15:13     ` Daniel Walker
@ 2007-01-31 17:19       ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 17:19 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> >          if (is_registered_source(c)) {
> >                  printk("register_clocksource: Cannot register %s. "
> >                         "Already registered!", c->name);
> >                  ret = -EBUSY;
> > 
> > and Thomas' change keeps that property, but doesnt printk. Your 
> > change makes double registry possible, potentially crashing the 
> > kernel later on! (And this isnt theoretical, double registry did 
> > happen in practice when i debugged suspend problems on my SMP 
> > laptop.)
> 
> My original patch set makes the duplicate register checking better 
> (which I dropped) .. I'll be happy to reintroduce that part of it..

why if Thomas' patch: simplify-the-registration-of-clocksources.patch 
already does it?

	Ingo

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

* Re: [PATCH 14/23] clocksource: increase initcall priority
  2007-01-31 17:10       ` Ingo Molnar
@ 2007-01-31 17:20         ` Daniel Walker
  2007-01-31 17:29           ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 17:20 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner

On Wed, 2007-01-31 at 18:10 +0100, Ingo Molnar wrote:
> * Daniel Walker <dwalker@mvista.com> wrote:
> 
> > On Wed, 2007-01-31 at 12:50 +0100, Ingo Molnar wrote:
> > > * Daniel Walker <dwalker@mvista.com> wrote:
> > > 
> > > > -module_init(init_acpi_pm_clocksource);
> > > > +/*
> > > > + * This clocksource is removed from the clocksource_initcall
> > > > + * macro since it's mandatory for it to be in fs_initcall as the
> > > > + * highest initcall level, or else it doesn't work properly with
> > > > + * it's PCI fix ups.
> > > > + */
> > > > +fs_initcall(init_acpi_pm_clocksource);
> > > 
> > > ugh - this bit looks quite interesting.
> > > 
> > > what's the purpose of this patch? Switching to high-res timers 
> > > should be done late in the bootup - in case there's a problem it's 
> > > more debuggable, etc.
> > 
> > The timekeeping code, and hrt/dynamic tick both wait till after boot 
> > up to switch to high res mode ..
> 
> again, let me repeat the question: what's the purpose of this (whole!) 
> patch. Not just of this chunk - the whole patch. You change around 
> initcall levels - why? It makes no sense to me. The explanation in the 
> patch header makes no sense to me.
> 
> Please if possible try to build clear arguments: first outlining "this 
> is how it worked before: <X>", then outlining "this is how it will work 
> after my change: <Y>", and then maybe a small blurb about "Y is better 
> than X, because: <Z>". That X, Y, Z analysis is what is needed to accept 
> a patch.

I don't know that I could explain it better than what's in the patch
header .. I'll think about it.

> > The specific code block you commented on above was added cause acpi_pm 
> > has special pci fixups that don't function properly earlier in boot 
> > up. So it can't be arbitrarily raised to order in the initcall 
> > sequence ..
> 
> i think you misunderstood my comment. In the chunk above you used 
> fs_initcall() initcall instead of clocksource_initcall(). (Which is 
> funny even ignoring the bad hack that clocksource_initcall is defined to 
> fs_initcall.)

The purpose of clocksource_initcall is so the initcall can be increased
without changing all the individual clocksources .. So I have to
disconnect that from the acpi_pm because it can't tolerate it.

Daniel


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

* Re: [PATCH 09/23] clocksource: add block notifier
  2007-01-31 15:25     ` Daniel Walker
@ 2007-01-31 17:22       ` Ingo Molnar
  0 siblings, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 17:22 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> > secondly, CLOCKSOURCE_NOTIFY_REGISTER is only used by the core 
> > clocksource code and no register-notifier interface is exposed: this 
> > makes the whole thing an expensive NOP.
> 
> I don't know what you mean when you say "no register-notifier 
> interface is exposed" .. The timekeeping code doesn't use this 
> notification , but it really should. [...]

what i say is that there's no public interface exposed of this notifier
(and even if there was, there isnt any user of it) and there's only a
single notifier used internally: this means that this thing is an
expensive function call.

	Ingo

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

* Re: [PATCH 23/23] clocksource tsc: add verify routine
  2007-01-31 17:02     ` Daniel Walker
@ 2007-01-31 17:22       ` Thomas Gleixner
  2007-01-31 17:33       ` Ingo Molnar
  1 sibling, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2007-01-31 17:22 UTC (permalink / raw)
  To: Daniel Walker; +Cc: Ingo Molnar, akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 09:02 -0800, Daniel Walker wrote:
> > well, this implementation is buggy in at least two ways:
> > 
> > firstly, it allows a circular verification dependency in highres+dyntick 
> > mode between the jiffies and tsc clocksources.
> 
> In the current implementation, it's only happens if the only clocks that
> exist are "tsc" and "jiffies" which makes verification impossible
> anyway .. It's unlikely, but it is possible , the fix is not that
> complex.

Wrong. You actually can verify against jiffies. Johns orginal code did
this and mine does too. Actually this _IS_ necessary otherwise you can
not detect that the BIOS changed the cpu freqeuncy behind the kernels
back. 

The circular problem is only relevant when you switch to highres/nohz.

	tglx



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

* Re: [PATCH 14/23] clocksource: increase initcall priority
  2007-01-31 17:20         ` Daniel Walker
@ 2007-01-31 17:29           ` Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2007-01-31 17:29 UTC (permalink / raw)
  To: Daniel Walker; +Cc: Ingo Molnar, akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 09:20 -0800, Daniel Walker wrote:
> The purpose of clocksource_initcall is so the initcall can be increased
> without changing all the individual clocksources .. So I have to
> disconnect that from the acpi_pm because it can't tolerate it.

Each clocksource has to decide on its own, when the registration is
done. ARM clocksources register in the timer init, pm timer needs to
wait. 

So what exactly is solved by an extra initcall ?

	tglx



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

* Re: [PATCH 23/23] clocksource tsc: add verify routine
  2007-01-31 17:02     ` Daniel Walker
  2007-01-31 17:22       ` Thomas Gleixner
@ 2007-01-31 17:33       ` Ingo Molnar
  1 sibling, 0 replies; 57+ messages in thread
From: Ingo Molnar @ 2007-01-31 17:33 UTC (permalink / raw)
  To: Daniel Walker; +Cc: akpm, linux-kernel, johnstul, Thomas Gleixner


* Daniel Walker <dwalker@mvista.com> wrote:

> > firstly, it allows a circular verification dependency in 
> > highres+dyntick mode between the jiffies and tsc clocksources.
> 
> In the current implementation, it's only happens if the only clocks 
> that exist are "tsc" and "jiffies" which makes verification impossible 
> anyway .. It's unlikely, but it is possible , the fix is not that 
> complex.

yes, the fix is not that complex and it already exists: Thomas' 
clocksource-add-verification-watchdog-helper.patch. You said before that 
Thomas' code was unnecessarily generic, but your version contained at 
least one bug, despite having had review feedback about precisely that 
issue.

	Ingo

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

* Re: [PATCH 22/23] clocksource: new clock lookup method
       [not found]         ` <1170265169.9781.145.camel@imap.mvista.com>
@ 2007-01-31 17:55           ` Thomas Gleixner
  2007-01-31 18:07             ` Daniel Walker
  0 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2007-01-31 17:55 UTC (permalink / raw)
  To: Daniel Walker; +Cc: Ingo Molnar, akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 09:39 -0800, Daniel Walker wrote:
> > please read my reply above! To repeat: such flags tend to get forgotten, 
> > resulting in a less safe default behavior. Clock hardware and thus 
> > clocksources are fundamentally fragile so we want to default to the 
> > safest behavior. I.e. if the IS_CONTINOUS flag is 'forgotten', the clock 
> > wont be usable as a clock verification base for example. The flag has to 
> > be affirmatively set to mark the clocksource continous.
> 
> I don't see this as an issue .. Your assuming that not continuous clocks
> will be prevalent which they aren't ..

And how does this change Ingo's statement ? Such beasts exist and having
them default to the safe side is good. 

Also I really do not see the "huge burden" for a clocksource coder to
add this flag. If he forgets it, then he can not use highres / dynticks
and nothing breaks.

	tglx







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

* Re: [PATCH 22/23] clocksource: new clock lookup method
  2007-01-31 17:55           ` Thomas Gleixner
@ 2007-01-31 18:07             ` Daniel Walker
  2007-01-31 21:09               ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: Daniel Walker @ 2007-01-31 18:07 UTC (permalink / raw)
  To: tglx; +Cc: Ingo Molnar, akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 18:55 +0100, Thomas Gleixner wrote:
> On Wed, 2007-01-31 at 09:39 -0800, Daniel Walker wrote:
> > > please read my reply above! To repeat: such flags tend to get forgotten, 
> > > resulting in a less safe default behavior. Clock hardware and thus 
> > > clocksources are fundamentally fragile so we want to default to the 
> > > safest behavior. I.e. if the IS_CONTINOUS flag is 'forgotten', the clock 
> > > wont be usable as a clock verification base for example. The flag has to 
> > > be affirmatively set to mark the clocksource continous.
> > 
> > I don't see this as an issue .. Your assuming that not continuous clocks
> > will be prevalent which they aren't ..
> 
> And how does this change Ingo's statement ? Such beasts exist and having
> them default to the safe side is good. 
> 
> Also I really do not see the "huge burden" for a clocksource coder to
> add this flag. If he forgets it, then he can not use highres / dynticks
> and nothing breaks.

We're not talking about a rare system runtime configuration . If that
were the case I would agree safe is better..

I'm assuming that programmers will test their code, and others will
review the code .. Catering to any other situation doesn't make sense to
me. On top of that those clocks are rare, and not desirable ..

Daniel


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

* Re: [PATCH 22/23] clocksource: new clock lookup method
  2007-01-31 18:07             ` Daniel Walker
@ 2007-01-31 21:09               ` Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2007-01-31 21:09 UTC (permalink / raw)
  To: Daniel Walker; +Cc: Ingo Molnar, akpm, linux-kernel, johnstul

On Wed, 2007-01-31 at 10:07 -0800, Daniel Walker wrote:
> I'm assuming that programmers will test their code, and others will
> review the code .. Catering to any other situation doesn't make sense to
> me. On top of that those clocks are rare, and not desirable ..

So what are you arguing about burden ? It is a property of the
clocksource, that it is continuous, and not the other way round. It does
not matter how rare or desirable devices are.

What about the other bunch of useless defines:

+#define CLOCKSOURCE_NOT_ATOMIC         4
+#define CLOCKSOURCE_UNDER_32BITS       8
+#define CLOCKSOURCE_64BITS             16

Are those just for fun or are you actually putting the burden to get
them straight on the poor overworked clocksource developer ?

Also please define bit values as hexadecimal constants and not as
integers.

	tglx



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

end of thread, other threads:[~2007-01-31 21:08 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-31  3:37 [PATCH 00/23] clocksource update v12 Daniel Walker
2007-01-31  3:37 ` [PATCH 01/23] clocksource: drop clocksource-add-verification-watchdog-helper-fix.patch Daniel Walker
2007-01-31 12:47   ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 02/23] clocksource: drop clocksource-add-verification-watchdog-helper.patch Daniel Walker
2007-01-31  3:37 ` [PATCH 03/23] clocksource: drop clocksource-remove-the-update-callback.patch Daniel Walker
2007-01-31  3:37 ` [PATCH 04/23] clocksource: drop time-x86_64-tsc-fixup-clocksource-changes.patch Daniel Walker
2007-01-31  3:37 ` [PATCH 05/23] clocksource: drop simplify-the-registration-of-clocksources.patch Daniel Walker
2007-01-31  3:37 ` [PATCH 06/23] timekeeping: create kernel/time/timekeeping.c Daniel Walker
2007-01-31  8:59   ` Ingo Molnar
2007-01-31 15:05     ` Daniel Walker
2007-01-31  3:37 ` [PATCH 07/23] clocksource: rating sorted list Daniel Walker
2007-01-31  9:34   ` Ingo Molnar
2007-01-31 15:07     ` Daniel Walker
2007-01-31  3:37 ` [PATCH 08/23] clocksource: drop duplicate register checking Daniel Walker
2007-01-31  9:59   ` Ingo Molnar
2007-01-31 15:13     ` Daniel Walker
2007-01-31 17:19       ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 09/23] clocksource: add block notifier Daniel Walker
2007-01-31 10:17   ` Ingo Molnar
2007-01-31 15:25     ` Daniel Walker
2007-01-31 17:22       ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 10/23] clocksource: remove update_callback Daniel Walker
2007-01-31 10:46   ` Ingo Molnar
2007-01-31 15:42     ` Daniel Walker
2007-01-31 17:18       ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 11/23] clocksource: atomic signals Daniel Walker
2007-01-31 11:07   ` Ingo Molnar
2007-01-31 15:59     ` Daniel Walker
2007-01-31 17:15       ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 12/23] clocksource: add clocksource_get_clock() Daniel Walker
2007-01-31 11:46   ` Ingo Molnar
2007-01-31 16:40     ` Daniel Walker
2007-01-31  3:37 ` [PATCH 13/23] timekeeping: move sysfs layer/drop API calls Daniel Walker
2007-01-31 11:49   ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 14/23] clocksource: increase initcall priority Daniel Walker
2007-01-31 11:50   ` Ingo Molnar
2007-01-31 16:42     ` Daniel Walker
2007-01-31 17:10       ` Ingo Molnar
2007-01-31 17:20         ` Daniel Walker
2007-01-31 17:29           ` Thomas Gleixner
2007-01-31  3:37 ` [PATCH 15/23] clocksource: add new flags Daniel Walker
2007-01-31  3:37 ` [PATCH 16/23] clocksource: arm update for " Daniel Walker
2007-01-31 12:27   ` Ingo Molnar
2007-01-31  3:37 ` [PATCH 17/23] clocksource: avr32 " Daniel Walker
2007-01-31  3:37 ` [PATCH 18/23] clocksource: i386 " Daniel Walker
2007-01-31  3:37 ` [PATCH 19/23] clocksource: mips " Daniel Walker
2007-01-31  3:37 ` [PATCH 20/23] clocksource: x86_64 " Daniel Walker
2007-01-31  3:37 ` [PATCH 21/23] clocksource: drivers/ " Daniel Walker
2007-01-31  3:37 ` [PATCH 22/23] clocksource: new clock lookup method Daniel Walker
     [not found]   ` <20070131122215.GE1847@elte.hu>
     [not found]     ` <1170261439.9781.96.camel@imap.mvista.com>
     [not found]       ` <20070131164918.GA4468@elte.hu>
     [not found]         ` <1170265169.9781.145.camel@imap.mvista.com>
2007-01-31 17:55           ` Thomas Gleixner
2007-01-31 18:07             ` Daniel Walker
2007-01-31 21:09               ` Thomas Gleixner
2007-01-31  3:37 ` [PATCH 23/23] clocksource tsc: add verify routine Daniel Walker
2007-01-31 12:43   ` Ingo Molnar
2007-01-31 17:02     ` Daniel Walker
2007-01-31 17:22       ` Thomas Gleixner
2007-01-31 17:33       ` Ingo Molnar

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.