[PATCH 2/8] dovetail/tick: implement proxy tick device installing and uninstalling

hongzha1 hongzhan.chen at intel.com
Fri Jan 15 02:16:32 CET 2021


Signed-off-by: hongzha1 <hongzhan.chen at intel.com>

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 <linux/tick.h>
+#include <linux/clockchips.h>
 #include <cobalt/kernel/intr.h>
 #include <pipeline/tick.h>
+#include <cobalt/kernel/sched.h>
+#include <cobalt/kernel/timer.h>
 
 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




More information about the Xenomai mailing list