From mboxrd@z Thu Jan 1 00:00:00 1970 From: hongzha1 Subject: [PATCH 07/10] dovetail/tick: implement proxy tick device installing and uninstalling Date: Mon, 11 Jan 2021 01:43:15 -0500 Message-Id: <20210111064318.6154-7-hongzhan.chen@intel.com> In-Reply-To: <20210111064318.6154-1-hongzhan.chen@intel.com> References: <20210111064318.6154-1-hongzhan.chen@intel.com> List-Id: Discussions about the Xenomai project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Xenomai@xenomai.org Signed-off-by: hongzha1 --- kernel/cobalt/dovetail/tick.c | 85 ++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/kernel/cobalt/dovetail/tick.c b/kernel/cobalt/dovetail/tick.c index 02cd86690..6a196496c 100644 --- a/kernel/cobalt/dovetail/tick.c +++ b/kernel/cobalt/dovetail/tick.c @@ -6,11 +6,92 @@ */ #include +#include #include #include +#include +#include extern struct xnintr nktimer; +static DEFINE_PER_CPU(struct clock_proxy_device *, proxy_device); + +static int proxy_set_next_ktime(ktime_t expires, + struct clock_event_device *proxy_dev) +{ + struct xnsched *sched; + ktime_t delta; + unsigned long flags; + int ret; + + /* + * When Negative delta have been observed, we set delta zero. + * Or else exntimer_start() will return -ETIMEDOUT and do not + * trigger shot + */ + delta = ktime_sub(expires, ktime_get_mono_fast_ns()); + if (delta < 0) + delta = 0; + + flags = hard_local_irq_save(); /* Prevent CPU migration. */ + sched = xnsched_current(); + ret = xntimer_start(&sched->htimer, delta, XN_INFINITE, XN_RELATIVE); + hard_local_irq_restore(flags); + + return ret ? -ETIME : 0; +} + + +void xn_core_tick(struct clock_event_device *dummy) /* hard irqs off */ +{ + xnintr_core_clock_handler(); +} + +static int proxy_set_oneshot_stopped(struct clock_event_device *proxy_dev) +{ + struct clock_event_device *real_dev; + struct clock_proxy_device *dev; + struct xnsched *sched; + spl_t s; + + dev = container_of(proxy_dev, struct clock_proxy_device, proxy_device); + + /* + * In-band wants to disable the clock hardware on entering a + * tickless state, so we have to stop our in-band tick + * emulation. Propagate the request for shutting down the + * hardware to the real device only if we have no outstanding + * OOB timers. CAUTION: the in-band timer is counted when + * assessing the RQ_IDLE condition, so we need to stop it + * prior to testing the latter. + */ + xnlock_get_irqsave(&nklock, s); + sched = xnsched_current(); + xntimer_stop(&sched->htimer); + //sched->lflags |= XNTSTOP; + + if (sched->lflags & XNIDLE) { + real_dev = dev->real_device; + real_dev->set_state_oneshot_stopped(real_dev); + } + + xnlock_put_irqrestore(&nklock, s); + + return 0; +} + +static void setup_proxy(struct clock_proxy_device *dev) +{ + struct clock_event_device *proxy_dev = &dev->proxy_device; + + dev->handle_oob_event = xn_core_tick; + proxy_dev->features |= CLOCK_EVT_FEAT_KTIME; + proxy_dev->set_next_ktime = proxy_set_next_ktime; + if (proxy_dev->set_state_oneshot_stopped) + proxy_dev->set_state_oneshot_stopped = proxy_set_oneshot_stopped; + __this_cpu_write(proxy_device, dev); +} + int pipeline_install_tick_proxy(void) { int ret; @@ -20,7 +101,7 @@ int pipeline_install_tick_proxy(void) return ret; /* Install the proxy tick device */ - TODO(); ret = 0; + ret = tick_install_proxy(setup_proxy, &xnsched_realtime_cpus); if (ret) goto fail_proxy; @@ -35,7 +116,7 @@ fail_proxy: void pipeline_uninstall_tick_proxy(void) { /* Uninstall the proxy tick device. */ - TODO(); + tick_uninstall_proxy(&xnsched_realtime_cpus); pipeline_free_timer_ipi(); -- 2.17.1