qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/21] transaction-based ptimer API
@ 2019-10-08 17:17 Peter Maydell
  2019-10-08 17:17 ` [PATCH v2 01/21] ptimer: Rename ptimer_init() to ptimer_init_with_bh() Peter Maydell
                   ` (20 more replies)
  0 siblings, 21 replies; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Currently the ptimer design uses a QEMU bottom-half as its mechanism
for calling back into the device model using the ptimer when the
timer has expired.  Unfortunately this design is fatally flawed,
because it means that there is a lag between the ptimer updating its
own state and the device callback function updating device state, and
guest accesses to device registers between the two can return
inconsistent device state. This was reported as a bug in a specific
timer device but it's a problem with the generic ptimer code:
https://bugs.launchpad.net/qemu/+bug/1777777

This patchset introduces a change to the ptimer API so that instead
of using a bottom-half for the trigger a device can choose to use a
new 'transaction' based approach.  In this design (suggested by RTH)
all calls which modify ptimer state:
     - ptimer_set_period()
     - ptimer_set_freq()
     - ptimer_set_limit()
     - ptimer_set_count()
     - ptimer_run()
     - ptimer_stop()
must be between matched calls to ptimer_transaction_begin() and
ptimer_transaction_commit().  When ptimer_transaction_commit() is
called it will evaluate the state of the timer after all the changes
in the transaction, and call the callback if necessary.
The callback itself is called from within a transaction block,
so any changes it makes to ptimer state that re-trigger the
timer will mean the callback is called again once it has returned.

Changes since the v1 RFC patchset:
 - In the ptimer implementation patch itself:
     * ptimer_transaction_begin() now sets need_reload to false
     * fixed assert condition in ptimer_transaction_begin()
     * ptimer_transaction_commit() now has a loop to call
       ptimer_reload() again if the callback function updated
       the ptimer state such that it needs to trigger again
     * fixed callback_opaque arg name mismatch in doc comment
     * don't cache delta, period, etc across ptimer_trigger() call,
       because the device's trigger function might update ptimer
       state
 - New patches which update all the devices used in various
   Arm boards to the new transaction-based API

(Most of the bugfixes listed are the result of the extra testing
in the wider variety of ptimer use cases. Thanks in particular
to Philippe for putting together a test image for the exynos4210,
which has several ptimer-using devices some of which are pretty
complicated.)

There are ten non-arm devices using ptimer:

microblaze and ppc:
  hw/timer/xilinx_timer.c
ppc:
  hw/net/fsl_etsec/etsec.c
nios2:
  hw/timer/altera_timer.c
cris:
  hw/timer/etraxfs_timer.c
lm32:
  hw/timer/lm32_timer.c
  hw/timer/milkymist-sysctl.c
sparc:
  hw/timer/grlib_gptimer.c
  hw/timer/slavio_timer.c
sh4:
  hw/timer/sh_timer.c
unicore32:
  hw/timer/puv3_ost.c

I do plan to convert those as well but this series seems big
enough to be going on with, and it means I can avoid the
awkwardness of getting acks from multiple submaintainers
on top of wrangling a big patchset.

thanks
-- PMM

Peter Maydell (21):
  ptimer: Rename ptimer_init() to ptimer_init_with_bh()
  ptimer: Provide new transaction-based API
  tests/ptimer-test: Switch to transaction-based ptimer API
  hw/timer/arm_timer.c: Switch to transaction-based ptimer API
  hw/arm/musicpal.c: Switch to transaction-based ptimer API
  hw/timer/allwinner-a10-pit.c: Switch to transaction-based ptimer API
  hw/timer/arm_mptimer.c: Switch to transaction-based ptimer API
  hw/timer/cmsdk-apb-dualtimer.c: Switch to transaction-based ptimer API
  hw/timer/cmsdk-apb-timer.c: Switch to transaction-based ptimer API
  hw/timer/digic-timer.c: Switch to transaction-based ptimer API
  hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  hw/timer/exynos4210_mct.c: Switch LFRC to transaction-based ptimer API
  hw/timer/exynos4210_mct.c: Switch ltick to transaction-based ptimer
    API
  hw/timer/exynos4210_pwm.c: Switch to transaction-based ptimer API
  hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API
  hw/timer/exynos4210_rtc.c: Switch main ptimer to transaction-based API
  hw/timer/imx_epit.c: Switch to transaction-based ptimer API
  hw/timer/imx_gpt.c: Switch to transaction-based ptimer API
  hw/timer/mss-timerc: Switch to transaction-based ptimer API
  hw/watchdog/cmsdk-apb-watchdog.c: Switch to transaction-based ptimer
    API
  hw/net/lan9118.c: Switch to transaction-based ptimer API

 include/hw/ptimer.h              |  83 ++++++++++++++++-
 include/hw/timer/mss-timer.h     |   1 -
 hw/arm/musicpal.c                |  16 ++--
 hw/core/ptimer.c                 | 154 +++++++++++++++++++++++++++----
 hw/dma/xilinx_axidma.c           |   2 +-
 hw/m68k/mcf5206.c                |   2 +-
 hw/m68k/mcf5208.c                |   2 +-
 hw/net/fsl_etsec/etsec.c         |   2 +-
 hw/net/lan9118.c                 |  11 ++-
 hw/timer/allwinner-a10-pit.c     |  12 ++-
 hw/timer/altera_timer.c          |   2 +-
 hw/timer/arm_mptimer.c           |  18 +++-
 hw/timer/arm_timer.c             |  16 +++-
 hw/timer/cmsdk-apb-dualtimer.c   |  14 ++-
 hw/timer/cmsdk-apb-timer.c       |  15 ++-
 hw/timer/digic-timer.c           |  16 +++-
 hw/timer/etraxfs_timer.c         |   6 +-
 hw/timer/exynos4210_mct.c        | 107 ++++++++++++++++++---
 hw/timer/exynos4210_pwm.c        |  17 +++-
 hw/timer/exynos4210_rtc.c        |  22 +++--
 hw/timer/grlib_gptimer.c         |   2 +-
 hw/timer/imx_epit.c              |  32 ++++++-
 hw/timer/imx_gpt.c               |  21 ++++-
 hw/timer/lm32_timer.c            |   2 +-
 hw/timer/milkymist-sysctl.c      |   4 +-
 hw/timer/mss-timer.c             |  11 ++-
 hw/timer/puv3_ost.c              |   2 +-
 hw/timer/sh_timer.c              |   2 +-
 hw/timer/slavio_timer.c          |   2 +-
 hw/timer/xilinx_timer.c          |   2 +-
 hw/watchdog/cmsdk-apb-watchdog.c |  13 ++-
 tests/ptimer-test.c              | 106 ++++++++++++++++-----
 32 files changed, 584 insertions(+), 133 deletions(-)

-- 
2.20.1



^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v2 01/21] ptimer: Rename ptimer_init() to ptimer_init_with_bh()
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-08 17:17 ` [PATCH v2 02/21] ptimer: Provide new transaction-based API Peter Maydell
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Currently the ptimer design uses a QEMU bottom-half as its
mechanism for calling back into the device model using the
ptimer when the timer has expired. Unfortunately this design
is fatally flawed, because it means that there is a lag
between the ptimer updating its own state and the device
callback function updating device state, and guest accesses
to device registers between the two can return inconsistent
device state.

We want to replace the bottom-half design with one where
the guest device's callback is called either immediately
(when the ptimer triggers by timeout) or when the device
model code closes a transaction-begin/end section (when the
ptimer triggers because the device model changed the
ptimer's count value or other state). As the first step,
rename ptimer_init() to ptimer_init_with_bh(), to free up
the ptimer_init() name for the new API. We can then convert
all the ptimer users away from ptimer_init_with_bh() before
removing it entirely.

(Commit created with
 git grep -l ptimer_init | xargs sed -i -e 's/ptimer_init/ptimer_init_with_bh/'
and three overlong lines folded by hand.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/hw/ptimer.h              | 11 ++++++-----
 hw/arm/musicpal.c                |  2 +-
 hw/core/ptimer.c                 |  2 +-
 hw/dma/xilinx_axidma.c           |  2 +-
 hw/m68k/mcf5206.c                |  2 +-
 hw/m68k/mcf5208.c                |  2 +-
 hw/net/fsl_etsec/etsec.c         |  2 +-
 hw/net/lan9118.c                 |  2 +-
 hw/timer/allwinner-a10-pit.c     |  2 +-
 hw/timer/altera_timer.c          |  2 +-
 hw/timer/arm_mptimer.c           |  6 +++---
 hw/timer/arm_timer.c             |  2 +-
 hw/timer/cmsdk-apb-dualtimer.c   |  2 +-
 hw/timer/cmsdk-apb-timer.c       |  2 +-
 hw/timer/digic-timer.c           |  2 +-
 hw/timer/etraxfs_timer.c         |  6 +++---
 hw/timer/exynos4210_mct.c        |  7 ++++---
 hw/timer/exynos4210_pwm.c        |  2 +-
 hw/timer/exynos4210_rtc.c        |  4 ++--
 hw/timer/grlib_gptimer.c         |  2 +-
 hw/timer/imx_epit.c              |  4 ++--
 hw/timer/imx_gpt.c               |  2 +-
 hw/timer/lm32_timer.c            |  2 +-
 hw/timer/milkymist-sysctl.c      |  4 ++--
 hw/timer/mss-timer.c             |  2 +-
 hw/timer/puv3_ost.c              |  2 +-
 hw/timer/sh_timer.c              |  2 +-
 hw/timer/slavio_timer.c          |  2 +-
 hw/timer/xilinx_timer.c          |  2 +-
 hw/watchdog/cmsdk-apb-watchdog.c |  2 +-
 tests/ptimer-test.c              | 22 +++++++++++-----------
 31 files changed, 56 insertions(+), 54 deletions(-)

diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index 9c770552290..2fb9ba1915e 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -72,7 +72,7 @@
  * ptimer_set_count() or ptimer_set_limit() will not trigger the timer
  * (though it will cause a reload). Only a counter decrement to "0"
  * will cause a trigger. Not compatible with NO_IMMEDIATE_TRIGGER;
- * ptimer_init() will assert() that you don't set both.
+ * ptimer_init_with_bh() will assert() that you don't set both.
  */
 #define PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT (1 << 5)
 
@@ -81,7 +81,7 @@ typedef struct ptimer_state ptimer_state;
 typedef void (*ptimer_cb)(void *opaque);
 
 /**
- * ptimer_init - Allocate and return a new ptimer
+ * ptimer_init_with_bh - Allocate and return a new ptimer
  * @bh: QEMU bottom half which is run on timer expiry
  * @policy: PTIMER_POLICY_* bits specifying behaviour
  *
@@ -89,13 +89,13 @@ typedef void (*ptimer_cb)(void *opaque);
  * The ptimer takes ownership of @bh and will delete it
  * when the ptimer is eventually freed.
  */
-ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask);
+ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask);
 
 /**
  * ptimer_free - Free a ptimer
  * @s: timer to free
  *
- * Free a ptimer created using ptimer_init() (including
+ * Free a ptimer created using ptimer_init_with_bh() (including
  * deleting the bottom half which it is using).
  */
 void ptimer_free(ptimer_state *s);
@@ -178,7 +178,8 @@ void ptimer_set_count(ptimer_state *s, uint64_t count);
  * @oneshot: non-zero if this timer should only count down once
  *
  * Start a ptimer counting down; when it reaches zero the bottom half
- * passed to ptimer_init() will be invoked. If the @oneshot argument is zero,
+ * passed to ptimer_init_with_bh() will be invoked.
+ * If the @oneshot argument is zero,
  * the counter value will then be reloaded from the limit and it will
  * start counting down again. If @oneshot is non-zero, then the counter
  * will disable itself when it reaches zero.
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 246cbb13363..b3624d5e280 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -849,7 +849,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
     s->freq = freq;
 
     bh = qemu_bh_new(mv88w8618_timer_tick, s);
-    s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
 }
 
 static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index d58e2dfdb08..f0d3ce11398 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -358,7 +358,7 @@ const VMStateDescription vmstate_ptimer = {
     }
 };
 
-ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
+ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask)
 {
     ptimer_state *s;
 
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index a254275b64e..e035d1f7504 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -552,7 +552,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
 
         st->nr = i;
         st->bh = qemu_bh_new(timer_hit, st);
-        st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
+        st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
         ptimer_set_freq(st->ptimer, s->freqhz);
     }
     return;
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
index a9c2c95b0d1..a49096367cb 100644
--- a/hw/m68k/mcf5206.c
+++ b/hw/m68k/mcf5206.c
@@ -141,7 +141,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
 
     s = g_new0(m5206_timer_state, 1);
     bh = qemu_bh_new(m5206_timer_trigger, s);
-    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
     s->irq = irq;
     m5206_timer_reset(s);
     return s;
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 012710d057d..45c28b75a17 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -192,7 +192,7 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
     for (i = 0; i < 2; i++) {
         s = g_new0(m5208_timer_state, 1);
         bh = qemu_bh_new(m5208_timer_trigger, s);
-        s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+        s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
         memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
                               "m5208-timer", 0x00004000);
         memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index 8451c17fb8f..d9b3e8c691e 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -393,7 +393,7 @@ static void etsec_realize(DeviceState *dev, Error **errp)
 
 
     etsec->bh     = qemu_bh_new(etsec_timer_hit, etsec);
-    etsec->ptimer = ptimer_init(etsec->bh, PTIMER_POLICY_DEFAULT);
+    etsec->ptimer = ptimer_init_with_bh(etsec->bh, PTIMER_POLICY_DEFAULT);
     ptimer_set_freq(etsec->ptimer, 100);
 }
 
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 8bba2a80568..0ea51433dca 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1350,7 +1350,7 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
     s->txp = &s->tx_packet;
 
     bh = qemu_bh_new(lan9118_tick, s);
-    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
     ptimer_set_freq(s->timer, 10000);
     ptimer_set_limit(s->timer, 0xffff, 1);
 }
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index ca5a9050591..28d055e42f3 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -271,7 +271,7 @@ static void a10_pit_init(Object *obj)
         tc->container = s;
         tc->index = i;
         bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
-        s->timer[i] = ptimer_init(bh[i], PTIMER_POLICY_DEFAULT);
+        s->timer[i] = ptimer_init_with_bh(bh[i], PTIMER_POLICY_DEFAULT);
     }
 }
 
diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c
index 936b31311d2..ee32e0ec1ff 100644
--- a/hw/timer/altera_timer.c
+++ b/hw/timer/altera_timer.c
@@ -184,7 +184,7 @@ static void altera_timer_realize(DeviceState *dev, Error **errp)
     }
 
     t->bh = qemu_bh_new(timer_hit, t);
-    t->ptimer = ptimer_init(t->bh, PTIMER_POLICY_DEFAULT);
+    t->ptimer = ptimer_init_with_bh(t->bh, PTIMER_POLICY_DEFAULT);
     ptimer_set_freq(t->ptimer, t->freq_hz);
 
     memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 9f63abef10e..2a54a011431 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -228,7 +228,7 @@ static void arm_mptimer_reset(DeviceState *dev)
     }
 }
 
-static void arm_mptimer_init(Object *obj)
+static void arm_mptimer_init_with_bh(Object *obj)
 {
     ARMMPTimerState *s = ARM_MPTIMER(obj);
 
@@ -261,7 +261,7 @@ static void arm_mptimer_realize(DeviceState *dev, Error **errp)
     for (i = 0; i < s->num_cpu; i++) {
         TimerBlock *tb = &s->timerblock[i];
         QEMUBH *bh = qemu_bh_new(timerblock_tick, tb);
-        tb->timer = ptimer_init(bh, PTIMER_POLICY);
+        tb->timer = ptimer_init_with_bh(bh, PTIMER_POLICY);
         sysbus_init_irq(sbd, &tb->irq);
         memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
                               "arm_mptimer_timerblock", 0x20);
@@ -311,7 +311,7 @@ static const TypeInfo arm_mptimer_info = {
     .name          = TYPE_ARM_MPTIMER,
     .parent        = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(ARMMPTimerState),
-    .instance_init = arm_mptimer_init,
+    .instance_init = arm_mptimer_init_with_bh,
     .class_init    = arm_mptimer_class_init,
 };
 
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 283ae1e74a9..848fbcb0e25 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -177,7 +177,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
     s->control = TIMER_CTRL_IE;
 
     bh = qemu_bh_new(arm_timer_tick, s);
-    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
     vmstate_register(NULL, -1, &vmstate_arm_timer, s);
     return s;
 }
diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
index 5e2352dd326..44d23c80364 100644
--- a/hw/timer/cmsdk-apb-dualtimer.c
+++ b/hw/timer/cmsdk-apb-dualtimer.c
@@ -453,7 +453,7 @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
         QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
 
         m->parent = s;
-        m->timer = ptimer_init(bh,
+        m->timer = ptimer_init_with_bh(bh,
                                PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
                                PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
                                PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
index c83e26566a9..c9ce9770cef 100644
--- a/hw/timer/cmsdk-apb-timer.c
+++ b/hw/timer/cmsdk-apb-timer.c
@@ -218,7 +218,7 @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
     }
 
     bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
-    s->timer = ptimer_init(bh,
+    s->timer = ptimer_init_with_bh(bh,
                            PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
                            PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
                            PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
index 021c4ef714f..b111e1fe643 100644
--- a/hw/timer/digic-timer.c
+++ b/hw/timer/digic-timer.c
@@ -129,7 +129,7 @@ static void digic_timer_init(Object *obj)
 {
     DigicTimerState *s = DIGIC_TIMER(obj);
 
-    s->ptimer = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init_with_bh(NULL, PTIMER_POLICY_DEFAULT);
 
     /*
      * FIXME: there is no documentation on Digic timer
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index d62025b8797..ab27fe1895b 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -328,9 +328,9 @@ static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
     t->bh_t0 = qemu_bh_new(timer0_hit, t);
     t->bh_t1 = qemu_bh_new(timer1_hit, t);
     t->bh_wd = qemu_bh_new(watchdog_hit, t);
-    t->ptimer_t0 = ptimer_init(t->bh_t0, PTIMER_POLICY_DEFAULT);
-    t->ptimer_t1 = ptimer_init(t->bh_t1, PTIMER_POLICY_DEFAULT);
-    t->ptimer_wd = ptimer_init(t->bh_wd, PTIMER_POLICY_DEFAULT);
+    t->ptimer_t0 = ptimer_init_with_bh(t->bh_t0, PTIMER_POLICY_DEFAULT);
+    t->ptimer_t1 = ptimer_init_with_bh(t->bh_t1, PTIMER_POLICY_DEFAULT);
+    t->ptimer_wd = ptimer_init_with_bh(t->bh_wd, PTIMER_POLICY_DEFAULT);
 
     sysbus_init_irq(sbd, &t->irq);
     sysbus_init_irq(sbd, &t->nmi);
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 77b9af05f41..9f2e8dd0a42 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -1429,7 +1429,7 @@ static void exynos4210_mct_init(Object *obj)
 
     /* Global timer */
     bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
-    s->g_timer.ptimer_frc = ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
+    s->g_timer.ptimer_frc = ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
     memset(&s->g_timer.reg, 0, sizeof(struct gregs));
 
     /* Local timers */
@@ -1437,8 +1437,9 @@ static void exynos4210_mct_init(Object *obj)
         bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
         bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
         s->l_timer[i].tick_timer.ptimer_tick =
-                                   ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
-        s->l_timer[i].ptimer_frc = ptimer_init(bh[1], PTIMER_POLICY_DEFAULT);
+            ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
+        s->l_timer[i].ptimer_frc =
+            ptimer_init_with_bh(bh[1], PTIMER_POLICY_DEFAULT);
         s->l_timer[i].id = i;
     }
 
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index b7fad2ad449..aa5dca68ef7 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -393,7 +393,7 @@ static void exynos4210_pwm_init(Object *obj)
     for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
         bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
         sysbus_init_irq(dev, &s->timer[i].irq);
-        s->timer[i].ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+        s->timer[i].ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
         s->timer[i].id = i;
         s->timer[i].parent = s;
     }
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index ea689042297..d5d7c91fb15 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -558,12 +558,12 @@ static void exynos4210_rtc_init(Object *obj)
     QEMUBH *bh;
 
     bh = qemu_bh_new(exynos4210_rtc_tick, s);
-    s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
     ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
     exynos4210_rtc_update_freq(s, 0);
 
     bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
-    s->ptimer_1Hz = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer_1Hz = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
     ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
 
     sysbus_init_irq(dev, &s->alm_irq);
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index 32dbf870d4b..bb09268ea14 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -366,7 +366,7 @@ static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
 
         timer->unit   = unit;
         timer->bh     = qemu_bh_new(grlib_gptimer_hit, timer);
-        timer->ptimer = ptimer_init(timer->bh, PTIMER_POLICY_DEFAULT);
+        timer->ptimer = ptimer_init_with_bh(timer->bh, PTIMER_POLICY_DEFAULT);
         timer->id     = i;
 
         /* One IRQ line for each timer */
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index f54e059910b..39810ac8b03 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -317,10 +317,10 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
                           0x00001000);
     sysbus_init_mmio(sbd, &s->iomem);
 
-    s->timer_reload = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
+    s->timer_reload = ptimer_init_with_bh(NULL, PTIMER_POLICY_DEFAULT);
 
     bh = qemu_bh_new(imx_epit_cmp, s);
-    s->timer_cmp = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->timer_cmp = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
 }
 
 static void imx_epit_class_init(ObjectClass *klass, void *data)
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 49a441f4517..c535d191292 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -492,7 +492,7 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
     sysbus_init_mmio(sbd, &s->iomem);
 
     bh = qemu_bh_new(imx_gpt_timeout, s);
-    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
 }
 
 static void imx_gpt_class_init(ObjectClass *klass, void *data)
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index ac3edaff4f8..f79f818d22c 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -187,7 +187,7 @@ static void lm32_timer_init(Object *obj)
     sysbus_init_irq(dev, &s->irq);
 
     s->bh = qemu_bh_new(timer_hit, s);
-    s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
 
     memory_region_init_io(&s->iomem, obj, &timer_ops, s,
                           "timer", R_MAX * 4);
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 958350767ae..aeba889bba4 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -285,8 +285,8 @@ static void milkymist_sysctl_init(Object *obj)
 
     s->bh0 = qemu_bh_new(timer0_hit, s);
     s->bh1 = qemu_bh_new(timer1_hit, s);
-    s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT);
-    s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT);
+    s->ptimer0 = ptimer_init_with_bh(s->bh0, PTIMER_POLICY_DEFAULT);
+    s->ptimer1 = ptimer_init_with_bh(s->bh1, PTIMER_POLICY_DEFAULT);
 
     memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s,
             "milkymist-sysctl", R_MAX * 4);
diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c
index 45f1cf42f9e..a34c2402b00 100644
--- a/hw/timer/mss-timer.c
+++ b/hw/timer/mss-timer.c
@@ -229,7 +229,7 @@ static void mss_timer_init(Object *obj)
         struct Msf2Timer *st = &t->timers[i];
 
         st->bh = qemu_bh_new(timer_hit, st);
-        st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
+        st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
         ptimer_set_freq(st->ptimer, t->freq_hz);
         sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq);
     }
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 6fe370049b5..0898da5ce97 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -129,7 +129,7 @@ static void puv3_ost_realize(DeviceState *dev, Error **errp)
     sysbus_init_irq(sbd, &s->irq);
 
     s->bh = qemu_bh_new(puv3_ost_tick, s);
-    s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
     ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
 
     memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index adcc0c138e7..48a81b4dc79 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -204,7 +204,7 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
     s->irq = irq;
 
     bh = qemu_bh_new(sh_timer_tick, s);
-    s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
 
     sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
     sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 38fd32b62a0..692d213897d 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -393,7 +393,7 @@ static void slavio_timer_init(Object *obj)
         tc->timer_index = i;
 
         bh = qemu_bh_new(slavio_timer_irq, tc);
-        s->cputimer[i].timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+        s->cputimer[i].timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
         ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
 
         size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index 355518232cd..92dbff304d9 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -221,7 +221,7 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
         xt->parent = t;
         xt->nr = i;
         xt->bh = qemu_bh_new(timer_hit, xt);
-        xt->ptimer = ptimer_init(xt->bh, PTIMER_POLICY_DEFAULT);
+        xt->ptimer = ptimer_init_with_bh(xt->bh, PTIMER_POLICY_DEFAULT);
         ptimer_set_freq(xt->ptimer, t->freq_hz);
     }
 
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index 6bf43f943fb..e42c3ebd29d 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -329,7 +329,7 @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
     }
 
     bh = qemu_bh_new(cmsdk_apb_watchdog_tick, s);
-    s->timer = ptimer_init(bh,
+    s->timer = ptimer_init_with_bh(bh,
                            PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
                            PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
                            PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
index 5b20e91599e..a3c82d1d147 100644
--- a/tests/ptimer-test.c
+++ b/tests/ptimer-test.c
@@ -68,7 +68,7 @@ static void check_set_count(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
 
     triggered = false;
 
@@ -82,7 +82,7 @@ static void check_set_limit(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
 
     triggered = false;
 
@@ -102,7 +102,7 @@ static void check_oneshot(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
@@ -205,7 +205,7 @@ static void check_periodic(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
@@ -373,7 +373,7 @@ static void check_on_the_fly_mode_change(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
@@ -420,7 +420,7 @@ static void check_on_the_fly_period_change(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
@@ -453,7 +453,7 @@ static void check_on_the_fly_freq_change(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
@@ -486,7 +486,7 @@ static void check_run_with_period_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
 
     triggered = false;
 
@@ -504,7 +504,7 @@ static void check_run_with_delta_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
@@ -610,7 +610,7 @@ static void check_periodic_with_load_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool continuous_trigger = (*policy & PTIMER_POLICY_CONTINUOUS_TRIGGER);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
@@ -670,7 +670,7 @@ static void check_oneshot_with_load_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
     QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init(bh, *policy);
+    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 02/21] ptimer: Provide new transaction-based API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
  2019-10-08 17:17 ` [PATCH v2 01/21] ptimer: Rename ptimer_init() to ptimer_init_with_bh() Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:44   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API Peter Maydell
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Provide the new transaction-based API. If a ptimer is created
using ptimer_init() rather than ptimer_init_with_bh(), then
instead of providing a QEMUBH, it provides a pointer to the
callback function directly, and has opted into the transaction
API. All calls to functions which modify ptimer state:
 - ptimer_set_period()
 - ptimer_set_freq()
 - ptimer_set_limit()
 - ptimer_set_count()
 - ptimer_run()
 - ptimer_stop()
must be between matched calls to ptimer_transaction_begin()
and ptimer_transaction_commit(). When ptimer_transaction_commit()
is called it will evaluate the state of the timer after all the
changes in the transaction, and call the callback if necessary.

In the old API the individual update functions generally would
call ptimer_trigger() immediately, which would schedule the QEMUBH.
In the new API the update functions will instead defer the
"set s->next_event and call ptimer_reload()" work to
ptimer_transaction_commit().

Because ptimer_trigger() can now immediately call into the
device code which may then call other ptimer functions that
update ptimer_state fields, we must be more careful in
ptimer_reload() not to cache fields from ptimer_state across
the ptimer_trigger() call. (This was harmless with the QEMUBH
mechanism as the BH would not be invoked until much later.)

We use assertions to check that:
 * the functions modifying ptimer state are not called outside
   a transaction block
 * ptimer_transaction_begin() and _commit() calls are paired
 * the transaction API is not used with a QEMUBH ptimer

There is some slight repetition of code:
 * most of the set functions have similar looking "if s->bh
   call ptimer_reload, otherwise set s->need_reload" code
 * ptimer_init() and ptimer_init_with_bh() have similar code
We deliberately don't try to avoid this repetition, because
it will all be deleted when the QEMUBH version of the API
is removed.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes since v1:
 * ptimer_transaction_begin() now sets need_reload to false
 * fixed assert condition in ptimer_transaction_begin()
 * ptimer_transaction_commit() now has a loop to call
   ptimer_reload() again if the callback function updated
   the ptimer state such that it needs to trigger again
 * fixed callback_opaque arg name mismatch in doc comment
 * don't cache delta, period, etc across ptimer_trigger() call

RTH: I know you gave a reviewed-by-with-caveats to v1 of
this patch but I feel like there turned out to be enough
things needing fixing that I'd rather you looked at v2 afresh.
---
 include/hw/ptimer.h |  72 +++++++++++++++++++++
 hw/core/ptimer.c    | 152 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 209 insertions(+), 15 deletions(-)

diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index 2fb9ba1915e..4c321f65dcb 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -91,6 +91,38 @@ typedef void (*ptimer_cb)(void *opaque);
  */
 ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask);
 
+/**
+ * ptimer_init - Allocate and return a new ptimer
+ * @callback: function to call on ptimer expiry
+ * @callback_opaque: opaque pointer passed to @callback
+ * @policy: PTIMER_POLICY_* bits specifying behaviour
+ *
+ * The ptimer returned must be freed using ptimer_free().
+ *
+ * If a ptimer is created using this API then will use the
+ * transaction-based API for modifying ptimer state: all calls
+ * to functions which modify ptimer state:
+ *  - ptimer_set_period()
+ *  - ptimer_set_freq()
+ *  - ptimer_set_limit()
+ *  - ptimer_set_count()
+ *  - ptimer_run()
+ *  - ptimer_stop()
+ * must be between matched calls to ptimer_transaction_begin()
+ * and ptimer_transaction_commit(). When ptimer_transaction_commit()
+ * is called it will evaluate the state of the timer after all the
+ * changes in the transaction, and call the callback if necessary.
+ *
+ * The callback function is always called from within a transaction
+ * begin/commit block, so the callback should not call the
+ * ptimer_transaction_begin() function itself. If the callback changes
+ * the ptimer state such that another ptimer expiry is triggered, then
+ * the callback will be called a second time after the first call returns.
+ */
+ptimer_state *ptimer_init(ptimer_cb callback,
+                          void *callback_opaque,
+                          uint8_t policy_mask);
+
 /**
  * ptimer_free - Free a ptimer
  * @s: timer to free
@@ -100,6 +132,28 @@ ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask);
  */
 void ptimer_free(ptimer_state *s);
 
+/**
+ * ptimer_transaction_begin() - Start a ptimer modification transaction
+ *
+ * This function must be called before making any calls to functions
+ * which modify the ptimer's state (see the ptimer_init() documentation
+ * for a list of these), and must always have a matched call to
+ * ptimer_transaction_commit().
+ * It is an error to call this function for a BH-based ptimer;
+ * attempting to do this will trigger an assert.
+ */
+void ptimer_transaction_begin(ptimer_state *s);
+
+/**
+ * ptimer_transaction_commit() - Commit a ptimer modification transaction
+ *
+ * This function must be called after calls to functions which modify
+ * the ptimer's state, and completes the update of the ptimer. If the
+ * ptimer state now means that we should trigger the timer expiry
+ * callback, it will be called directly.
+ */
+void ptimer_transaction_commit(ptimer_state *s);
+
 /**
  * ptimer_set_period - Set counter increment interval in nanoseconds
  * @s: ptimer to configure
@@ -108,6 +162,9 @@ void ptimer_free(ptimer_state *s);
  * Note that if your counter behaviour is specified as having a
  * particular frequency rather than a period then ptimer_set_freq()
  * may be more appropriate.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
  */
 void ptimer_set_period(ptimer_state *s, int64_t period);
 
@@ -121,6 +178,9 @@ void ptimer_set_period(ptimer_state *s, int64_t period);
  * as setting the frequency then this function is more appropriate,
  * because it allows specifying an effective period which is
  * precise to fractions of a nanosecond, avoiding rounding errors.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
  */
 void ptimer_set_freq(ptimer_state *s, uint32_t freq);
 
@@ -148,6 +208,9 @@ uint64_t ptimer_get_limit(ptimer_state *s);
  * Set the limit value of the down-counter. The @reload flag can
  * be used to emulate the behaviour of timers which immediately
  * reload the counter when their reload register is written to.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
  */
 void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload);
 
@@ -169,6 +232,9 @@ uint64_t ptimer_get_count(ptimer_state *s);
  * Set the value of the down-counter. If the counter is currently
  * enabled this will arrange for a timer callback at the appropriate
  * point in the future.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
  */
 void ptimer_set_count(ptimer_state *s, uint64_t count);
 
@@ -183,6 +249,9 @@ void ptimer_set_count(ptimer_state *s, uint64_t count);
  * the counter value will then be reloaded from the limit and it will
  * start counting down again. If @oneshot is non-zero, then the counter
  * will disable itself when it reaches zero.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
  */
 void ptimer_run(ptimer_state *s, int oneshot);
 
@@ -195,6 +264,9 @@ void ptimer_run(ptimer_state *s, int oneshot);
  *
  * Note that this can cause it to "lose" time, even if it is immediately
  * restarted.
+ *
+ * This function will assert if it is called outside a
+ * ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
  */
 void ptimer_stop(ptimer_state *s);
 
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index f0d3ce11398..7239b8227cc 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -31,6 +31,16 @@ struct ptimer_state
     uint8_t policy_mask;
     QEMUBH *bh;
     QEMUTimer *timer;
+    ptimer_cb callback;
+    void *callback_opaque;
+    /*
+     * These track whether we're in a transaction block, and if we
+     * need to do a timer reload when the block finishes. They don't
+     * need to be migrated because migration can never happen in the
+     * middle of a transaction block.
+     */
+    bool in_transaction;
+    bool need_reload;
 };
 
 /* Use a bottom-half routine to avoid reentrancy issues.  */
@@ -39,13 +49,16 @@ static void ptimer_trigger(ptimer_state *s)
     if (s->bh) {
         replay_bh_schedule_event(s->bh);
     }
+    if (s->callback) {
+        s->callback(s->callback_opaque);
+    }
 }
 
 static void ptimer_reload(ptimer_state *s, int delta_adjust)
 {
-    uint32_t period_frac = s->period_frac;
-    uint64_t period = s->period;
-    uint64_t delta = s->delta;
+    uint32_t period_frac;
+    uint64_t period;
+    uint64_t delta;
     bool suppress_trigger = false;
 
     /*
@@ -58,11 +71,20 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
         (s->policy_mask & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT)) {
         suppress_trigger = true;
     }
-    if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)
+    if (s->delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)
         && !suppress_trigger) {
         ptimer_trigger(s);
     }
 
+    /*
+     * Note that ptimer_trigger() might call the device callback function,
+     * which can then modify timer state, so we must not cache any fields
+     * from ptimer_state until after we have called it.
+     */
+    delta = s->delta;
+    period = s->period;
+    period_frac = s->period_frac;
+
     if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
         delta = s->delta = s->limit;
     }
@@ -136,6 +158,15 @@ static void ptimer_tick(void *opaque)
     ptimer_state *s = (ptimer_state *)opaque;
     bool trigger = true;
 
+    /*
+     * We perform all the tick actions within a begin/commit block
+     * because the callback function that ptimer_trigger() calls
+     * might make calls into the ptimer APIs that provoke another
+     * trigger, and we want that to cause the callback function
+     * to be called iteratively, not recursively.
+     */
+    ptimer_transaction_begin(s);
+
     if (s->enabled == 2) {
         s->delta = 0;
         s->enabled = 0;
@@ -164,6 +195,8 @@ static void ptimer_tick(void *opaque)
     if (trigger) {
         ptimer_trigger(s);
     }
+
+    ptimer_transaction_commit(s);
 }
 
 uint64_t ptimer_get_count(ptimer_state *s)
@@ -263,10 +296,15 @@ uint64_t ptimer_get_count(ptimer_state *s)
 
 void ptimer_set_count(ptimer_state *s, uint64_t count)
 {
+    assert(s->in_transaction || !s->callback);
     s->delta = count;
     if (s->enabled) {
-        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-        ptimer_reload(s, 0);
+        if (!s->callback) {
+            s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            ptimer_reload(s, 0);
+        } else {
+            s->need_reload = true;
+        }
     }
 }
 
@@ -274,6 +312,8 @@ void ptimer_run(ptimer_state *s, int oneshot)
 {
     bool was_disabled = !s->enabled;
 
+    assert(s->in_transaction || !s->callback);
+
     if (was_disabled && s->period == 0) {
         if (!qtest_enabled()) {
             fprintf(stderr, "Timer with period zero, disabling\n");
@@ -282,8 +322,12 @@ void ptimer_run(ptimer_state *s, int oneshot)
     }
     s->enabled = oneshot ? 2 : 1;
     if (was_disabled) {
-        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-        ptimer_reload(s, 0);
+        if (!s->callback) {
+            s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            ptimer_reload(s, 0);
+        } else {
+            s->need_reload = true;
+        }
     }
 }
 
@@ -291,35 +335,50 @@ void ptimer_run(ptimer_state *s, int oneshot)
    is immediately restarted.  */
 void ptimer_stop(ptimer_state *s)
 {
+    assert(s->in_transaction || !s->callback);
+
     if (!s->enabled)
         return;
 
     s->delta = ptimer_get_count(s);
     timer_del(s->timer);
     s->enabled = 0;
+    if (s->callback) {
+        s->need_reload = false;
+    }
 }
 
 /* Set counter increment interval in nanoseconds.  */
 void ptimer_set_period(ptimer_state *s, int64_t period)
 {
+    assert(s->in_transaction || !s->callback);
     s->delta = ptimer_get_count(s);
     s->period = period;
     s->period_frac = 0;
     if (s->enabled) {
-        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-        ptimer_reload(s, 0);
+        if (!s->callback) {
+            s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            ptimer_reload(s, 0);
+        } else {
+            s->need_reload = true;
+        }
     }
 }
 
 /* Set counter frequency in Hz.  */
 void ptimer_set_freq(ptimer_state *s, uint32_t freq)
 {
+    assert(s->in_transaction || !s->callback);
     s->delta = ptimer_get_count(s);
     s->period = 1000000000ll / freq;
     s->period_frac = (1000000000ll << 32) / freq;
     if (s->enabled) {
-        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-        ptimer_reload(s, 0);
+        if (!s->callback) {
+            s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            ptimer_reload(s, 0);
+        } else {
+            s->need_reload = true;
+        }
     }
 }
 
@@ -327,12 +386,17 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
    count = limit.  */
 void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
 {
+    assert(s->in_transaction || !s->callback);
     s->limit = limit;
     if (reload)
         s->delta = limit;
     if (s->enabled && reload) {
-        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-        ptimer_reload(s, 0);
+        if (!s->callback) {
+            s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            ptimer_reload(s, 0);
+        } else {
+            s->need_reload = true;
+        }
     }
 }
 
@@ -341,6 +405,32 @@ uint64_t ptimer_get_limit(ptimer_state *s)
     return s->limit;
 }
 
+void ptimer_transaction_begin(ptimer_state *s)
+{
+    assert(!s->in_transaction || !s->callback);
+    s->in_transaction = true;
+    s->need_reload = false;
+}
+
+void ptimer_transaction_commit(ptimer_state *s)
+{
+    assert(s->in_transaction);
+    /*
+     * We must loop here because ptimer_reload() can call the callback
+     * function, which might then update ptimer state in a way that
+     * means we need to do another reload and possibly another callback.
+     * A disabled timer never needs reloading (and if we don't check
+     * this then we loop forever if ptimer_reload() disables the timer).
+     */
+    while (s->need_reload && s->enabled) {
+        s->need_reload = false;
+        s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+        ptimer_reload(s, 0);
+    }
+    /* Now we've finished reload we can leave the transaction block. */
+    s->in_transaction = false;
+}
+
 const VMStateDescription vmstate_ptimer = {
     .name = "ptimer",
     .version_id = 1,
@@ -377,9 +467,41 @@ ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask)
     return s;
 }
 
+ptimer_state *ptimer_init(ptimer_cb callback, void *callback_opaque,
+                          uint8_t policy_mask)
+{
+    ptimer_state *s;
+
+    /*
+     * The callback function is mandatory; so we use it to distinguish
+     * old-style QEMUBH ptimers from new transaction API ptimers.
+     * (ptimer_init_with_bh() allows a NULL bh pointer and at least
+     * one device (digic-timer) passes NULL, so it's not the case
+     * that either s->bh != NULL or s->callback != NULL.)
+     */
+    assert(callback);
+
+    s = g_new0(ptimer_state, 1);
+    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
+    s->policy_mask = policy_mask;
+    s->callback = callback;
+    s->callback_opaque = callback_opaque;
+
+    /*
+     * These two policies are incompatible -- trigger-on-decrement implies
+     * a timer trigger when the count becomes 0, but no-immediate-trigger
+     * implies a trigger when the count stops being 0.
+     */
+    assert(!((policy_mask & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) &&
+             (policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)));
+    return s;
+}
+
 void ptimer_free(ptimer_state *s)
 {
-    qemu_bh_delete(s->bh);
+    if (s->bh) {
+        qemu_bh_delete(s->bh);
+    }
     timer_free(s->timer);
     g_free(s);
 }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
  2019-10-08 17:17 ` [PATCH v2 01/21] ptimer: Rename ptimer_init() to ptimer_init_with_bh() Peter Maydell
  2019-10-08 17:17 ` [PATCH v2 02/21] ptimer: Provide new transaction-based API Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:46   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 04/21] hw/timer/arm_timer.c: " Peter Maydell
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Convert the ptimer test cases to the transaction-based ptimer API,
by changing to ptimer_init(), dropping the now-unused QEMUBH
variables, and surrounding each set of changes to the ptimer
state in ptimer_transaction_begin/commit calls.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/ptimer-test.c | 106 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 84 insertions(+), 22 deletions(-)

diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
index a3c82d1d147..e16c30ce573 100644
--- a/tests/ptimer-test.c
+++ b/tests/ptimer-test.c
@@ -67,12 +67,13 @@ static void qemu_clock_step(uint64_t ns)
 static void check_set_count(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 1000);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000);
     g_assert_false(triggered);
     ptimer_free(ptimer);
@@ -81,17 +82,20 @@ static void check_set_count(gconstpointer arg)
 static void check_set_limit(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_limit(ptimer, 1000, 0);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
     g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_limit(ptimer, 2000, 1);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000);
     g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000);
     g_assert_false(triggered);
@@ -101,22 +105,25 @@ static void check_set_limit(gconstpointer arg)
 static void check_oneshot(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_set_count(ptimer, 10);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 2 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_stop(ptimer);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
     g_assert_false(triggered);
@@ -126,7 +133,9 @@ static void check_oneshot(gconstpointer arg)
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 7 + 1);
 
@@ -157,28 +166,36 @@ static void check_oneshot(gconstpointer arg)
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 10);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(20000000 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_limit(ptimer, 9, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(20000000 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 20);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 19 + 1);
 
@@ -190,7 +207,9 @@ static void check_oneshot(gconstpointer arg)
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
     g_assert_true(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_stop(ptimer);
+    ptimer_transaction_commit(ptimer);
 
     triggered = false;
 
@@ -204,8 +223,7 @@ static void check_oneshot(gconstpointer arg)
 static void check_periodic(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
@@ -214,9 +232,11 @@ static void check_periodic(gconstpointer arg)
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_set_limit(ptimer, 10, 1);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
     g_assert_false(triggered);
@@ -245,7 +265,9 @@ static void check_periodic(gconstpointer arg)
                     (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 20);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 20);
     g_assert_false(triggered);
@@ -268,7 +290,9 @@ static void check_periodic(gconstpointer arg)
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 3);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
     g_assert_false(triggered);
@@ -284,7 +308,9 @@ static void check_periodic(gconstpointer arg)
                     (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
     g_assert_true(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_stop(ptimer);
+    ptimer_transaction_commit(ptimer);
     triggered = false;
 
     qemu_clock_step(2000000);
@@ -293,8 +319,10 @@ static void check_periodic(gconstpointer arg)
                     (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 3);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 3 + 1);
 
@@ -310,7 +338,9 @@ static void check_periodic(gconstpointer arg)
                     (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0));
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==,
                      no_immediate_reload ? 0 : 10);
 
@@ -348,7 +378,9 @@ static void check_periodic(gconstpointer arg)
                     (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0));
     g_assert_true(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_stop(ptimer);
+    ptimer_transaction_commit(ptimer);
 
     triggered = false;
 
@@ -358,8 +390,13 @@ static void check_periodic(gconstpointer arg)
                     (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0));
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
+
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 + 1);
 
@@ -372,23 +409,26 @@ static void check_periodic(gconstpointer arg)
 static void check_on_the_fly_mode_change(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_set_limit(ptimer, 10, 1);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 9 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0);
     g_assert_false(triggered);
@@ -403,7 +443,9 @@ static void check_on_the_fly_mode_change(gconstpointer arg)
 
     qemu_clock_step(2000000 * 9);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==,
                      (no_round_down ? 1 : 0) + (wrap_policy ? 1 : 0));
@@ -419,22 +461,25 @@ static void check_on_the_fly_mode_change(gconstpointer arg)
 static void check_on_the_fly_period_change(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_set_limit(ptimer, 8, 1);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 4 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 4000000);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
 
     qemu_clock_step(4000000 * 2 + 1);
@@ -452,22 +497,25 @@ static void check_on_the_fly_period_change(gconstpointer arg)
 static void check_on_the_fly_freq_change(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_freq(ptimer, 500);
     ptimer_set_limit(ptimer, 8, 1);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 4 + 1);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
     g_assert_false(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_freq(ptimer, 250);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3);
 
     qemu_clock_step(2000000 * 4 + 1);
@@ -485,13 +533,14 @@ static void check_on_the_fly_freq_change(gconstpointer arg)
 static void check_run_with_period_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 99);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(10 * NANOSECONDS_PER_SECOND);
 
@@ -503,8 +552,7 @@ static void check_run_with_period_0(gconstpointer arg)
 static void check_run_with_delta_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
@@ -513,9 +561,11 @@ static void check_run_with_delta_0(gconstpointer arg)
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_set_limit(ptimer, 99, 0);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==,
                      no_immediate_reload ? 0 : 99);
 
@@ -541,8 +591,10 @@ static void check_run_with_delta_0(gconstpointer arg)
             g_assert_false(triggered);
         }
 
+        ptimer_transaction_begin(ptimer);
         ptimer_set_count(ptimer, 99);
         ptimer_run(ptimer, 1);
+        ptimer_transaction_commit(ptimer);
     }
 
     qemu_clock_step(2000000 + 1);
@@ -562,8 +614,10 @@ static void check_run_with_delta_0(gconstpointer arg)
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 0);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
     g_assert_cmpuint(ptimer_get_count(ptimer), ==,
                      no_immediate_reload ? 0 : 99);
 
@@ -602,23 +656,26 @@ static void check_run_with_delta_0(gconstpointer arg)
                     wrap_policy ? 0 : (no_round_down ? 99 : 98));
     g_assert_true(triggered);
 
+    ptimer_transaction_begin(ptimer);
     ptimer_stop(ptimer);
+    ptimer_transaction_commit(ptimer);
     ptimer_free(ptimer);
 }
 
 static void check_periodic_with_load_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool continuous_trigger = (*policy & PTIMER_POLICY_CONTINUOUS_TRIGGER);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 
@@ -642,8 +699,10 @@ static void check_periodic_with_load_0(gconstpointer arg)
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_count(ptimer, 10);
     ptimer_run(ptimer, 0);
+    ptimer_transaction_commit(ptimer);
 
     qemu_clock_step(2000000 * 10 + 1);
 
@@ -662,22 +721,25 @@ static void check_periodic_with_load_0(gconstpointer arg)
         g_assert_false(triggered);
     }
 
+    ptimer_transaction_begin(ptimer);
     ptimer_stop(ptimer);
+    ptimer_transaction_commit(ptimer);
     ptimer_free(ptimer);
 }
 
 static void check_oneshot_with_load_0(gconstpointer arg)
 {
     const uint8_t *policy = arg;
-    QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-    ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+    ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
     bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
     bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
 
     triggered = false;
 
+    ptimer_transaction_begin(ptimer);
     ptimer_set_period(ptimer, 2000000);
     ptimer_run(ptimer, 1);
+    ptimer_transaction_commit(ptimer);
 
     g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 04/21] hw/timer/arm_timer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (2 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:47   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 05/21] hw/arm/musicpal.c: " Peter Maydell
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the arm_timer.c code away from bottom-half based ptimers
to the new transaction-based ptimer API. This just requires
adding begin/commit calls around the various arms of
arm_timer_write() that modify the ptimer state, and using the
new ptimer_init() function to create the timer.

Fixes: https://bugs.launchpad.net/qemu/+bug/1777777
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/arm_timer.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 848fbcb0e25..255def3deec 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -14,7 +14,6 @@
 #include "hw/irq.h"
 #include "hw/ptimer.h"
 #include "hw/qdev-properties.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 #include "trace.h"
@@ -79,7 +78,10 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset)
     }
 }
 
-/* Reset the timer limit after settings have changed.  */
+/*
+ * Reset the timer limit after settings have changed.
+ * May only be called from inside a ptimer transaction block.
+ */
 static void arm_timer_recalibrate(arm_timer_state *s, int reload)
 {
     uint32_t limit;
@@ -106,13 +108,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
     switch (offset >> 2) {
     case 0: /* TimerLoad */
         s->limit = value;
+        ptimer_transaction_begin(s->timer);
         arm_timer_recalibrate(s, 1);
+        ptimer_transaction_commit(s->timer);
         break;
     case 1: /* TimerValue */
         /* ??? Linux seems to want to write to this readonly register.
            Ignore it.  */
         break;
     case 2: /* TimerControl */
+        ptimer_transaction_begin(s->timer);
         if (s->control & TIMER_CTRL_ENABLE) {
             /* Pause the timer if it is running.  This may cause some
                inaccuracy dure to rounding, but avoids a whole lot of other
@@ -132,13 +137,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
             /* Restart the timer if still enabled.  */
             ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
         }
+        ptimer_transaction_commit(s->timer);
         break;
     case 3: /* TimerIntClr */
         s->int_level = 0;
         break;
     case 6: /* TimerBGLoad */
         s->limit = value;
+        ptimer_transaction_begin(s->timer);
         arm_timer_recalibrate(s, 0);
+        ptimer_transaction_commit(s->timer);
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -170,14 +178,12 @@ static const VMStateDescription vmstate_arm_timer = {
 static arm_timer_state *arm_timer_init(uint32_t freq)
 {
     arm_timer_state *s;
-    QEMUBH *bh;
 
     s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
     s->freq = freq;
     s->control = TIMER_CTRL_IE;
 
-    bh = qemu_bh_new(arm_timer_tick, s);
-    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init(arm_timer_tick, s, PTIMER_POLICY_DEFAULT);
     vmstate_register(NULL, -1, &vmstate_arm_timer, s);
     return s;
 }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 05/21] hw/arm/musicpal.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (3 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 04/21] hw/timer/arm_timer.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:48   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: " Peter Maydell
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the musicpal code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/musicpal.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index b3624d5e280..f68a399a984 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -843,13 +843,10 @@ static void mv88w8618_timer_tick(void *opaque)
 static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
                                  uint32_t freq)
 {
-    QEMUBH *bh;
-
     sysbus_init_irq(dev, &s->irq);
     s->freq = freq;
 
-    bh = qemu_bh_new(mv88w8618_timer_tick, s);
-    s->ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_DEFAULT);
 }
 
 static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
@@ -879,16 +876,19 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
     case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
         t = &s->timer[offset >> 2];
         t->limit = value;
+        ptimer_transaction_begin(t->ptimer);
         if (t->limit > 0) {
             ptimer_set_limit(t->ptimer, t->limit, 1);
         } else {
             ptimer_stop(t->ptimer);
         }
+        ptimer_transaction_commit(t->ptimer);
         break;
 
     case MP_PIT_CONTROL:
         for (i = 0; i < 4; i++) {
             t = &s->timer[i];
+            ptimer_transaction_begin(t->ptimer);
             if (value & 0xf && t->limit > 0) {
                 ptimer_set_limit(t->ptimer, t->limit, 0);
                 ptimer_set_freq(t->ptimer, t->freq);
@@ -896,6 +896,7 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
             } else {
                 ptimer_stop(t->ptimer);
             }
+            ptimer_transaction_commit(t->ptimer);
             value >>= 4;
         }
         break;
@@ -914,8 +915,11 @@ static void mv88w8618_pit_reset(DeviceState *d)
     int i;
 
     for (i = 0; i < 4; i++) {
-        ptimer_stop(s->timer[i].ptimer);
-        s->timer[i].limit = 0;
+        mv88w8618_timer_state *t = &s->timer[i];
+        ptimer_transaction_begin(t->ptimer);
+        ptimer_stop(t->ptimer);
+        ptimer_transaction_commit(t->ptimer);
+        t->limit = 0;
     }
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (4 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 05/21] hw/arm/musicpal.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:49   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 07/21] hw/timer/arm_mptimer.c: " Peter Maydell
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the allwinner-a10-pit code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/allwinner-a10-pit.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index 28d055e42f3..aae880f5b35 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -22,7 +22,6 @@
 #include "hw/timer/allwinner-a10-pit.h"
 #include "migration/vmstate.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 
 static void a10_pit_update_irq(AwA10PITState *s)
@@ -80,6 +79,7 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
     return 0;
 }
 
+/* Must be called inside a ptimer transaction block for s->timer[index] */
 static void a10_pit_set_freq(AwA10PITState *s, int index)
 {
     uint32_t prescaler, source, source_freq;
@@ -118,6 +118,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
         switch (offset & 0x0f) {
         case AW_A10_PIT_TIMER_CONTROL:
             s->control[index] = value;
+            ptimer_transaction_begin(s->timer[index]);
             a10_pit_set_freq(s, index);
             if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
                 ptimer_set_count(s->timer[index], s->interval[index]);
@@ -131,10 +132,13 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
             } else {
                 ptimer_stop(s->timer[index]);
             }
+            ptimer_transaction_commit(s->timer[index]);
             break;
         case AW_A10_PIT_TIMER_INTERVAL:
             s->interval[index] = value;
+            ptimer_transaction_begin(s->timer[index]);
             ptimer_set_limit(s->timer[index], s->interval[index], 1);
+            ptimer_transaction_commit(s->timer[index]);
             break;
         case AW_A10_PIT_TIMER_COUNT:
             s->count[index] = value;
@@ -225,8 +229,10 @@ static void a10_pit_reset(DeviceState *dev)
         s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
         s->interval[i] = 0;
         s->count[i] = 0;
+        ptimer_transaction_begin(s->timer[i]);
         ptimer_stop(s->timer[i]);
         a10_pit_set_freq(s, i);
+        ptimer_transaction_commit(s->timer[i]);
     }
     s->watch_dog_mode = 0;
     s->watch_dog_control = 0;
@@ -255,7 +261,6 @@ static void a10_pit_init(Object *obj)
 {
     AwA10PITState *s = AW_A10_PIT(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-    QEMUBH * bh[AW_A10_PIT_TIMER_NR];
     uint8_t i;
 
     for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
@@ -270,8 +275,7 @@ static void a10_pit_init(Object *obj)
 
         tc->container = s;
         tc->index = i;
-        bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
-        s->timer[i] = ptimer_init_with_bh(bh[i], PTIMER_POLICY_DEFAULT);
+        s->timer[i] = ptimer_init(a10_pit_timer_cb, tc, PTIMER_POLICY_DEFAULT);
     }
 }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 07/21] hw/timer/arm_mptimer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (5 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:50   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: " Peter Maydell
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the arm_mptimer.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/arm_mptimer.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 2a54a011431..fdf97d1800f 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -27,7 +27,6 @@
 #include "hw/timer/arm_mptimer.h"
 #include "migration/vmstate.h"
 #include "qapi/error.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/core/cpu.h"
 
@@ -65,6 +64,7 @@ static inline uint32_t timerblock_scale(uint32_t control)
     return (((control >> 8) & 0xff) + 1) * 10;
 }
 
+/* Must be called within a ptimer transaction block */
 static inline void timerblock_set_count(struct ptimer_state *timer,
                                         uint32_t control, uint64_t *count)
 {
@@ -77,6 +77,7 @@ static inline void timerblock_set_count(struct ptimer_state *timer,
     ptimer_set_count(timer, *count);
 }
 
+/* Must be called within a ptimer transaction block */
 static inline void timerblock_run(struct ptimer_state *timer,
                                   uint32_t control, uint32_t load)
 {
@@ -124,6 +125,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
     uint32_t control = tb->control;
     switch (addr) {
     case 0: /* Load */
+        ptimer_transaction_begin(tb->timer);
         /* Setting load to 0 stops the timer without doing the tick if
          * prescaler = 0.
          */
@@ -132,8 +134,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
         }
         ptimer_set_limit(tb->timer, value, 1);
         timerblock_run(tb->timer, control, value);
+        ptimer_transaction_commit(tb->timer);
         break;
     case 4: /* Counter.  */
+        ptimer_transaction_begin(tb->timer);
         /* Setting counter to 0 stops the one-shot timer, or periodic with
          * load = 0, without doing the tick if prescaler = 0.
          */
@@ -143,8 +147,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
         }
         timerblock_set_count(tb->timer, control, &value);
         timerblock_run(tb->timer, control, value);
+        ptimer_transaction_commit(tb->timer);
         break;
     case 8: /* Control.  */
+        ptimer_transaction_begin(tb->timer);
         if ((control & 3) != (value & 3)) {
             ptimer_stop(tb->timer);
         }
@@ -160,6 +166,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
             timerblock_run(tb->timer, value, count);
         }
         tb->control = value;
+        ptimer_transaction_commit(tb->timer);
         break;
     case 12: /* Interrupt status.  */
         tb->status &= ~value;
@@ -212,9 +219,11 @@ static void timerblock_reset(TimerBlock *tb)
     tb->control = 0;
     tb->status = 0;
     if (tb->timer) {
+        ptimer_transaction_begin(tb->timer);
         ptimer_stop(tb->timer);
         ptimer_set_limit(tb->timer, 0, 1);
         ptimer_set_period(tb->timer, timerblock_scale(0));
+        ptimer_transaction_commit(tb->timer);
     }
 }
 
@@ -260,8 +269,7 @@ static void arm_mptimer_realize(DeviceState *dev, Error **errp)
      */
     for (i = 0; i < s->num_cpu; i++) {
         TimerBlock *tb = &s->timerblock[i];
-        QEMUBH *bh = qemu_bh_new(timerblock_tick, tb);
-        tb->timer = ptimer_init_with_bh(bh, PTIMER_POLICY);
+        tb->timer = ptimer_init(timerblock_tick, tb, PTIMER_POLICY);
         sysbus_init_irq(sbd, &tb->irq);
         memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
                               "arm_mptimer_timerblock", 0x20);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (6 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 07/21] hw/timer/arm_mptimer.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:51   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: " Peter Maydell
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the cmsdk-apb-dualtimer code away from bottom-half based
ptimers to the new transaction-based ptimer API.  This just requires
adding begin/commit calls around the various places that modify the
ptimer state, and using the new ptimer_init() function to create the
timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/cmsdk-apb-dualtimer.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
index 44d23c80364..e28ba9c90a8 100644
--- a/hw/timer/cmsdk-apb-dualtimer.c
+++ b/hw/timer/cmsdk-apb-dualtimer.c
@@ -20,7 +20,6 @@
 #include "qemu/log.h"
 #include "trace.h"
 #include "qapi/error.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "hw/irq.h"
@@ -112,6 +111,8 @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
     /* Handle a write to the CONTROL register */
     uint32_t changed;
 
+    ptimer_transaction_begin(m->timer);
+
     newctrl &= R_CONTROL_VALID_MASK;
 
     changed = m->control ^ newctrl;
@@ -213,6 +214,8 @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
     }
 
     m->control = newctrl;
+
+    ptimer_transaction_commit(m->timer);
 }
 
 static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
@@ -330,6 +333,7 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
             if (!(m->control & R_CONTROL_SIZE_MASK)) {
                 value &= 0xffff;
             }
+            ptimer_transaction_begin(m->timer);
             if (!(m->control & R_CONTROL_MODE_MASK)) {
                 /*
                  * In free-running mode this won't set the limit but will
@@ -346,6 +350,7 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
                     ptimer_run(m->timer, 1);
                 }
             }
+            ptimer_transaction_commit(m->timer);
             break;
         case A_TIMER1BGLOAD:
             /* Set the limit, but not the current count */
@@ -357,7 +362,9 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
             if (!(m->control & R_CONTROL_SIZE_MASK)) {
                 value &= 0xffff;
             }
+            ptimer_transaction_begin(m->timer);
             ptimer_set_limit(m->timer, value, 0);
+            ptimer_transaction_commit(m->timer);
             break;
         case A_TIMER1CONTROL:
             cmsdk_dualtimermod_write_control(m, value);
@@ -398,6 +405,7 @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
     m->intstatus = 0;
     m->load = 0;
     m->value = 0xffffffff;
+    ptimer_transaction_begin(m->timer);
     ptimer_stop(m->timer);
     /*
      * We start in free-running mode, with VALUE at 0xffffffff, and
@@ -406,6 +414,7 @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
      */
     ptimer_set_limit(m->timer, 0xffff, 1);
     ptimer_set_freq(m->timer, m->parent->pclk_frq);
+    ptimer_transaction_commit(m->timer);
 }
 
 static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
@@ -450,10 +459,9 @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
 
     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
         CMSDKAPBDualTimerModule *m = &s->timermod[i];
-        QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
 
         m->parent = s;
-        m->timer = ptimer_init_with_bh(bh,
+        m->timer = ptimer_init(cmsdk_dualtimermod_tick, m,
                                PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
                                PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
                                PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (7 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:52   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 10/21] hw/timer/digic-timer.c: " Peter Maydell
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the cmsdk-apb-timer code away from bottom-half based ptimers
to the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/cmsdk-apb-timer.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
index c9ce9770cef..40728e85e20 100644
--- a/hw/timer/cmsdk-apb-timer.c
+++ b/hw/timer/cmsdk-apb-timer.c
@@ -29,7 +29,6 @@
 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "trace.h"
@@ -121,14 +120,17 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
                           "CMSDK APB timer: EXTIN input not supported\n");
         }
         s->ctrl = value & 0xf;
+        ptimer_transaction_begin(s->timer);
         if (s->ctrl & R_CTRL_EN_MASK) {
             ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
         } else {
             ptimer_stop(s->timer);
         }
+        ptimer_transaction_commit(s->timer);
         break;
     case A_RELOAD:
         /* Writing to reload also sets the current timer value */
+        ptimer_transaction_begin(s->timer);
         if (!value) {
             ptimer_stop(s->timer);
         }
@@ -140,8 +142,10 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
              */
             ptimer_run(s->timer, 0);
         }
+        ptimer_transaction_commit(s->timer);
         break;
     case A_VALUE:
+        ptimer_transaction_begin(s->timer);
         if (!value && !ptimer_get_limit(s->timer)) {
             ptimer_stop(s->timer);
         }
@@ -149,6 +153,7 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
         if (value && (s->ctrl & R_CTRL_EN_MASK)) {
             ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
         }
+        ptimer_transaction_commit(s->timer);
         break;
     case A_INTSTATUS:
         /* Just one bit, which is W1C. */
@@ -191,9 +196,11 @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
     trace_cmsdk_apb_timer_reset();
     s->ctrl = 0;
     s->intstatus = 0;
+    ptimer_transaction_begin(s->timer);
     ptimer_stop(s->timer);
     /* Set the limit and the count */
     ptimer_set_limit(s->timer, 0, 1);
+    ptimer_transaction_commit(s->timer);
 }
 
 static void cmsdk_apb_timer_init(Object *obj)
@@ -210,21 +217,21 @@ static void cmsdk_apb_timer_init(Object *obj)
 static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
 {
     CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
-    QEMUBH *bh;
 
     if (s->pclk_frq == 0) {
         error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
         return;
     }
 
-    bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
-    s->timer = ptimer_init_with_bh(bh,
+    s->timer = ptimer_init(cmsdk_apb_timer_tick, s,
                            PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
                            PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
                            PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
                            PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
+    ptimer_transaction_begin(s->timer);
     ptimer_set_freq(s->timer, s->pclk_frq);
+    ptimer_transaction_commit(s->timer);
 }
 
 static const VMStateDescription cmsdk_apb_timer_vmstate = {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 10/21] hw/timer/digic-timer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (8 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:53   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC " Peter Maydell
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the digic-timer.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/digic-timer.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
index b111e1fe643..32612228daf 100644
--- a/hw/timer/digic-timer.c
+++ b/hw/timer/digic-timer.c
@@ -29,7 +29,6 @@
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 
@@ -52,7 +51,9 @@ static void digic_timer_reset(DeviceState *dev)
 {
     DigicTimerState *s = DIGIC_TIMER(dev);
 
+    ptimer_transaction_begin(s->ptimer);
     ptimer_stop(s->ptimer);
+    ptimer_transaction_commit(s->ptimer);
     s->control = 0;
     s->relvalue = 0;
 }
@@ -93,16 +94,20 @@ static void digic_timer_write(void *opaque, hwaddr offset,
             break;
         }
 
+        ptimer_transaction_begin(s->ptimer);
         if (value & DIGIC_TIMER_CONTROL_EN) {
             ptimer_run(s->ptimer, 0);
         }
 
         s->control = (uint32_t)value;
+        ptimer_transaction_commit(s->ptimer);
         break;
 
     case DIGIC_TIMER_RELVALUE:
         s->relvalue = extract32(value, 0, 16);
+        ptimer_transaction_begin(s->ptimer);
         ptimer_set_limit(s->ptimer, s->relvalue, 1);
+        ptimer_transaction_commit(s->ptimer);
         break;
 
     case DIGIC_TIMER_VALUE:
@@ -125,17 +130,24 @@ static const MemoryRegionOps digic_timer_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static void digic_timer_tick(void *opaque)
+{
+    /* Nothing to do on timer rollover */
+}
+
 static void digic_timer_init(Object *obj)
 {
     DigicTimerState *s = DIGIC_TIMER(obj);
 
-    s->ptimer = ptimer_init_with_bh(NULL, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init(digic_timer_tick, NULL, PTIMER_POLICY_DEFAULT);
 
     /*
      * FIXME: there is no documentation on Digic timer
      * frequency setup so let it always run at 1 MHz
      */
+    ptimer_transaction_begin(s->ptimer);
     ptimer_set_freq(s->ptimer, 1 * 1000 * 1000);
+    ptimer_transaction_commit(s->ptimer);
 
     memory_region_init_io(&s->iomem, OBJECT(s), &digic_timer_ops, s,
                           TYPE_DIGIC_TIMER, 0x100);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (9 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 10/21] hw/timer/digic-timer.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:56   ` Richard Henderson
  2019-10-09  1:58   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC " Peter Maydell
                   ` (9 subsequent siblings)
  20 siblings, 2 replies; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

We want to switch the exynos MCT code away from bottom-half based ptimers to
the new transaction-based ptimer API. The MCT is complicated
and uses multiple different ptimers, so it's clearer to switch
it a piece at a time. Here we change over only the GFRC.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/exynos4210_mct.c | 48 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 9f2e8dd0a42..fcf91c75cc5 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -364,6 +364,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s);
 
 /*
  * Set counter of FRC global timer.
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_set_count(Exynos4210MCTGT *s, uint64_t count)
 {
@@ -385,6 +386,7 @@ static uint64_t exynos4210_gfrc_get_count(Exynos4210MCTGT *s)
 
 /*
  * Stop global FRC timer
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
 {
@@ -395,6 +397,7 @@ static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
 
 /*
  * Start global FRC timer
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
 {
@@ -403,6 +406,21 @@ static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
     ptimer_run(s->ptimer_frc, 1);
 }
 
+/*
+ * Start ptimer transaction for global FRC timer; this is just for
+ * consistency with the way we wrap operations like stop and run.
+ */
+static void exynos4210_gfrc_tx_begin(Exynos4210MCTGT *s)
+{
+    ptimer_transaction_begin(s->ptimer_frc);
+}
+
+/* Commit ptimer transaction for global FRC timer. */
+static void exynos4210_gfrc_tx_commit(Exynos4210MCTGT *s)
+{
+    ptimer_transaction_commit(s->ptimer_frc);
+}
+
 /*
  * Find next nearest Comparator. If current Comparator value equals to other
  * Comparator value, skip them both
@@ -492,6 +510,7 @@ static uint64_t exynos4210_gcomp_get_distance(Exynos4210MCTState *s, int32_t id)
 
 /*
  * Restart global FRC timer
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_restart(Exynos4210MCTState *s)
 {
@@ -933,6 +952,19 @@ static void exynos4210_ltick_event(void *opaque)
     exynos4210_ltick_int_start(&s->tick_timer);
 }
 
+static void tx_ptimer_set_freq(ptimer_state *s, uint32_t freq)
+{
+    /*
+     * callers of exynos4210_mct_update_freq() never do anything
+     * else that needs to be in the same ptimer transaction, so
+     * to avoid a lot of repetition we have a convenience function
+     * for begin/set_freq/commit.
+     */
+    ptimer_transaction_begin(s);
+    ptimer_set_freq(s, freq);
+    ptimer_transaction_commit(s);
+}
+
 /* update timer frequency */
 static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
 {
@@ -945,7 +977,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
         DPRINTF("freq=%dHz\n", s->freq);
 
         /* global timer */
-        ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
+        tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
 
         /* local timer */
         ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
@@ -965,7 +997,9 @@ static void exynos4210_mct_reset(DeviceState *d)
 
     /* global timer */
     memset(&s->g_timer.reg, 0, sizeof(s->g_timer.reg));
+    exynos4210_gfrc_tx_begin(&s->g_timer);
     exynos4210_gfrc_stop(&s->g_timer);
+    exynos4210_gfrc_tx_commit(&s->g_timer);
 
     /* local timer */
     memset(s->l_timer[0].reg.cnt, 0, sizeof(s->l_timer[0].reg.cnt));
@@ -1144,7 +1178,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
         }
 
         s->g_timer.reg.cnt = new_frc;
+        exynos4210_gfrc_tx_begin(&s->g_timer);
         exynos4210_gfrc_restart(s);
+        exynos4210_gfrc_tx_commit(&s->g_timer);
         break;
 
     case G_CNT_WSTAT:
@@ -1168,7 +1204,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
             s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
         }
 
+        exynos4210_gfrc_tx_begin(&s->g_timer);
         exynos4210_gfrc_restart(s);
+        exynos4210_gfrc_tx_commit(&s->g_timer);
         break;
 
     case G_TCON:
@@ -1178,6 +1216,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
 
         DPRINTF("global timer write to reg.g_tcon %llx\n", value);
 
+        exynos4210_gfrc_tx_begin(&s->g_timer);
+
         /* Start FRC if transition from disabled to enabled */
         if ((value & G_TCON_TIMER_ENABLE) > (old_val &
                 G_TCON_TIMER_ENABLE)) {
@@ -1195,6 +1235,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
                 exynos4210_gfrc_restart(s);
             }
         }
+
+        exynos4210_gfrc_tx_commit(&s->g_timer);
         break;
 
     case G_INT_CSTAT:
@@ -1428,8 +1470,8 @@ static void exynos4210_mct_init(Object *obj)
     QEMUBH *bh[2];
 
     /* Global timer */
-    bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
-    s->g_timer.ptimer_frc = ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
+    s->g_timer.ptimer_frc = ptimer_init(exynos4210_gfrc_event, s,
+                                        PTIMER_POLICY_DEFAULT);
     memset(&s->g_timer.reg, 0, sizeof(struct gregs));
 
     /* Local timers */
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (10 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:58   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick " Peter Maydell
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the exynos MCT LFRC timers over to the ptimer transaction API.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/exynos4210_mct.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index fcf91c75cc5..82803ef9a02 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -608,6 +608,7 @@ static uint64_t exynos4210_lfrc_get_count(Exynos4210MCTLT *s)
 
 /*
  * Set counter of FRC local timer.
+ * Must be called from within exynos4210_lfrc_tx_begin/commit block.
  */
 static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
 {
@@ -620,6 +621,7 @@ static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
 
 /*
  * Start local FRC timer
+ * Must be called from within exynos4210_lfrc_tx_begin/commit block.
  */
 static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
 {
@@ -628,12 +630,25 @@ static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
 
 /*
  * Stop local FRC timer
+ * Must be called from within exynos4210_lfrc_tx_begin/commit block.
  */
 static void exynos4210_lfrc_stop(Exynos4210MCTLT *s)
 {
     ptimer_stop(s->ptimer_frc);
 }
 
+/* Start ptimer transaction for local FRC timer */
+static void exynos4210_lfrc_tx_begin(Exynos4210MCTLT *s)
+{
+    ptimer_transaction_begin(s->ptimer_frc);
+}
+
+/* Commit ptimer transaction for local FRC timer */
+static void exynos4210_lfrc_tx_commit(Exynos4210MCTLT *s)
+{
+    ptimer_transaction_commit(s->ptimer_frc);
+}
+
 /*
  * Local timer free running counter tick handler
  */
@@ -981,9 +996,9 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
 
         /* local timer */
         ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
-        ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
+        tx_ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
         ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
-        ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
+        tx_ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
     }
 }
 
@@ -1012,7 +1027,9 @@ static void exynos4210_mct_reset(DeviceState *d)
         s->l_timer[i].tick_timer.count = 0;
         s->l_timer[i].tick_timer.distance = 0;
         s->l_timer[i].tick_timer.progress = 0;
+        exynos4210_lfrc_tx_begin(&s->l_timer[i]);
         ptimer_stop(s->l_timer[i].ptimer_frc);
+        exynos4210_lfrc_tx_commit(&s->l_timer[i]);
 
         exynos4210_ltick_timer_init(&s->l_timer[i].tick_timer);
     }
@@ -1316,6 +1333,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
         }
 
         /* Start or Stop local FRC if TCON changed */
+        exynos4210_lfrc_tx_begin(&s->l_timer[lt_i]);
         if ((value & L_TCON_FRC_START) >
         (s->l_timer[lt_i].reg.tcon & L_TCON_FRC_START)) {
             DPRINTF("local timer[%d] start frc\n", lt_i);
@@ -1326,6 +1344,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
             DPRINTF("local timer[%d] stop frc\n", lt_i);
             exynos4210_lfrc_stop(&s->l_timer[lt_i]);
         }
+        exynos4210_lfrc_tx_commit(&s->l_timer[lt_i]);
         break;
 
     case L0_TCNTB: case L1_TCNTB:
@@ -1477,11 +1496,11 @@ static void exynos4210_mct_init(Object *obj)
     /* Local timers */
     for (i = 0; i < 2; i++) {
         bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
-        bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
         s->l_timer[i].tick_timer.ptimer_tick =
             ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
         s->l_timer[i].ptimer_frc =
-            ptimer_init_with_bh(bh[1], PTIMER_POLICY_DEFAULT);
+            ptimer_init(exynos4210_lfrc_event, &s->l_timer[i],
+                        PTIMER_POLICY_DEFAULT);
         s->l_timer[i].id = i;
     }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (11 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  1:59   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch " Peter Maydell
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the ltick ptimer over to the ptimer transaction API.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/exynos4210_mct.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 82803ef9a02..72257584145 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -58,7 +58,6 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/timer.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/ptimer.h"
 
@@ -735,6 +734,7 @@ static uint32_t exynos4210_ltick_int_get_cnto(struct tick_timer *s)
 
 /*
  * Start local tick cnt timer.
+ * Must be called within exynos4210_ltick_tx_begin/commit block.
  */
 static void exynos4210_ltick_cnt_start(struct tick_timer *s)
 {
@@ -750,6 +750,7 @@ static void exynos4210_ltick_cnt_start(struct tick_timer *s)
 
 /*
  * Stop local tick cnt timer.
+ * Must be called within exynos4210_ltick_tx_begin/commit block.
  */
 static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
 {
@@ -767,6 +768,18 @@ static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
     }
 }
 
+/* Start ptimer transaction for local tick timer */
+static void exynos4210_ltick_tx_begin(struct tick_timer *s)
+{
+    ptimer_transaction_begin(s->ptimer_tick);
+}
+
+/* Commit ptimer transaction for local tick timer */
+static void exynos4210_ltick_tx_commit(struct tick_timer *s)
+{
+    ptimer_transaction_commit(s->ptimer_tick);
+}
+
 /*
  * Get counter for CNT timer
  */
@@ -812,6 +825,7 @@ static uint32_t exynos4210_ltick_cnt_get_cnto(struct tick_timer *s)
 
 /*
  * Set new values of counters for CNT and INT timers
+ * Must be called within exynos4210_ltick_tx_begin/commit block.
  */
 static void exynos4210_ltick_set_cntb(struct tick_timer *s, uint32_t new_cnt,
         uint32_t new_int)
@@ -885,7 +899,9 @@ static void exynos4210_ltick_recalc_count(struct tick_timer *s)
 static void exynos4210_ltick_timer_init(struct tick_timer *s)
 {
     exynos4210_ltick_int_stop(s);
+    exynos4210_ltick_tx_begin(s);
     exynos4210_ltick_cnt_stop(s);
+    exynos4210_ltick_tx_commit(s);
 
     s->count = 0;
     s->distance = 0;
@@ -995,9 +1011,9 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
         tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
 
         /* local timer */
-        ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
+        tx_ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
         tx_ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
-        ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
+        tx_ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
         tx_ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
     }
 }
@@ -1304,6 +1320,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
         s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCON_WRITE;
         s->l_timer[lt_i].reg.tcon = value;
 
+        exynos4210_ltick_tx_begin(&s->l_timer[lt_i].tick_timer);
         /* Stop local CNT */
         if ((value & L_TCON_TICK_START) <
                 (old_val & L_TCON_TICK_START)) {
@@ -1331,6 +1348,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
             DPRINTF("local timer[%d] start int\n", lt_i);
             exynos4210_ltick_int_start(&s->l_timer[lt_i].tick_timer);
         }
+        exynos4210_ltick_tx_commit(&s->l_timer[lt_i].tick_timer);
 
         /* Start or Stop local FRC if TCON changed */
         exynos4210_lfrc_tx_begin(&s->l_timer[lt_i]);
@@ -1356,8 +1374,10 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
          * Due to this we should reload timer to nearest moment when CNT is
          * expired and then in event handler update tcntb to new TCNTB value.
          */
+        exynos4210_ltick_tx_begin(&s->l_timer[lt_i].tick_timer);
         exynos4210_ltick_set_cntb(&s->l_timer[lt_i].tick_timer, value,
                 s->l_timer[lt_i].tick_timer.icntb);
+        exynos4210_ltick_tx_commit(&s->l_timer[lt_i].tick_timer);
 
         s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCNTB_WRITE;
         s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB] = value;
@@ -1486,7 +1506,6 @@ static void exynos4210_mct_init(Object *obj)
     int i;
     Exynos4210MCTState *s = EXYNOS4210_MCT(obj);
     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    QEMUBH *bh[2];
 
     /* Global timer */
     s->g_timer.ptimer_frc = ptimer_init(exynos4210_gfrc_event, s,
@@ -1495,9 +1514,9 @@ static void exynos4210_mct_init(Object *obj)
 
     /* Local timers */
     for (i = 0; i < 2; i++) {
-        bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
         s->l_timer[i].tick_timer.ptimer_tick =
-            ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
+            ptimer_init(exynos4210_ltick_event, &s->l_timer[i],
+                        PTIMER_POLICY_DEFAULT);
         s->l_timer[i].ptimer_frc =
             ptimer_init(exynos4210_lfrc_event, &s->l_timer[i],
                         PTIMER_POLICY_DEFAULT);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (12 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:00   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API Peter Maydell
                   ` (6 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the exynos4210_pwm code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/exynos4210_pwm.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index aa5dca68ef7..59a8c08db0f 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -25,7 +25,6 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/timer.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/ptimer.h"
 
@@ -150,7 +149,9 @@ static const VMStateDescription vmstate_exynos4210_pwm_state = {
 };
 
 /*
- * PWM update frequency
+ * PWM update frequency.
+ * Must be called within a ptimer_transaction_begin/commit block
+ * for s->timer[id].ptimer.
  */
 static void exynos4210_pwm_update_freq(Exynos4210PWMState *s, uint32_t id)
 {
@@ -281,12 +282,15 @@ static void exynos4210_pwm_write(void *opaque, hwaddr offset,
 
         /* update timers frequencies */
         for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
+            ptimer_transaction_begin(s->timer[i].ptimer);
             exynos4210_pwm_update_freq(s, s->timer[i].id);
+            ptimer_transaction_commit(s->timer[i].ptimer);
         }
         break;
 
     case TCON:
         for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
+            ptimer_transaction_begin(s->timer[i].ptimer);
             if ((value & TCON_TIMER_MANUAL_UPD(i)) >
             (s->reg_tcon & TCON_TIMER_MANUAL_UPD(i))) {
                 /*
@@ -315,6 +319,7 @@ static void exynos4210_pwm_write(void *opaque, hwaddr offset,
                 ptimer_stop(s->timer[i].ptimer);
                 DPRINTF("stop timer %d\n", i);
             }
+            ptimer_transaction_commit(s->timer[i].ptimer);
         }
         s->reg_tcon = value;
         break;
@@ -369,8 +374,10 @@ static void exynos4210_pwm_reset(DeviceState *d)
         s->timer[i].reg_tcmpb = 0;
         s->timer[i].reg_tcntb = 0;
 
+        ptimer_transaction_begin(s->timer[i].ptimer);
         exynos4210_pwm_update_freq(s, s->timer[i].id);
         ptimer_stop(s->timer[i].ptimer);
+        ptimer_transaction_commit(s->timer[i].ptimer);
     }
 }
 
@@ -388,12 +395,12 @@ static void exynos4210_pwm_init(Object *obj)
     Exynos4210PWMState *s = EXYNOS4210_PWM(obj);
     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
     int i;
-    QEMUBH *bh;
 
     for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
-        bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
         sysbus_init_irq(dev, &s->timer[i].irq);
-        s->timer[i].ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+        s->timer[i].ptimer = ptimer_init(exynos4210_pwm_tick,
+                                         &s->timer[i],
+                                         PTIMER_POLICY_DEFAULT);
         s->timer[i].id = i;
         s->timer[i].parent = s;
     }
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (13 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:01   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main " Peter Maydell
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the exynos41210_rtc 1Hz ptimer over to the transaction-based
API. (We will switch the other ptimer used by this device in a
separate commit.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/exynos4210_rtc.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index d5d7c91fb15..b7ae99e9aa7 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -401,6 +401,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr offset,
         }
         break;
     case RTCCON:
+        ptimer_transaction_begin(s->ptimer_1Hz);
         if (value & RTC_ENABLE) {
             exynos4210_rtc_update_freq(s, value);
         }
@@ -430,6 +431,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr offset,
                 ptimer_stop(s->ptimer);
             }
         }
+        ptimer_transaction_commit(s->ptimer_1Hz);
         s->reg_rtccon = value;
         break;
     case TICCNT:
@@ -539,7 +541,9 @@ static void exynos4210_rtc_reset(DeviceState *d)
 
     exynos4210_rtc_update_freq(s, s->reg_rtccon);
     ptimer_stop(s->ptimer);
+    ptimer_transaction_begin(s->ptimer_1Hz);
     ptimer_stop(s->ptimer_1Hz);
+    ptimer_transaction_commit(s->ptimer_1Hz);
 }
 
 static const MemoryRegionOps exynos4210_rtc_ops = {
@@ -562,9 +566,11 @@ static void exynos4210_rtc_init(Object *obj)
     ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
     exynos4210_rtc_update_freq(s, 0);
 
-    bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
-    s->ptimer_1Hz = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer_1Hz = ptimer_init(exynos4210_rtc_1Hz_tick,
+                                s, PTIMER_POLICY_DEFAULT);
+    ptimer_transaction_begin(s->ptimer_1Hz);
     ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
+    ptimer_transaction_commit(s->ptimer_1Hz);
 
     sysbus_init_irq(dev, &s->alm_irq);
     sysbus_init_irq(dev, &s->tick_irq);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main ptimer to transaction-based API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (14 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:02   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API Peter Maydell
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the exynos41210_rtc main ptimer over to the transaction-based
API, completing the transition for this device.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/exynos4210_rtc.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index b7ae99e9aa7..f85483a07f8 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -28,7 +28,6 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
@@ -195,6 +194,7 @@ static void check_alarm_raise(Exynos4210RTCState *s)
  * RTC update frequency
  * Parameters:
  *     reg_value - current RTCCON register or his new value
+ * Must be called within a ptimer_transaction_begin/commit block for s->ptimer.
  */
 static void exynos4210_rtc_update_freq(Exynos4210RTCState *s,
                                        uint32_t reg_value)
@@ -402,6 +402,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr offset,
         break;
     case RTCCON:
         ptimer_transaction_begin(s->ptimer_1Hz);
+        ptimer_transaction_begin(s->ptimer);
         if (value & RTC_ENABLE) {
             exynos4210_rtc_update_freq(s, value);
         }
@@ -432,6 +433,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr offset,
             }
         }
         ptimer_transaction_commit(s->ptimer_1Hz);
+        ptimer_transaction_commit(s->ptimer);
         s->reg_rtccon = value;
         break;
     case TICCNT:
@@ -539,8 +541,10 @@ static void exynos4210_rtc_reset(DeviceState *d)
 
     s->reg_curticcnt = 0;
 
+    ptimer_transaction_begin(s->ptimer);
     exynos4210_rtc_update_freq(s, s->reg_rtccon);
     ptimer_stop(s->ptimer);
+    ptimer_transaction_commit(s->ptimer);
     ptimer_transaction_begin(s->ptimer_1Hz);
     ptimer_stop(s->ptimer_1Hz);
     ptimer_transaction_commit(s->ptimer_1Hz);
@@ -559,12 +563,12 @@ static void exynos4210_rtc_init(Object *obj)
 {
     Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
     SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-    QEMUBH *bh;
 
-    bh = qemu_bh_new(exynos4210_rtc_tick, s);
-    s->ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->ptimer = ptimer_init(exynos4210_rtc_tick, s, PTIMER_POLICY_DEFAULT);
+    ptimer_transaction_begin(s->ptimer);
     ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
     exynos4210_rtc_update_freq(s, 0);
+    ptimer_transaction_commit(s->ptimer);
 
     s->ptimer_1Hz = ptimer_init(exynos4210_rtc_1Hz_tick,
                                 s, PTIMER_POLICY_DEFAULT);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (15 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:03   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 18/21] hw/timer/imx_gpt.c: " Peter Maydell
                   ` (3 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the imx_epit.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/imx_epit.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 39810ac8b03..baf6338e1a6 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -17,7 +17,6 @@
 #include "migration/vmstate.h"
 #include "hw/irq.h"
 #include "hw/misc/imx_ccm.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 
@@ -74,6 +73,10 @@ static void imx_epit_update_int(IMXEPITState *s)
     }
 }
 
+/*
+ * Must be called from within a ptimer_transaction_begin/commit block
+ * for both s->timer_cmp and s->timer_reload.
+ */
 static void imx_epit_set_freq(IMXEPITState *s)
 {
     uint32_t clksrc;
@@ -105,6 +108,8 @@ static void imx_epit_reset(DeviceState *dev)
     s->lr = EPIT_TIMER_MAX;
     s->cmp = 0;
     s->cnt = 0;
+    ptimer_transaction_begin(s->timer_cmp);
+    ptimer_transaction_begin(s->timer_reload);
     /* stop both timers */
     ptimer_stop(s->timer_cmp);
     ptimer_stop(s->timer_reload);
@@ -117,6 +122,8 @@ static void imx_epit_reset(DeviceState *dev)
         /* if the timer is still enabled, restart it */
         ptimer_run(s->timer_reload, 0);
     }
+    ptimer_transaction_commit(s->timer_cmp);
+    ptimer_transaction_commit(s->timer_reload);
 }
 
 static uint32_t imx_epit_update_count(IMXEPITState *s)
@@ -164,6 +171,7 @@ static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
     return reg_value;
 }
 
+/* Must be called from ptimer_transaction_begin/commit block for s->timer_cmp */
 static void imx_epit_reload_compare_timer(IMXEPITState *s)
 {
     if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN))  {
@@ -191,6 +199,8 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
 
     switch (offset >> 2) {
     case 0: /* CR */
+        ptimer_transaction_begin(s->timer_cmp);
+        ptimer_transaction_begin(s->timer_reload);
 
         oldcr = s->cr;
         s->cr = value & 0x03ffffff;
@@ -231,6 +241,9 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
         } else {
             ptimer_stop(s->timer_cmp);
         }
+
+        ptimer_transaction_commit(s->timer_cmp);
+        ptimer_transaction_commit(s->timer_reload);
         break;
 
     case 1: /* SR - ACK*/
@@ -244,6 +257,8 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
     case 2: /* LR - set ticks */
         s->lr = value;
 
+        ptimer_transaction_begin(s->timer_cmp);
+        ptimer_transaction_begin(s->timer_reload);
         if (s->cr & CR_RLD) {
             /* Also set the limit if the LRD bit is set */
             /* If IOVW bit is set then set the timer value */
@@ -255,12 +270,16 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
         }
 
         imx_epit_reload_compare_timer(s);
+        ptimer_transaction_commit(s->timer_cmp);
+        ptimer_transaction_commit(s->timer_reload);
         break;
 
     case 3: /* CMP */
         s->cmp = value;
 
+        ptimer_transaction_begin(s->timer_cmp);
         imx_epit_reload_compare_timer(s);
+        ptimer_transaction_commit(s->timer_cmp);
 
         break;
 
@@ -281,6 +300,11 @@ static void imx_epit_cmp(void *opaque)
     imx_epit_update_int(s);
 }
 
+static void imx_epit_reload(void *opaque)
+{
+    /* No action required on rollover of timer_reload */
+}
+
 static const MemoryRegionOps imx_epit_ops = {
     .read = imx_epit_read,
     .write = imx_epit_write,
@@ -308,7 +332,6 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
 {
     IMXEPITState *s = IMX_EPIT(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-    QEMUBH *bh;
 
     DPRINTF("\n");
 
@@ -317,10 +340,9 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
                           0x00001000);
     sysbus_init_mmio(sbd, &s->iomem);
 
-    s->timer_reload = ptimer_init_with_bh(NULL, PTIMER_POLICY_DEFAULT);
+    s->timer_reload = ptimer_init(imx_epit_reload, s, PTIMER_POLICY_DEFAULT);
 
-    bh = qemu_bh_new(imx_epit_cmp, s);
-    s->timer_cmp = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->timer_cmp = ptimer_init(imx_epit_cmp, s, PTIMER_POLICY_DEFAULT);
 }
 
 static void imx_epit_class_init(ObjectClass *klass, void *data)
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 18/21] hw/timer/imx_gpt.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (16 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:04   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 19/21] hw/timer/mss-timerc: " Peter Maydell
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the imx_epit.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/imx_gpt.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index c535d191292..5c0d9a269ce 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -16,7 +16,6 @@
 #include "hw/irq.h"
 #include "hw/timer/imx_gpt.h"
 #include "migration/vmstate.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 
@@ -127,6 +126,7 @@ static const IMXClk imx7_gpt_clocks[] = {
     CLK_NONE,      /* 111 not defined */
 };
 
+/* Must be called from within ptimer_transaction_begin/commit block */
 static void imx_gpt_set_freq(IMXGPTState *s)
 {
     uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
@@ -167,6 +167,7 @@ static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg,
     return timeout;
 }
 
+/* Must be called from within ptimer_transaction_begin/commit block */
 static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event)
 {
     uint32_t timeout = GPT_TIMER_MAX;
@@ -313,6 +314,7 @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
 
 static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
 {
+    ptimer_transaction_begin(s->timer);
     /* stop timer */
     ptimer_stop(s->timer);
 
@@ -350,6 +352,7 @@ static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
     if (s->freq && (s->cr & GPT_CR_EN)) {
         ptimer_run(s->timer, 1);
     }
+    ptimer_transaction_commit(s->timer);
 }
 
 static void imx_gpt_soft_reset(DeviceState *dev)
@@ -382,6 +385,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
             imx_gpt_soft_reset(DEVICE(s));
         } else {
             /* set our freq, as the source might have changed */
+            ptimer_transaction_begin(s->timer);
             imx_gpt_set_freq(s);
 
             if ((oldreg ^ s->cr) & GPT_CR_EN) {
@@ -397,12 +401,15 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
                     ptimer_stop(s->timer);
                 }
             }
+            ptimer_transaction_commit(s->timer);
         }
         break;
 
     case 1: /* Prescaler */
         s->pr = value & 0xfff;
+        ptimer_transaction_begin(s->timer);
         imx_gpt_set_freq(s);
+        ptimer_transaction_commit(s->timer);
         break;
 
     case 2: /* SR */
@@ -414,13 +421,16 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
         s->ir = value & 0x3f;
         imx_gpt_update_int(s);
 
+        ptimer_transaction_begin(s->timer);
         imx_gpt_compute_next_timeout(s, false);
+        ptimer_transaction_commit(s->timer);
 
         break;
 
     case 4: /* OCR1 -- output compare register */
         s->ocr1 = value;
 
+        ptimer_transaction_begin(s->timer);
         /* In non-freerun mode, reset count when this register is written */
         if (!(s->cr & GPT_CR_FRR)) {
             s->next_timeout = GPT_TIMER_MAX;
@@ -429,6 +439,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
 
         /* compute the new timeout */
         imx_gpt_compute_next_timeout(s, false);
+        ptimer_transaction_commit(s->timer);
 
         break;
 
@@ -436,7 +447,9 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
         s->ocr2 = value;
 
         /* compute the new timeout */
+        ptimer_transaction_begin(s->timer);
         imx_gpt_compute_next_timeout(s, false);
+        ptimer_transaction_commit(s->timer);
 
         break;
 
@@ -444,7 +457,9 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
         s->ocr3 = value;
 
         /* compute the new timeout */
+        ptimer_transaction_begin(s->timer);
         imx_gpt_compute_next_timeout(s, false);
+        ptimer_transaction_commit(s->timer);
 
         break;
 
@@ -484,15 +499,13 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
 {
     IMXGPTState *s = IMX_GPT(dev);
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-    QEMUBH *bh;
 
     sysbus_init_irq(sbd, &s->irq);
     memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT,
                           0x00001000);
     sysbus_init_mmio(sbd, &s->iomem);
 
-    bh = qemu_bh_new(imx_gpt_timeout, s);
-    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init(imx_gpt_timeout, s, PTIMER_POLICY_DEFAULT);
 }
 
 static void imx_gpt_class_init(ObjectClass *klass, void *data)
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 19/21] hw/timer/mss-timerc: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (17 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 18/21] hw/timer/imx_gpt.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:05   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: " Peter Maydell
  2019-10-08 17:17 ` [PATCH v2 21/21] hw/net/lan9118.c: " Peter Maydell
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the mss-timer code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/timer/mss-timer.h |  1 -
 hw/timer/mss-timer.c         | 11 ++++++++---
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/hw/timer/mss-timer.h b/include/hw/timer/mss-timer.h
index d15d1732f81..e5a784b27e4 100644
--- a/include/hw/timer/mss-timer.h
+++ b/include/hw/timer/mss-timer.h
@@ -46,7 +46,6 @@
 #define R_TIM1_MAX        6
 
 struct Msf2Timer {
-    QEMUBH *bh;
     ptimer_state *ptimer;
 
     uint32_t regs[R_TIM1_MAX];
diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c
index a34c2402b00..b1c9a805011 100644
--- a/hw/timer/mss-timer.c
+++ b/hw/timer/mss-timer.c
@@ -24,7 +24,6 @@
  */
 
 #include "qemu/osdep.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 #include "hw/irq.h"
@@ -67,6 +66,7 @@ static void timer_update_irq(struct Msf2Timer *st)
     qemu_set_irq(st->irq, (ier && isr));
 }
 
+/* Must be called from within a ptimer_transaction_begin/commit block */
 static void timer_update(struct Msf2Timer *st)
 {
     uint64_t count;
@@ -159,7 +159,9 @@ timer_write(void *opaque, hwaddr offset,
     switch (addr) {
     case R_TIM_CTRL:
         st->regs[R_TIM_CTRL] = value;
+        ptimer_transaction_begin(st->ptimer);
         timer_update(st);
+        ptimer_transaction_commit(st->ptimer);
         break;
 
     case R_TIM_RIS:
@@ -171,7 +173,9 @@ timer_write(void *opaque, hwaddr offset,
     case R_TIM_LOADVAL:
         st->regs[R_TIM_LOADVAL] = value;
         if (st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL) {
+            ptimer_transaction_begin(st->ptimer);
             timer_update(st);
+            ptimer_transaction_commit(st->ptimer);
         }
         break;
 
@@ -228,9 +232,10 @@ static void mss_timer_init(Object *obj)
     for (i = 0; i < NUM_TIMERS; i++) {
         struct Msf2Timer *st = &t->timers[i];
 
-        st->bh = qemu_bh_new(timer_hit, st);
-        st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
+        st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
+        ptimer_transaction_begin(st->ptimer);
         ptimer_set_freq(st->ptimer, t->freq_hz);
+        ptimer_transaction_commit(st->ptimer);
         sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq);
     }
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (18 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 19/21] hw/timer/mss-timerc: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:06   ` Richard Henderson
  2019-10-08 17:17 ` [PATCH v2 21/21] hw/net/lan9118.c: " Peter Maydell
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the cmsdk-apb-watchdog code away from bottom-half based
ptimers to the new transaction-based ptimer API.  This just requires
adding begin/commit calls around the various places that modify the
ptimer state, and using the new ptimer_init() function to create the
timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/watchdog/cmsdk-apb-watchdog.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index e42c3ebd29d..e6f3b93c44e 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -24,7 +24,6 @@
 #include "qemu/log.h"
 #include "trace.h"
 #include "qapi/error.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "sysemu/watchdog.h"
 #include "hw/sysbus.h"
@@ -200,8 +199,10 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
          * Reset the load value and the current count, and make sure
          * we're counting.
          */
+        ptimer_transaction_begin(s->timer);
         ptimer_set_limit(s->timer, value, 1);
         ptimer_run(s->timer, 0);
+        ptimer_transaction_commit(s->timer);
         break;
     case A_WDOGCONTROL:
         if (s->is_luminary && 0 != (R_WDOGCONTROL_INTEN_MASK & s->control)) {
@@ -217,7 +218,9 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
         break;
     case A_WDOGINTCLR:
         s->intstatus = 0;
+        ptimer_transaction_begin(s->timer);
         ptimer_set_count(s->timer, ptimer_get_limit(s->timer));
+        ptimer_transaction_commit(s->timer);
         cmsdk_apb_watchdog_update(s);
         break;
     case A_WDOGLOCK:
@@ -299,8 +302,10 @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
     s->itop = 0;
     s->resetstatus = 0;
     /* Set the limit and the count */
+    ptimer_transaction_begin(s->timer);
     ptimer_set_limit(s->timer, 0xffffffff, 1);
     ptimer_run(s->timer, 0);
+    ptimer_transaction_commit(s->timer);
 }
 
 static void cmsdk_apb_watchdog_init(Object *obj)
@@ -320,7 +325,6 @@ static void cmsdk_apb_watchdog_init(Object *obj)
 static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
 {
     CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
-    QEMUBH *bh;
 
     if (s->wdogclk_frq == 0) {
         error_setg(errp,
@@ -328,14 +332,15 @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
         return;
     }
 
-    bh = qemu_bh_new(cmsdk_apb_watchdog_tick, s);
-    s->timer = ptimer_init_with_bh(bh,
+    s->timer = ptimer_init(cmsdk_apb_watchdog_tick, s,
                            PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
                            PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
                            PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
                            PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
+    ptimer_transaction_begin(s->timer);
     ptimer_set_freq(s->timer, s->wdogclk_frq);
+    ptimer_transaction_commit(s->timer);
 }
 
 static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v2 21/21] hw/net/lan9118.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
                   ` (19 preceding siblings ...)
  2019-10-08 17:17 ` [PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: " Peter Maydell
@ 2019-10-08 17:17 ` Peter Maydell
  2019-10-09  2:07   ` Richard Henderson
  20 siblings, 1 reply; 45+ messages in thread
From: Peter Maydell @ 2019-10-08 17:17 UTC (permalink / raw)
  To: qemu-arm, qemu-devel
  Cc: Philippe Mathieu-Daudé, Richard Henderson, Paolo Bonzini

Switch the cmsdk-apb-watchdog code away from bottom-half based
ptimers to the new transaction-based ptimer API.  This just requires
adding begin/commit calls around the various places that modify the
ptimer state, and using the new ptimer_init() function to create the
timer.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/net/lan9118.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 0ea51433dca..ed551f2178b 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -21,7 +21,6 @@
 #include "hw/ptimer.h"
 #include "hw/qdev-properties.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 /* For crc32 */
 #include <zlib.h>
@@ -450,8 +449,10 @@ static void lan9118_reset(DeviceState *d)
     s->e2p_data = 0;
     s->free_timer_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40;
 
+    ptimer_transaction_begin(s->timer);
     ptimer_stop(s->timer);
     ptimer_set_count(s->timer, 0xffff);
+    ptimer_transaction_commit(s->timer);
     s->gpt_cfg = 0xffff;
 
     s->mac_cr = MAC_CR_PRMS;
@@ -1100,6 +1101,7 @@ static void lan9118_writel(void *opaque, hwaddr offset,
         break;
     case CSR_GPT_CFG:
         if ((s->gpt_cfg ^ val) & GPT_TIMER_EN) {
+            ptimer_transaction_begin(s->timer);
             if (val & GPT_TIMER_EN) {
                 ptimer_set_count(s->timer, val & 0xffff);
                 ptimer_run(s->timer, 0);
@@ -1107,6 +1109,7 @@ static void lan9118_writel(void *opaque, hwaddr offset,
                 ptimer_stop(s->timer);
                 ptimer_set_count(s->timer, 0xffff);
             }
+            ptimer_transaction_commit(s->timer);
         }
         s->gpt_cfg = val & (GPT_TIMER_EN | 0xffff);
         break;
@@ -1328,7 +1331,6 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
 {
     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
     lan9118_state *s = LAN9118(dev);
-    QEMUBH *bh;
     int i;
     const MemoryRegionOps *mem_ops =
             s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
@@ -1349,10 +1351,11 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
     s->pmt_ctrl = 1;
     s->txp = &s->tx_packet;
 
-    bh = qemu_bh_new(lan9118_tick, s);
-    s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+    s->timer = ptimer_init(lan9118_tick, s, PTIMER_POLICY_DEFAULT);
+    ptimer_transaction_begin(s->timer);
     ptimer_set_freq(s->timer, 10000);
     ptimer_set_limit(s->timer, 0xffff, 1);
+    ptimer_transaction_commit(s->timer);
 }
 
 static Property lan9118_properties[] = {
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 02/21] ptimer: Provide new transaction-based API
  2019-10-08 17:17 ` [PATCH v2 02/21] ptimer: Provide new transaction-based API Peter Maydell
@ 2019-10-09  1:44   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:44 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Provide the new transaction-based API. If a ptimer is created
> using ptimer_init() rather than ptimer_init_with_bh(), then
> instead of providing a QEMUBH, it provides a pointer to the
> callback function directly, and has opted into the transaction
> API. All calls to functions which modify ptimer state:
>  - ptimer_set_period()
>  - ptimer_set_freq()
>  - ptimer_set_limit()
>  - ptimer_set_count()
>  - ptimer_run()
>  - ptimer_stop()
> must be between matched calls to ptimer_transaction_begin()
> and ptimer_transaction_commit(). When ptimer_transaction_commit()
> is called it will evaluate the state of the timer after all the
> changes in the transaction, and call the callback if necessary.
> 
> In the old API the individual update functions generally would
> call ptimer_trigger() immediately, which would schedule the QEMUBH.
> In the new API the update functions will instead defer the
> "set s->next_event and call ptimer_reload()" work to
> ptimer_transaction_commit().
> 
> Because ptimer_trigger() can now immediately call into the
> device code which may then call other ptimer functions that
> update ptimer_state fields, we must be more careful in
> ptimer_reload() not to cache fields from ptimer_state across
> the ptimer_trigger() call. (This was harmless with the QEMUBH
> mechanism as the BH would not be invoked until much later.)
> 
> We use assertions to check that:
>  * the functions modifying ptimer state are not called outside
>    a transaction block
>  * ptimer_transaction_begin() and _commit() calls are paired
>  * the transaction API is not used with a QEMUBH ptimer
> 
> There is some slight repetition of code:
>  * most of the set functions have similar looking "if s->bh
>    call ptimer_reload, otherwise set s->need_reload" code
>  * ptimer_init() and ptimer_init_with_bh() have similar code
> We deliberately don't try to avoid this repetition, because
> it will all be deleted when the QEMUBH version of the API
> is removed.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API Peter Maydell
@ 2019-10-09  1:46   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:46 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Convert the ptimer test cases to the transaction-based ptimer API,
> by changing to ptimer_init(), dropping the now-unused QEMUBH
> variables, and surrounding each set of changes to the ptimer
> state in ptimer_transaction_begin/commit calls.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 04/21] hw/timer/arm_timer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 04/21] hw/timer/arm_timer.c: " Peter Maydell
@ 2019-10-09  1:47   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:47 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the arm_timer.c code away from bottom-half based ptimers
> to the new transaction-based ptimer API. This just requires
> adding begin/commit calls around the various arms of
> arm_timer_write() that modify the ptimer state, and using the
> new ptimer_init() function to create the timer.
> 
> Fixes: https://bugs.launchpad.net/qemu/+bug/1777777
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/arm_timer.c | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 05/21] hw/arm/musicpal.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 05/21] hw/arm/musicpal.c: " Peter Maydell
@ 2019-10-09  1:48   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:48 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the musicpal code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: " Peter Maydell
@ 2019-10-09  1:49   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:49 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the allwinner-a10-pit code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/allwinner-a10-pit.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 07/21] hw/timer/arm_mptimer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 07/21] hw/timer/arm_mptimer.c: " Peter Maydell
@ 2019-10-09  1:50   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:50 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the arm_mptimer.c code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/arm_mptimer.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: " Peter Maydell
@ 2019-10-09  1:51   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:51 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the cmsdk-apb-dualtimer code away from bottom-half based
> ptimers to the new transaction-based ptimer API.  This just requires
> adding begin/commit calls around the various places that modify the
> ptimer state, and using the new ptimer_init() function to create the
> timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/cmsdk-apb-dualtimer.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: " Peter Maydell
@ 2019-10-09  1:52   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:52 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the cmsdk-apb-timer code away from bottom-half based ptimers
> to the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/cmsdk-apb-timer.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 10/21] hw/timer/digic-timer.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 10/21] hw/timer/digic-timer.c: " Peter Maydell
@ 2019-10-09  1:53   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:53 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the digic-timer.c code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/digic-timer.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC " Peter Maydell
@ 2019-10-09  1:56   ` Richard Henderson
  2019-10-09  1:58     ` Richard Henderson
  2019-10-09  1:58   ` Richard Henderson
  1 sibling, 1 reply; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:56 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> @@ -945,7 +977,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
>          DPRINTF("freq=%dHz\n", s->freq);
>  
>          /* global timer */
> -        ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
> +        tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
>  
>          /* local timer */
>          ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);

Failed to update them all, it would appear.


r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  2019-10-09  1:56   ` Richard Henderson
@ 2019-10-09  1:58     ` Richard Henderson
  2019-10-09 13:49       ` Peter Maydell
  0 siblings, 1 reply; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:58 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 9:56 PM, Richard Henderson wrote:
> On 10/8/19 1:17 PM, Peter Maydell wrote:
>> @@ -945,7 +977,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
>>          DPRINTF("freq=%dHz\n", s->freq);
>>  
>>          /* global timer */
>> -        ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
>> +        tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
>>  
>>          /* local timer */
>>          ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
> 
> Failed to update them all, it would appear.

Ho hum.  Done in a subsequent patch.
I didn't realize that you weren't converting the entire file at once.


r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC " Peter Maydell
@ 2019-10-09  1:58   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:58 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the exynos MCT LFRC timers over to the ptimer transaction API.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/exynos4210_mct.c | 27 +++++++++++++++++++++++----
>  1 file changed, 23 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC " Peter Maydell
  2019-10-09  1:56   ` Richard Henderson
@ 2019-10-09  1:58   ` Richard Henderson
  1 sibling, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:58 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> We want to switch the exynos MCT code away from bottom-half based ptimers to
> the new transaction-based ptimer API. The MCT is complicated
> and uses multiple different ptimers, so it's clearer to switch
> it a piece at a time. Here we change over only the GFRC.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/exynos4210_mct.c | 48 ++++++++++++++++++++++++++++++++++++---
>  1 file changed, 45 insertions(+), 3 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick " Peter Maydell
@ 2019-10-09  1:59   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  1:59 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the ltick ptimer over to the ptimer transaction API.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/exynos4210_mct.c | 31 +++++++++++++++++++++++++------
>  1 file changed, 25 insertions(+), 6 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch " Peter Maydell
@ 2019-10-09  2:00   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:00 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the exynos4210_pwm code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/exynos4210_pwm.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API
  2019-10-08 17:17 ` [PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API Peter Maydell
@ 2019-10-09  2:01   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:01 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the exynos41210_rtc 1Hz ptimer over to the transaction-based
> API. (We will switch the other ptimer used by this device in a
> separate commit.)
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/exynos4210_rtc.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main ptimer to transaction-based API
  2019-10-08 17:17 ` [PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main " Peter Maydell
@ 2019-10-09  2:02   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:02 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the exynos41210_rtc main ptimer over to the transaction-based
> API, completing the transition for this device.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/exynos4210_rtc.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API Peter Maydell
@ 2019-10-09  2:03   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:03 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the imx_epit.c code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/imx_epit.c | 32 +++++++++++++++++++++++++++-----
>  1 file changed, 27 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 18/21] hw/timer/imx_gpt.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 18/21] hw/timer/imx_gpt.c: " Peter Maydell
@ 2019-10-09  2:04   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:04 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the imx_epit.c code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/timer/imx_gpt.c | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 19/21] hw/timer/mss-timerc: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 19/21] hw/timer/mss-timerc: " Peter Maydell
@ 2019-10-09  2:05   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:05 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the mss-timer code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  include/hw/timer/mss-timer.h |  1 -
>  hw/timer/mss-timer.c         | 11 ++++++++---
>  2 files changed, 8 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: " Peter Maydell
@ 2019-10-09  2:06   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:06 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the cmsdk-apb-watchdog code away from bottom-half based
> ptimers to the new transaction-based ptimer API.  This just requires
> adding begin/commit calls around the various places that modify the
> ptimer state, and using the new ptimer_init() function to create the
> timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/watchdog/cmsdk-apb-watchdog.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 21/21] hw/net/lan9118.c: Switch to transaction-based ptimer API
  2019-10-08 17:17 ` [PATCH v2 21/21] hw/net/lan9118.c: " Peter Maydell
@ 2019-10-09  2:07   ` Richard Henderson
  0 siblings, 0 replies; 45+ messages in thread
From: Richard Henderson @ 2019-10-09  2:07 UTC (permalink / raw)
  To: Peter Maydell, qemu-arm, qemu-devel
  Cc: Paolo Bonzini, Philippe Mathieu-Daudé

On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the cmsdk-apb-watchdog code away from bottom-half based
> ptimers to the new transaction-based ptimer API.  This just requires
> adding begin/commit calls around the various places that modify the
> ptimer state, and using the new ptimer_init() function to create the
> timer.
> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/net/lan9118.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  2019-10-09  1:58     ` Richard Henderson
@ 2019-10-09 13:49       ` Peter Maydell
  0 siblings, 0 replies; 45+ messages in thread
From: Peter Maydell @ 2019-10-09 13:49 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Paolo Bonzini, qemu-arm, Philippe Mathieu-Daudé, QEMU Developers

On Wed, 9 Oct 2019 at 02:58, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 10/8/19 9:56 PM, Richard Henderson wrote:
> > On 10/8/19 1:17 PM, Peter Maydell wrote:
> >> @@ -945,7 +977,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
> >>          DPRINTF("freq=%dHz\n", s->freq);
> >>
> >>          /* global timer */
> >> -        ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
> >> +        tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
> >>
> >>          /* local timer */
> >>          ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
> >
> > Failed to update them all, it would appear.
>
> Ho hum.  Done in a subsequent patch.
> I didn't realize that you weren't converting the entire file at once.

Yeah, the MCT device is pretty complicated and (per the commit
message) I felt it was easier to write and debug by switching
each ptimer one at a time rather than trying to do the whole
lot at the same time.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2019-10-09 18:50 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-08 17:17 [PATCH v2 00/21] transaction-based ptimer API Peter Maydell
2019-10-08 17:17 ` [PATCH v2 01/21] ptimer: Rename ptimer_init() to ptimer_init_with_bh() Peter Maydell
2019-10-08 17:17 ` [PATCH v2 02/21] ptimer: Provide new transaction-based API Peter Maydell
2019-10-09  1:44   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API Peter Maydell
2019-10-09  1:46   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 04/21] hw/timer/arm_timer.c: " Peter Maydell
2019-10-09  1:47   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 05/21] hw/arm/musicpal.c: " Peter Maydell
2019-10-09  1:48   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: " Peter Maydell
2019-10-09  1:49   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 07/21] hw/timer/arm_mptimer.c: " Peter Maydell
2019-10-09  1:50   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: " Peter Maydell
2019-10-09  1:51   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: " Peter Maydell
2019-10-09  1:52   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 10/21] hw/timer/digic-timer.c: " Peter Maydell
2019-10-09  1:53   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC " Peter Maydell
2019-10-09  1:56   ` Richard Henderson
2019-10-09  1:58     ` Richard Henderson
2019-10-09 13:49       ` Peter Maydell
2019-10-09  1:58   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC " Peter Maydell
2019-10-09  1:58   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick " Peter Maydell
2019-10-09  1:59   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch " Peter Maydell
2019-10-09  2:00   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API Peter Maydell
2019-10-09  2:01   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main " Peter Maydell
2019-10-09  2:02   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API Peter Maydell
2019-10-09  2:03   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 18/21] hw/timer/imx_gpt.c: " Peter Maydell
2019-10-09  2:04   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 19/21] hw/timer/mss-timerc: " Peter Maydell
2019-10-09  2:05   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: " Peter Maydell
2019-10-09  2:06   ` Richard Henderson
2019-10-08 17:17 ` [PATCH v2 21/21] hw/net/lan9118.c: " Peter Maydell
2019-10-09  2:07   ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).