Skip to content

Commit

Permalink
rtc: add ability to push out an existing wakealarm using sysfs
Browse files Browse the repository at this point in the history
This adds the ability for the rtc sysfs code to handle += characters at
the beginning of a wakealarm setting string.  This will allow the user
to attempt to push out an existing wakealarm by a provided amount.

In the case that the += characters are provided but the alarm is not
active -EINVAL is returned.

his is useful, at least for my purposes in suspend/resume testing.  The
basic test goes something like:

1. Set a wake alarm from userspace 5 seconds in the future

2. Start the suspend process (echo mem > /sys/power/state)

3. After ~2.5 seconds if userspace is still running (using another
   thread to check this), move the wake alarm 5 more seconds

If the "move" involves an unset of the wakealarm then there's a period
   of time where the system is midway through suspending but has no wake
   alarm.  It will get stuck.

We'd rather not remove the "move" since the idea is to avoid a cancelled
suspend when the alarm fires _during_ suspend.  It is difficult for the
test to tell the difference between a suspend that was cancelled because
the alarm fired too early and a suspend that was

Signed-off-by: Bernie Thompson <bhthompson@chromium.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Doug Anderson <dianders@chromium.org>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Bernie Thompson authored and torvalds committed Jul 3, 2013
1 parent c67d96e commit 1df0a47
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 8 deletions.
7 changes: 4 additions & 3 deletions Documentation/rtc.txt
Expand Up @@ -153,9 +153,10 @@ since_epoch: The number of seconds since the epoch according to the RTC
time: RTC-provided time
wakealarm: The time at which the clock will generate a system wakeup
event. This is a one shot wakeup event, so must be reset
after wake if a daily wakeup is required. Format is either
seconds since the epoch or, if there's a leading +, seconds
in the future.
after wake if a daily wakeup is required. Format is seconds since
the epoch by default, or if there's a leading +, seconds in the
future, or if there is a leading +=, seconds ahead of the current
alarm.

IOCTL INTERFACE
---------------
Expand Down
20 changes: 15 additions & 5 deletions drivers/rtc/rtc-sysfs.c
Expand Up @@ -164,6 +164,7 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
{
ssize_t retval;
unsigned long now, alarm;
unsigned long push = 0;
struct rtc_wkalrm alm;
struct rtc_device *rtc = to_rtc_device(dev);
char *buf_ptr;
Expand All @@ -180,23 +181,32 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
buf_ptr = (char *)buf;
if (*buf_ptr == '+') {
buf_ptr++;
adjust = 1;
if (*buf_ptr == '=') {
buf_ptr++;
push = 1;
} else
adjust = 1;
}
alarm = simple_strtoul(buf_ptr, NULL, 0);
if (adjust) {
alarm += now;
}
if (alarm > now) {
if (alarm > now || push) {
/* Avoid accidentally clobbering active alarms; we can't
* entirely prevent that here, without even the minimal
* locking from the /dev/rtcN api.
*/
retval = rtc_read_alarm(rtc, &alm);
if (retval < 0)
return retval;
if (alm.enabled)
return -EBUSY;

if (alm.enabled) {
if (push) {
rtc_tm_to_time(&alm.time, &push);
alarm += push;
} else
return -EBUSY;
} else if (push)
return -EINVAL;
alm.enabled = 1;
} else {
alm.enabled = 0;
Expand Down

0 comments on commit 1df0a47

Please sign in to comment.