Skip to content

Commit 50d6b3c

Browse files
Russell Kingtmlind
authored andcommitted
ARM: OMAP2+: fix lack of timer interrupts on CPU1 after hotplug
If we have a kernel configured for periodic timer interrupts, and we have cpuidle enabled, then we end up with CPU1 losing timer interupts after a hotplug. This can manifest itself in RCU stall warnings, or userspace becoming unresponsive. The problem is that the kernel initially wants to use the TWD timer for interrupts, but the TWD loses context when we enter the C3 cpuidle state. Nothing reprograms the TWD after idle. We have solved this in the past by switching to broadcast timer ticks, and cpuidle44xx switches to that mode at boot time. However, there is nothing to switch from periodic mode local timers after a hotplug operation. We call tick_broadcast_enter() in omap_enter_idle_coupled(), which one would expect would take care of the issue, but internally this only deals with one-shot local timers - tick_broadcast_enable() on the other hand only deals with periodic local timers. So, we need to call both. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> [tony@atomide.com: just standardized the subject line] Signed-off-by: Tony Lindgren <tony@atomide.com>
1 parent dc30e70 commit 50d6b3c

File tree

1 file changed

+4
-12
lines changed

1 file changed

+4
-12
lines changed

arch/arm/mach-omap2/cpuidle44xx.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
152152
mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
153153
(cx->mpu_logic_state == PWRDM_POWER_OFF);
154154

155+
/* Enter broadcast mode for periodic timers */
156+
tick_broadcast_enable();
157+
158+
/* Enter broadcast mode for one-shot timers */
155159
tick_broadcast_enter();
156160

157161
/*
@@ -218,15 +222,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
218222
return index;
219223
}
220224

221-
/*
222-
* For each cpu, setup the broadcast timer because local timers
223-
* stops for the states above C1.
224-
*/
225-
static void omap_setup_broadcast_timer(void *arg)
226-
{
227-
tick_broadcast_enable();
228-
}
229-
230225
static struct cpuidle_driver omap4_idle_driver = {
231226
.name = "omap4_idle",
232227
.owner = THIS_MODULE,
@@ -319,8 +314,5 @@ int __init omap4_idle_init(void)
319314
if (!cpu_clkdm[0] || !cpu_clkdm[1])
320315
return -ENODEV;
321316

322-
/* Configure the broadcast timer on each cpu */
323-
on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
324-
325317
return cpuidle_register(idle_driver, cpu_online_mask);
326318
}

0 commit comments

Comments
 (0)