0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/cpu.h>
0011 #include <linux/err.h>
0012 #include <linux/hrtimer.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/percpu.h>
0015 #include <linux/profile.h>
0016 #include <linux/sched.h>
0017
0018 #include "tick-internal.h"
0019
0020
0021
0022
0023 int tick_program_event(ktime_t expires, int force)
0024 {
0025 struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
0026
0027 if (unlikely(expires == KTIME_MAX)) {
0028
0029
0030
0031 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED);
0032 dev->next_event = KTIME_MAX;
0033 return 0;
0034 }
0035
0036 if (unlikely(clockevent_state_oneshot_stopped(dev))) {
0037
0038
0039
0040
0041 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
0042 }
0043
0044 return clockevents_program_event(dev, expires, force);
0045 }
0046
0047
0048
0049
0050 void tick_resume_oneshot(void)
0051 {
0052 struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
0053
0054 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
0055 clockevents_program_event(dev, ktime_get(), true);
0056 }
0057
0058
0059
0060
0061 void tick_setup_oneshot(struct clock_event_device *newdev,
0062 void (*handler)(struct clock_event_device *),
0063 ktime_t next_event)
0064 {
0065 newdev->event_handler = handler;
0066 clockevents_switch_state(newdev, CLOCK_EVT_STATE_ONESHOT);
0067 clockevents_program_event(newdev, next_event, true);
0068 }
0069
0070
0071
0072
0073 int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
0074 {
0075 struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
0076 struct clock_event_device *dev = td->evtdev;
0077
0078 if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
0079 !tick_device_is_functional(dev)) {
0080
0081 pr_info("Clockevents: could not switch to one-shot mode:");
0082 if (!dev) {
0083 pr_cont(" no tick device\n");
0084 } else {
0085 if (!tick_device_is_functional(dev))
0086 pr_cont(" %s is not functional.\n", dev->name);
0087 else
0088 pr_cont(" %s does not support one-shot mode.\n",
0089 dev->name);
0090 }
0091 return -EINVAL;
0092 }
0093
0094 td->mode = TICKDEV_MODE_ONESHOT;
0095 dev->event_handler = handler;
0096 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
0097 tick_broadcast_switch_to_oneshot();
0098 return 0;
0099 }
0100
0101
0102
0103
0104
0105
0106 int tick_oneshot_mode_active(void)
0107 {
0108 unsigned long flags;
0109 int ret;
0110
0111 local_irq_save(flags);
0112 ret = __this_cpu_read(tick_cpu_device.mode) == TICKDEV_MODE_ONESHOT;
0113 local_irq_restore(flags);
0114
0115 return ret;
0116 }
0117
0118 #ifdef CONFIG_HIGH_RES_TIMERS
0119
0120
0121
0122
0123
0124 int tick_init_highres(void)
0125 {
0126 return tick_switch_to_oneshot(hrtimer_interrupt);
0127 }
0128 #endif