]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.31/arm-omap2-fix-lack-of-timer-interrupts-on-cpu1-after.patch
Linux 4.14.108
[thirdparty/kernel/stable-queue.git] / releases / 4.19.31 / arm-omap2-fix-lack-of-timer-interrupts-on-cpu1-after.patch
1 From 55d27a9d7932c1fdd318ab0c33745c087506ad6b Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Wed, 12 Dec 2018 11:49:47 +0000
4 Subject: ARM: OMAP2+: fix lack of timer interrupts on CPU1 after hotplug
5
6 [ Upstream commit 50d6b3cf9403879911e06d69c7ef41e43f8f7b4b ]
7
8 If we have a kernel configured for periodic timer interrupts, and we
9 have cpuidle enabled, then we end up with CPU1 losing timer interupts
10 after a hotplug.
11
12 This can manifest itself in RCU stall warnings, or userspace becoming
13 unresponsive.
14
15 The problem is that the kernel initially wants to use the TWD timer
16 for interrupts, but the TWD loses context when we enter the C3 cpuidle
17 state. Nothing reprograms the TWD after idle.
18
19 We have solved this in the past by switching to broadcast timer ticks,
20 and cpuidle44xx switches to that mode at boot time. However, there is
21 nothing to switch from periodic mode local timers after a hotplug
22 operation.
23
24 We call tick_broadcast_enter() in omap_enter_idle_coupled(), which one
25 would expect would take care of the issue, but internally this only
26 deals with one-shot local timers - tick_broadcast_enable() on the other
27 hand only deals with periodic local timers. So, we need to call both.
28
29 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
30 [tony@atomide.com: just standardized the subject line]
31 Signed-off-by: Tony Lindgren <tony@atomide.com>
32 Signed-off-by: Sasha Levin <sashal@kernel.org>
33 ---
34 arch/arm/mach-omap2/cpuidle44xx.c | 16 ++++------------
35 1 file changed, 4 insertions(+), 12 deletions(-)
36
37 diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
38 index a8b291f00109..dae514c8276a 100644
39 --- a/arch/arm/mach-omap2/cpuidle44xx.c
40 +++ b/arch/arm/mach-omap2/cpuidle44xx.c
41 @@ -152,6 +152,10 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
42 mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
43 (cx->mpu_logic_state == PWRDM_POWER_OFF);
44
45 + /* Enter broadcast mode for periodic timers */
46 + tick_broadcast_enable();
47 +
48 + /* Enter broadcast mode for one-shot timers */
49 tick_broadcast_enter();
50
51 /*
52 @@ -218,15 +222,6 @@ fail:
53 return index;
54 }
55
56 -/*
57 - * For each cpu, setup the broadcast timer because local timers
58 - * stops for the states above C1.
59 - */
60 -static void omap_setup_broadcast_timer(void *arg)
61 -{
62 - tick_broadcast_enable();
63 -}
64 -
65 static struct cpuidle_driver omap4_idle_driver = {
66 .name = "omap4_idle",
67 .owner = THIS_MODULE,
68 @@ -319,8 +314,5 @@ int __init omap4_idle_init(void)
69 if (!cpu_clkdm[0] || !cpu_clkdm[1])
70 return -ENODEV;
71
72 - /* Configure the broadcast timer on each cpu */
73 - on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
74 -
75 return cpuidle_register(idle_driver, cpu_online_mask);
76 }
77 --
78 2.19.1
79