Commit 8c660065 authored by Dave Johnson's avatar Dave Johnson Committed by Thomas Gleixner

x86: fix more TSC clock source calibration errors

The previous patch wasn't correctly handling the 'count' variable.  If
a CPU gave bad results on the 1st or 2nd run but good results on the
3rd, it wouldn't do the correct thing.  No idea if any such CPU
exists, but the patch below handles that case by discarding the bad
runs.

If a bad result (too quick, or too slow) occurs on any of the 3 runs
it will be discarded.

Also updated some comments to explain what's going on.
Signed-off-by: default avatarDave Johnson <djohnson@sw.starentnetworks.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent edaf420f
...@@ -137,14 +137,13 @@ unsigned long native_calculate_cpu_khz(void) ...@@ -137,14 +137,13 @@ unsigned long native_calculate_cpu_khz(void)
local_irq_save(flags); local_irq_save(flags);
/* run 3 times to ensure the cache is warm */ /* run 3 times to ensure the cache is warm and to get an accurate reading */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
mach_prepare_counter(); mach_prepare_counter();
rdtscll(start); rdtscll(start);
mach_countup(&count); mach_countup(&count);
rdtscll(end); rdtscll(end);
delta64 = min(delta64, (end - start));
}
/* /*
* Error: ECTCNEVERSET * Error: ECTCNEVERSET
* The CTC wasn't reliable: we got a hit on the very first read, * The CTC wasn't reliable: we got a hit on the very first read,
...@@ -152,14 +151,21 @@ unsigned long native_calculate_cpu_khz(void) ...@@ -152,14 +151,21 @@ unsigned long native_calculate_cpu_khz(void)
* 32 bits.. * 32 bits..
*/ */
if (count <= 1) if (count <= 1)
goto err; continue;
/* cpu freq too fast: */
if (delta64 > (1ULL<<32))
goto err;
/* cpu freq too slow: */ /* cpu freq too slow: */
if (delta64 <= CALIBRATE_TIME_MSEC) if ((end - start) <= CALIBRATE_TIME_MSEC)
continue;
/*
* We want the minimum time of all runs in case one of them
* is inaccurate due to SMI or other delay
*/
delta64 = min(delta64, (end - start));
}
/* cpu freq too fast (or every run was bad): */
if (delta64 > (1ULL<<32))
goto err; goto err;
delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */ delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment