linux/kernel/time/tick-common.c
<<
>>
Prefs
   1/*
   2 * linux/kernel/time/tick-common.c
   3 *
   4 * This file contains the base functions to manage periodic tick
   5 * related events.
   6 *
   7 * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
   8 * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
   9 * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
  10 *
  11 * This code is licenced under the GPL version 2. For details see
  12 * kernel-base/COPYING.
  13 */
  14#include <linux/cpu.h>
  15#include <linux/err.h>
  16#include <linux/hrtimer.h>
  17#include <linux/interrupt.h>
  18#include <linux/percpu.h>
  19#include <linux/profile.h>
  20#include <linux/sched.h>
  21#include <linux/tick.h>
  22
  23#include <asm/irq_regs.h>
  24
  25#include "tick-internal.h"
  26
  27/*
  28 * Tick devices
  29 */
  30DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  31/*
  32 * Tick next event: keeps track of the tick time
  33 */
  34ktime_t tick_next_period;
  35ktime_t tick_period;
  36int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
  37DEFINE_SPINLOCK(tick_device_lock);
  38
  39/*
  40 * Debugging: see timer_list.c
  41 */
  42struct tick_device *tick_get_device(int cpu)
  43{
  44        return &per_cpu(tick_cpu_device, cpu);
  45}
  46
  47/**
  48 * tick_is_oneshot_available - check for a oneshot capable event device
  49 */
  50int tick_is_oneshot_available(void)
  51{
  52        struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
  53
  54        return dev && (dev->features & CLOCK_EVT_FEAT_ONESHOT);
  55}
  56
  57/*
  58 * Periodic tick
  59 */
  60static void tick_periodic(int cpu)
  61{
  62        if (tick_do_timer_cpu == cpu) {
  63                write_seqlock(&xtime_lock);
  64
  65                /* Keep track of the next tick event */
  66                tick_next_period = ktime_add(tick_next_period, tick_period);
  67
  68                do_timer(1);
  69                write_sequnlock(&xtime_lock);
  70        }
  71
  72        update_process_times(user_mode(get_irq_regs()));
  73        profile_tick(CPU_PROFILING);
  74}
  75
  76/*
  77 * Event handler for periodic ticks
  78 */
  79void tick_handle_periodic(struct clock_event_device *dev)
  80{
  81        int cpu = smp_processor_id();
  82        ktime_t next;
  83
  84        tick_periodic(cpu);
  85
  86        if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
  87                return;
  88        /*
  89         * Setup the next period for devices, which do not have
  90         * periodic mode:
  91         */
  92        next = ktime_add(dev->next_event, tick_period);
  93        for (;;) {
  94                if (!clockevents_program_event(dev, next, ktime_get()))
  95                        return;
  96                tick_periodic(cpu);
  97                next = ktime_add(next, tick_period);
  98        }
  99}
 100
 101/*
 102 * Setup the device for a periodic tick
 103 */
 104void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
 105{
 106        tick_set_periodic_handler(dev, broadcast);
 107
 108        /* Broadcast setup ? */
 109        if (!tick_device_is_functional(dev))
 110                return;
 111
 112        if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) &&
 113            !tick_broadcast_oneshot_active()) {
 114                clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC);
 115        } else {
 116                unsigned long seq;
 117                ktime_t next;
 118
 119                do {
 120                        seq = read_seqbegin(&xtime_lock);
 121                        next = tick_next_period;
 122                } while (read_seqretry(&xtime_lock, seq));
 123
 124                clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
 125
 126                for (;;) {
 127                        if (!clockevents_program_event(dev, next, ktime_get()))
 128                                return;
 129                        next = ktime_add(next, tick_period);
 130                }
 131        }
 132}
 133
 134/*
 135 * Setup the tick device
 136 */
 137static void tick_setup_device(struct tick_device *td,
 138                              struct clock_event_device *newdev, int cpu,
 139                              const cpumask_t *cpumask)
 140{
 141        ktime_t next_event;
 142        void (*handler)(struct clock_event_device *) = NULL;
 143
 144        /*
 145         * First device setup ?
 146         */
 147        if (!td->evtdev) {
 148                /*
 149                 * If no cpu took the do_timer update, assign it to
 150                 * this cpu:
 151                 */
 152                if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
 153                        tick_do_timer_cpu = cpu;
 154                        tick_next_period = ktime_get();
 155                        tick_period = ktime_set(0, NSEC_PER_SEC / HZ);
 156                }
 157
 158                /*
 159                 * Startup in periodic mode first.
 160                 */
 161                td->mode = TICKDEV_MODE_PERIODIC;
 162        } else {
 163                handler = td->evtdev->event_handler;
 164                next_event = td->evtdev->next_event;
 165                td->evtdev->event_handler = clockevents_handle_noop;
 166        }
 167
 168        td->evtdev = newdev;
 169
 170        /*
 171         * When the device is not per cpu, pin the interrupt to the
 172         * current cpu:
 173         */
 174        if (!cpus_equal(newdev->cpumask, *cpumask))
 175                irq_set_affinity(newdev->irq, *cpumask);
 176
 177        /*
 178         * When global broadcasting is active, check if the current
 179         * device is registered as a placeholder for broadcast mode.
 180         * This allows us to handle this x86 misfeature in a generic
 181         * way.
 182         */
 183        if (tick_device_uses_broadcast(newdev, cpu))
 184                return;
 185
 186        if (td->mode == TICKDEV_MODE_PERIODIC)
 187                tick_setup_periodic(newdev, 0);
 188        else
 189                tick_setup_oneshot(newdev, handler, next_event);
 190}
 191
 192/*
 193 * Check, if the new registered device should be used.
 194 */
 195static int tick_check_new_device(struct clock_event_device *newdev)
 196{
 197        struct clock_event_device *curdev;
 198        struct tick_device *td;
 199        int cpu, ret = NOTIFY_OK;
 200        unsigned long flags;
 201
 202        spin_lock_irqsave(&tick_device_lock, flags);
 203
 204        cpu = smp_processor_id();
 205        if (!cpu_isset(cpu, newdev->cpumask))
 206                goto out_bc;
 207
 208        td = &per_cpu(tick_cpu_device, cpu);
 209        curdev = td->evtdev;
 210
 211        /* cpu local device ? */
 212        if (!cpus_equal(newdev->cpumask, cpumask_of_cpu(cpu))) {
 213
 214                /*
 215                 * If the cpu affinity of the device interrupt can not
 216                 * be set, ignore it.
 217                 */
 218                if (!irq_can_set_affinity(newdev->irq))
 219                        goto out_bc;
 220
 221                /*
 222                 * If we have a cpu local device already, do not replace it
 223                 * by a non cpu local device
 224                 */
 225                if (curdev && cpus_equal(curdev->cpumask, cpumask_of_cpu(cpu)))
 226                        goto out_bc;
 227        }
 228
 229        /*
 230         * If we have an active device, then check the rating and the oneshot
 231         * feature.
 232         */
 233        if (curdev) {
 234                /*
 235                 * Prefer one shot capable devices !
 236                 */
 237                if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) &&
 238                    !(newdev->features & CLOCK_EVT_FEAT_ONESHOT))
 239                        goto out_bc;
 240                /*
 241                 * Check the rating
 242                 */
 243                if (curdev->rating >= newdev->rating)
 244                        goto out_bc;
 245        }
 246
 247        /*
 248         * Replace the eventually existing device by the new
 249         * device. If the current device is the broadcast device, do
 250         * not give it back to the clockevents layer !
 251         */
 252        if (tick_is_broadcast_device(curdev)) {
 253                clockevents_shutdown(curdev);
 254                curdev = NULL;
 255        }
 256        clockevents_exchange_device(curdev, newdev);
 257        tick_setup_device(td, newdev, cpu, &cpumask_of_cpu(cpu));
 258        if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
 259                tick_oneshot_notify();
 260
 261        spin_unlock_irqrestore(&tick_device_lock, flags);
 262        return NOTIFY_STOP;
 263
 264out_bc:
 265        /*
 266         * Can the new device be used as a broadcast device ?
 267         */
 268        if (tick_check_broadcast_device(newdev))
 269                ret = NOTIFY_STOP;
 270
 271        spin_unlock_irqrestore(&tick_device_lock, flags);
 272
 273        return ret;
 274}
 275
 276/*
 277 * Shutdown an event device on a given cpu:
 278 *
 279 * This is called on a life CPU, when a CPU is dead. So we cannot
 280 * access the hardware device itself.
 281 * We just set the mode and remove it from the lists.
 282 */
 283static void tick_shutdown(unsigned int *cpup)
 284{
 285        struct tick_device *td = &per_cpu(tick_cpu_device, *cpup);
 286        struct clock_event_device *dev = td->evtdev;
 287        unsigned long flags;
 288
 289        spin_lock_irqsave(&tick_device_lock, flags);
 290        td->mode = TICKDEV_MODE_PERIODIC;
 291        if (dev) {
 292                /*
 293                 * Prevent that the clock events layer tries to call
 294                 * the set mode function!
 295                 */
 296                dev->mode = CLOCK_EVT_MODE_UNUSED;
 297                clockevents_exchange_device(dev, NULL);
 298                td->evtdev = NULL;
 299        }
 300        /* Transfer the do_timer job away from this cpu */
 301        if (*cpup == tick_do_timer_cpu) {
 302                int cpu = first_cpu(cpu_online_map);
 303
 304                tick_do_timer_cpu = (cpu != NR_CPUS) ? cpu :
 305                        TICK_DO_TIMER_NONE;
 306        }
 307        spin_unlock_irqrestore(&tick_device_lock, flags);
 308}
 309
 310static void tick_suspend(void)
 311{
 312        struct tick_device *td = &__get_cpu_var(tick_cpu_device);
 313        unsigned long flags;
 314
 315        spin_lock_irqsave(&tick_device_lock, flags);
 316        clockevents_shutdown(td->evtdev);
 317        spin_unlock_irqrestore(&tick_device_lock, flags);
 318}
 319
 320static void tick_resume(void)
 321{
 322        struct tick_device *td = &__get_cpu_var(tick_cpu_device);
 323        unsigned long flags;
 324        int broadcast = tick_resume_broadcast();
 325
 326        spin_lock_irqsave(&tick_device_lock, flags);
 327        clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
 328
 329        if (!broadcast) {
 330                if (td->mode == TICKDEV_MODE_PERIODIC)
 331                        tick_setup_periodic(td->evtdev, 0);
 332                else
 333                        tick_resume_oneshot();
 334        }
 335        spin_unlock_irqrestore(&tick_device_lock, flags);
 336}
 337
 338/*
 339 * Notification about clock event devices
 340 */
 341static int tick_notify(struct notifier_block *nb, unsigned long reason,
 342                               void *dev)
 343{
 344        switch (reason) {
 345
 346        case CLOCK_EVT_NOTIFY_ADD:
 347                return tick_check_new_device(dev);
 348
 349        case CLOCK_EVT_NOTIFY_BROADCAST_ON:
 350        case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
 351        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
 352                tick_broadcast_on_off(reason, dev);
 353                break;
 354
 355        case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
 356        case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
 357                tick_broadcast_oneshot_control(reason);
 358                break;
 359
 360        case CLOCK_EVT_NOTIFY_CPU_DEAD:
 361                tick_shutdown_broadcast_oneshot(dev);
 362                tick_shutdown_broadcast(dev);
 363                tick_shutdown(dev);
 364                break;
 365
 366        case CLOCK_EVT_NOTIFY_SUSPEND:
 367                tick_suspend();
 368                tick_suspend_broadcast();
 369                break;
 370
 371        case CLOCK_EVT_NOTIFY_RESUME:
 372                tick_resume();
 373                break;
 374
 375        default:
 376                break;
 377        }
 378
 379        return NOTIFY_OK;
 380}
 381
 382static struct notifier_block tick_notifier = {
 383        .notifier_call = tick_notify,
 384};
 385
 386/**
 387 * tick_init - initialize the tick control
 388 *
 389 * Register the notifier with the clockevents framework
 390 */
 391void __init tick_init(void)
 392{
 393        clockevents_register_notifier(&tick_notifier);
 394}
 395