diff mbox

arm_mptimer: Fix timer shutdown

Message ID 1435785330-7384-1-git-send-email-digetx@gmail.com
State New
Headers show

Commit Message

Dmitry Osipenko July 1, 2015, 9:15 p.m. UTC
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 checking enable bit and deleting timer if bit isn't set.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 hw/timer/arm_mptimer.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

Peter Maydell July 2, 2015, 9:27 a.m. UTC | #1
On 1 July 2015 at 22:15, Dmitry Osipenko <digetx@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 checking enable bit and deleting timer if bit isn't set.
>
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  hw/timer/arm_mptimer.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
> index 8b93b3c..917a10f 100644
> --- a/hw/timer/arm_mptimer.c
> +++ b/hw/timer/arm_mptimer.c
> @@ -127,6 +127,9 @@ static void timerblock_write(void *opaque, hwaddr addr,
>                  tb->count = tb->load;
>              }
>              timerblock_reload(tb, 1);
> +        } else if (!(value & 1)) {
> +            /* Shutdown timer.  */
> +            timer_del(tb->timer);
>          }
>          break;
>      case 12: /* Interrupt status.  */

Thanks; this does look like a bug. This change will mean we
call timer_del() even if the timer was already disabled,
though, so I think it would be slightly better to rearrange
the existing logic something like this:

  if ((old & 1) != (value & 1)) {
     if (value & 1) {
         if (tb->count == 0 && (tb->control & 2)) {
             tb->count = tb->load;
         }
         timerblock_reload(tb, 1);
     } else {
         timer_del(tb->timer);
     }
  }

thanks
-- PMM
Dmitry Osipenko July 2, 2015, 12:10 p.m. UTC | #2
Hello Peter, thanks a lot for comment.

02.07.2015 12:27, Peter Maydell пишет:
> Thanks; this does look like a bug. This change will mean we
> call timer_del() even if the timer was already disabled,
> though, so I think it would be slightly better to rearrange
> the existing logic something like this:
>
>    if ((old & 1) != (value & 1)) {
>       if (value & 1) {
>           if (tb->count == 0 && (tb->control & 2)) {
>               tb->count = tb->load;
>           }
>           timerblock_reload(tb, 1);
>       } else {
>           timer_del(tb->timer);
>       }
>    }
>
> thanks
> -- PMM
>

Calling timer_del() twice is safe, but I agree that it would be better to avoid 
it. I'll send V2.
diff mbox

Patch

diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 8b93b3c..917a10f 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -127,6 +127,9 @@  static void timerblock_write(void *opaque, hwaddr addr,
                 tb->count = tb->load;
             }
             timerblock_reload(tb, 1);
+        } else if (!(value & 1)) {
+            /* Shutdown timer.  */
+            timer_del(tb->timer);
         }
         break;
     case 12: /* Interrupt status.  */