diff options
| author | Andrew Morton <akpm@digeo.com> | 2003-03-28 03:19:37 -0800 |
|---|---|---|
| committer | Dave Jones <davej@tetrachloride.(none)> | 2003-03-28 03:19:37 -0800 |
| commit | 5958cbab6a2cc8a194847f13eb7b6e9eab4512f0 (patch) | |
| tree | 90132c577158bb136f4be0030400fe7f56248fd3 | |
| parent | 3a2631dacf63ac7e929abeb0a1478f4b700c46ac (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.txt | 6 | ||||
| -rw-r--r-- | arch/i386/kernel/smpboot.c | 4 | ||||
| -rw-r--r-- | arch/i386/kernel/timers/timer.c | 15 | ||||
| -rw-r--r-- | arch/i386/kernel/timers/timer_cyclone.c | 8 | ||||
| -rw-r--r-- | arch/i386/kernel/timers/timer_none.c | 3 | ||||
| -rw-r--r-- | arch/i386/kernel/timers/timer_pit.c | 6 | ||||
| -rw-r--r-- | arch/i386/kernel/timers/timer_tsc.c | 8 | ||||
| -rw-r--r-- | include/asm-i386/timer.h | 6 |
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); |
