2011-04-04 06:49:36     Gptimer issues

Document created by Aaronwu Employee on Aug 26, 2013
Version 1Show Document
  • View in full screen mode

2011-04-04 06:49:36     Gptimer issues

isabelle leonardi (FRANCE)

Message: 99561   


Hi all,


We are currently running 2010-RC5 on a blackfin 548. Our linux configuration includes, among others, CONFIG_NO_HZ and CONFIG_HIGH_RES_TIMERS.


We experienced scheduling issues (see Thread named "Scheduling issues"). We found out that one reason comes from the idle_with_irq_disabled() macro (in arch/blackfin/include/asm/irq.h) that performs the following sequence of operations:


  sti %0




If an interrupt occurs between sti and idle (and we did observe it), after the handler ends, the system enters idle without properly scheduling the task that way have been awaken by the IT.


To work around this, we made the following changes:


- updated the arch/blackfin/mach-common/ints-priority.c to update SIC_IWRx registers when enabling/disabling interrupts so that the IDLE instruction is interrupted by any peripheral interrupt


- set up the kernel to use GPTIMER0 as the clock source (so that is wakes up the idle instruction too)


- remove the "sti %0"  instruction before the "idle" instruction in idle_with_irq_disabled() macro.




When testing this workaround, we discovered 2 issues relative implementation of gptimers in linux:


1. In arch/blackfin/kernel/gptimers.c, disable_gptimers() should reset only the flags relative to the timer to disable.


the original code


      group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i];



was resetting any bit set in the TIMER_STATUS register. When several timers are in use and 2 timers have finished their period, the first call to disable_gptimers impacts both timers. If the second timer was configured to trigger an interrupt, this interrupt was lost.


We changed this line into:


     group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i] | timil_mask[i] | tovf_mask[i];



2. In arch/blackfin/kernel/time-ts.c, bfin_gptmr0_interrupt() was acknowledging the IT after calling the timer callback. The problem is that the callback (responsible for hrtimers) rearms the timer and if the width is small enough, the timer expires before the end of the previous interrupt handler and by acklowledging the IT at the end of the IT handler, the IT for the newly expired timer is lost. The consequence for a NO_HZ system is that the scheduler and the hrtimer callbacks are no more run and the system does not respond anymore.


We simply invert the lines bfin_gptmr0_interrupt():






By implementing all these changes, our system is now running for several days without any problem.


Maybe it would be useful to include these fixes in a future release.


Best regards,






2011-04-04 11:26:38     Re: Gptimer issues

Mike Frysinger (UNITED STATES)

Message: 99571   


thanks, that disable_gptimers is clearly a thinko.  ive changed it to only clear the run bit now.  i'm not sure we want it to clear the other bits when disabling, so ive left that part out.


the 2nd part makes sense too, so ive added a comment to the source and inverted the steps as you suggested.