aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2009-06-10 04:42:41 -0400
committerMike Frysinger <vapier@gentoo.org>2009-06-13 07:20:09 -0400
commit86f2008bf546af9a434f480710e8d33891616bf5 (patch)
treee55bf8eec1f6dbbf3ba052c3a595f4806c724a6e /arch
parentf9ee3ab81c222219ad4467b75b406efe2616d8a4 (diff)
Blackfin: fix deadlock in SMP IPI handler
When a low priority interrupt (like ethernet) is triggered between 2 high priority IPI messages, a deadlock in disable_irq() is hit by the second IPI handler. This is because the second IPI message is queued within the first IPI handler, but the handler doesn't process all messages, and new ones are inserted rather than appended. So now we process all the pending messages, and append new ones to the pending list. URL: http://blackfin.uclinux.org/gf/tracker/5226 Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/blackfin/mach-common/smp.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index c187da2448bf..61840059dfac 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -144,7 +144,7 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
144 144
145static irqreturn_t ipi_handler(int irq, void *dev_instance) 145static irqreturn_t ipi_handler(int irq, void *dev_instance)
146{ 146{
147 struct ipi_message *msg, *mg; 147 struct ipi_message *msg;
148 struct ipi_message_queue *msg_queue; 148 struct ipi_message_queue *msg_queue;
149 unsigned int cpu = smp_processor_id(); 149 unsigned int cpu = smp_processor_id();
150 150
@@ -154,7 +154,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance)
154 msg_queue->count++; 154 msg_queue->count++;
155 155
156 spin_lock(&msg_queue->lock); 156 spin_lock(&msg_queue->lock);
157 list_for_each_entry_safe(msg, mg, &msg_queue->head, list) { 157 while (!list_empty(&msg_queue->head)) {
158 msg = list_entry(msg_queue->head.next, typeof(*msg), list);
158 list_del(&msg->list); 159 list_del(&msg->list);
159 switch (msg->type) { 160 switch (msg->type) {
160 case BFIN_IPI_RESCHEDULE: 161 case BFIN_IPI_RESCHEDULE:
@@ -221,7 +222,7 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
221 for_each_cpu_mask(cpu, callmap) { 222 for_each_cpu_mask(cpu, callmap) {
222 msg_queue = &per_cpu(ipi_msg_queue, cpu); 223 msg_queue = &per_cpu(ipi_msg_queue, cpu);
223 spin_lock_irqsave(&msg_queue->lock, flags); 224 spin_lock_irqsave(&msg_queue->lock, flags);
224 list_add(&msg->list, &msg_queue->head); 225 list_add_tail(&msg->list, &msg_queue->head);
225 spin_unlock_irqrestore(&msg_queue->lock, flags); 226 spin_unlock_irqrestore(&msg_queue->lock, flags);
226 platform_send_ipi_cpu(cpu); 227 platform_send_ipi_cpu(cpu);
227 } 228 }
@@ -261,7 +262,7 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
261 262
262 msg_queue = &per_cpu(ipi_msg_queue, cpu); 263 msg_queue = &per_cpu(ipi_msg_queue, cpu);
263 spin_lock_irqsave(&msg_queue->lock, flags); 264 spin_lock_irqsave(&msg_queue->lock, flags);
264 list_add(&msg->list, &msg_queue->head); 265 list_add_tail(&msg->list, &msg_queue->head);
265 spin_unlock_irqrestore(&msg_queue->lock, flags); 266 spin_unlock_irqrestore(&msg_queue->lock, flags);
266 platform_send_ipi_cpu(cpu); 267 platform_send_ipi_cpu(cpu);
267 268
@@ -292,7 +293,7 @@ void smp_send_reschedule(int cpu)
292 293
293 msg_queue = &per_cpu(ipi_msg_queue, cpu); 294 msg_queue = &per_cpu(ipi_msg_queue, cpu);
294 spin_lock_irqsave(&msg_queue->lock, flags); 295 spin_lock_irqsave(&msg_queue->lock, flags);
295 list_add(&msg->list, &msg_queue->head); 296 list_add_tail(&msg->list, &msg_queue->head);
296 spin_unlock_irqrestore(&msg_queue->lock, flags); 297 spin_unlock_irqrestore(&msg_queue->lock, flags);
297 platform_send_ipi_cpu(cpu); 298 platform_send_ipi_cpu(cpu);
298 299
@@ -320,7 +321,7 @@ void smp_send_stop(void)
320 for_each_cpu_mask(cpu, callmap) { 321 for_each_cpu_mask(cpu, callmap) {
321 msg_queue = &per_cpu(ipi_msg_queue, cpu); 322 msg_queue = &per_cpu(ipi_msg_queue, cpu);
322 spin_lock_irqsave(&msg_queue->lock, flags); 323 spin_lock_irqsave(&msg_queue->lock, flags);
323 list_add(&msg->list, &msg_queue->head); 324 list_add_tail(&msg->list, &msg_queue->head);
324 spin_unlock_irqrestore(&msg_queue->lock, flags); 325 spin_unlock_irqrestore(&msg_queue->lock, flags);
325 platform_send_ipi_cpu(cpu); 326 platform_send_ipi_cpu(cpu);
326 } 327 }