Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c67c36e4b86872ac875716d502748b84b2541de5
Commit:     c67c36e4b86872ac875716d502748b84b2541de5
Parent:     c9927c2bf4f45bb85e8b502ab3fb79ad6483c244
Author:     Linus Torvalds <[EMAIL PROTECTED]>
AuthorDate: Wed Oct 17 23:18:32 2007 -0400
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Thu Oct 25 15:08:03 2007 -0700

    Fix /proc/acpi/alarm BCD alarm encodings
    
    This fixes some totally illogical and wrong code that converts things to
    and from BCD mode essentially randomly, does math on values in BCD mode
    etc etc.  Introduce a few helper functions to make it a bit more obvious
    what is going on, and make sure that we always do all the arithmetic
    (and anythign else, for that matter) in binary, not BCD.
    
    Tested by Mark Lord, who found the problem originally, and also pushed
    the patch back and reminded me about it.
    
    Signed-off-by: Mark Lord <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 drivers/acpi/sleep/proc.c |   66 +++++++++++++++++++-------------------------
 1 files changed, 29 insertions(+), 37 deletions(-)

diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 3839efd..1538355 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -194,6 +194,23 @@ static int get_date_field(char **p, u32 * value)
        return result;
 }
 
+/* Read a possibly BCD register, always return binary */
+static u32 cmos_bcd_read(int offset, int rtc_control)
+{
+       u32 val = CMOS_READ(offset);
+       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+               BCD_TO_BIN(val);
+       return val;
+}
+
+/* Write binary value into possibly BCD register */
+static void cmos_bcd_write(u32 val, int offset, int rtc_control)
+{
+       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+               BIN_TO_BCD(val);
+       CMOS_WRITE(val, offset);
+}
+
 static ssize_t
 acpi_system_write_alarm(struct file *file,
                        const char __user * buffer, size_t count, loff_t * ppos)
@@ -258,35 +275,18 @@ acpi_system_write_alarm(struct file *file,
        spin_lock_irq(&rtc_lock);
 
        rtc_control = CMOS_READ(RTC_CONTROL);
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BIN_TO_BCD(yr);
-               BIN_TO_BCD(mo);
-               BIN_TO_BCD(day);
-               BIN_TO_BCD(hr);
-               BIN_TO_BCD(min);
-               BIN_TO_BCD(sec);
-       }
 
        if (adjust) {
-               yr += CMOS_READ(RTC_YEAR);
-               mo += CMOS_READ(RTC_MONTH);
-               day += CMOS_READ(RTC_DAY_OF_MONTH);
-               hr += CMOS_READ(RTC_HOURS);
-               min += CMOS_READ(RTC_MINUTES);
-               sec += CMOS_READ(RTC_SECONDS);
+               yr += cmos_bcd_read(RTC_YEAR, rtc_control);
+               mo += cmos_bcd_read(RTC_MONTH, rtc_control);
+               day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
+               hr += cmos_bcd_read(RTC_HOURS, rtc_control);
+               min += cmos_bcd_read(RTC_MINUTES, rtc_control);
+               sec += cmos_bcd_read(RTC_SECONDS, rtc_control);
        }
 
        spin_unlock_irq(&rtc_lock);
 
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(yr);
-               BCD_TO_BIN(mo);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(hr);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(sec);
-       }
-
        if (sec > 59) {
                min++;
                sec -= 60;
@@ -307,14 +307,6 @@ acpi_system_write_alarm(struct file *file,
                yr++;
                mo -= 12;
        }
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BIN_TO_BCD(yr);
-               BIN_TO_BCD(mo);
-               BIN_TO_BCD(day);
-               BIN_TO_BCD(hr);
-               BIN_TO_BCD(min);
-               BIN_TO_BCD(sec);
-       }
 
        spin_lock_irq(&rtc_lock);
        /*
@@ -326,9 +318,9 @@ acpi_system_write_alarm(struct file *file,
        CMOS_READ(RTC_INTR_FLAGS);
 
        /* write the fields the rtc knows about */
-       CMOS_WRITE(hr, RTC_HOURS_ALARM);
-       CMOS_WRITE(min, RTC_MINUTES_ALARM);
-       CMOS_WRITE(sec, RTC_SECONDS_ALARM);
+       cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control);
+       cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control);
+       cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control);
 
        /*
         * If the system supports an enhanced alarm it will have non-zero
@@ -336,11 +328,11 @@ acpi_system_write_alarm(struct file *file,
         * to the RTC area of memory.
         */
        if (acpi_gbl_FADT.day_alarm)
-               CMOS_WRITE(day, acpi_gbl_FADT.day_alarm);
+               cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control);
        if (acpi_gbl_FADT.month_alarm)
-               CMOS_WRITE(mo, acpi_gbl_FADT.month_alarm);
+               cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control);
        if (acpi_gbl_FADT.century)
-               CMOS_WRITE(yr / 100, acpi_gbl_FADT.century);
+               cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control);
        /* enable the rtc alarm interrupt */
        rtc_control |= RTC_AIE;
        CMOS_WRITE(rtc_control, RTC_CONTROL);
-
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