diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-09-07 02:19:51 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-09-07 02:19:51 -0400 |
| commit | a1922ed661ab2c1637d0b10cde933bd9cd33d965 (patch) | |
| tree | 0f1777542b385ebefd30b3586d830fd8ed6fda5b /arch/x86/kernel/tsc.c | |
| parent | 75e33751ca8bbb72dd6f1a74d2810ddc8cbe4bdf (diff) | |
| parent | d28daf923ac5e4a0d7cecebae56f3e339189366b (diff) | |
Merge branch 'tracing/core' into tracing/hw-breakpoints
Conflicts:
arch/Kconfig
kernel/trace/trace.h
Merge reason: resolve the conflicts, plus adopt to the new
ring-buffer APIs.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/tsc.c')
| -rw-r--r-- | arch/x86/kernel/tsc.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index ae3180c506a6..71f4368b357e 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -275,15 +275,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin) | |||
| 275 | * use the TSC value at the transitions to calculate a pretty | 275 | * use the TSC value at the transitions to calculate a pretty |
| 276 | * good value for the TSC frequencty. | 276 | * good value for the TSC frequencty. |
| 277 | */ | 277 | */ |
| 278 | static inline int pit_verify_msb(unsigned char val) | ||
| 279 | { | ||
| 280 | /* Ignore LSB */ | ||
| 281 | inb(0x42); | ||
| 282 | return inb(0x42) == val; | ||
| 283 | } | ||
| 284 | |||
| 278 | static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap) | 285 | static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap) |
| 279 | { | 286 | { |
| 280 | int count; | 287 | int count; |
| 281 | u64 tsc = 0; | 288 | u64 tsc = 0; |
| 282 | 289 | ||
| 283 | for (count = 0; count < 50000; count++) { | 290 | for (count = 0; count < 50000; count++) { |
| 284 | /* Ignore LSB */ | 291 | if (!pit_verify_msb(val)) |
| 285 | inb(0x42); | ||
| 286 | if (inb(0x42) != val) | ||
| 287 | break; | 292 | break; |
| 288 | tsc = get_cycles(); | 293 | tsc = get_cycles(); |
| 289 | } | 294 | } |
| @@ -336,8 +341,7 @@ static unsigned long quick_pit_calibrate(void) | |||
| 336 | * to do that is to just read back the 16-bit counter | 341 | * to do that is to just read back the 16-bit counter |
| 337 | * once from the PIT. | 342 | * once from the PIT. |
| 338 | */ | 343 | */ |
| 339 | inb(0x42); | 344 | pit_verify_msb(0); |
| 340 | inb(0x42); | ||
| 341 | 345 | ||
| 342 | if (pit_expect_msb(0xff, &tsc, &d1)) { | 346 | if (pit_expect_msb(0xff, &tsc, &d1)) { |
| 343 | for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) { | 347 | for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) { |
| @@ -348,8 +352,19 @@ static unsigned long quick_pit_calibrate(void) | |||
| 348 | * Iterate until the error is less than 500 ppm | 352 | * Iterate until the error is less than 500 ppm |
| 349 | */ | 353 | */ |
| 350 | delta -= tsc; | 354 | delta -= tsc; |
| 351 | if (d1+d2 < delta >> 11) | 355 | if (d1+d2 >= delta >> 11) |
| 352 | goto success; | 356 | continue; |
| 357 | |||
| 358 | /* | ||
| 359 | * Check the PIT one more time to verify that | ||
| 360 | * all TSC reads were stable wrt the PIT. | ||
| 361 | * | ||
| 362 | * This also guarantees serialization of the | ||
| 363 | * last cycle read ('d2') in pit_expect_msb. | ||
| 364 | */ | ||
| 365 | if (!pit_verify_msb(0xfe - i)) | ||
| 366 | break; | ||
| 367 | goto success; | ||
| 353 | } | 368 | } |
| 354 | } | 369 | } |
| 355 | printk("Fast TSC calibration failed\n"); | 370 | printk("Fast TSC calibration failed\n"); |
| @@ -590,22 +605,26 @@ EXPORT_SYMBOL(recalibrate_cpu_khz); | |||
| 590 | */ | 605 | */ |
| 591 | 606 | ||
| 592 | DEFINE_PER_CPU(unsigned long, cyc2ns); | 607 | DEFINE_PER_CPU(unsigned long, cyc2ns); |
| 608 | DEFINE_PER_CPU(unsigned long long, cyc2ns_offset); | ||
| 593 | 609 | ||
| 594 | static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) | 610 | static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu) |
| 595 | { | 611 | { |
| 596 | unsigned long long tsc_now, ns_now; | 612 | unsigned long long tsc_now, ns_now, *offset; |
| 597 | unsigned long flags, *scale; | 613 | unsigned long flags, *scale; |
| 598 | 614 | ||
| 599 | local_irq_save(flags); | 615 | local_irq_save(flags); |
| 600 | sched_clock_idle_sleep_event(); | 616 | sched_clock_idle_sleep_event(); |
| 601 | 617 | ||
| 602 | scale = &per_cpu(cyc2ns, cpu); | 618 | scale = &per_cpu(cyc2ns, cpu); |
| 619 | offset = &per_cpu(cyc2ns_offset, cpu); | ||
| 603 | 620 | ||
| 604 | rdtscll(tsc_now); | 621 | rdtscll(tsc_now); |
| 605 | ns_now = __cycles_2_ns(tsc_now); | 622 | ns_now = __cycles_2_ns(tsc_now); |
| 606 | 623 | ||
| 607 | if (cpu_khz) | 624 | if (cpu_khz) { |
| 608 | *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz; | 625 | *scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz; |
| 626 | *offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR); | ||
| 627 | } | ||
| 609 | 628 | ||
| 610 | sched_clock_idle_wakeup_event(0); | 629 | sched_clock_idle_wakeup_event(0); |
| 611 | local_irq_restore(flags); | 630 | local_irq_restore(flags); |
| @@ -632,17 +651,15 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | |||
| 632 | void *data) | 651 | void *data) |
| 633 | { | 652 | { |
| 634 | struct cpufreq_freqs *freq = data; | 653 | struct cpufreq_freqs *freq = data; |
| 635 | unsigned long *lpj, dummy; | 654 | unsigned long *lpj; |
| 636 | 655 | ||
| 637 | if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC)) | 656 | if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC)) |
| 638 | return 0; | 657 | return 0; |
| 639 | 658 | ||
| 640 | lpj = &dummy; | 659 | lpj = &boot_cpu_data.loops_per_jiffy; |
| 641 | if (!(freq->flags & CPUFREQ_CONST_LOOPS)) | ||
| 642 | #ifdef CONFIG_SMP | 660 | #ifdef CONFIG_SMP |
| 661 | if (!(freq->flags & CPUFREQ_CONST_LOOPS)) | ||
| 643 | lpj = &cpu_data(freq->cpu).loops_per_jiffy; | 662 | lpj = &cpu_data(freq->cpu).loops_per_jiffy; |
| 644 | #else | ||
| 645 | lpj = &boot_cpu_data.loops_per_jiffy; | ||
| 646 | #endif | 663 | #endif |
| 647 | 664 | ||
| 648 | if (!ref_freq) { | 665 | if (!ref_freq) { |
