summaryrefslogtreecommitdiff
path: root/kernel/panic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/panic.c')
-rw-r--r--kernel/panic.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/kernel/panic.c b/kernel/panic.c
index 50715f14cf04..08072bfae422 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -371,8 +371,9 @@ int __weak panic_smp_redirect_cpu(int target_cpu, void *msg)
* for the crash kernel to function correctly. This function redirects
* panic handling to the CPU specified via the panic_force_cpu= boot parameter.
*
- * Returns false if panic should proceed on current CPU.
- * Returns true if panic was redirected.
+ * Returns true when this CPU must stop: the panic was redirected or is
+ * already running on another CPU.
+ * Returns false when panic() should proceed on this CPU.
*/
__printf(1, 0)
static bool panic_try_force_cpu(const char *fmt, va_list args)
@@ -396,16 +397,20 @@ static bool panic_try_force_cpu(const char *fmt, va_list args)
return false;
}
- /* Another panic already in progress */
+ /*
+ * Don't redirect when a panic is already in progress. Stop this
+ * CPU when it's another one, proceed when it's this one.
+ */
if (panic_in_progress())
- return false;
+ return panic_on_other_cpu();
/*
- * Only one CPU can do the redirect. Use atomic cmpxchg to ensure
- * we don't race with another CPU also trying to redirect.
+ * Only one CPU can do the redirection. Others should go offline.
+ * Continue with panic() when we already tried the redirection
+ * from this CPU before, for example via nmi_panic().
*/
if (!atomic_try_cmpxchg(&panic_redirect_cpu, &old_cpu, this_cpu))
- return false;
+ return old_cpu != this_cpu;
/*
* Use dynamically allocated buffer if available, otherwise