Commit:     b291aa7a6564e859af144e1bd14ffa463519b198
Parent:     d31c5ab147e0b17b9ec0daa5e4d1fc0bd6b19974
Author:     Robin Holt <[EMAIL PROTECTED]>
AuthorDate: Fri Aug 10 13:00:43 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Sat Aug 11 15:47:39 2007 -0700

    x86_64: fix HPET init race
    I have had four seperate system lockups attributable to this exact problem
    in two days of testing.  Instead of trying to handle all the weird end
    cases and wrap, how about changing it to look for exactly what we appear
    to want.
    The following patch removes a couple races in setup_APIC_timer.  One occurs
    when the HPET advances the COUNTER past the T0_CMP value between the time
    the T0_CMP was originally read and when COUNTER is read.  This results in
    a delay waiting for the counter to wrap.  The other results from the counter
    This change takes a snapshot of T0_CMP at the beginning of the loop and
    simply loops until T0_CMP has changed (a tick has happened).
    I have one small concern about the patch.  I am not sure it meets the intent
    as well as it should.  I think we are trying to match APIC timer interrupts 
    with the hpet counter increment.  The event which appears to be disturbing
    this loop in our test environment is the NMI watchdog.  What we believe has
    been happening with the existing code is the setup_APIC_timer loop has read
    the CMP value, and the NMI watchdog code fires for the first time.  This
    results in a series of icache miss slowdowns and by the time we get back to
    things it has wrapped.
    I think this code is trying to get the CMP as close to the counter value as
    possible.  If that is the intent, maybe we should really be testing against 
    "window" around the CMP.  Something like COUNTER = CMP+/2.  It appears 
    should get advanced every 89nSec (IIRC).  The above seems like an 
    small window, but may be necessary.  Without documentation, I am not sure of
    the original intent with this code.
    In summary, this code fixes my boot hangs, but since I am not certain of the
    intent of the existing code, I am not certain this has not introduced new 
    or unexpected behaviors.
    Signed-off-by: Robin Holt <[EMAIL PROTECTED]>
    Acked-by: Andi Kleen <[EMAIL PROTECTED]>
    Cc: Vojtech Pavlik <[EMAIL PROTECTED]>
    Cc: "Aaron Durbin" <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
 arch/x86_64/kernel/apic.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 900ff38..925758d 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -791,10 +791,8 @@ static void setup_APIC_timer(unsigned int clocks)
        /* wait for irq slice */
        if (hpet_address && hpet_use_timer) {
-               int trigger = hpet_readl(HPET_T0_CMP);
-               while (hpet_readl(HPET_COUNTER) >= trigger)
-                       /* do nothing */ ;
-               while (hpet_readl(HPET_COUNTER) <  trigger)
+               u32 trigger = hpet_readl(HPET_T0_CMP);
+               while (hpet_readl(HPET_T0_CMP) == trigger)
                        /* do nothing */ ;
        } else {
                int c1, c2;
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

Reply via email to