From 323a8771cfb96ab752c9d27e939a2fbac1380b1c Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 25 Mar 2014 19:22:06 +0100 Subject: [PATCH] allwinner-a10-pit: avoid generation of spurious interrupts The model was generating interrupts for all enabled timers after the expiration of one of them. Avoid this by passing explicitly the timer index to the callback function. Signed-off-by: Beniamino Galvani Reviewed-by: Li Guang Reviewed-by: Peter Crosthwaite Message-id: 1395771730-16882-4-git-send-email-b.galvani@gmail.com [PMM: avoid duplicate typedef of AwA10PITState] Signed-off-by: Peter Maydell --- hw/timer/allwinner-a10-pit.c | 25 ++++++++++++++----------- include/hw/timer/allwinner-a10-pit.h | 12 ++++++++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c index b27fce8cd2..696b7d9977 100644 --- a/hw/timer/allwinner-a10-pit.c +++ b/hw/timer/allwinner-a10-pit.c @@ -193,18 +193,17 @@ static void a10_pit_reset(DeviceState *dev) static void a10_pit_timer_cb(void *opaque) { - AwA10PITState *s = AW_A10_PIT(opaque); - uint8_t i; + AwA10TimerContext *tc = opaque; + AwA10PITState *s = tc->container; + uint8_t i = tc->index; - for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) { - if (s->control[i] & AW_A10_PIT_TIMER_EN) { - s->irq_status |= 1 << i; - if (s->control[i] & AW_A10_PIT_TIMER_MODE) { - ptimer_stop(s->timer[i]); - s->control[i] &= ~AW_A10_PIT_TIMER_EN; - } - qemu_irq_pulse(s->irq[i]); + if (s->control[i] & AW_A10_PIT_TIMER_EN) { + s->irq_status |= 1 << i; + if (s->control[i] & AW_A10_PIT_TIMER_MODE) { + ptimer_stop(s->timer[i]); + s->control[i] &= ~AW_A10_PIT_TIMER_EN; } + qemu_irq_pulse(s->irq[i]); } } @@ -223,7 +222,11 @@ static void a10_pit_init(Object *obj) sysbus_init_mmio(sbd, &s->iomem); for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) { - bh[i] = qemu_bh_new(a10_pit_timer_cb, s); + AwA10TimerContext *tc = &s->timer_context[i]; + + tc->container = s; + tc->index = i; + bh[i] = qemu_bh_new(a10_pit_timer_cb, tc); s->timer[i] = ptimer_init(bh[i]); ptimer_set_freq(s->timer[i], 240000); } diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h index 15efab8b5f..2158fc0d7b 100644 --- a/include/hw/timer/allwinner-a10-pit.h +++ b/include/hw/timer/allwinner-a10-pit.h @@ -35,12 +35,20 @@ #define AW_A10_PIT_DEFAULT_CLOCK 0x4 -typedef struct AwA10PITState { +typedef struct AwA10PITState AwA10PITState; + +typedef struct AwA10TimerContext { + AwA10PITState *container; + int index; +} AwA10TimerContext; + +struct AwA10PITState { /*< private >*/ SysBusDevice parent_obj; /*< public >*/ qemu_irq irq[AW_A10_PIT_TIMER_NR]; ptimer_state * timer[AW_A10_PIT_TIMER_NR]; + AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR]; MemoryRegion iomem; uint32_t irq_enable; @@ -53,6 +61,6 @@ typedef struct AwA10PITState { uint32_t count_lo; uint32_t count_hi; uint32_t count_ctl; -} AwA10PITState; +}; #endif