Skip to content

Commit 42a929e

Browse files
alexandrebellonigregkh
authored andcommitted
rtc: disable uie before setting time and enable after
commit 7e7c005 upstream. When setting the time in the future with the uie timer enabled, rtc_timer_do_work will loop for a while because the expiration of the uie timer was way before the current RTC time and a new timer will be enqueued until the current rtc time is reached. If the uie timer is enabled, disable it before setting the time and enable it after expiring current timers (which may actually be an alarm). This is the safest thing to do to ensure the uie timer is still synchronized with the RTC, especially in the UIE emulation case. Reported-by: [email protected] Fixes: 6610e08 ("RTC: Rework RTC code to use timerqueue for events") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Belloni <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 32b02bf commit 42a929e

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

drivers/rtc/interface.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ EXPORT_SYMBOL_GPL(rtc_read_time);
127127

128128
int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
129129
{
130-
int err;
130+
int err, uie;
131131

132132
err = rtc_valid_tm(tm);
133133
if (err != 0)
@@ -139,6 +139,17 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
139139

140140
rtc_subtract_offset(rtc, tm);
141141

142+
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
143+
uie = rtc->uie_rtctimer.enabled || rtc->uie_irq_active;
144+
#else
145+
uie = rtc->uie_rtctimer.enabled;
146+
#endif
147+
if (uie) {
148+
err = rtc_update_irq_enable(rtc, 0);
149+
if (err)
150+
return err;
151+
}
152+
142153
err = mutex_lock_interruptible(&rtc->ops_lock);
143154
if (err)
144155
return err;
@@ -162,6 +173,12 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
162173
/* A timer might have just expired */
163174
schedule_work(&rtc->irqwork);
164175

176+
if (uie) {
177+
err = rtc_update_irq_enable(rtc, 1);
178+
if (err)
179+
return err;
180+
}
181+
165182
trace_rtc_set_time(rtc_tm_to_time64(tm), err);
166183
return err;
167184
}

0 commit comments

Comments
 (0)