From: Troy Mitchell <troy.mitchell@linux.dev>
To: "Thomas Gleixner" <tglx@kernel.org>,
"Radu Rendec" <radu@rendec.net>,
"Anup Patel" <anup@brainfault.org>,
"Paul Walmsley" <pjw@kernel.org>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>,
"Alexandre Ghiti" <alex@ghiti.fr>,
"Sebastian Andrzej Siewior" <bigeasy@linutronix.de>,
"Clark Williams" <clrkwllms@kernel.org>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Björn Töpel" <bjorn@rivosinc.com>
Cc: Anup Patel <apatel@ventanamicro.com>,
linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org,
linux-rt-devel@lists.linux.dev,
Troy Mitchell <troy.mitchell@linux.dev>
Subject: [PATCH v2 1/2] irqchip/riscv-imsic: Synchronize remote state with IRQ work
Date: Thu, 12 Nov 2026 07:54:32 +0000 [thread overview]
Message-ID: <20261112-imsic-remote-sync-irqwork-v2-1-680f65b24ff6@linux.dev> (raw)
In-Reply-To: <20261112-imsic-remote-sync-irqwork-v2-0-680f65b24ff6@linux.dev>
Remote IMSIC state updates are deferred to a timer on the target CPU.
If that CPU has stopped its local clockevent and is waiting for a
broadcast interrupt, enabling the broadcast IRQ can depend on delivery
of that same interrupt. This can stall timer delivery when the broadcast
IRQ is unmasked or moved to another CPU, including during CPU hotplug.
Queue hard IRQ work to synchronize remote state independently of timer
delivery. Keep synchronous updates on the local CPU and the timer retry
for an unfinished vector move. Hard IRQ work also avoids depending on a
schedulable worker when PREEMPT_RT is enabled.
Fixes: 21a8f8a0eb35 ("irqchip: Add RISC-V incoming MSI controller early driver")
Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev>
---
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-riscv-imsic-state.c | 19 +++++++++++++------
drivers/irqchip/irq-riscv-imsic-state.h | 4 ++++
3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 136bab41f801..5cdc3f52198c 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -651,6 +651,7 @@ config RISCV_IMSIC
bool
depends on RISCV
select IRQ_DOMAIN_HIERARCHY
+ select IRQ_WORK if SMP
select GENERIC_IRQ_MATRIX_ALLOCATOR
select GENERIC_MSI_IRQ
select IRQ_MSI_LIB
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index 01620373b43a..f6373e4019a2 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -252,6 +252,11 @@ void imsic_local_delivery(bool enable)
}
#ifdef CONFIG_SMP
+static void imsic_local_sync_work(struct irq_work *work)
+{
+ imsic_local_sync_all(false);
+}
+
static void imsic_local_timer_callback(struct timer_list *timer)
{
imsic_local_sync_all(false);
@@ -268,18 +273,19 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu
*/
/*
- * We schedule a timer on the target CPU if the target CPU is not
- * same as the current CPU. An offline CPU will unconditionally
- * synchronize IDs through imsic_starting_cpu() when the
- * CPU is brought up.
+ * A remote CPU may have stopped its local timer and be waiting for
+ * the broadcast interrupt whose IMSIC state needs updating. Use an
+ * IPI-backed work item so enabling that interrupt does not depend on
+ * its delivery. An offline CPU synchronizes IDs in imsic_starting_cpu().
*/
if (cpu_online(cpu)) {
if (cpu == smp_processor_id()) {
if (__imsic_local_sync(lpriv))
return;
+ __imsic_local_timer_start(lpriv, cpu);
+ } else {
+ irq_work_queue_on(&lpriv->sync_work, cpu);
}
-
- __imsic_local_timer_start(lpriv, cpu);
}
}
#else
@@ -510,6 +516,7 @@ static int __init imsic_local_init(void)
#ifdef CONFIG_SMP
/* Setup lazy timer for synchronization */
timer_setup(&lpriv->timer, imsic_local_timer_callback, TIMER_PINNED);
+ lpriv->sync_work = IRQ_WORK_INIT_HARD(imsic_local_sync_work);
#endif
/* Allocate vector array */
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index 189829b8673a..a36b9f0ef840 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -9,6 +9,7 @@
#include <linux/irqchip/riscv-imsic.h>
#include <linux/irqdomain.h>
+#include <linux/irq_work.h>
#include <linux/fwnode.h>
#include <linux/timer.h>
@@ -34,6 +35,9 @@ struct imsic_local_priv {
unsigned long *dirty_bitmap;
#ifdef CONFIG_SMP
+ /* Remote synchronization must not depend on a timer interrupt. */
+ struct irq_work sync_work;
+
/* Local timer for synchronization */
struct timer_list timer;
#endif
--
2.56.0
next prev parent reply other threads:[~2026-11-12 7:54 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 7:54 [PATCH v2 0/2] " Troy Mitchell
2026-11-12 7:54 ` Troy Mitchell [this message]
2026-11-12 7:54 ` [PATCH v2 2/2] irqchip/riscv-imsic: Complete vector moves without a timer Troy Mitchell
2026-11-12 8:35 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261112-imsic-remote-sync-irqwork-v2-1-680f65b24ff6@linux.dev \
--to=troy.mitchell@linux.dev \
--cc=alex@ghiti.fr \
--cc=anup@brainfault.org \
--cc=aou@eecs.berkeley.edu \
--cc=apatel@ventanamicro.com \
--cc=bigeasy@linutronix.de \
--cc=bjorn@rivosinc.com \
--cc=clrkwllms@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=palmer@dabbelt.com \
--cc=pjw@kernel.org \
--cc=radu@rendec.net \
--cc=rostedt@goodmis.org \
--cc=tglx@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®