static int s390_next_event(unsigned long delta, struct clock_event_device *evt) { S390_lowcore.clock_comparator = get_clock() + delta; set_clock_comparator(S390_lowcore.clock_comparator); return 0; }
/* * Set up per cpu jiffy timer and set the clock comparator. */ static void setup_jiffy_timer(void) { /* Set up clock comparator to next jiffy. */ S390_lowcore.jiffy_timer = jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY; set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); }
/* * Set up lowcore and control register of the current cpu to * enable TOD clock and clock comparator interrupts. */ void init_cpu_timer(void) { struct clock_event_device *cd; int cpu; S390_lowcore.clock_comparator = -1ULL; set_clock_comparator(S390_lowcore.clock_comparator); cpu = smp_processor_id(); cd = &per_cpu(comparators, cpu); cd->name = "comparator"; cd->features = CLOCK_EVT_FEAT_ONESHOT; cd->mult = 16777; cd->shift = 12; cd->min_delta_ns = 1; cd->max_delta_ns = LONG_MAX; cd->rating = 400; cd->cpumask = cpumask_of(cpu); cd->set_next_event = s390_next_event; cd->set_mode = s390_set_mode; clockevents_register_device(cd); /* Enable clock comparator timer interrupt. */ __ctl_set_bit(0,11); /* Always allow the timing alert external interrupt. */ __ctl_set_bit(0, 4); }
static void clock_comparator_interrupt(unsigned int ext_int_code, unsigned int param32, unsigned long param64) { if (S390_lowcore.clock_comparator == -1ULL) set_clock_comparator(S390_lowcore.clock_comparator); }
/* * Fixup the clock comparator. */ static void fixup_clock_comparator(unsigned long long delta) { /* If nobody is waiting there's nothing to fix. */ if (S390_lowcore.clock_comparator == -1ULL) return; S390_lowcore.clock_comparator += delta; set_clock_comparator(S390_lowcore.clock_comparator); }
static void clock_comparator_interrupt(struct ext_code ext_code, unsigned int param32, unsigned long param64) { inc_irq_stat(IRQEXT_CLK); if (S390_lowcore.clock_comparator == -1ULL) set_clock_comparator(S390_lowcore.clock_comparator); }
static void clock_comparator_interrupt(struct ext_code ext_code, unsigned int param32, unsigned long param64) { kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++; if (S390_lowcore.clock_comparator == -1ULL) set_clock_comparator(S390_lowcore.clock_comparator); }
void clock_comparator_work(void) { struct clock_event_device *cd; S390_lowcore.clock_comparator = -1ULL; set_clock_comparator(S390_lowcore.clock_comparator); cd = &__get_cpu_var(comparators); cd->event_handler(cd); }
/* * Start the HZ tick on the current CPU. * Only cpu_idle may call this function. */ static void start_hz_timer(void) { BUG_ON(!in_interrupt()); if (!cpu_isset(smp_processor_id(), nohz_cpu_mask)) return; account_ticks(get_clock()); set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); cpu_clear(smp_processor_id(), nohz_cpu_mask); }
static int s390_next_ktime(ktime_t expires, struct clock_event_device *evt) { struct timespec ts; u64 nsecs; ts.tv_sec = ts.tv_nsec = 0; monotonic_to_bootbased(&ts); nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires)); do_div(nsecs, 125); S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9); set_clock_comparator(S390_lowcore.clock_comparator); return 0; }
static int s390_next_ktime(ktime_t expires, struct clock_event_device *evt) { struct timespec ts; u64 nsecs; ts.tv_sec = ts.tv_nsec = 0; monotonic_to_bootbased(&ts); nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires)); do_div(nsecs, 125); S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9); /* Program the maximum value if we have an overflow (== year 2042) */ if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc)) S390_lowcore.clock_comparator = -1ULL; set_clock_comparator(S390_lowcore.clock_comparator); return 0; }
/* * Stop the HZ tick on the current CPU. * Only cpu_idle may call this function. */ static void stop_hz_timer(void) { unsigned long flags; unsigned long seq, next; __u64 timer, todval; int cpu = smp_processor_id(); if (sysctl_hz_timer != 0) return; cpu_set(cpu, nohz_cpu_mask); /* * Leave the clock comparator set up for the next timer * tick if either rcu or a softirq is pending. */ if (rcu_needs_cpu(cpu) || local_softirq_pending()) { cpu_clear(cpu, nohz_cpu_mask); return; } /* * This cpu is going really idle. Set up the clock comparator * for the next event. */ next = next_timer_interrupt(); do { seq = read_seqbegin_irqsave(&xtime_lock, flags); timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64; } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) { timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; if (timer >= jiffies_timer_cc) todval = timer; } set_clock_comparator(todval); }
static void clock_comparator_interrupt(__u16 code) { /* set clock comparator for next tick */ set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION); }
static void clock_comparator_interrupt(__u16 code) { if (S390_lowcore.clock_comparator == -1ULL) set_clock_comparator(S390_lowcore.clock_comparator); }