From: john stultz 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). The new changes in this release are basically better whitespace and __init usage. I'm still tracking an issue between this and the cpu_freq code, so let me know if it doesn't work or if you see anything terminally stupid. Documentation/kernel-parameters.txt | 6 ++++++ arch/i386/kernel/smpboot.c | 4 ++-- arch/i386/kernel/timers/timer.c | 15 ++++++++++++++- arch/i386/kernel/timers/timer_cyclone.c | 8 ++++++-- arch/i386/kernel/timers/timer_none.c | 3 ++- arch/i386/kernel/timers/timer_pit.c | 6 +++++- arch/i386/kernel/timers/timer_tsc.c | 8 +++++++- include/asm-i386/timer.h | 6 +++--- 8 files changed, 45 insertions(+), 11 deletions(-) diff -puN arch/i386/kernel/smpboot.c~x86-clock-override-option arch/i386/kernel/smpboot.c --- 25/arch/i386/kernel/smpboot.c~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/arch/i386/kernel/smpboot.c 2003-03-22 22:14:50.000000000 -0800 @@ -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(unsigne /* * Synchronize the TSC with the AP */ - if (cpu_has_tsc && cpucount) + if (cpu_has_tsc && cpucount && cpu_khz) synchronize_tsc_bp(); } diff -puN arch/i386/kernel/timers/timer.c~x86-clock-override-option arch/i386/kernel/timers/timer.c --- 25/arch/i386/kernel/timers/timer.c~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/arch/i386/kernel/timers/timer.c 2003-03-22 22:14:50.000000000 -0800 @@ -1,4 +1,6 @@ +#include #include +#include #include /* 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 -puN arch/i386/kernel/timers/timer_cyclone.c~x86-clock-override-option arch/i386/kernel/timers/timer_cyclone.c --- 25/arch/i386/kernel/timers/timer_cyclone.c~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/arch/i386/kernel/timers/timer_cyclone.c 2003-03-22 22:14:50.000000000 -0800 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -73,7 +74,7 @@ static unsigned long get_offset_cyclone( 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 -puN arch/i386/kernel/timers/timer_none.c~x86-clock-override-option arch/i386/kernel/timers/timer_none.c --- 25/arch/i386/kernel/timers/timer_none.c~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/arch/i386/kernel/timers/timer_none.c 2003-03-22 22:14:50.000000000 -0800 @@ -1,6 +1,7 @@ +#include #include -static int init_none(void) +static int __init init_none(char* override) { return 0; } diff -puN arch/i386/kernel/timers/timer_pit.c~x86-clock-override-option arch/i386/kernel/timers/timer_pit.c --- 25/arch/i386/kernel/timers/timer_pit.c~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/arch/i386/kernel/timers/timer_pit.c 2003-03-22 22:14:50.000000000 -0800 @@ -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 -puN arch/i386/kernel/timers/timer_tsc.c~x86-clock-override-option arch/i386/kernel/timers/timer_tsc.c --- 25/arch/i386/kernel/timers/timer_tsc.c~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/arch/i386/kernel/timers/timer_tsc.c 2003-03-22 22:14:50.000000000 -0800 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -244,8 +245,13 @@ static struct notifier_block time_cpufre #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 -puN Documentation/kernel-parameters.txt~x86-clock-override-option Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/Documentation/kernel-parameters.txt 2003-03-22 22:14:50.000000000 -0800 @@ -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 | [,][] } diff -puN include/asm-i386/timer.h~x86-clock-override-option include/asm-i386/timer.h --- 25/include/asm-i386/timer.h~x86-clock-override-option 2003-03-22 22:14:50.000000000 -0800 +++ 25-akpm/include/asm-i386/timer.h 2003-03-22 22:14:50.000000000 -0800 @@ -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); _