Commit 4cbe7558 authored by Hongzhan Chen's avatar Hongzhan Chen Committed by Jan Kiszka

cobalt/tick: dovetail: install/uninstall proxy tick device

Signed-off-by: default avatarHongzhan Chen <hongzhan.chen@intel.com>
[Philippe: protect xntimer_start with nklock]
Signed-off-by: Philippe Gerum's avatarPhilippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 544cd293
......@@ -6,8 +6,87 @@
*/
#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>
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;
xnlock_get_irqsave(&nklock, flags);
sched = xnsched_current();
ret = xntimer_start(&sched->htimer, delta, XN_INFINITE, XN_RELATIVE);
xnlock_put_irqrestore(&nklock, 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);
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)
{
......@@ -18,7 +97,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;
......@@ -33,7 +112,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();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment