Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ca1b940ce6495541efe76499b3de39aa5e4941ed
Commit:     ca1b940ce6495541efe76499b3de39aa5e4941ed
Parent:     303cd1535f6257b9fd8214534ca87b1a1567a2c5
Author:     Thomas Gleixner <[EMAIL PROTECTED]>
AuthorDate: Sun Mar 18 01:26:13 2007 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Sun Mar 18 11:35:08 2007 -0700

    [PATCH] i386: trust the PM-Timer calibration of the local APIC timer
    
    When PM-Timer is available for local APIC timer calibration we can skip the
    verification of the calibrated time value.  The resulting error is quite
    small on a bunch of evaluated platforms and is less harming than the
    observed false positives.
    
    We need to keep the verification on systems, which have no PM-Timer to
    avoid bogus local APIC timer calibrations in the range of factor 2-10,
    which can be observed when swicthing off the PM-timer support in the kernel
    configuration.
    
    The wrong calibration values are probably caused by SMM code trying to
    emulate a PS/2 keyboard from a (maybe connected or not) USB keyboard.  This
    prohibits the accurate delivery of PIT interrupts, which are used to
    calibrate the local APIC timer.  Unfortunately we have no way to disable
    this BIOS misfeature in the early boot process.
    
    Add also the dropped cpu_relax() back to the wait loops.
    
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
    Acked-by: Ingo Molnar <[EMAIL PROTECTED]>
    Acked-by: Andi Kleen <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 arch/i386/kernel/apic.c |   78 ++++++++++++++++------------------------------
 1 files changed, 27 insertions(+), 51 deletions(-)

diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 2383bcf..5cff797 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -338,6 +338,7 @@ void __init setup_boot_APIC_clock(void)
        void (*real_handler)(struct clock_event_device *dev);
        unsigned long deltaj;
        long delta, deltapm;
+       int pm_referenced = 0;
 
        apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
                    "calibrating APIC timer ...\n");
@@ -357,7 +358,8 @@ void __init setup_boot_APIC_clock(void)
        /* Let the interrupts run */
        local_irq_enable();
 
-       while(lapic_cal_loops <= LAPIC_CAL_LOOPS);
+       while (lapic_cal_loops <= LAPIC_CAL_LOOPS)
+               cpu_relax();
 
        local_irq_disable();
 
@@ -394,6 +396,7 @@ void __init setup_boot_APIC_clock(void)
                               "%lu (%ld)\n", (unsigned long) res, delta);
                        delta = (long) res;
                }
+               pm_referenced = 1;
        }
 
        /* Calculate the scaled math multiplication factor */
@@ -423,68 +426,41 @@ void __init setup_boot_APIC_clock(void)
                    calibration_result / (1000000 / HZ),
                    calibration_result % (1000000 / HZ));
 
-
-       apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
-
-       /*
-        * Setup the apic timer manually
-        */
        local_apic_timer_verify_ok = 1;
-       levt->event_handler = lapic_cal_handler;
-       lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
-       lapic_cal_loops = -1;
 
-       /* Let the interrupts run */
-       local_irq_enable();
+       /* We trust the pm timer based calibration */
+       if (!pm_referenced) {
+               apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
 
-       while(lapic_cal_loops <= LAPIC_CAL_LOOPS);
+               /*
+                * Setup the apic timer manually
+                */
+               levt->event_handler = lapic_cal_handler;
+               lapic_timer_setup(CLOCK_EVT_MODE_PERIODIC, levt);
+               lapic_cal_loops = -1;
 
-       local_irq_disable();
+               /* Let the interrupts run */
+               local_irq_enable();
 
-       /* Stop the lapic timer */
-       lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
+               while(lapic_cal_loops <= LAPIC_CAL_LOOPS)
+                       cpu_relax();
 
-       local_irq_enable();
+               local_irq_disable();
 
-       /* Jiffies delta */
-       deltaj = lapic_cal_j2 - lapic_cal_j1;
-       apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
+               /* Stop the lapic timer */
+               lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, levt);
 
-       /* Check, if the PM timer is available */
-       deltapm = lapic_cal_pm2 - lapic_cal_pm1;
-       apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
+               local_irq_enable();
 
-       local_apic_timer_verify_ok = 0;
+               /* Jiffies delta */
+               deltaj = lapic_cal_j2 - lapic_cal_j1;
+               apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
 
-       if (deltapm) {
-               if (deltapm > (pm_100ms - pm_thresh) &&
-                   deltapm < (pm_100ms + pm_thresh)) {
-                       apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
-                       /* Check, if the jiffies result is consistent */
-                       if (deltaj < LAPIC_CAL_LOOPS-2 ||
-                           deltaj > LAPIC_CAL_LOOPS+2) {
-                               /*
-                                * Not sure, what we can do about this one.
-                                * When high resultion timers are active
-                                * and the lapic timer does not stop in C3
-                                * we are fine. Otherwise more trouble might
-                                * be waiting. -- tglx
-                                */
-                               printk(KERN_WARNING "Global event device %s "
-                                      "has wrong frequency "
-                                      "(%lu ticks instead of %d)\n",
-                                      global_clock_event->name, deltaj,
-                                      LAPIC_CAL_LOOPS);
-                       }
-                       local_apic_timer_verify_ok = 1;
-               }
-       } else {
                /* Check, if the jiffies result is consistent */
-               if (deltaj >= LAPIC_CAL_LOOPS-2 &&
-                   deltaj <= LAPIC_CAL_LOOPS+2) {
+               if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2)
                        apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
-                       local_apic_timer_verify_ok = 1;
-               }
+               else
+                       local_apic_timer_verify_ok = 0;
        }
 
        if (!local_apic_timer_verify_ok) {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to