--- /dev/null
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jonas Jelonek <jelonek.jonas@gmail.com>
+Date: Thu, 04 Jun 2026 00:00:00 +0200
+Subject: [PATCH] MIPS: smp: report dying CPU to RCU in stop_this_cpu()
+
+smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function
+marks the CPU offline for the scheduler via set_cpu_online(false) but never
+informs RCU, so RCU keeps expecting a quiescent state from CPUs that are
+now spinning forever with interrupts disabled.
+
+As long as nothing waits for an RCU grace period after smp_send_stop() this
+is harmless, which is why it went unnoticed. Since v6.18.34, however,
+irq_work_sync() calls synchronize_rcu() on architectures without an
+irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns false.
+That is the asm-generic default used by MIPS. Any irq_work_sync() issued in
+the reboot/shutdown path after smp_send_stop() then blocks on a grace period
+that can never complete, hanging the reboot:
+
+ WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on
+ ...
+ rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
+ rcu: Offline CPU 1 blocking current GP.
+ rcu: Offline CPU 2 blocking current GP.
+ rcu: Offline CPU 3 blocking current GP.
+
+Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the
+generic CPU-hotplug offline path (and arm64's stop handling), so RCU stops
+waiting on the parked CPUs and grace periods can still complete.
+
+Fixes: 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT")
+Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
+---
+ arch/mips/kernel/smp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/mips/kernel/smp.c
++++ b/arch/mips/kernel/smp.c
+@@ -20,6 +20,7 @@
+ #include <linux/sched/mm.h>
+ #include <linux/cpumask.h>
+ #include <linux/cpu.h>
++#include <linux/rcupdate.h>
+ #include <linux/err.h>
+ #include <linux/ftrace.h>
+ #include <linux/irqdomain.h>
+@@ -422,6 +423,7 @@ static void stop_this_cpu(void *dummy)
+ set_cpu_online(smp_processor_id(), false);
+ calculate_cpu_foreign_map();
+ local_irq_disable();
++ rcutree_report_cpu_dead();
+ while (1);
+ }
+
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
-@@ -32,6 +32,7 @@
+@@ -33,6 +33,7 @@
#include <asm/processor.h>
#include <asm/idle.h>
#include <asm/r4k-timer.h>
#include <asm/mips-cps.h>
#include <asm/mmu_context.h>
#include <asm/time.h>
-@@ -413,6 +414,8 @@ asmlinkage void start_secondary(void)
+@@ -414,6 +415,8 @@ asmlinkage void start_secondary(void)
cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
}
static void stop_this_cpu(void *dummy)
{
/*
-@@ -422,13 +425,66 @@ static void stop_this_cpu(void *dummy)
- set_cpu_online(smp_processor_id(), false);
+@@ -424,13 +427,66 @@ static void stop_this_cpu(void *dummy)
calculate_cpu_foreign_map();
local_irq_disable();
+ rcutree_report_cpu_dead();
- while (1);
+
+ if (mips_cm_present() && r4k_blast_dcache) {