diff options
Diffstat (limited to 'arch/x86/kernel/tsc.c')
-rw-r--r-- | arch/x86/kernel/tsc.c | 61 |
1 files changed, 51 insertions, 10 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index e169e85db434..fb4302738410 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/geode.h> | 25 | #include <asm/geode.h> |
26 | #include <asm/apic.h> | 26 | #include <asm/apic.h> |
27 | #include <asm/intel-family.h> | 27 | #include <asm/intel-family.h> |
28 | #include <asm/i8259.h> | ||
28 | 29 | ||
29 | unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ | 30 | unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */ |
30 | EXPORT_SYMBOL(cpu_khz); | 31 | EXPORT_SYMBOL(cpu_khz); |
@@ -363,6 +364,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin) | |||
363 | unsigned long tscmin, tscmax; | 364 | unsigned long tscmin, tscmax; |
364 | int pitcnt; | 365 | int pitcnt; |
365 | 366 | ||
367 | if (!has_legacy_pic()) { | ||
368 | /* | ||
369 | * Relies on tsc_early_delay_calibrate() to have given us semi | ||
370 | * usable udelay(), wait for the same 50ms we would have with | ||
371 | * the PIT loop below. | ||
372 | */ | ||
373 | udelay(10 * USEC_PER_MSEC); | ||
374 | udelay(10 * USEC_PER_MSEC); | ||
375 | udelay(10 * USEC_PER_MSEC); | ||
376 | udelay(10 * USEC_PER_MSEC); | ||
377 | udelay(10 * USEC_PER_MSEC); | ||
378 | return ULONG_MAX; | ||
379 | } | ||
380 | |||
366 | /* Set the Gate high, disable speaker */ | 381 | /* Set the Gate high, disable speaker */ |
367 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | 382 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); |
368 | 383 | ||
@@ -487,6 +502,9 @@ static unsigned long quick_pit_calibrate(void) | |||
487 | u64 tsc, delta; | 502 | u64 tsc, delta; |
488 | unsigned long d1, d2; | 503 | unsigned long d1, d2; |
489 | 504 | ||
505 | if (!has_legacy_pic()) | ||
506 | return 0; | ||
507 | |||
490 | /* Set the Gate high, disable speaker */ | 508 | /* Set the Gate high, disable speaker */ |
491 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | 509 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); |
492 | 510 | ||
@@ -988,8 +1006,6 @@ static void __init detect_art(void) | |||
988 | 1006 | ||
989 | /* clocksource code */ | 1007 | /* clocksource code */ |
990 | 1008 | ||
991 | static struct clocksource clocksource_tsc; | ||
992 | |||
993 | static void tsc_resume(struct clocksource *cs) | 1009 | static void tsc_resume(struct clocksource *cs) |
994 | { | 1010 | { |
995 | tsc_verify_tsc_adjust(true); | 1011 | tsc_verify_tsc_adjust(true); |
@@ -1040,12 +1056,31 @@ static void tsc_cs_tick_stable(struct clocksource *cs) | |||
1040 | /* | 1056 | /* |
1041 | * .mask MUST be CLOCKSOURCE_MASK(64). See comment above read_tsc() | 1057 | * .mask MUST be CLOCKSOURCE_MASK(64). See comment above read_tsc() |
1042 | */ | 1058 | */ |
1059 | static struct clocksource clocksource_tsc_early = { | ||
1060 | .name = "tsc-early", | ||
1061 | .rating = 299, | ||
1062 | .read = read_tsc, | ||
1063 | .mask = CLOCKSOURCE_MASK(64), | ||
1064 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | | ||
1065 | CLOCK_SOURCE_MUST_VERIFY, | ||
1066 | .archdata = { .vclock_mode = VCLOCK_TSC }, | ||
1067 | .resume = tsc_resume, | ||
1068 | .mark_unstable = tsc_cs_mark_unstable, | ||
1069 | .tick_stable = tsc_cs_tick_stable, | ||
1070 | }; | ||
1071 | |||
1072 | /* | ||
1073 | * Must mark VALID_FOR_HRES early such that when we unregister tsc_early | ||
1074 | * this one will immediately take over. We will only register if TSC has | ||
1075 | * been found good. | ||
1076 | */ | ||
1043 | static struct clocksource clocksource_tsc = { | 1077 | static struct clocksource clocksource_tsc = { |
1044 | .name = "tsc", | 1078 | .name = "tsc", |
1045 | .rating = 300, | 1079 | .rating = 300, |
1046 | .read = read_tsc, | 1080 | .read = read_tsc, |
1047 | .mask = CLOCKSOURCE_MASK(64), | 1081 | .mask = CLOCKSOURCE_MASK(64), |
1048 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | | 1082 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | |
1083 | CLOCK_SOURCE_VALID_FOR_HRES | | ||
1049 | CLOCK_SOURCE_MUST_VERIFY, | 1084 | CLOCK_SOURCE_MUST_VERIFY, |
1050 | .archdata = { .vclock_mode = VCLOCK_TSC }, | 1085 | .archdata = { .vclock_mode = VCLOCK_TSC }, |
1051 | .resume = tsc_resume, | 1086 | .resume = tsc_resume, |
@@ -1169,8 +1204,8 @@ static void tsc_refine_calibration_work(struct work_struct *work) | |||
1169 | int cpu; | 1204 | int cpu; |
1170 | 1205 | ||
1171 | /* Don't bother refining TSC on unstable systems */ | 1206 | /* Don't bother refining TSC on unstable systems */ |
1172 | if (check_tsc_unstable()) | 1207 | if (tsc_unstable) |
1173 | goto out; | 1208 | return; |
1174 | 1209 | ||
1175 | /* | 1210 | /* |
1176 | * Since the work is started early in boot, we may be | 1211 | * Since the work is started early in boot, we may be |
@@ -1222,9 +1257,13 @@ static void tsc_refine_calibration_work(struct work_struct *work) | |||
1222 | set_cyc2ns_scale(tsc_khz, cpu, tsc_stop); | 1257 | set_cyc2ns_scale(tsc_khz, cpu, tsc_stop); |
1223 | 1258 | ||
1224 | out: | 1259 | out: |
1260 | if (tsc_unstable) | ||
1261 | return; | ||
1262 | |||
1225 | if (boot_cpu_has(X86_FEATURE_ART)) | 1263 | if (boot_cpu_has(X86_FEATURE_ART)) |
1226 | art_related_clocksource = &clocksource_tsc; | 1264 | art_related_clocksource = &clocksource_tsc; |
1227 | clocksource_register_khz(&clocksource_tsc, tsc_khz); | 1265 | clocksource_register_khz(&clocksource_tsc, tsc_khz); |
1266 | clocksource_unregister(&clocksource_tsc_early); | ||
1228 | } | 1267 | } |
1229 | 1268 | ||
1230 | 1269 | ||
@@ -1233,13 +1272,11 @@ static int __init init_tsc_clocksource(void) | |||
1233 | if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz) | 1272 | if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz) |
1234 | return 0; | 1273 | return 0; |
1235 | 1274 | ||
1275 | if (check_tsc_unstable()) | ||
1276 | return 0; | ||
1277 | |||
1236 | if (tsc_clocksource_reliable) | 1278 | if (tsc_clocksource_reliable) |
1237 | clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | 1279 | clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; |
1238 | /* lower the rating if we already know its unstable: */ | ||
1239 | if (check_tsc_unstable()) { | ||
1240 | clocksource_tsc.rating = 0; | ||
1241 | clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; | ||
1242 | } | ||
1243 | 1280 | ||
1244 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) | 1281 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) |
1245 | clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; | 1282 | clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; |
@@ -1252,6 +1289,7 @@ static int __init init_tsc_clocksource(void) | |||
1252 | if (boot_cpu_has(X86_FEATURE_ART)) | 1289 | if (boot_cpu_has(X86_FEATURE_ART)) |
1253 | art_related_clocksource = &clocksource_tsc; | 1290 | art_related_clocksource = &clocksource_tsc; |
1254 | clocksource_register_khz(&clocksource_tsc, tsc_khz); | 1291 | clocksource_register_khz(&clocksource_tsc, tsc_khz); |
1292 | clocksource_unregister(&clocksource_tsc_early); | ||
1255 | return 0; | 1293 | return 0; |
1256 | } | 1294 | } |
1257 | 1295 | ||
@@ -1356,9 +1394,12 @@ void __init tsc_init(void) | |||
1356 | 1394 | ||
1357 | check_system_tsc_reliable(); | 1395 | check_system_tsc_reliable(); |
1358 | 1396 | ||
1359 | if (unsynchronized_tsc()) | 1397 | if (unsynchronized_tsc()) { |
1360 | mark_tsc_unstable("TSCs unsynchronized"); | 1398 | mark_tsc_unstable("TSCs unsynchronized"); |
1399 | return; | ||
1400 | } | ||
1361 | 1401 | ||
1402 | clocksource_register_khz(&clocksource_tsc_early, tsc_khz); | ||
1362 | detect_art(); | 1403 | detect_art(); |
1363 | } | 1404 | } |
1364 | 1405 | ||