panic: Fix a possible deadlock in panic()

panic_lock is meant to ensure that panic processing takes
place only on one cpu; if any of the other cpus encounter
a panic, they will spin waiting to be shut down.

However, this causes a regression in this scenario:

1. Cpu 0 encounters a panic and acquires the panic_lock
   and proceeds with the panic processing.
2. There is an interrupt on cpu 0 that also encounters
   an error condition and invokes panic.
3. This second invocation fails to acquire the panic_lock
   and enters the infinite while loop in panic_smp_self_stop.

Thus all panic processing is stopped, and the cpu is stuck
for eternity in the while(1) inside panic_smp_self_stop.

To address this, disable local interrupts with
local_irq_disable before acquiring the panic_lock. This will
prevent interrupt handlers from executing during the panic
processing, thus avoiding this particular problem.

Change-Id: Ibf70e96343d35587571968bbc39062e28b7d3c0a
Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
(cherry picked from commit dd58afef43357f265e803c317bbaa91f8c440663)
This commit is contained in:
Vikram Mulukutla 2012-06-27 17:25:46 -07:00 committed by Rohit Vaswani
parent 715363e77e
commit 8041e1099b

View file

@ -74,6 +74,14 @@ void panic(const char *fmt, ...)
long i, i_next = 0;
int state = 0;
/*
* Disable local interrupts. This will prevent panic_smp_self_stop
* from deadlocking the first cpu that invokes the panic, since
* there is nothing to prevent an interrupt handler (that runs
* after the panic_lock is acquired) from invoking panic again.
*/
local_irq_disable();
/*
* It's possible to come here directly from a panic-assertion and
* not have preempt disabled. Some functions called from here want