Commit 86f2008b authored by Sonic Zhang's avatar Sonic Zhang Committed by Mike Frysinger

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/5226Signed-off-by: default avatarSonic Zhang <sonic.zhang@analog.com>
Signed-off-by: default avatarMike Frysinger <vapier@gentoo.org>
parent f9ee3ab8
...@@ -144,7 +144,7 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) ...@@ -144,7 +144,7 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
static irqreturn_t ipi_handler(int irq, void *dev_instance) static irqreturn_t ipi_handler(int irq, void *dev_instance)
{ {
struct ipi_message *msg, *mg; struct ipi_message *msg;
struct ipi_message_queue *msg_queue; struct ipi_message_queue *msg_queue;
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
...@@ -154,7 +154,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance) ...@@ -154,7 +154,8 @@ static irqreturn_t ipi_handler(int irq, void *dev_instance)
msg_queue->count++; msg_queue->count++;
spin_lock(&msg_queue->lock); spin_lock(&msg_queue->lock);
list_for_each_entry_safe(msg, mg, &msg_queue->head, list) { while (!list_empty(&msg_queue->head)) {
msg = list_entry(msg_queue->head.next, typeof(*msg), list);
list_del(&msg->list); list_del(&msg->list);
switch (msg->type) { switch (msg->type) {
case BFIN_IPI_RESCHEDULE: case BFIN_IPI_RESCHEDULE:
...@@ -221,7 +222,7 @@ int smp_call_function(void (*func)(void *info), void *info, int wait) ...@@ -221,7 +222,7 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
for_each_cpu_mask(cpu, callmap) { for_each_cpu_mask(cpu, callmap) {
msg_queue = &per_cpu(ipi_msg_queue, cpu); msg_queue = &per_cpu(ipi_msg_queue, cpu);
spin_lock_irqsave(&msg_queue->lock, flags); spin_lock_irqsave(&msg_queue->lock, flags);
list_add(&msg->list, &msg_queue->head); list_add_tail(&msg->list, &msg_queue->head);
spin_unlock_irqrestore(&msg_queue->lock, flags); spin_unlock_irqrestore(&msg_queue->lock, flags);
platform_send_ipi_cpu(cpu); platform_send_ipi_cpu(cpu);
} }
...@@ -261,7 +262,7 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info, ...@@ -261,7 +262,7 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
msg_queue = &per_cpu(ipi_msg_queue, cpu); msg_queue = &per_cpu(ipi_msg_queue, cpu);
spin_lock_irqsave(&msg_queue->lock, flags); spin_lock_irqsave(&msg_queue->lock, flags);
list_add(&msg->list, &msg_queue->head); list_add_tail(&msg->list, &msg_queue->head);
spin_unlock_irqrestore(&msg_queue->lock, flags); spin_unlock_irqrestore(&msg_queue->lock, flags);
platform_send_ipi_cpu(cpu); platform_send_ipi_cpu(cpu);
...@@ -292,7 +293,7 @@ void smp_send_reschedule(int cpu) ...@@ -292,7 +293,7 @@ void smp_send_reschedule(int cpu)
msg_queue = &per_cpu(ipi_msg_queue, cpu); msg_queue = &per_cpu(ipi_msg_queue, cpu);
spin_lock_irqsave(&msg_queue->lock, flags); spin_lock_irqsave(&msg_queue->lock, flags);
list_add(&msg->list, &msg_queue->head); list_add_tail(&msg->list, &msg_queue->head);
spin_unlock_irqrestore(&msg_queue->lock, flags); spin_unlock_irqrestore(&msg_queue->lock, flags);
platform_send_ipi_cpu(cpu); platform_send_ipi_cpu(cpu);
...@@ -320,7 +321,7 @@ void smp_send_stop(void) ...@@ -320,7 +321,7 @@ void smp_send_stop(void)
for_each_cpu_mask(cpu, callmap) { for_each_cpu_mask(cpu, callmap) {
msg_queue = &per_cpu(ipi_msg_queue, cpu); msg_queue = &per_cpu(ipi_msg_queue, cpu);
spin_lock_irqsave(&msg_queue->lock, flags); spin_lock_irqsave(&msg_queue->lock, flags);
list_add(&msg->list, &msg_queue->head); list_add_tail(&msg->list, &msg_queue->head);
spin_unlock_irqrestore(&msg_queue->lock, flags); spin_unlock_irqrestore(&msg_queue->lock, flags);
platform_send_ipi_cpu(cpu); platform_send_ipi_cpu(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