Lines Matching +full:local +full:- +full:timer +full:- +full:stop
1 // SPDX-License-Identifier: GPL-2.0
3 * This file contains functions which emulate a local clock-event
6 * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
7 * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
8 * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
20 #include "tick-internal.h"
23 * Broadcast support for broken x86 hardware, where the local apic
24 * timer stops in C3 state.
79 if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) || in tick_check_broadcast_device()
80 (newdev->features & CLOCK_EVT_FEAT_PERCPU) || in tick_check_broadcast_device()
81 (newdev->features & CLOCK_EVT_FEAT_C3STOP)) in tick_check_broadcast_device()
85 !(newdev->features & CLOCK_EVT_FEAT_ONESHOT)) in tick_check_broadcast_device()
88 return !curdev || newdev->rating > curdev->rating; in tick_check_broadcast_device()
101 if (!try_module_get(dev->owner)) in tick_install_broadcast_device()
106 cur->event_handler = clockevents_handle_noop; in tick_install_broadcast_device()
118 if (dev->features & CLOCK_EVT_FEAT_ONESHOT) in tick_install_broadcast_device()
132 int ret = -ENODEV; in tick_broadcast_update_freq()
145 pr_crit_once("Failed to broadcast timer tick. Some CPUs may be unresponsive.\n"); in err_broadcast()
150 if (!dev->broadcast) in tick_device_setup_broadcast_func()
151 dev->broadcast = tick_broadcast; in tick_device_setup_broadcast_func()
152 if (!dev->broadcast) { in tick_device_setup_broadcast_func()
154 dev->name); in tick_device_setup_broadcast_func()
155 dev->broadcast = err_broadcast; in tick_device_setup_broadcast_func()
175 * the cpu local device. in tick_device_uses_broadcast()
178 dev->event_handler = tick_handle_periodic; in tick_device_uses_broadcast()
191 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) in tick_device_uses_broadcast()
210 * state affected device to stop. Let the in tick_device_uses_broadcast()
233 if (bc && !(bc->features & CLOCK_EVT_FEAT_HRTIMER)) in tick_device_uses_broadcast()
248 struct clock_event_device *evt = td->evtdev; in tick_receive_broadcast()
251 return -ENODEV; in tick_receive_broadcast()
253 if (!evt->event_handler) in tick_receive_broadcast()
254 return -EINVAL; in tick_receive_broadcast()
256 evt->event_handler(evt); in tick_receive_broadcast()
268 bool local = false; in tick_do_broadcast() local
278 * We only run the local handler, if the broadcast in tick_do_broadcast()
282 * local timer_interrupt() in tick_do_broadcast()
289 local = !(bc->features & CLOCK_EVT_FEAT_HRTIMER); in tick_do_broadcast()
300 td->evtdev->broadcast(mask); in tick_do_broadcast()
302 return local; in tick_do_broadcast()
307 * - invoke the broadcast handlers
334 ktime_t next = ktime_add(dev->next_event, tick_period); in tick_handle_periodic_broadcast()
341 * We run the handler of the local cpu after dropping in tick_handle_periodic_broadcast()
346 td->evtdev->event_handler(td->evtdev); in tick_handle_periodic_broadcast()
350 * tick_broadcast_control - Enable/disable or force broadcast mode
354 * might stop. Note: TICK_BROADCAST_FORCE cannot be undone.
363 /* Protects also the local clockevent device. */ in tick_broadcast_control()
366 dev = td->evtdev; in tick_broadcast_control()
371 if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) in tick_broadcast_control()
389 * Only shutdown the cpu local device, if: in tick_broadcast_control()
391 * - the broadcast device exists in tick_broadcast_control()
392 * - the broadcast device is not a hrtimer based one in tick_broadcast_control()
393 * - the broadcast device is in periodic mode to in tick_broadcast_control()
396 if (bc && !(bc->features & CLOCK_EVT_FEAT_HRTIMER) && in tick_broadcast_control()
436 dev->event_handler = tick_handle_periodic; in tick_set_periodic_handler()
438 dev->event_handler = tick_handle_periodic_broadcast; in tick_set_periodic_handler()
555 if (!(bc->features & CLOCK_EVT_FEAT_DYNIRQ)) in tick_broadcast_set_affinity()
558 if (cpumask_equal(bc->cpumask, cpumask)) in tick_broadcast_set_affinity()
561 bc->cpumask = cpumask; in tick_broadcast_set_affinity()
562 irq_set_affinity(bc->irq, bc->cpumask); in tick_broadcast_set_affinity()
594 if (td->mode == TICKDEV_MODE_ONESHOT) { in tick_check_oneshot_broadcast_this_cpu()
595 clockevents_switch_state(td->evtdev, in tick_check_oneshot_broadcast_this_cpu()
612 dev->next_event = KTIME_MAX; in tick_handle_oneshot_broadcast()
627 if (td->evtdev->next_event <= now) { in tick_handle_oneshot_broadcast()
631 * it can avoid reprogramming the cpu local in tick_handle_oneshot_broadcast()
632 * timer in tick_broadcast_oneshot_control(). in tick_handle_oneshot_broadcast()
635 } else if (td->evtdev->next_event < next_event) { in tick_handle_oneshot_broadcast()
636 next_event = td->evtdev->next_event; in tick_handle_oneshot_broadcast()
666 * - The global event did not expire any CPU local in tick_handle_oneshot_broadcast()
670 * - There are pending events on sleeping CPUs which were not in tick_handle_oneshot_broadcast()
680 td->evtdev->event_handler(td->evtdev); in tick_handle_oneshot_broadcast()
686 if (!(bc->features & CLOCK_EVT_FEAT_HRTIMER)) in broadcast_needs_cpu()
688 if (bc->next_event == KTIME_MAX) in broadcast_needs_cpu()
690 return bc->bound_on == cpu ? -EBUSY : 0; in broadcast_needs_cpu()
698 * local device if our own event is the first one to expire or in broadcast_shutdown_local()
699 * if we own the broadcast timer. in broadcast_shutdown_local()
701 if (bc->features & CLOCK_EVT_FEAT_HRTIMER) { in broadcast_shutdown_local()
704 if (dev->next_event < bc->next_event) in broadcast_shutdown_local()
721 return -EBUSY; in __tick_broadcast_oneshot_control()
723 dev = this_cpu_ptr(&tick_cpu_device)->evtdev; in __tick_broadcast_oneshot_control()
734 * through the EXIT path as the local timer is not in __tick_broadcast_oneshot_control()
747 if (bc->features & CLOCK_EVT_FEAT_HRTIMER) in __tick_broadcast_oneshot_control()
748 ret = -EBUSY; in __tick_broadcast_oneshot_control()
755 /* Conditionally shut down the local timer. */ in __tick_broadcast_oneshot_control()
759 * We only reprogram the broadcast timer if we in __tick_broadcast_oneshot_control()
761 * if the cpu local event is earlier than the in __tick_broadcast_oneshot_control()
769 ret = -EBUSY; in __tick_broadcast_oneshot_control()
770 } else if (dev->next_event < bc->next_event) { in __tick_broadcast_oneshot_control()
771 tick_broadcast_set_event(bc, cpu, dev->next_event); in __tick_broadcast_oneshot_control()
775 * timer to this cpu. If yes, remove in __tick_broadcast_oneshot_control()
791 * timer marked this cpu in the broadcast in __tick_broadcast_oneshot_control()
795 * handler. No need to reprogram the timer in __tick_broadcast_oneshot_control()
805 if (dev->next_event == KTIME_MAX) in __tick_broadcast_oneshot_control()
813 * if the cpu local expiry time is already in __tick_broadcast_oneshot_control()
814 * reached, we would reprogram the cpu local in __tick_broadcast_oneshot_control()
815 * timer with an already expired event. in __tick_broadcast_oneshot_control()
817 * This can lead to a ping-pong when we return in __tick_broadcast_oneshot_control()
819 * timer before the cpu local timer was able in __tick_broadcast_oneshot_control()
824 * enough out that the ping-pong starts. in __tick_broadcast_oneshot_control()
826 * If the cpu local next_event has expired in __tick_broadcast_oneshot_control()
827 * then we know that the broadcast timer in __tick_broadcast_oneshot_control()
832 * will invoke the cpu local handler. in __tick_broadcast_oneshot_control()
840 if (dev->next_event <= now) { in __tick_broadcast_oneshot_control()
846 * the cpu local timer device. in __tick_broadcast_oneshot_control()
848 tick_program_event(dev->next_event, 1); in __tick_broadcast_oneshot_control()
875 if (td->evtdev) in tick_broadcast_init_next_event()
876 td->evtdev->next_event = expires; in tick_broadcast_init_next_event()
881 * tick_broadcast_setup_oneshot - setup the broadcast device
891 if (bc->event_handler != tick_handle_oneshot_broadcast) { in tick_broadcast_setup_oneshot()
894 bc->event_handler = tick_handle_oneshot_broadcast; in tick_broadcast_setup_oneshot()
913 bc->next_event = KTIME_MAX; in tick_broadcast_setup_oneshot()
955 clockevents_program_event(bc, bc->next_event, 1); in hotplug_cpu__broadcast_tick_pull()
966 * Clear the broadcast masks for the dead cpu, but do not stop in tick_broadcast_oneshot_offline()
990 return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false; in tick_broadcast_oneshot_available()
998 if (!bc || (bc->features & CLOCK_EVT_FEAT_HRTIMER)) in __tick_broadcast_oneshot_control()
999 return -EBUSY; in __tick_broadcast_oneshot_control()