aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic.c')
-rw-r--r--arch/x86/kernel/apic.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c
index 8bd801db24d9..cf2ca19e62da 100644
--- a/arch/x86/kernel/apic.c
+++ b/arch/x86/kernel/apic.c
@@ -555,7 +555,8 @@ static void __init lapic_cal_handler(struct clock_event_device *dev)
555 } 555 }
556} 556}
557 557
558static int __init calibrate_by_pmtimer(long deltapm, long *delta) 558static int __init
559calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc)
559{ 560{
560 const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; 561 const long pm_100ms = PMTMR_TICKS_PER_SEC / 10;
561 const long pm_thresh = pm_100ms / 100; 562 const long pm_thresh = pm_100ms / 100;
@@ -566,7 +567,7 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta)
566 return -1; 567 return -1;
567#endif 568#endif
568 569
569 apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm); 570 apic_printk(APIC_VERBOSE, "... PM-Timer delta = %ld\n", deltapm);
570 571
571 /* Check, if the PM timer is available */ 572 /* Check, if the PM timer is available */
572 if (!deltapm) 573 if (!deltapm)
@@ -576,19 +577,30 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta)
576 577
577 if (deltapm > (pm_100ms - pm_thresh) && 578 if (deltapm > (pm_100ms - pm_thresh) &&
578 deltapm < (pm_100ms + pm_thresh)) { 579 deltapm < (pm_100ms + pm_thresh)) {
579 apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); 580 apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n");
580 } else { 581 return 0;
581 res = (((u64)deltapm) * mult) >> 22; 582 }
582 do_div(res, 1000000); 583
583 pr_warning("APIC calibration not consistent " 584 res = (((u64)deltapm) * mult) >> 22;
584 "with PM Timer: %ldms instead of 100ms\n", 585 do_div(res, 1000000);
585 (long)res); 586 pr_warning("APIC calibration not consistent "
586 /* Correct the lapic counter value */ 587 "with PM-Timer: %ldms instead of 100ms\n",(long)res);
587 res = (((u64)(*delta)) * pm_100ms); 588
589 /* Correct the lapic counter value */
590 res = (((u64)(*delta)) * pm_100ms);
591 do_div(res, deltapm);
592 pr_info("APIC delta adjusted to PM-Timer: "
593 "%lu (%ld)\n", (unsigned long)res, *delta);
594 *delta = (long)res;
595
596 /* Correct the tsc counter value */
597 if (cpu_has_tsc) {
598 res = (((u64)(*deltatsc)) * pm_100ms);
588 do_div(res, deltapm); 599 do_div(res, deltapm);
589 pr_info("APIC delta adjusted to PM-Timer: " 600 apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
590 "%lu (%ld)\n", (unsigned long)res, *delta); 601 "PM-Timer: %lu (%ld) \n",
591 *delta = (long)res; 602 (unsigned long)res, *deltatsc);
603 *deltatsc = (long)res;
592 } 604 }
593 605
594 return 0; 606 return 0;
@@ -599,7 +611,7 @@ static int __init calibrate_APIC_clock(void)
599 struct clock_event_device *levt = &__get_cpu_var(lapic_events); 611 struct clock_event_device *levt = &__get_cpu_var(lapic_events);
600 void (*real_handler)(struct clock_event_device *dev); 612 void (*real_handler)(struct clock_event_device *dev);
601 unsigned long deltaj; 613 unsigned long deltaj;
602 long delta; 614 long delta, deltatsc;
603 int pm_referenced = 0; 615 int pm_referenced = 0;
604 616
605 local_irq_disable(); 617 local_irq_disable();
@@ -629,9 +641,11 @@ static int __init calibrate_APIC_clock(void)
629 delta = lapic_cal_t1 - lapic_cal_t2; 641 delta = lapic_cal_t1 - lapic_cal_t2;
630 apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); 642 apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
631 643
644 deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
645
632 /* we trust the PM based calibration if possible */ 646 /* we trust the PM based calibration if possible */
633 pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, 647 pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1,
634 &delta); 648 &delta, &deltatsc);
635 649
636 /* Calculate the scaled math multiplication factor */ 650 /* Calculate the scaled math multiplication factor */
637 lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, 651 lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
@@ -649,11 +663,10 @@ static int __init calibrate_APIC_clock(void)
649 calibration_result); 663 calibration_result);
650 664
651 if (cpu_has_tsc) { 665 if (cpu_has_tsc) {
652 delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
653 apic_printk(APIC_VERBOSE, "..... CPU clock speed is " 666 apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
654 "%ld.%04ld MHz.\n", 667 "%ld.%04ld MHz.\n",
655 (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ), 668 (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
656 (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ)); 669 (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
657 } 670 }
658 671
659 apic_printk(APIC_VERBOSE, "..... host bus clock speed is " 672 apic_printk(APIC_VERBOSE, "..... host bus clock speed is "