aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Lord <lkml@rtr.ca>2008-12-09 10:46:30 -0500
committerLen Brown <len.brown@intel.com>2008-12-10 00:29:35 -0500
commit48452e5f99ab35d643df0463b6ad11aea8ea7bdc (patch)
tree9d5418951b0064f231d1df81f96b1ba624e46f99 /drivers
parent437f2f91d6597c67662f847d9ed4c99cb3c440cd (diff)
/proc/acpi/alarm: handle day-of-month wraparound on readback
Fix month wrap issue with readback from /proc/acpi/alarm This bug has been around *forever*. $ echo '2008-12-01 10:36:20' > /proc/acpi/alarm $ cat /proc/acpi/alarm 2008-11-01 10:36:20 Note how the readback above shows the month incorrectly when the alarm is set in the *next* calendar month. But with this patch applied, it shows the correct month (12). Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/sleep/proc.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 4dbc2271acf5..232d4b64140b 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -84,12 +84,15 @@ acpi_system_write_sleep(struct file *file,
84#define HAVE_ACPI_LEGACY_ALARM 84#define HAVE_ACPI_LEGACY_ALARM
85#endif 85#endif
86 86
87static u32 cmos_bcd_read(int offset, int rtc_control);
88
87#ifdef HAVE_ACPI_LEGACY_ALARM 89#ifdef HAVE_ACPI_LEGACY_ALARM
88 90
89static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset) 91static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
90{ 92{
91 u32 sec, min, hr; 93 u32 sec, min, hr;
92 u32 day, mo, yr, cent = 0; 94 u32 day, mo, yr, cent = 0;
95 u32 today = 0;
93 unsigned char rtc_control = 0; 96 unsigned char rtc_control = 0;
94 unsigned long flags; 97 unsigned long flags;
95 98
@@ -97,38 +100,32 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
97 100
98 spin_lock_irqsave(&rtc_lock, flags); 101 spin_lock_irqsave(&rtc_lock, flags);
99 102
100 sec = CMOS_READ(RTC_SECONDS_ALARM);
101 min = CMOS_READ(RTC_MINUTES_ALARM);
102 hr = CMOS_READ(RTC_HOURS_ALARM);
103 rtc_control = CMOS_READ(RTC_CONTROL); 103 rtc_control = CMOS_READ(RTC_CONTROL);
104 sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control);
105 min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control);
106 hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control);
104 107
105 /* If we ever get an FACP with proper values... */ 108 /* If we ever get an FACP with proper values... */
106 if (acpi_gbl_FADT.day_alarm) 109 if (acpi_gbl_FADT.day_alarm) {
107 /* ACPI spec: only low 6 its should be cared */ 110 /* ACPI spec: only low 6 its should be cared */
108 day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F; 111 day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F;
109 else 112 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
110 day = CMOS_READ(RTC_DAY_OF_MONTH); 113 day = bcd2bin(day);
114 } else
115 day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
111 if (acpi_gbl_FADT.month_alarm) 116 if (acpi_gbl_FADT.month_alarm)
112 mo = CMOS_READ(acpi_gbl_FADT.month_alarm); 117 mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control);
113 else 118 else {
114 mo = CMOS_READ(RTC_MONTH); 119 mo = cmos_bcd_read(RTC_MONTH, rtc_control);
120 today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
121 }
115 if (acpi_gbl_FADT.century) 122 if (acpi_gbl_FADT.century)
116 cent = CMOS_READ(acpi_gbl_FADT.century); 123 cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control);
117 124
118 yr = CMOS_READ(RTC_YEAR); 125 yr = cmos_bcd_read(RTC_YEAR, rtc_control);
119 126
120 spin_unlock_irqrestore(&rtc_lock, flags); 127 spin_unlock_irqrestore(&rtc_lock, flags);
121 128
122 if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
123 sec = bcd2bin(sec);
124 min = bcd2bin(min);
125 hr = bcd2bin(hr);
126 day = bcd2bin(day);
127 mo = bcd2bin(mo);
128 yr = bcd2bin(yr);
129 cent = bcd2bin(cent);
130 }
131
132 /* we're trusting the FADT (see above) */ 129 /* we're trusting the FADT (see above) */
133 if (!acpi_gbl_FADT.century) 130 if (!acpi_gbl_FADT.century)
134 /* If we're not trusting the FADT, we should at least make it 131 /* If we're not trusting the FADT, we should at least make it
@@ -153,6 +150,20 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
153 else 150 else
154 yr += cent * 100; 151 yr += cent * 100;
155 152
153 /*
154 * Show correct dates for alarms up to a month into the future.
155 * This solves issues for nearly all situations with the common
156 * 30-day alarm clocks in PC hardware.
157 */
158 if (day < today) {
159 if (mo < 12) {
160 mo += 1;
161 } else {
162 mo = 1;
163 yr += 1;
164 }
165 }
166
156 seq_printf(seq, "%4.4u-", yr); 167 seq_printf(seq, "%4.4u-", yr);
157 (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo); 168 (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
158 (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day); 169 (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);