aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-02-12 09:47:04 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-02-12 09:47:04 -0500
commit0ec67667ab414b18a0518d5b11c842fd342e9cb1 (patch)
treea68f29d957fc4dc24145c22b040242406cee8054
parent509cb37e173d4e39cec47238397e91b718730794 (diff)
[S390] smp_call_function/smp_call_function_on locking.
smp_call_function and smp_call_function_on share the same lock and smp_call_function_on disables softirq's so it can be called from softirq context as well. Hence smp_call_function muss disable softirqs as well to avoid deadlocks. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/kernel/smp.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 65b52320d145..83a4ea6e3d60 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -57,7 +57,7 @@ static void smp_ext_bitcall(int, ec_bit_sig);
57static void smp_ext_bitcall_others(ec_bit_sig); 57static void smp_ext_bitcall_others(ec_bit_sig);
58 58
59/* 59/*
605B * Structure and data for smp_call_function(). This is designed to minimise 60 * Structure and data for smp_call_function(). This is designed to minimise
61 * static memory requirements. It also looks cleaner. 61 * static memory requirements. It also looks cleaner.
62 */ 62 */
63static DEFINE_SPINLOCK(call_lock); 63static DEFINE_SPINLOCK(call_lock);
@@ -104,7 +104,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
104 * remote CPUs are nearly ready to execute <<func>> or are or have executed. 104 * remote CPUs are nearly ready to execute <<func>> or are or have executed.
105 * 105 *
106 * You must not call this function with disabled interrupts or from a 106 * You must not call this function with disabled interrupts or from a
107 * hardware interrupt handler or from a bottom half handler. 107 * hardware interrupt handler.
108 */ 108 */
109{ 109{
110 struct call_data_struct data; 110 struct call_data_struct data;
@@ -113,8 +113,8 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
113 if (cpus <= 0) 113 if (cpus <= 0)
114 return 0; 114 return 0;
115 115
116 /* Can deadlock when called with interrupts disabled */ 116 /* Can deadlock when interrupts are disabled or if in wrong context */
117 WARN_ON(irqs_disabled()); 117 WARN_ON(irqs_disabled() || in_irq());
118 118
119 data.func = func; 119 data.func = func;
120 data.info = info; 120 data.info = info;
@@ -123,7 +123,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
123 if (wait) 123 if (wait)
124 atomic_set(&data.finished, 0); 124 atomic_set(&data.finished, 0);
125 125
126 spin_lock(&call_lock); 126 spin_lock_bh(&call_lock);
127 call_data = &data; 127 call_data = &data;
128 /* Send a message to all other CPUs and wait for them to respond */ 128 /* Send a message to all other CPUs and wait for them to respond */
129 smp_ext_bitcall_others(ec_call_function); 129 smp_ext_bitcall_others(ec_call_function);
@@ -135,7 +135,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
135 if (wait) 135 if (wait)
136 while (atomic_read(&data.finished) != cpus) 136 while (atomic_read(&data.finished) != cpus)
137 cpu_relax(); 137 cpu_relax();
138 spin_unlock(&call_lock); 138 spin_unlock_bh(&call_lock);
139 139
140 return 0; 140 return 0;
141} 141}
@@ -159,6 +159,9 @@ int smp_call_function_on(void (*func) (void *info), void *info,
159 if (!cpu_online(cpu)) 159 if (!cpu_online(cpu))
160 return -EINVAL; 160 return -EINVAL;
161 161
162 /* Can deadlock when interrupts are disabled or if in wrong context */
163 WARN_ON(irqs_disabled() || in_irq());
164
162 /* disable preemption for local function call */ 165 /* disable preemption for local function call */
163 curr_cpu = get_cpu(); 166 curr_cpu = get_cpu();
164 167