Re: Problem when function alarmtimer_suspend returns 0 if time delta is zero
From: Alexandre Belloni
Date: Mon Sep 02 2019 - 03:49:23 EST
Hello Michael,
This code is maintained by the timekeeping maintainers, now in Cc and I
think John will be able to answer.
On 31/08/2019 20:32:06+0200, Michael wrote:
> Dear members of the linux-rtc list,
>
> currently I have a problem with the alarmtimer i'm using to cyclically wake
> up my i.MX6 ULL board from suspend to RAM.
>
> The problem is that in principle the timer wake ups work fine but seem to be
> not 100% stable. In about 1 percent the wake up alarm from suspend is
> missing.
>
> When I look at the code of alarmtimer in function alarmtimer_suspend
> (kernel/time/alarmtimer.c)
> I find the following:
>
> ....
>
> /* Find the soonest timer to expire*/
>
> for (i = 0; i < ALARM_NUMTYPE; i++) {
> struct alarm_base *base = &alarm_bases[i];
> struct timerqueue_node *next;
> ktime_t delta;
>
> spin_lock_irqsave(&base->lock, flags);
> next = timerqueue_getnext(&base->timerqueue);
> spin_unlock_irqrestore(&base->lock, flags);
> if (!next)
> continue;
> delta = ktime_sub(next->expires, base->gettime());
> if (!min || (delta < min)) {
> expires = next->expires;
> min = delta;
> type = i;
> }
> }
> if (min == 0)
> return 0;
>
> if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
> __pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
> return -EBUSY;
> }
>
> In my error case the alarm wake up always fails if the path "if(min==0)" is
> entered. If I understand this code correctly that means that
> when ever one of the timers in the list has a remaining tick time of zero,
> the function just returns 0 and continues the suspend process until
> it reaches suspend mode.
>
> If I implement a hack here "if(min == 0) {min = 1;}" and do not return, my
> system runs 100% ok, as the following -EBUSY path is hit.
>
> So my question to you is: Why is there a check if min < 2 seconds and do a
> return -EBUSY here, but handle (min==0) differently?
> Could there be some race condition here, where the function
> alarmtimer_suspend just returns 0 and shortly after this the alarmtimer
> expires
> right before the RTC driver was able to allow the wake up interrupt?
>
> If I look through the kernel versions I found the alarmtimer_suspend to be a
> very stable function, so I don't think there is anything wrong here.
>
> But do you have a hint for me where else I could have a look to encircle the
> error?
>
> Thank you very much!
>
> Br,
> Michael
>
--
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com