aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-02-06 04:38:45 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:13 -0500
commit8a0bdfd7a05f5bb0486fbe7146a2cf775957e95e (patch)
tree2de49bb837ef636cd07c10ef7773194731f412da
parent739d340dba45ab786a5553144bbffbee0afe15dd (diff)
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>
-rw-r--r--drivers/rtc/rtc-cmos.c14
-rw-r--r--drivers/rtc/rtc-dev.c9
-rw-r--r--drivers/rtc/rtc-sysfs.c19
3 files changed, 35 insertions, 7 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;
472static irqreturn_t cmos_interrupt(int irq, void *p) 472static irqreturn_t cmos_interrupt(int irq, void *p)
473{ 473{
474 u8 irqstat; 474 u8 irqstat;
475 u8 rtc_control;
475 476
476 spin_lock(&rtc_lock); 477 spin_lock(&rtc_lock);
477 irqstat = CMOS_READ(RTC_INTR_FLAGS); 478 irqstat = CMOS_READ(RTC_INTR_FLAGS);
478 irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF; 479 rtc_control = CMOS_READ(RTC_CONTROL);
480 irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
481
482 /* All Linux RTC alarms should be treated as if they were oneshot.
483 * Similar code may be needed in system wakeup paths, in case the
484 * alarm woke the system.
485 */
486 if (irqstat & RTC_AIE) {
487 rtc_control &= ~RTC_AIE;
488 CMOS_WRITE(rtc_control, RTC_CONTROL);
489 CMOS_READ(RTC_INTR_FLAGS);
490 }
479 spin_unlock(&rtc_lock); 491 spin_unlock(&rtc_lock);
480 492
481 if (is_intr(irqstat)) { 493 if (is_intr(irqstat)) {
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 025c60a17a4a..90dfa0df747a 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -246,6 +246,15 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
246 /* if the driver does not provide the ioctl interface 246 /* if the driver does not provide the ioctl interface
247 * or if that particular ioctl was not implemented 247 * or if that particular ioctl was not implemented
248 * (-ENOIOCTLCMD), we will try to emulate here. 248 * (-ENOIOCTLCMD), we will try to emulate here.
249 *
250 * Drivers *SHOULD NOT* provide ioctl implementations
251 * for these requests. Instead, provide methods to
252 * support the following code, so that the RTC's main
253 * features are accessible without using ioctls.
254 *
255 * RTC and alarm times will be in UTC, by preference,
256 * but dual-booting with MS-Windows implies RTCs must
257 * use the local wall clock time.
249 */ 258 */
250 259
251 switch (cmd) { 260 switch (cmd) {
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 2ae0e8304d3a..4d27ccc4fc06 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -17,6 +17,13 @@
17 17
18/* device attributes */ 18/* device attributes */
19 19
20/*
21 * NOTE: RTC times displayed in sysfs use the RTC's timezone. That's
22 * ideally UTC. However, PCs that also boot to MS-Windows normally use
23 * the local time and change to match daylight savings time. That affects
24 * attributes including date, time, since_epoch, and wakealarm.
25 */
26
20static ssize_t 27static ssize_t
21rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, 28rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr,
22 char *buf) 29 char *buf)
@@ -113,13 +120,13 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
113 unsigned long alarm; 120 unsigned long alarm;
114 struct rtc_wkalrm alm; 121 struct rtc_wkalrm alm;
115 122
116 /* Don't show disabled alarms; but the RTC could leave the 123 /* Don't show disabled alarms. For uniformity, RTC alarms are
117 * alarm enabled after it's already triggered. Alarms are 124 * conceptually one-shot, even though some common RTCs (on PCs)
118 * conceptually one-shot, even though some common hardware 125 * don't actually work that way.
119 * (PCs) doesn't actually work that way.
120 * 126 *
121 * REVISIT maybe we should require RTC implementations to 127 * NOTE: RTC implementations where the alarm doesn't match an
122 * disable the RTC alarm after it triggers, for uniformity. 128 * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC
129 * alarms after they trigger, to ensure one-shot semantics.
123 */ 130 */
124 retval = rtc_read_alarm(to_rtc_device(dev), &alm); 131 retval = rtc_read_alarm(to_rtc_device(dev), &alm);
125 if (retval == 0 && alm.enabled) { 132 if (retval == 0 && alm.enabled) {