diff options
-rw-r--r-- | Documentation/rtc.txt | 7 | ||||
-rw-r--r-- | drivers/rtc/rtc-sysfs.c | 20 |
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 | |||
153 | time: RTC-provided time | 153 | time: RTC-provided time |
154 | wakealarm: The time at which the clock will generate a system wakeup | 154 | wakealarm: 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 | ||
160 | IOCTL INTERFACE | 161 | IOCTL 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; |