aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/rtc.txt7
-rw-r--r--drivers/rtc/rtc-sysfs.c20
2 files changed, 19 insertions, 8 deletions
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 32aa4002de4a..596b60c08b74 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -153,9 +153,10 @@ since_epoch: The number of seconds since the epoch according to the RTC
153time: RTC-provided time 153time: RTC-provided time
154wakealarm: The time at which the clock will generate a system wakeup 154wakealarm: The time at which the clock will generate a system wakeup
155 event. This is a one shot wakeup event, so must be reset 155 event. This is a one shot wakeup event, so must be reset
156 after wake if a daily wakeup is required. Format is either 156 after wake if a daily wakeup is required. Format is seconds since
157 seconds since the epoch or, if there's a leading +, seconds 157 the epoch by default, or if there's a leading +, seconds in the
158 in the future. 158 future, or if there is a leading +=, seconds ahead of the current
159 alarm.
159 160
160IOCTL INTERFACE 161IOCTL INTERFACE
161--------------- 162---------------
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index b70e2bb63645..4b26f8672b2d 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -164,6 +164,7 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
164{ 164{
165 ssize_t retval; 165 ssize_t retval;
166 unsigned long now, alarm; 166 unsigned long now, alarm;
167 unsigned long push = 0;
167 struct rtc_wkalrm alm; 168 struct rtc_wkalrm alm;
168 struct rtc_device *rtc = to_rtc_device(dev); 169 struct rtc_device *rtc = to_rtc_device(dev);
169 char *buf_ptr; 170 char *buf_ptr;
@@ -180,13 +181,17 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
180 buf_ptr = (char *)buf; 181 buf_ptr = (char *)buf;
181 if (*buf_ptr == '+') { 182 if (*buf_ptr == '+') {
182 buf_ptr++; 183 buf_ptr++;
183 adjust = 1; 184 if (*buf_ptr == '=') {
185 buf_ptr++;
186 push = 1;
187 } else
188 adjust = 1;
184 } 189 }
185 alarm = simple_strtoul(buf_ptr, NULL, 0); 190 alarm = simple_strtoul(buf_ptr, NULL, 0);
186 if (adjust) { 191 if (adjust) {
187 alarm += now; 192 alarm += now;
188 } 193 }
189 if (alarm > now) { 194 if (alarm > now || push) {
190 /* Avoid accidentally clobbering active alarms; we can't 195 /* Avoid accidentally clobbering active alarms; we can't
191 * entirely prevent that here, without even the minimal 196 * entirely prevent that here, without even the minimal
192 * locking from the /dev/rtcN api. 197 * locking from the /dev/rtcN api.
@@ -194,9 +199,14 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
194 retval = rtc_read_alarm(rtc, &alm); 199 retval = rtc_read_alarm(rtc, &alm);
195 if (retval < 0) 200 if (retval < 0)
196 return retval; 201 return retval;
197 if (alm.enabled) 202 if (alm.enabled) {
198 return -EBUSY; 203 if (push) {
199 204 rtc_tm_to_time(&alm.time, &push);
205 alarm += push;
206 } else
207 return -EBUSY;
208 } else if (push)
209 return -EINVAL;
200 alm.enabled = 1; 210 alm.enabled = 1;
201 } else { 211 } else {
202 alm.enabled = 0; 212 alm.enabled = 0;