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