From e3056c781e393c68a96aa9d8879f607fbb1f1b37 Mon Sep 17 00:00:00 2001 From: Stuart Ianna Date: Fri, 31 May 2024 14:23:31 +1000 Subject: [PATCH] arch/risc-v/riscv_mtimer: Update the mtimecmp value once per interrupt event. Cache the next timeout value in the drivers instance and update the mtimecmp value once. This is advantageous as the opensbi ecall to set the timer is expensive in systems which don't have the supervisor mode timer extension. --- arch/risc-v/src/common/riscv_mtimer.c | 43 ++++++++++++++++++--------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/arch/risc-v/src/common/riscv_mtimer.c b/arch/risc-v/src/common/riscv_mtimer.c index bd17bafe59..baa704c79b 100644 --- a/arch/risc-v/src/common/riscv_mtimer.c +++ b/arch/risc-v/src/common/riscv_mtimer.c @@ -212,18 +212,27 @@ static int riscv_mtimer_start(struct oneshot_lowerhalf_s *lower, struct riscv_mtimer_lowerhalf_s *priv = (struct riscv_mtimer_lowerhalf_s *)lower; uint64_t mtime = riscv_mtimer_get_mtime(priv); + uint64_t alarm = mtime + ts->tv_sec * priv->freq + + ts->tv_nsec * priv->freq / NSEC_PER_SEC; - priv->alarm = mtime + ts->tv_sec * priv->freq + - ts->tv_nsec * priv->freq / NSEC_PER_SEC; - if (priv->alarm < mtime) + if (alarm < mtime) { - priv->alarm = UINT64_MAX; + priv->alarm = UINT64_MAX; + priv->callback = NULL; + priv->arg = NULL; + } + else + { + priv->alarm = alarm; + priv->callback = callback; + priv->arg = arg; } - priv->callback = callback; - priv->arg = arg; + if (!up_interrupt_context()) + { + riscv_mtimer_set_mtimecmp(priv, priv->alarm); + } - riscv_mtimer_set_mtimecmp(priv, priv->alarm); return 0; } @@ -257,15 +266,18 @@ static int riscv_mtimer_cancel(struct oneshot_lowerhalf_s *lower, struct riscv_mtimer_lowerhalf_s *priv = (struct riscv_mtimer_lowerhalf_s *)lower; uint64_t mtime; + uint64_t alarm = priv->alarm; - riscv_mtimer_set_mtimecmp(priv, UINT64_MAX); + priv->alarm = UINT64_MAX; + if (!up_interrupt_context()) + { + riscv_mtimer_set_mtimecmp(priv, priv->alarm); + } mtime = riscv_mtimer_get_mtime(priv); - if (priv->alarm > mtime) + if (alarm > mtime) { - uint64_t nsec = (priv->alarm - mtime) * - NSEC_PER_SEC / priv->freq; - + uint64_t nsec = (alarm - mtime) * NSEC_PER_SEC / priv->freq; ts->tv_sec = nsec / NSEC_PER_SEC; ts->tv_nsec = nsec % NSEC_PER_SEC; } @@ -319,12 +331,14 @@ static int riscv_mtimer_interrupt(int irq, void *context, void *arg) { struct riscv_mtimer_lowerhalf_s *priv = arg; - riscv_mtimer_set_mtimecmp(priv, UINT64_MAX); + priv->alarm = UINT64_MAX; + if (priv->callback != NULL) { priv->callback(&priv->lower, priv->arg); } + riscv_mtimer_set_mtimecmp(priv, priv->alarm); return 0; } @@ -345,8 +359,9 @@ riscv_mtimer_initialize(uintptr_t mtime, uintptr_t mtimecmp, priv->mtime = mtime; priv->mtimecmp = mtimecmp; priv->freq = freq; + priv->alarm = UINT64_MAX; - riscv_mtimer_set_mtimecmp(priv, UINT64_MAX); + riscv_mtimer_set_mtimecmp(priv, priv->alarm); irq_attach(irq, riscv_mtimer_interrupt, priv); up_enable_irq(irq); }