static int epit_set_oneshot(struct clock_event_device *evt) { unsigned long flags; /* * The timer interrupt generation is disabled at least * for enough time to call epit_set_next_event() */ local_irq_save(flags); /* Disable interrupt in GPT module */ epit_irq_disable(); /* Clear pending interrupt, only while switching mode */ if (!clockevent_state_oneshot(evt)) epit_irq_acknowledge(); /* * Do not put overhead of interrupt enable/disable into * epit_set_next_event(), the core has about 4 minutes * to call epit_set_next_event() or shutdown clock after * mode switching */ epit_irq_enable(); local_irq_restore(flags); return 0; }
/* * Event handler for periodic broadcast ticks */ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) { struct tick_device *td = this_cpu_ptr(&tick_cpu_device); bool bc_local; raw_spin_lock(&tick_broadcast_lock); /* Handle spurious interrupts gracefully */ if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { raw_spin_unlock(&tick_broadcast_lock); return; } bc_local = tick_do_periodic_broadcast(); if (clockevent_state_oneshot(dev)) { ktime_t next = ktime_add(dev->next_event, tick_period); clockevents_program_event(dev, next, true); } raw_spin_unlock(&tick_broadcast_lock); /* * We run the handler of the local cpu after dropping * tick_broadcast_lock because the handler might deadlock when * trying to switch to oneshot mode. */ if (bc_local) td->evtdev->event_handler(td->evtdev); }
static irqreturn_t gt_clockevent_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; if (!(readl_relaxed(gt_base + GT_INT_STATUS) & GT_INT_STATUS_EVENT_FLAG)) return IRQ_NONE; /** * ERRATA 740657( Global Timer can send 2 interrupts for * the same event in single-shot mode) * Workaround: * Either disable single-shot mode. * Or * Modify the Interrupt Handler to avoid the * offending sequence. This is achieved by clearing * the Global Timer flag _after_ having incremented * the Comparator register value to a higher value. */ if (clockevent_state_oneshot(evt)) gt_compare_set(ULONG_MAX, 0); writel_relaxed(GT_INT_STATUS_EVENT_FLAG, gt_base + GT_INT_STATUS); evt->event_handler(evt); return IRQ_HANDLED; }
static void tick_broadcast_set_event(struct clock_event_device *bc, int cpu, ktime_t expires) { if (!clockevent_state_oneshot(bc)) clockevents_switch_state(bc, CLOCK_EVT_STATE_ONESHOT); clockevents_program_event(bc, expires, 1); tick_broadcast_set_affinity(bc, cpumask_of(cpu)); }
static int timer8_clock_event_next(unsigned long delta, struct clock_event_device *ced) { struct timer8_priv *p = ced_to_priv(ced); BUG_ON(!clockevent_state_oneshot(ced)); timer8_set_next(p, delta - 1); return 0; }
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; /* Stop the timer tick */ if (clockevent_state_oneshot(evt)) { u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); ctrl &= ~TIMER_ENABLE_EN; writel_relaxed(ctrl, event_base + TIMER_ENABLE); } evt->event_handler(evt); return IRQ_HANDLED; }
static irqreturn_t timer8_interrupt(int irq, void *dev_id) { struct timer8_priv *p = dev_id; if (clockevent_state_oneshot(&p->ced)) iowrite16be(0x0000, p->mapbase + _8TCR); p->ced.event_handler(&p->ced); bclr(CMFA, p->mapbase + _8TCSR); return IRQ_HANDLED; }
static int xen_timerop_set_next_event(unsigned long delta, struct clock_event_device *evt) { WARN_ON(!clockevent_state_oneshot(evt)); if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0) BUG(); /* We may have missed the deadline, but there's no real way of knowing for sure. If the event was in the past, then we'll get an immediate interrupt. */ return 0; }
static irqreturn_t ftm_evt_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; ftm_irq_acknowledge(priv->clkevt_base); if (likely(clockevent_state_oneshot(evt))) { ftm_irq_disable(priv->clkevt_base); ftm_counter_disable(priv->clkevt_base); } evt->event_handler(evt); return IRQ_HANDLED; }
/* timer interrupt handler */ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *ce = dev_id; int cpu = smp_processor_id(); /* clear timer interrupt */ writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS); if (clockevent_state_oneshot(ce)) sirfsoc_timer_count_disable(cpu); ce->event_handler(ce); return IRQ_HANDLED; }
static int xen_vcpuop_set_next_event(unsigned long delta, struct clock_event_device *evt) { int cpu = smp_processor_id(); struct vcpu_set_singleshot_timer single; int ret; WARN_ON(!clockevent_state_oneshot(evt)); single.timeout_abs_ns = get_abs_timeout(delta); single.flags = VCPU_SSHOTTMR_future; ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single); BUG_ON(ret != 0 && ret != -ETIME); return ret; }
static int xen_vcpuop_set_next_event(unsigned long delta, struct clock_event_device *evt) { int cpu = smp_processor_id(); struct vcpu_set_singleshot_timer single; int ret; WARN_ON(!clockevent_state_oneshot(evt)); single.timeout_abs_ns = get_abs_timeout(delta); /* Get an event anyway, even if the timeout is already expired */ single.flags = 0; ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single); BUG_ON(ret != 0); return ret; }
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; pit_irq_acknowledge(); /* * pit hardware doesn't support oneshot, it will generate an interrupt * and reload the counter value from PITLDVAL when PITCVAL reach zero, * and start the counter again. So software need to disable the timer * to stop the counter loop in ONESHOT mode. */ if (likely(clockevent_state_oneshot(evt))) pit_timer_disable(); evt->event_handler(evt); return IRQ_HANDLED; }
/* * Event handler for periodic ticks */ void tick_handle_periodic(struct clock_event_device *dev) { int cpu = smp_processor_id(); ktime_t next = dev->next_event; tick_periodic(cpu); #if defined(CONFIG_HIGH_RES_TIMERS) || defined(CONFIG_NO_HZ_COMMON) /* * The cpu might have transitioned to HIGHRES or NOHZ mode via * update_process_times() -> run_local_timers() -> * hrtimer_run_queues(). */ if (dev->event_handler != tick_handle_periodic) return; #endif if (!clockevent_state_oneshot(dev)) return; for (;;) { /* * Setup the next period for devices, which do not have * periodic mode: */ next = ktime_add(next, tick_period); if (!clockevents_program_event(dev, next, false)) return; /* * Have to be careful here. If we're in oneshot mode, * before we call tick_periodic() in a loop, we need * to be sure we're using a real hardware clocksource. * Otherwise we could get trapped in an infinite * loop, as the tick_periodic() increments jiffies, * which then will increment time, possibly causing * the loop to trigger again and again. */ if (timekeeping_valid_for_hres()) tick_periodic(cpu); } }