diff -urp a/init/calibrate.c b/init/calibrate.c --- a/init/calibrate.c 2006-10-02 11:39:32.000000000 -0400 +++ b/init/calibrate.c 2007-01-27 16:39:35.000000000 -0500 @@ -1,5 +1,7 @@ /* calibrate.c: default delay calibration * + * vim:sw=8 noet + * * Excised from init/main.c * Copyright (C) 1991, 1992 Linus Torvalds */ @@ -7,9 +9,36 @@ #include #include #include +#include +#include #include +/* On Macbook we have trouble calibrating the delay loop due to excessive + * latency in the system management interrupt. We fix this problem by + * disabling the "legacy USB" function of the SMC during delay loop + * calibration. From Intel ICH7 manual, this is bit 3 of SMI_EN register + * located at 0x430. + */ +static int __initdata macbook_calibrate_quirk; + +static int __init init_macbook_calibrate_quirk (struct dmi_system_id *d) +{ + printk(KERN_WARNING "%s detected (calibration quirk enabled)\n", + d->ident); + macbook_calibrate_quirk = 1; + return 0; +} + +static struct dmi_system_id __initdata calibrate_quirks[] = { + { + .callback = init_macbook_calibrate_quirk, + .ident = "Apple MacBook", + .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),}, + }, + {}, +}; + static unsigned long preset_lpj; static int __init lpj_setup(char *str) { @@ -37,8 +66,16 @@ static unsigned long __devinit calibrate unsigned long tsc_rate_min, tsc_rate_max; unsigned long good_tsc_sum = 0; unsigned long good_tsc_count = 0; + unsigned long saved_smi_en = 0; int i; + if (macbook_calibrate_quirk) + { + saved_smi_en = inl(0x430); + /* mask out bit 3 */ + outl(saved_smi_en & ~8, 0x430); + } + if (read_current_timer(&pre_start) < 0 ) return 0; @@ -94,6 +131,9 @@ static unsigned long __devinit calibrate } } + if (macbook_calibrate_quirk) + outl(saved_smi_en, 0x430); + if (good_tsc_count) return (good_tsc_sum/good_tsc_count); @@ -117,6 +157,8 @@ void __devinit calibrate_delay(void) unsigned long ticks, loopbit; int lps_precision = LPS_PREC; + dmi_check_system(calibrate_quirks); + if (preset_lpj) { loops_per_jiffy = preset_lpj; printk("Calibrating delay loop (skipped)... "