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.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 3044a88357fa..5744f40b2697 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -210,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why)
210 struct clock_event_device *bc, *dev; 210 struct clock_event_device *bc, *dev;
211 struct tick_device *td; 211 struct tick_device *td;
212 unsigned long flags, *reason = why; 212 unsigned long flags, *reason = why;
213 int cpu; 213 int cpu, bc_stopped;
214 214
215 spin_lock_irqsave(&tick_broadcast_lock, flags); 215 spin_lock_irqsave(&tick_broadcast_lock, flags);
216 216
@@ -228,6 +228,8 @@ static void tick_do_broadcast_on_off(void *why)
228 if (!tick_device_is_functional(dev)) 228 if (!tick_device_is_functional(dev))
229 goto out; 229 goto out;
230 230
231 bc_stopped = cpus_empty(tick_broadcast_mask);
232
231 switch (*reason) { 233 switch (*reason) {
232 case CLOCK_EVT_NOTIFY_BROADCAST_ON: 234 case CLOCK_EVT_NOTIFY_BROADCAST_ON:
233 case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: 235 case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
@@ -250,9 +252,10 @@ static void tick_do_broadcast_on_off(void *why)
250 break; 252 break;
251 } 253 }
252 254
253 if (cpus_empty(tick_broadcast_mask)) 255 if (cpus_empty(tick_broadcast_mask)) {
254 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 256 if (!bc_stopped)
255 else { 257 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN);
258 } else if (bc_stopped) {
256 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) 259 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
257 tick_broadcast_start_periodic(bc); 260 tick_broadcast_start_periodic(bc);
258 else 261 else
@@ -501,9 +504,12 @@ static void tick_broadcast_clear_oneshot(int cpu)
501 */ 504 */
502void tick_broadcast_setup_oneshot(struct clock_event_device *bc) 505void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
503{ 506{
504 bc->event_handler = tick_handle_oneshot_broadcast; 507 /* Set it up only once ! */
505 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); 508 if (bc->event_handler != tick_handle_oneshot_broadcast) {
506 bc->next_event.tv64 = KTIME_MAX; 509 bc->event_handler = tick_handle_oneshot_broadcast;
510 clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
511 bc->next_event.tv64 = KTIME_MAX;
512 }
507} 513}
508 514
509/* 515/*