aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-broadcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/tick-broadcast.c')
-rw-r--r--kernel/time/tick-broadcast.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 8001d37071f5..db8e0f3d409b 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -31,6 +31,12 @@ struct tick_device tick_broadcast_device;
31static cpumask_t tick_broadcast_mask; 31static cpumask_t tick_broadcast_mask;
32static DEFINE_SPINLOCK(tick_broadcast_lock); 32static DEFINE_SPINLOCK(tick_broadcast_lock);
33 33
34#ifdef CONFIG_TICK_ONESHOT
35static void tick_broadcast_clear_oneshot(int cpu);
36#else
37static inline void tick_broadcast_clear_oneshot(int cpu) { }
38#endif
39
34/* 40/*
35 * Debugging: see timer_list.c 41 * Debugging: see timer_list.c
36 */ 42 */
@@ -49,7 +55,7 @@ cpumask_t *tick_get_broadcast_mask(void)
49 */ 55 */
50static void tick_broadcast_start_periodic(struct clock_event_device *bc) 56static void tick_broadcast_start_periodic(struct clock_event_device *bc)
51{ 57{
52 if (bc && bc->mode == CLOCK_EVT_MODE_SHUTDOWN) 58 if (bc)
53 tick_setup_periodic(bc, 1); 59 tick_setup_periodic(bc, 1);
54} 60}
55 61
@@ -99,8 +105,19 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
99 cpu_set(cpu, tick_broadcast_mask); 105 cpu_set(cpu, tick_broadcast_mask);
100 tick_broadcast_start_periodic(tick_broadcast_device.evtdev); 106 tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
101 ret = 1; 107 ret = 1;
102 } 108 } else {
109 /*
110 * When the new device is not affected by the stop
111 * feature and the cpu is marked in the broadcast mask
112 * then clear the broadcast bit.
113 */
114 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) {
115 int cpu = smp_processor_id();
103 116
117 cpu_clear(cpu, tick_broadcast_mask);
118 tick_broadcast_clear_oneshot(cpu);
119 }
120 }
104 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 121 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
105 return ret; 122 return ret;
106} 123}
@@ -299,7 +316,7 @@ void tick_suspend_broadcast(void)
299 spin_lock_irqsave(&tick_broadcast_lock, flags); 316 spin_lock_irqsave(&tick_broadcast_lock, flags);
300 317
301 bc = tick_broadcast_device.evtdev; 318 bc = tick_broadcast_device.evtdev;
302 if (bc && tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) 319 if (bc)
303 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 320 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
304 321
305 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 322 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
@@ -316,6 +333,8 @@ int tick_resume_broadcast(void)
316 bc = tick_broadcast_device.evtdev; 333 bc = tick_broadcast_device.evtdev;
317 334
318 if (bc) { 335 if (bc) {
336 clockevents_set_mode(bc, CLOCK_EVT_MODE_RESUME);
337
319 switch (tick_broadcast_device.mode) { 338 switch (tick_broadcast_device.mode) {
320 case TICKDEV_MODE_PERIODIC: 339 case TICKDEV_MODE_PERIODIC:
321 if(!cpus_empty(tick_broadcast_mask)) 340 if(!cpus_empty(tick_broadcast_mask))
@@ -485,6 +504,16 @@ out:
485 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 504 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
486} 505}
487 506
507/*
508 * Reset the one shot broadcast for a cpu
509 *
510 * Called with tick_broadcast_lock held
511 */
512static void tick_broadcast_clear_oneshot(int cpu)
513{
514 cpu_clear(cpu, tick_broadcast_oneshot_mask);
515}
516
488/** 517/**
489 * tick_broadcast_setup_highres - setup the broadcast device for highres 518 * tick_broadcast_setup_highres - setup the broadcast device for highres
490 */ 519 */