From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37248) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAnLW-0001tA-HQ for qemu-devel@nongnu.org; Thu, 02 Jul 2015 18:52:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZAnLV-0001gZ-NP for qemu-devel@nongnu.org; Thu, 02 Jul 2015 18:52:42 -0400 Received: from mail-lb0-x22f.google.com ([2a00:1450:4010:c04::22f]:33555) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAnLV-0001gL-Fa for qemu-devel@nongnu.org; Thu, 02 Jul 2015 18:52:41 -0400 Received: by lbcui10 with SMTP id ui10so40261747lbc.0 for ; Thu, 02 Jul 2015 15:52:40 -0700 (PDT) From: Dmitry Osipenko Date: Fri, 3 Jul 2015 01:52:09 +0300 Message-Id: <1435877531-24983-2-git-send-email-digetx@gmail.com> In-Reply-To: <1435877531-24983-1-git-send-email-digetx@gmail.com> References: <1435877531-24983-1-git-send-email-digetx@gmail.com> Subject: [Qemu-devel] [PATCH 1/3 v3] 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. v3: Do not change "reload the timer" logic as it is separate bug. 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..e230063 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) == (value & 1)) { + 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