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