Commit 0ec67667 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

[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: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 509cb37e
...@@ -57,7 +57,7 @@ static void smp_ext_bitcall(int, ec_bit_sig); ...@@ -57,7 +57,7 @@ static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall_others(ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig);
/* /*
5B * Structure and data for smp_call_function(). This is designed to minimise * Structure and data for smp_call_function(). This is designed to minimise
* static memory requirements. It also looks cleaner. * static memory requirements. It also looks cleaner.
*/ */
static DEFINE_SPINLOCK(call_lock); static DEFINE_SPINLOCK(call_lock);
...@@ -104,7 +104,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, ...@@ -104,7 +104,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
* remote CPUs are nearly ready to execute <<func>> or are or have executed. * remote CPUs are nearly ready to execute <<func>> or are or have executed.
* *
* You must not call this function with disabled interrupts or from a * You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler. * hardware interrupt handler.
*/ */
{ {
struct call_data_struct data; struct call_data_struct data;
...@@ -113,8 +113,8 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, ...@@ -113,8 +113,8 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (cpus <= 0) if (cpus <= 0)
return 0; return 0;
/* Can deadlock when called with interrupts disabled */ /* Can deadlock when interrupts are disabled or if in wrong context */
WARN_ON(irqs_disabled()); WARN_ON(irqs_disabled() || in_irq());
data.func = func; data.func = func;
data.info = info; data.info = info;
...@@ -123,7 +123,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, ...@@ -123,7 +123,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (wait) if (wait)
atomic_set(&data.finished, 0); atomic_set(&data.finished, 0);
spin_lock(&call_lock); spin_lock_bh(&call_lock);
call_data = &data; call_data = &data;
/* Send a message to all other CPUs and wait for them to respond */ /* Send a message to all other CPUs and wait for them to respond */
smp_ext_bitcall_others(ec_call_function); smp_ext_bitcall_others(ec_call_function);
...@@ -135,7 +135,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, ...@@ -135,7 +135,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (wait) if (wait)
while (atomic_read(&data.finished) != cpus) while (atomic_read(&data.finished) != cpus)
cpu_relax(); cpu_relax();
spin_unlock(&call_lock); spin_unlock_bh(&call_lock);
return 0; return 0;
} }
...@@ -159,6 +159,9 @@ int smp_call_function_on(void (*func) (void *info), void *info, ...@@ -159,6 +159,9 @@ int smp_call_function_on(void (*func) (void *info), void *info,
if (!cpu_online(cpu)) if (!cpu_online(cpu))
return -EINVAL; return -EINVAL;
/* Can deadlock when interrupts are disabled or if in wrong context */
WARN_ON(irqs_disabled() || in_irq());
/* disable preemption for local function call */ /* disable preemption for local function call */
curr_cpu = get_cpu(); curr_cpu = get_cpu();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment