summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-cmos.c
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-02-06 01:38:45 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 10:41:13 -0800
commit8a0bdfd7a05f5bb0486fbe7146a2cf775957e95e (patch)
tree2de49bb837ef636cd07c10ef7773194731f412da /drivers/rtc/rtc-cmos.c
parent739d340dba45ab786a5553144bbffbee0afe15dd (diff)
downloadlinux-8a0bdfd7a05f5bb0486fbe7146a2cf775957e95e.tar.bz2
rtc-cmos alarm acts as oneshot
Start making the rtc-cmos alarm act more like a oneshot alarm by disabling that alarm after its IRQ fires. (ACPI hooks are also needed.) The Linux RTC framework has previously been a bit vague in this area, but any other behavior is problematic and not very portable. RTCs with full YYYY-MM-DD HH:MM[:SS] alarms won't have a problem here. Only ones with partial match criteria, with the most visible example being the PC RTC, get confused. (Because the criteria will match repeatedly.) Update comments relating to that oneshot behavior and timezone handling. (Timezones are another issue that's mostly visible with rtc-cmos. That's because PCs often dual-boot MS-Windows, which likes its RTC to match local wall-clock time instead of UTC.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r--drivers/rtc/rtc-cmos.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index ab455ddb16cf..ff7539a4dbea 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -472,10 +472,22 @@ static struct cmos_rtc cmos_rtc;
static irqreturn_t cmos_interrupt(int irq, void *p)
{
u8 irqstat;
+ u8 rtc_control;
spin_lock(&rtc_lock);
irqstat = CMOS_READ(RTC_INTR_FLAGS);
- irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF;
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+
+ /* All Linux RTC alarms should be treated as if they were oneshot.
+ * Similar code may be needed in system wakeup paths, in case the
+ * alarm woke the system.
+ */
+ if (irqstat & RTC_AIE) {
+ rtc_control &= ~RTC_AIE;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+ }
spin_unlock(&rtc_lock);
if (is_intr(irqstat)) {