Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bbbd99955bfe84c9ae63f51db946a7bcd21f48be
Commit:     bbbd99955bfe84c9ae63f51db946a7bcd21f48be
Parent:     c399da0d97e06803e51085ec076b63a3168aad1b
Author:     David P. Reed <[EMAIL PROTECTED]>
AuthorDate: Wed Nov 14 20:14:50 2007 -0500
Committer:  Thomas Gleixner <[EMAIL PROTECTED](none)>
CommitDate: Sat Nov 17 16:27:01 2007 +0100

    x86: on x86_64, correct reading of PC RTC when update in progress in 
time_64.c
    
    Correct potentially unstable PC RTC time register reading in time_64.c
    
    Stop the use of an incorrect technique for reading the standard PC RTC
    timer, which is documented to "disconnect" time registers from the bus
    while updates are in progress.  The use of UIP flag while interrupts
    are disabled to protect a 244 microsecond window is one of the
    Motorola spec sheet's documented ways to read the RTC time registers
    reliably.
    
    tglx: removed locking changes from original patch, as they gain nothing
    (read_persistent_clock is only called during boot, suspend, resume - so
    no hot path affected) and conflict with the paravirt locking scheme
    (see 32bit code), which we do not want to complicate for no benefit.
    
    Signed-off-by: David P. Reed <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
---
 arch/x86/kernel/time_64.c |   30 ++++++++++++++++++------------
 1 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c
index 4ad1f7a..368b194 100644
--- a/arch/x86/kernel/time_64.c
+++ b/arch/x86/kernel/time_64.c
@@ -161,21 +161,27 @@ unsigned long read_persistent_clock(void)
        unsigned century = 0;
 
        spin_lock_irqsave(&rtc_lock, flags);
+       /*
+        * if UIP is clear, then we have >= 244 microseconds before RTC
+        * registers will be updated.  Spec sheet says that this is the
+        * reliable way to read RTC - registers invalid (off bus) during update
+        */
+       while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+               cpu_relax();
 
-       do {
-               sec = CMOS_READ(RTC_SECONDS);
-               min = CMOS_READ(RTC_MINUTES);
-               hour = CMOS_READ(RTC_HOURS);
-               day = CMOS_READ(RTC_DAY_OF_MONTH);
-               mon = CMOS_READ(RTC_MONTH);
-               year = CMOS_READ(RTC_YEAR);
+
+       /* now read all RTC registers while stable with interrupts disabled */
+       sec = CMOS_READ(RTC_SECONDS);
+       min = CMOS_READ(RTC_MINUTES);
+       hour = CMOS_READ(RTC_HOURS);
+       day = CMOS_READ(RTC_DAY_OF_MONTH);
+       mon = CMOS_READ(RTC_MONTH);
+       year = CMOS_READ(RTC_YEAR);
 #ifdef CONFIG_ACPI
-               if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
-                                       acpi_gbl_FADT.century)
-                       century = CMOS_READ(acpi_gbl_FADT.century);
+       if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+                               acpi_gbl_FADT.century)
+               century = CMOS_READ(acpi_gbl_FADT.century);
 #endif
-       } while (sec != CMOS_READ(RTC_SECONDS));
-
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        /*
-
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