Message ID | 1463415774-28014-1-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
Hi Colin, On 16/05/2016 at 17:22:54 +0100, Colin King wrote : > From: Colin Ian King <colin.king@canonical.com> > > This patch fixes a RTC wakealarm issue, namely, the event fires during > hibernate and is not cleared from the list, causing hwclock to block. > > The current enqueuing does not trigger an alarm if any expired timers > already exist on the timerqueue. This can occur when a RTC wake alarm > is used to wake a machine out of hibernate and the resumed state has > old expired timers that have not been removed from the timer queue. > This fix skips over any expired timers and triggers an alarm if there > are no pending timers on the timerqueue. Note that the skipped expired > timer will get repead later on, so there is no need to clean it up > immediately. > > The issue can be reproduced by putting a machine into hibernate and > waking it with the RTC wakealarm. Running the example RTC test program > from tools/testing/selftests/timers/rtctest.c after the hibernate will > block indefinitely. With the fix, it no longer blocks after the > hibernate resume. > > BugLink: http://bugs.launchpad.net/bugs/1333569 > > Signed-off-by: Colin Ian King <colin.king@canonical.com> Thanks for the resend. I was still planning to have a look at the patch you send in September 2014. I believe that one replaces it. I'll definitely have a look after 4.7-rc1.
On 16/05/2016 at 17:22:54 +0100, Colin King wrote : > From: Colin Ian King <colin.king@canonical.com> > > This patch fixes a RTC wakealarm issue, namely, the event fires during > hibernate and is not cleared from the list, causing hwclock to block. > > The current enqueuing does not trigger an alarm if any expired timers > already exist on the timerqueue. This can occur when a RTC wake alarm > is used to wake a machine out of hibernate and the resumed state has > old expired timers that have not been removed from the timer queue. > This fix skips over any expired timers and triggers an alarm if there > are no pending timers on the timerqueue. Note that the skipped expired > timer will get repead later on, so there is no need to clean it up > immediately. > > The issue can be reproduced by putting a machine into hibernate and > waking it with the RTC wakealarm. Running the example RTC test program > from tools/testing/selftests/timers/rtctest.c after the hibernate will > block indefinitely. With the fix, it no longer blocks after the > hibernate resume. > > BugLink: http://bugs.launchpad.net/bugs/1333569 > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > drivers/rtc/interface.c | 16 +++++++++++++++- > 1 file changed, 15 insertions(+), 1 deletion(-) > Applied, thanks.
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 9ef5f6f..7fa910f 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -748,9 +748,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); */ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) { + struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); + struct rtc_time tm; + ktime_t now; + timer->enabled = 1; + __rtc_read_time(rtc, &tm); + now = rtc_tm_to_ktime(tm); + + /* Skip over expired timers */ + while (next) { + if (next->expires.tv64 >= now.tv64) + break; + next = timerqueue_iterate_next(next); + } + timerqueue_add(&rtc->timerqueue, &timer->node); - if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { + if (!next) { struct rtc_wkalrm alarm; int err; alarm.time = rtc_ktime_to_tm(timer->node.expires);