From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58719) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAiDM-0006Tu-9D for qemu-devel@nongnu.org; Thu, 02 Jul 2015 13:23:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZAiDJ-0003pw-4O for qemu-devel@nongnu.org; Thu, 02 Jul 2015 13:23:56 -0400 Received: from mail-la0-x22e.google.com ([2a00:1450:4010:c03::22e]:33155) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAiDI-0003pl-SP for qemu-devel@nongnu.org; Thu, 02 Jul 2015 13:23:53 -0400 Received: by laar3 with SMTP id r3so65737918laa.0 for ; Thu, 02 Jul 2015 10:23:52 -0700 (PDT) From: Dmitry Osipenko Date: Thu, 2 Jul 2015 20:20:02 +0300 Message-Id: <1435857603-30613-1-git-send-email-digetx@gmail.com> In-Reply-To: <55952A1D.2030806@gmail.com> References: <55952A1D.2030806@gmail.com> Subject: [Qemu-devel] [PATCH v2] arm_mptimer: Fix timer shutdown List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Peter Maydell Cc: Paolo Bonzini , Peter Crosthwaite , QEMU Developers 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 timer if enable bit isn't set. Signed-off-by: Dmitry Osipenko --- v2: Avoid calling timer_del() if the timer was already disabled as per Peter Maydell suggestion. hw/timer/arm_mptimer.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 8b93b3c..51c18de 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -122,11 +122,17 @@ static void timerblock_write(void *opaque, hwaddr addr, case 8: /* Control. */ old = tb->control; tb->control = value; - if (((old & 1) == 0) && (value & 1)) { + if (((old & 1) == 0) && ((value & 1) == 0)) { + break; + } + if (value & 1) { if (tb->count == 0 && (tb->control & 2)) { tb->count = tb->load; } timerblock_reload(tb, 1); + } else { + /* Shutdown timer. */ + timer_del(tb->timer); } break; case 12: /* Interrupt status. */ -- 2.4.4