2016-06-04 16:46 GMT+02:00 Alexandre Belloni <alexandre.bell...@free-electrons.com>: > Hi, > > On 01/06/2016 at 17:40:14 +0200, Gabriele Mazzotta wrote : >> If the system wakes up because of a wake alarm, the internal state >> of the alarm is not updated. As consequence, the state no longer >> reflects the actual state of the hardware and setting a new alarm >> is not possible until the expired alarm is cleared. >> > > I'm not completely sure to understand what is happening but could you > check whether that one is solved by > 2b2f5ff00f63847d95adad6289bd8b05f5983dd5 in my tree (rtc-next). >
I picked 2b2f5ff00f63847d95adad6289bd8b05f5983dd5 and applied it on top of 4.7-rc1, but that didn't fix the problem. Let me explain the problem by showing you how I reproduce it: root@localhost:~# cat /proc/driver/rtc | grep alarm_IRQ alarm_IRQ : no root@localhost:~# echo +10 > /sys/class/rtc/rtc0/wakealarm root@localhost:~# echo mem > /sys/power/state # wait for auto-resume root@localhost:~# echo +10 > /sys/class/rtc/rtc0/wakealarm bash: echo: write error: Device or resource busy root@localhost:~# cat /proc/driver/rtc | grep alarm_IRQ alarm_IRQ : yes To set another alarm, I have to first write 0 to wakealarm. After that I can set what I want. This doesn't happen if the alarm fires while the system is awake, it happens only if the system is suspended and the alarm wakes it. I actually forgot to say that maybe this problem is not limited to rtc-cmos and that maybe a general solution could be used. I've just looked better into what is causing this and the problem seems to be caused by the fact that rtc_timer_do_work() is not executed if the timer expires while the system is suspended. The following solves this particular problem: diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 74fd974..80d6a12 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -102,6 +102,9 @@ static int rtc_resume(struct device *dev) struct timespec64 sleep_time; int err; + /* A timer might have expired while suspended */ + schedule_work(&rtc->irqwork); + if (timekeeping_rtc_skipresume()) return 0; > -- > Alexandre Belloni, Free Electrons > Embedded Linux, Kernel and Android engineering > http://free-electrons.com