diff options
Diffstat (limited to 'drivers/rtc/rtc-dev.c')
-rw-r--r-- | drivers/rtc/rtc-dev.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 671b14ec28bb..f4e5f0040ff7 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -277,12 +277,48 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
277 | 277 | ||
278 | alarm.enabled = 0; | 278 | alarm.enabled = 0; |
279 | alarm.pending = 0; | 279 | alarm.pending = 0; |
280 | alarm.time.tm_mday = -1; | ||
281 | alarm.time.tm_mon = -1; | ||
282 | alarm.time.tm_year = -1; | ||
283 | alarm.time.tm_wday = -1; | 280 | alarm.time.tm_wday = -1; |
284 | alarm.time.tm_yday = -1; | 281 | alarm.time.tm_yday = -1; |
285 | alarm.time.tm_isdst = -1; | 282 | alarm.time.tm_isdst = -1; |
283 | |||
284 | /* RTC_ALM_SET alarms may be up to 24 hours in the future. | ||
285 | * Rather than expecting every RTC to implement "don't care" | ||
286 | * for day/month/year fields, just force the alarm to have | ||
287 | * the right values for those fields. | ||
288 | * | ||
289 | * RTC_WKALM_SET should be used instead. Not only does it | ||
290 | * eliminate the need for a separate RTC_AIE_ON call, it | ||
291 | * doesn't have the "alarm 23:59:59 in the future" race. | ||
292 | * | ||
293 | * NOTE: some legacy code may have used invalid fields as | ||
294 | * wildcards, exposing hardware "periodic alarm" capabilities. | ||
295 | * Not supported here. | ||
296 | */ | ||
297 | { | ||
298 | unsigned long now, then; | ||
299 | |||
300 | err = rtc_read_time(rtc, &tm); | ||
301 | if (err < 0) | ||
302 | return err; | ||
303 | rtc_tm_to_time(&tm, &now); | ||
304 | |||
305 | alarm.time.tm_mday = tm.tm_mday; | ||
306 | alarm.time.tm_mon = tm.tm_mon; | ||
307 | alarm.time.tm_year = tm.tm_year; | ||
308 | err = rtc_valid_tm(&alarm.time); | ||
309 | if (err < 0) | ||
310 | return err; | ||
311 | rtc_tm_to_time(&alarm.time, &then); | ||
312 | |||
313 | /* alarm may need to wrap into tomorrow */ | ||
314 | if (then < now) { | ||
315 | rtc_time_to_tm(now + 24 * 60 * 60, &tm); | ||
316 | alarm.time.tm_mday = tm.tm_mday; | ||
317 | alarm.time.tm_mon = tm.tm_mon; | ||
318 | alarm.time.tm_year = tm.tm_year; | ||
319 | } | ||
320 | } | ||
321 | |||
286 | err = rtc_set_alarm(rtc, &alarm); | 322 | err = rtc_set_alarm(rtc, &alarm); |
287 | break; | 323 | break; |
288 | 324 | ||