|
@@ -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;
|