summaryrefslogtreecommitdiffstats
path: root/timers-fix-timer-hotplug-on-rt.patch
blob: 4955fafdb430ca3bac90602cbd1976a1053b0a0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
From f335bcc4033fef31042428ecf989027d9d9b65d8 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 3 Jul 2009 08:30:32 -0500
Subject: [PATCH] timers: fix timer hotplug on -rt

commit e5e57bd60fce5d9e674f8fb3a1eaeb0dee114337 in tip.

Here we are in the CPU_DEAD notifier, and we must not sleep nor
enable interrupts.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 kernel/timer.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/kernel/timer.c b/kernel/timer.c
index e342eef..a081803 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1655,6 +1655,7 @@ static void __cpuinit migrate_timers(int cpu)
 {
 	struct tvec_base *old_base;
 	struct tvec_base *new_base;
+	unsigned long flags;
 	int i;
 
 	BUG_ON(cpu_online(cpu));
@@ -1664,8 +1665,11 @@ static void __cpuinit migrate_timers(int cpu)
 	 * The caller is globally serialized and nobody else
 	 * takes two locks at once, deadlock is not possible.
 	 */
-	spin_lock_irq(&new_base->lock);
-	spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
+	local_irq_save(flags);
+	while (!spin_trylock(&new_base->lock))
+		cpu_relax();
+	while (!spin_trylock(&old_base->lock))
+		cpu_relax();
 
 	BUG_ON(old_base->running_timer);
 
@@ -1679,7 +1683,9 @@ static void __cpuinit migrate_timers(int cpu)
 	}
 
 	spin_unlock(&old_base->lock);
-	spin_unlock_irq(&new_base->lock);
+	spin_unlock(&new_base->lock);
+	local_irq_restore(flags);
+
 	put_cpu_var(tvec_bases);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
-- 
1.7.0.4