diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2007-02-12 09:47:04 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-02-12 09:47:04 -0500 |
commit | 0ec67667ab414b18a0518d5b11c842fd342e9cb1 (patch) | |
tree | a68f29d957fc4dc24145c22b040242406cee8054 | |
parent | 509cb37e173d4e39cec47238397e91b718730794 (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.c | 15 |
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); | |||
57 | static void smp_ext_bitcall_others(ec_bit_sig); | 57 | static void smp_ext_bitcall_others(ec_bit_sig); |
58 | 58 | ||
59 | /* | 59 | /* |
60 | 5B * 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 | */ |
63 | static DEFINE_SPINLOCK(call_lock); | 63 | static 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 | ||