0001
0002
0003
0004
0005 #include <linux/cpu.h>
0006 #include <linux/err.h>
0007 #include <linux/hrtimer.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/percpu.h>
0010 #include <linux/profile.h>
0011 #include <linux/clockchips.h>
0012 #include <linux/sched.h>
0013 #include <linux/smp.h>
0014 #include <linux/module.h>
0015
0016 #include "tick-internal.h"
0017
0018 static struct hrtimer bctimer;
0019
0020 static int bc_shutdown(struct clock_event_device *evt)
0021 {
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 hrtimer_try_to_cancel(&bctimer);
0036 return 0;
0037 }
0038
0039
0040
0041
0042
0043 static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
0044 {
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 RCU_NONIDLE( {
0065 hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED_HARD);
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 bc->bound_on = bctimer.base->cpu_base->cpu;
0077 } );
0078 return 0;
0079 }
0080
0081 static struct clock_event_device ce_broadcast_hrtimer = {
0082 .name = "bc_hrtimer",
0083 .set_state_shutdown = bc_shutdown,
0084 .set_next_ktime = bc_set_next,
0085 .features = CLOCK_EVT_FEAT_ONESHOT |
0086 CLOCK_EVT_FEAT_KTIME |
0087 CLOCK_EVT_FEAT_HRTIMER,
0088 .rating = 0,
0089 .bound_on = -1,
0090 .min_delta_ns = 1,
0091 .max_delta_ns = KTIME_MAX,
0092 .min_delta_ticks = 1,
0093 .max_delta_ticks = ULONG_MAX,
0094 .mult = 1,
0095 .shift = 0,
0096 .cpumask = cpu_possible_mask,
0097 };
0098
0099 static enum hrtimer_restart bc_handler(struct hrtimer *t)
0100 {
0101 ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
0102
0103 return HRTIMER_NORESTART;
0104 }
0105
0106 void tick_setup_hrtimer_broadcast(void)
0107 {
0108 hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
0109 bctimer.function = bc_handler;
0110 clockevents_register_device(&ce_broadcast_hrtimer);
0111 }