Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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