mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
rtc: add ability to push out an existing wakealarm using sysfs
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>
This commit is contained in:
parent
c67d96e317
commit
1df0a4711f
2 changed files with 19 additions and 8 deletions
|
@ -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
|
||||
---------------
|
||||
|
|
|
@ -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;
|
||||
|
@ -180,13 +181,17 @@ 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.
|
||||
|
@ -194,9 +199,14 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue