summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@digeo.com>2003-03-28 03:19:37 -0800
committerDave Jones <davej@tetrachloride.(none)>2003-03-28 03:19:37 -0800
commit5958cbab6a2cc8a194847f13eb7b6e9eab4512f0 (patch)
tree90132c577158bb136f4be0030400fe7f56248fd3
parent3a2631dacf63ac7e929abeb0a1478f4b700c46ac (diff)
[PATCH] x86 clock override boot option
From: john stultz <johnstul@us.ibm.com> This patch allows one to manually specify the i386 gettimeofday time-source by passing clock=[pit|tsc|cyclone|...] as a boot argument. The argument will override the default probled selection, and in case the selected time-source not be avalible the code defaults to using the PIT (printing a warning saying so).
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--arch/i386/kernel/smpboot.c4
-rw-r--r--arch/i386/kernel/timers/timer.c15
-rw-r--r--arch/i386/kernel/timers/timer_cyclone.c8
-rw-r--r--arch/i386/kernel/timers/timer_none.c3
-rw-r--r--arch/i386/kernel/timers/timer_pit.c6
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c8
-rw-r--r--include/asm-i386/timer.h6
8 files changed, 45 insertions, 11 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1e0b17303ed1..2d87a0293cb5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -207,6 +207,12 @@ running once the system is up.
chandev= [HW,NET] Generic channel device initialisation
+ clock= [BUGS=IA-32, HW] gettimeofday timesource override.
+ Forces specified timesource (if avaliable) to be used
+ when calculating gettimeofday(). If specicified timesource
+ is not avalible, it defaults to PIT.
+ Format: { pit | tsc | cyclone | ... }
+
cm206= [HW,CD]
Format: { auto | [<io>,][<irq>] }
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 803c3fb80911..861c9831b5b1 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -422,7 +422,7 @@ void __init smp_callin(void)
/*
* Synchronize the TSC with the BP
*/
- if (cpu_has_tsc)
+ if (cpu_has_tsc && cpu_khz)
synchronize_tsc_ap();
}
@@ -1114,7 +1114,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
/*
* Synchronize the TSC with the AP
*/
- if (cpu_has_tsc && cpucount)
+ if (cpu_has_tsc && cpucount && cpu_khz)
synchronize_tsc_bp();
}
diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
index c8c2c4f72f0c..fc23421ead74 100644
--- a/arch/i386/kernel/timers/timer.c
+++ b/arch/i386/kernel/timers/timer.c
@@ -1,4 +1,6 @@
+#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <asm/timer.h>
/* list of externed timers */
@@ -17,6 +19,17 @@ static struct timer_opts* timers[] = {
NULL,
};
+static char clock_override[10] __initdata;
+
+static int __init clock_setup(char* str)
+{
+ if (str) {
+ strncpy(clock_override, str,10);
+ clock_override[9] = '\0';
+ }
+ return 1;
+}
+__setup("clock=", clock_setup);
/* iterates through the list of timers, returning the first
* one that initializes successfully.
@@ -28,7 +41,7 @@ struct timer_opts* select_timer(void)
/* find most preferred working timer */
while (timers[i]) {
if (timers[i]->init)
- if (timers[i]->init() == 0)
+ if (timers[i]->init(clock_override) == 0)
return timers[i];
++i;
}
diff --git a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
index a1bac8e00e0f..54a5026487f8 100644
--- a/arch/i386/kernel/timers/timer_cyclone.c
+++ b/arch/i386/kernel/timers/timer_cyclone.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/timex.h>
#include <linux/errno.h>
+#include <linux/string.h>
#include <asm/timer.h>
#include <asm/io.h>
@@ -73,7 +74,7 @@ static unsigned long get_offset_cyclone(void)
return delay_at_last_interrupt + offset;
}
-static int init_cyclone(void)
+static int __init init_cyclone(char* override)
{
u32* reg;
u32 base; /* saved cyclone base address */
@@ -81,8 +82,11 @@ static int init_cyclone(void)
u32 offset; /* offset from pageaddr to cyclone_timer register */
int i;
+ /* check clock override */
+ if (override[0] && strncmp(override,"cyclone",7))
+ return -ENODEV;
+
/*make sure we're on a summit box*/
- /*XXX need to use proper summit hooks! such as xapic -john*/
if(!use_cyclone) return -ENODEV;
printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
diff --git a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c
index 786ac5bc560c..5367a601e1e3 100644
--- a/arch/i386/kernel/timers/timer_none.c
+++ b/arch/i386/kernel/timers/timer_none.c
@@ -1,6 +1,7 @@
+#include <linux/init.h>
#include <asm/timer.h>
-static int init_none(void)
+static int __init init_none(char* override)
{
return 0;
}
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
index 8b9507e70e05..d9c97e5a9744 100644
--- a/arch/i386/kernel/timers/timer_pit.c
+++ b/arch/i386/kernel/timers/timer_pit.c
@@ -17,8 +17,12 @@ extern spinlock_t i8259A_lock;
extern spinlock_t i8253_lock;
#include "do_timer.h"
-static int init_pit(void)
+static int __init init_pit(char* override)
{
+ /* check clock override */
+ if (override[0] && strncmp(override,"pit",3))
+ printk(KERN_ERR "Warning: clock= override failed. Defaulting to PIT\n");
+
return 0;
}
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 264a20f9b96b..8292e481527f 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -8,6 +8,7 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/cpufreq.h>
+#include <linux/string.h>
#include <asm/timer.h>
#include <asm/io.h>
@@ -244,8 +245,13 @@ static struct notifier_block time_cpufreq_notifier_block = {
#endif
-static int init_tsc(void)
+static int __init init_tsc(char* override)
{
+
+ /* check clock override */
+ if (override[0] && strncmp(override,"tsc",3))
+ return -ENODEV;
+
/*
* If we have APM enabled or the CPU clock speed is variable
* (CPU stops clock on HLT or slows clock to save power)
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index 749ee25b8999..2384ec395c9a 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -4,14 +4,14 @@
/**
* struct timer_ops - used to define a timer source
*
- * @init: Probes and initializes the timer. Returns 0 on success, anything
- * else on failure.
+ * @init: Probes and initializes the timer. Takes clock= override
+ * string as an argument. Returns 0 on success, anything else on failure.
* @mark_offset: called by the timer interrupt
* @get_offset: called by gettimeofday(). Returns the number of ms since the
* last timer intruupt.
*/
struct timer_opts{
- int (*init)(void);
+ int (*init)(char *override);
void (*mark_offset)(void);
unsigned long (*get_offset)(void);
void (*delay)(unsigned long);