/*
 * Check, if the new registered device should be used. Called with
 * clockevents_lock held and interrupts disabled.
 */
void tick_check_new_device(struct clock_event_device *newdev)
{
 struct clock_event_device *curdev;
 struct tick_device *td;
 int cpu;
 cpu = smp_processor_id();
 td = &per_cpu(tick_cpu_device, cpu);
 curdev = td->evtdev;
 /* cpu local device ? */
 if (!tick_check_percpu(curdev, newdev, cpu))
  goto out_bc;
 /* Preference decision */
 if (!tick_check_preferred(curdev, newdev))
  goto out_bc;
 if (!try_module_get(newdev->owner))
  return;
 /*
  * Replace the eventually existing device by the new
  * device. If the current device is the broadcast device, do
  * not give it back to the clockevents layer !
  */
 if (tick_is_broadcast_device(curdev)) {
  clockevents_shutdown(curdev);
  curdev = NULL;
 }
 clockevents_exchange_device(curdev, newdev);
 tick_setup_device(td, newdev, cpu, cpumask_of(cpu));
 if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
  tick_oneshot_notify();
 return;
out_bc:
 /*
  * Can the new device be used as a broadcast device ?
  */
 tick_install_broadcast_device(newdev);
}

 
/**
 * clockevents_exchange_device - release and request clock devices
 * @old: device to release (can be NULL)
 * @new: device to request (can be NULL)
 *
 * Called from various tick functions with clockevents_lock held and
 * interrupts disabled.
 */
void clockevents_exchange_device(struct clock_event_device *old,
     struct clock_event_device *new)
{
 /*
  * Caller releases a clock event device. We queue it into the
  * released list and do a notify add later.
  */
 if (old) {
  module_put(old->owner);
  clockevents_switch_state(old, CLOCK_EVT_STATE_DETACHED);
  list_del(&old->list);
  list_add(&old->list, &clockevents_released);
 }
 if (new) {
  BUG_ON(!clockevent_state_detached(new));
  clockevents_shutdown(new);
 }
}

/*
 * Setup the tick device
 */
static void tick_setup_device(struct tick_device *td,
         struct clock_event_device *newdev, int cpu,
         const struct cpumask *cpumask)
{
 ktime_t next_event;
 void (*handler)(struct clock_event_device *) = NULL;
 /*
  * First device setup ?
  */
 if (!td->evtdev) {
  /*
   * If no cpu took the do_timer update, assign it to
   * this cpu:
   */
  if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
   if (!tick_nohz_full_cpu(cpu))
    tick_do_timer_cpu = cpu;
   else
    tick_do_timer_cpu = TICK_DO_TIMER_NONE;
   tick_next_period = ktime_get();
   tick_period = ktime_set(0, NSEC_PER_SEC / HZ);
  }
  /*
   * Startup in periodic mode first.
   */
  td->mode = TICKDEV_MODE_PERIODIC;
 } else {
  handler = td->evtdev->event_handler;
  next_event = td->evtdev->next_event;
  td->evtdev->event_handler = clockevents_handle_noop;
 }
 td->evtdev = newdev;
 /*
  * When the device is not per cpu, pin the interrupt to the
  * current cpu:
  */
 if (!cpumask_equal(newdev->cpumask, cpumask))
  irq_set_affinity(newdev->irq, cpumask);
 /*
  * When global broadcasting is active, check if the current
  * device is registered as a placeholder for broadcast mode.
  * This allows us to handle this x86 misfeature in a generic
  * way. This function also returns !=0 when we keep the
  * current active broadcast state for this CPU.
  */
 if (tick_device_uses_broadcast(newdev, cpu))
  return;
 if (td->mode == TICKDEV_MODE_PERIODIC)
  tick_setup_periodic(newdev, 0);
 else
  tick_setup_oneshot(newdev, handler, next_event);
}