diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/tick-broadcast.c | 20 |
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 | */ |
502 | void tick_broadcast_setup_oneshot(struct clock_event_device *bc) | 505 | void 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 | /* |