On Sun, Jul 5, 2015 at 8:39 AM, Dmitry Osipenko <dig...@gmail.com> wrote: > Timer, running in periodic mode, can't be stopped or coming one-shot > tick won't be canceled because timer control code just doesn't handle > timer disabling. Fix it by deleting the timer if enable bit isn't set. > > Timer won't start periodic ticking if ONE-SHOT -> PERIODIC mode change > happened after one-shot tick was completed. Fix it by starting ticking > only if the timer isn't ticking right now. > > To avoid code churning, these two fixes are squashed in one commit. > > Signed-off-by: Dmitry Osipenko <dig...@gmail.com> > --- > > Commits are squashed as per Peter Crosthwaite suggestion. > > hw/timer/arm_mptimer.c | 11 +++++++++-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c > index 8b93b3c..0e132b1 100644 > --- a/hw/timer/arm_mptimer.c > +++ b/hw/timer/arm_mptimer.c > @@ -122,11 +122,18 @@ static void timerblock_write(void *opaque, hwaddr addr, > case 8: /* Control. */ > old = tb->control; > tb->control = value; > - if (((old & 1) == 0) && (value & 1)) { > - if (tb->count == 0 && (tb->control & 2)) { > + if (value & 1) { > + if ((old & 1) && (tb->count != 0)) { > + /* Do nothing if timer is ticking right now. */ > + break; > + } > + if (tb->control & 2) {
So when the timer was previously disabled (!(old & 1)) and the count is non-zero this will cause a spurious auto-reload. I don't this causes a bug today because the code as-is doesn't support arbitrary count values, but it is a developer trap should the assumption that tb->count equals either 0 or the reload value not hold true. > tb->count = tb->load; > } > timerblock_reload(tb, 1); > + } else if (old & 1) { > + /* Shutdown the timer. */ > + timer_del(tb->timer); In general, this seems to now dup the code paths for control and load/counter writes. Both now have a del and reload call for various changes-of state. I had a go to see if I can consolidate. Turns out, doing so should implement timer pause and resumption while fixing both of your bugs, I'll send some patches. Regards, Peter > } > break; > case 12: /* Interrupt status. */ > -- > 2.4.4 > >