From: john stultz Add a blacklist infrastructure to the TSC clocksource as well as an entry for the 380XD Thinkpad. This allows us to manually add systems (mainly older-laptops) where the TSC frequency is changed by the BIOS without any notification to the OS. The justification for using a blacklist instead of trying to detect the problem is because the detectable symptoms are exactly the same as what is observed when interrupts arrive too frequently (a semi-common issue w/ broken PIT hardware), and the number of other older laptops with this issue is likely small. This patch resolves bugme bug #5868. Signed-off-by: John Stultz Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton --- arch/i386/kernel/tsc.c | 35 +++++++++++++++++++++++++++++++---- 1 files changed, 31 insertions(+), 4 deletions(-) diff -puN arch/i386/kernel/tsc.c~x86-blacklist-tsc-from-systems-where-it-is-known-to-be-bad arch/i386/kernel/tsc.c --- devel/arch/i386/kernel/tsc.c~x86-blacklist-tsc-from-systems-where-it-is-known-to-be-bad 2006-02-21 13:35:15.000000000 -0800 +++ devel-akpm/arch/i386/kernel/tsc.c 2006-02-21 13:35:15.000000000 -0800 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -365,6 +366,27 @@ static int tsc_update_callback(void) return change; } +static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d) +{ + printk(KERN_NOTICE "%s detected: marking TSC unstable.\n", + d->ident); + mark_tsc_unstable(); + return 0; +} + +/* List of systems that have known TSC problems */ +static struct dmi_system_id __initdata bad_tsc_dmi_table[] = { + { + .callback = dmi_mark_tsc_unstable, + .ident = "IBM Thinkpad 380XD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), + DMI_MATCH(DMI_BOARD_NAME, "2635FA0"), + }, + }, + {} +}; + /* * Make an educated guess if the TSC is trustworthy and synchronized * over all CPUs. @@ -382,17 +404,22 @@ static __init int unsynchronized_tsc(voi return num_possible_cpus() > 1; } -/* NUMAQ can't use TSC: */ static int __init init_tsc_clocksource(void) { - /* TSC initialization is done in arch/i386/kernel/tsc.c */ + if (cpu_has_tsc && tsc_khz && !tsc_disable) { - if (unsynchronized_tsc()) /* lower rating if unsynced */ + /* check blacklist */ + dmi_check_system(bad_tsc_dmi_table); + + if (unsynchronized_tsc()) /* mark unstable if unsynced */ mark_tsc_unstable(); current_tsc_khz = tsc_khz; clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz, clocksource_tsc.shift); - register_clocksource(&clocksource_tsc); + /* lower the rating if we already know its unstable: */ + if (check_tsc_unstable()) + clocksource_tsc.rating = 50; + return register_clocksource(&clocksource_tsc); } return 0; _