15d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy/*
25d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy * linux/kernel/time/tick-broadcast-hrtimer.c
35d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy * This file emulates a local clock event device
45d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy * via a pseudo clock device.
55d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy */
65d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/cpu.h>
75d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/err.h>
85d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/hrtimer.h>
95d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/interrupt.h>
105d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/percpu.h>
115d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/profile.h>
125d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/clockchips.h>
135d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/sched.h>
145d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/smp.h>
155d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include <linux/module.h>
165d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
175d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy#include "tick-internal.h"
185d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
195d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthystatic struct hrtimer bctimer;
205d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
215d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthystatic void bc_set_mode(enum clock_event_mode mode,
225d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy			struct clock_event_device *bc)
235d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy{
245d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	switch (mode) {
255d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	case CLOCK_EVT_MODE_SHUTDOWN:
265d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		/*
275d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 * Note, we cannot cancel the timer here as we might
285d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 * run into the following live lock scenario:
295d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 *
305d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 * cpu 0		cpu1
315d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 * lock(broadcast_lock);
325d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 *			hrtimer_interrupt()
335d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 *			bc_handler()
345d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 *			   tick_handle_oneshot_broadcast();
355d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 *			    lock(broadcast_lock);
365d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 * hrtimer_cancel()
375d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 *  wait_for_callback()
385d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		 */
395d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		hrtimer_try_to_cancel(&bctimer);
405d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		break;
415d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	default:
425d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		break;
435d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	}
445d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy}
455d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
465d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy/*
475d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy * This is called from the guts of the broadcast code when the cpu
485d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy * which is about to enter idle has the earliest broadcast timer event.
495d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy */
505d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthystatic int bc_set_next(ktime_t expires, struct clock_event_device *bc)
515d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy{
525d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	/*
535d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * We try to cancel the timer first. If the callback is on
545d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * flight on some other cpu then we let it handle it. If we
555d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * were able to cancel the timer nothing can rearm it as we
565d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * own broadcast_lock.
575d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 *
585d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * However we can also be called from the event handler of
595d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * ce_broadcast_hrtimer itself when it expires. We cannot
605d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * restart the timer because we are in the callback, but we
615d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * can set the expiry time and let the callback return
625d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 * HRTIMER_RESTART.
635d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	 */
645d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	if (hrtimer_try_to_cancel(&bctimer) >= 0) {
655d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED);
665d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		/* Bind the "device" to the cpu */
675d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		bc->bound_on = smp_processor_id();
685d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	} else if (bc->bound_on == smp_processor_id()) {
695d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		hrtimer_set_expires(&bctimer, expires);
705d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	}
715d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	return 0;
725d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy}
735d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
745d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthystatic struct clock_event_device ce_broadcast_hrtimer = {
755d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.set_mode		= bc_set_mode,
765d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.set_next_ktime		= bc_set_next,
775d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.features		= CLOCK_EVT_FEAT_ONESHOT |
785d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy				  CLOCK_EVT_FEAT_KTIME |
795d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy				  CLOCK_EVT_FEAT_HRTIMER,
805d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.rating			= 0,
815d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.bound_on		= -1,
825d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.min_delta_ns		= 1,
835d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.max_delta_ns		= KTIME_MAX,
845d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.min_delta_ticks	= 1,
85849401b66d305f3feb75b6db7459b95ad190552aPreeti U Murthy	.max_delta_ticks	= ULONG_MAX,
865d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.mult			= 1,
875d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.shift			= 0,
885d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	.cpumask		= cpu_all_mask,
895d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy};
905d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
915d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthystatic enum hrtimer_restart bc_handler(struct hrtimer *t)
925d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy{
935d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
945d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
955d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	if (ce_broadcast_hrtimer.next_event.tv64 == KTIME_MAX)
965d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy		return HRTIMER_NORESTART;
975d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
985d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	return HRTIMER_RESTART;
995d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy}
1005d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy
1015d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthyvoid tick_setup_hrtimer_broadcast(void)
1025d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy{
1035d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1045d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	bctimer.function = bc_handler;
1055d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy	clockevents_register_device(&ce_broadcast_hrtimer);
1065d1638acb9f62fa7eb0c07cb85318bbe1f13b227Preeti U Murthy}
107