diff options
Diffstat (limited to 'kernel/time/tick-common.c')
| -rw-r--r-- | kernel/time/tick-common.c | 82 |
1 files changed, 63 insertions, 19 deletions
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index f7c515595b42..3ae6afa1eb98 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
| @@ -102,7 +102,7 @@ void tick_handle_periodic(struct clock_event_device *dev) | |||
| 102 | 102 | ||
| 103 | tick_periodic(cpu); | 103 | tick_periodic(cpu); |
| 104 | 104 | ||
| 105 | if (dev->mode != CLOCK_EVT_MODE_ONESHOT) | 105 | if (dev->state != CLOCK_EVT_STATE_ONESHOT) |
| 106 | return; | 106 | return; |
| 107 | for (;;) { | 107 | for (;;) { |
| 108 | /* | 108 | /* |
| @@ -140,7 +140,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast) | |||
| 140 | 140 | ||
| 141 | if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && | 141 | if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && |
| 142 | !tick_broadcast_oneshot_active()) { | 142 | !tick_broadcast_oneshot_active()) { |
| 143 | clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC); | 143 | clockevents_set_state(dev, CLOCK_EVT_STATE_PERIODIC); |
| 144 | } else { | 144 | } else { |
| 145 | unsigned long seq; | 145 | unsigned long seq; |
| 146 | ktime_t next; | 146 | ktime_t next; |
| @@ -150,7 +150,7 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast) | |||
| 150 | next = tick_next_period; | 150 | next = tick_next_period; |
| 151 | } while (read_seqretry(&jiffies_lock, seq)); | 151 | } while (read_seqretry(&jiffies_lock, seq)); |
| 152 | 152 | ||
| 153 | clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT); | 153 | clockevents_set_state(dev, CLOCK_EVT_STATE_ONESHOT); |
| 154 | 154 | ||
| 155 | for (;;) { | 155 | for (;;) { |
| 156 | if (!clockevents_program_event(dev, next, false)) | 156 | if (!clockevents_program_event(dev, next, false)) |
| @@ -332,14 +332,16 @@ out_bc: | |||
| 332 | tick_install_broadcast_device(newdev); | 332 | tick_install_broadcast_device(newdev); |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 335 | /* | 336 | /* |
| 336 | * Transfer the do_timer job away from a dying cpu. | 337 | * Transfer the do_timer job away from a dying cpu. |
| 337 | * | 338 | * |
| 338 | * Called with interrupts disabled. | 339 | * Called with interrupts disabled. Not locking required. If |
| 340 | * tick_do_timer_cpu is owned by this cpu, nothing can change it. | ||
| 339 | */ | 341 | */ |
| 340 | void tick_handover_do_timer(int *cpup) | 342 | void tick_handover_do_timer(void) |
| 341 | { | 343 | { |
| 342 | if (*cpup == tick_do_timer_cpu) { | 344 | if (tick_do_timer_cpu == smp_processor_id()) { |
| 343 | int cpu = cpumask_first(cpu_online_mask); | 345 | int cpu = cpumask_first(cpu_online_mask); |
| 344 | 346 | ||
| 345 | tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu : | 347 | tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu : |
| @@ -354,9 +356,9 @@ void tick_handover_do_timer(int *cpup) | |||
| 354 | * access the hardware device itself. | 356 | * access the hardware device itself. |
| 355 | * We just set the mode and remove it from the lists. | 357 | * We just set the mode and remove it from the lists. |
| 356 | */ | 358 | */ |
| 357 | void tick_shutdown(unsigned int *cpup) | 359 | void tick_shutdown(unsigned int cpu) |
| 358 | { | 360 | { |
| 359 | struct tick_device *td = &per_cpu(tick_cpu_device, *cpup); | 361 | struct tick_device *td = &per_cpu(tick_cpu_device, cpu); |
| 360 | struct clock_event_device *dev = td->evtdev; | 362 | struct clock_event_device *dev = td->evtdev; |
| 361 | 363 | ||
| 362 | td->mode = TICKDEV_MODE_PERIODIC; | 364 | td->mode = TICKDEV_MODE_PERIODIC; |
| @@ -365,27 +367,42 @@ void tick_shutdown(unsigned int *cpup) | |||
| 365 | * Prevent that the clock events layer tries to call | 367 | * Prevent that the clock events layer tries to call |
| 366 | * the set mode function! | 368 | * the set mode function! |
| 367 | */ | 369 | */ |
| 370 | dev->state = CLOCK_EVT_STATE_DETACHED; | ||
| 368 | dev->mode = CLOCK_EVT_MODE_UNUSED; | 371 | dev->mode = CLOCK_EVT_MODE_UNUSED; |
| 369 | clockevents_exchange_device(dev, NULL); | 372 | clockevents_exchange_device(dev, NULL); |
| 370 | dev->event_handler = clockevents_handle_noop; | 373 | dev->event_handler = clockevents_handle_noop; |
| 371 | td->evtdev = NULL; | 374 | td->evtdev = NULL; |
| 372 | } | 375 | } |
| 373 | } | 376 | } |
| 377 | #endif | ||
| 374 | 378 | ||
| 375 | void tick_suspend(void) | 379 | /** |
| 380 | * tick_suspend_local - Suspend the local tick device | ||
| 381 | * | ||
| 382 | * Called from the local cpu for freeze with interrupts disabled. | ||
| 383 | * | ||
| 384 | * No locks required. Nothing can change the per cpu device. | ||
| 385 | */ | ||
| 386 | void tick_suspend_local(void) | ||
| 376 | { | 387 | { |
| 377 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); | 388 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); |
| 378 | 389 | ||
| 379 | clockevents_shutdown(td->evtdev); | 390 | clockevents_shutdown(td->evtdev); |
| 380 | } | 391 | } |
| 381 | 392 | ||
| 382 | void tick_resume(void) | 393 | /** |
| 394 | * tick_resume_local - Resume the local tick device | ||
| 395 | * | ||
| 396 | * Called from the local CPU for unfreeze or XEN resume magic. | ||
| 397 | * | ||
| 398 | * No locks required. Nothing can change the per cpu device. | ||
| 399 | */ | ||
| 400 | void tick_resume_local(void) | ||
| 383 | { | 401 | { |
| 384 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); | 402 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); |
| 385 | int broadcast = tick_resume_broadcast(); | 403 | bool broadcast = tick_resume_check_broadcast(); |
| 386 | |||
| 387 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME); | ||
| 388 | 404 | ||
| 405 | clockevents_tick_resume(td->evtdev); | ||
| 389 | if (!broadcast) { | 406 | if (!broadcast) { |
| 390 | if (td->mode == TICKDEV_MODE_PERIODIC) | 407 | if (td->mode == TICKDEV_MODE_PERIODIC) |
| 391 | tick_setup_periodic(td->evtdev, 0); | 408 | tick_setup_periodic(td->evtdev, 0); |
| @@ -394,6 +411,35 @@ void tick_resume(void) | |||
| 394 | } | 411 | } |
| 395 | } | 412 | } |
| 396 | 413 | ||
| 414 | /** | ||
| 415 | * tick_suspend - Suspend the tick and the broadcast device | ||
| 416 | * | ||
| 417 | * Called from syscore_suspend() via timekeeping_suspend with only one | ||
| 418 | * CPU online and interrupts disabled or from tick_unfreeze() under | ||
| 419 | * tick_freeze_lock. | ||
| 420 | * | ||
| 421 | * No locks required. Nothing can change the per cpu device. | ||
| 422 | */ | ||
| 423 | void tick_suspend(void) | ||
| 424 | { | ||
| 425 | tick_suspend_local(); | ||
| 426 | tick_suspend_broadcast(); | ||
| 427 | } | ||
| 428 | |||
| 429 | /** | ||
| 430 | * tick_resume - Resume the tick and the broadcast device | ||
| 431 | * | ||
| 432 | * Called from syscore_resume() via timekeeping_resume with only one | ||
| 433 | * CPU online and interrupts disabled. | ||
| 434 | * | ||
| 435 | * No locks required. Nothing can change the per cpu device. | ||
| 436 | */ | ||
| 437 | void tick_resume(void) | ||
| 438 | { | ||
| 439 | tick_resume_broadcast(); | ||
| 440 | tick_resume_local(); | ||
| 441 | } | ||
| 442 | |||
| 397 | static DEFINE_RAW_SPINLOCK(tick_freeze_lock); | 443 | static DEFINE_RAW_SPINLOCK(tick_freeze_lock); |
| 398 | static unsigned int tick_freeze_depth; | 444 | static unsigned int tick_freeze_depth; |
| 399 | 445 | ||
| @@ -411,12 +457,10 @@ void tick_freeze(void) | |||
| 411 | raw_spin_lock(&tick_freeze_lock); | 457 | raw_spin_lock(&tick_freeze_lock); |
| 412 | 458 | ||
| 413 | tick_freeze_depth++; | 459 | tick_freeze_depth++; |
| 414 | if (tick_freeze_depth == num_online_cpus()) { | 460 | if (tick_freeze_depth == num_online_cpus()) |
| 415 | timekeeping_suspend(); | 461 | timekeeping_suspend(); |
| 416 | } else { | 462 | else |
| 417 | tick_suspend(); | 463 | tick_suspend_local(); |
| 418 | tick_suspend_broadcast(); | ||
| 419 | } | ||
| 420 | 464 | ||
| 421 | raw_spin_unlock(&tick_freeze_lock); | 465 | raw_spin_unlock(&tick_freeze_lock); |
| 422 | } | 466 | } |
| @@ -437,7 +481,7 @@ void tick_unfreeze(void) | |||
| 437 | if (tick_freeze_depth == num_online_cpus()) | 481 | if (tick_freeze_depth == num_online_cpus()) |
| 438 | timekeeping_resume(); | 482 | timekeeping_resume(); |
| 439 | else | 483 | else |
| 440 | tick_resume(); | 484 | tick_resume_local(); |
| 441 | 485 | ||
| 442 | tick_freeze_depth--; | 486 | tick_freeze_depth--; |
| 443 | 487 | ||
