diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 580bc66ae136..ac2f6d6d4868 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1591,11 +1591,12 @@ static void __cpuinit init_hrtimers_cpu(int cpu) | |||
1591 | 1591 | ||
1592 | #ifdef CONFIG_HOTPLUG_CPU | 1592 | #ifdef CONFIG_HOTPLUG_CPU |
1593 | 1593 | ||
1594 | static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, | 1594 | static int migrate_hrtimer_list(struct hrtimer_clock_base *old_base, |
1595 | struct hrtimer_clock_base *new_base) | 1595 | struct hrtimer_clock_base *new_base) |
1596 | { | 1596 | { |
1597 | struct hrtimer *timer; | 1597 | struct hrtimer *timer; |
1598 | struct rb_node *node; | 1598 | struct rb_node *node; |
1599 | int raise = 0; | ||
1599 | 1600 | ||
1600 | while ((node = rb_first(&old_base->active))) { | 1601 | while ((node = rb_first(&old_base->active))) { |
1601 | timer = rb_entry(node, struct hrtimer, node); | 1602 | timer = rb_entry(node, struct hrtimer, node); |
@@ -1607,7 +1608,27 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, | |||
1607 | * Enqueue the timer. Allow reprogramming of the event device | 1608 | * Enqueue the timer. Allow reprogramming of the event device |
1608 | */ | 1609 | */ |
1609 | enqueue_hrtimer(timer, new_base, 1); | 1610 | enqueue_hrtimer(timer, new_base, 1); |
1611 | |||
1612 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
1613 | /* | ||
1614 | * Happens with high res enabled when the timer was | ||
1615 | * already expired and the callback mode is | ||
1616 | * HRTIMER_CB_IRQSAFE_NO_SOFTIRQ | ||
1617 | * (hrtimer_sleeper). The enqueue code does not move | ||
1618 | * them to the soft irq pending list for | ||
1619 | * performance/latency reasons, but in the migration | ||
1620 | * state, we need to do that otherwise we end up with | ||
1621 | * a stale timer. | ||
1622 | */ | ||
1623 | if (timer->state == HRTIMER_STATE_INACTIVE) { | ||
1624 | timer->state = HRTIMER_STATE_PENDING; | ||
1625 | list_add_tail(&timer->cb_entry, | ||
1626 | &new_base->cpu_base->cb_pending); | ||
1627 | raise = 1; | ||
1628 | } | ||
1629 | #endif | ||
1610 | } | 1630 | } |
1631 | return raise; | ||
1611 | } | 1632 | } |
1612 | 1633 | ||
1613 | #ifdef CONFIG_HIGH_RES_TIMERS | 1634 | #ifdef CONFIG_HIGH_RES_TIMERS |
@@ -1652,8 +1673,9 @@ static void migrate_hrtimers(int cpu) | |||
1652 | spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); | 1673 | spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); |
1653 | 1674 | ||
1654 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { | 1675 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { |
1655 | migrate_hrtimer_list(&old_base->clock_base[i], | 1676 | if (migrate_hrtimer_list(&old_base->clock_base[i], |
1656 | &new_base->clock_base[i]); | 1677 | &new_base->clock_base[i])) |
1678 | raise = 1; | ||
1657 | } | 1679 | } |
1658 | 1680 | ||
1659 | if (migrate_hrtimer_pending(old_base, new_base)) | 1681 | if (migrate_hrtimer_pending(old_base, new_base)) |