aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/tsc_32.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c
index f04d08a7d022..9ebc0dab66b4 100644
--- a/arch/x86/kernel/tsc_32.c
+++ b/arch/x86/kernel/tsc_32.c
@@ -137,31 +137,37 @@ unsigned long native_calculate_cpu_khz(void)
137 137
138 local_irq_save(flags); 138 local_irq_save(flags);
139 139
140 /* run 3 times to ensure the cache is warm */ 140 /* run 3 times to ensure the cache is warm and to get an accurate reading */
141 for (i = 0; i < 3; i++) { 141 for (i = 0; i < 3; i++) {
142 mach_prepare_counter(); 142 mach_prepare_counter();
143 rdtscll(start); 143 rdtscll(start);
144 mach_countup(&count); 144 mach_countup(&count);
145 rdtscll(end); 145 rdtscll(end);
146
147 /*
148 * Error: ECTCNEVERSET
149 * The CTC wasn't reliable: we got a hit on the very first read,
150 * or the CPU was so fast/slow that the quotient wouldn't fit in
151 * 32 bits..
152 */
153 if (count <= 1)
154 continue;
155
156 /* cpu freq too slow: */
157 if ((end - start) <= CALIBRATE_TIME_MSEC)
158 continue;
159
160 /*
161 * We want the minimum time of all runs in case one of them
162 * is inaccurate due to SMI or other delay
163 */
146 delta64 = min(delta64, (end - start)); 164 delta64 = min(delta64, (end - start));
147 } 165 }
148 /*
149 * Error: ECTCNEVERSET
150 * The CTC wasn't reliable: we got a hit on the very first read,
151 * or the CPU was so fast/slow that the quotient wouldn't fit in
152 * 32 bits..
153 */
154 if (count <= 1)
155 goto err;
156 166
157 /* cpu freq too fast: */ 167 /* cpu freq too fast (or every run was bad): */
158 if (delta64 > (1ULL<<32)) 168 if (delta64 > (1ULL<<32))
159 goto err; 169 goto err;
160 170
161 /* cpu freq too slow: */
162 if (delta64 <= CALIBRATE_TIME_MSEC)
163 goto err;
164
165 delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */ 171 delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */
166 do_div(delta64,CALIBRATE_TIME_MSEC); 172 do_div(delta64,CALIBRATE_TIME_MSEC);
167 173