]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
irqchip/riscv-imsic: Start local sync timer on correct CPU
authorAndrew Bresticker <abrestic@rivosinc.com>
Wed, 14 May 2025 17:13:20 +0000 (10:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:13:57 +0000 (11:13 +0200)
[ Upstream commit 08fb624802d8786253994d8ebdbbcdaa186f04f5 ]

When starting the local sync timer to synchronize the state of a remote
CPU it should be added on the CPU to be synchronized, not the initiating
CPU. This results in interrupt delivery being delayed until the timer
eventually runs (due to another mask/unmask/migrate operation) on the
target CPU.

Fixes: 0f67911e821c ("irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector")
Signed-off-by: Andrew Bresticker <abrestic@rivosinc.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/all/20250514171320.3494917-1-abrestic@rivosinc.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/irqchip/irq-riscv-imsic-state.c

index 1aeba76d72795a455e2318ac41c6227761f906e6..06ff0e17c0c33714056160f0ca92d4f2bd2ecc6c 100644 (file)
@@ -186,17 +186,17 @@ skip:
 }
 
 #ifdef CONFIG_SMP
-static void __imsic_local_timer_start(struct imsic_local_priv *lpriv)
+static void __imsic_local_timer_start(struct imsic_local_priv *lpriv, unsigned int cpu)
 {
        lockdep_assert_held(&lpriv->lock);
 
        if (!timer_pending(&lpriv->timer)) {
                lpriv->timer.expires = jiffies + 1;
-               add_timer_on(&lpriv->timer, smp_processor_id());
+               add_timer_on(&lpriv->timer, cpu);
        }
 }
 #else
-static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv)
+static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv, unsigned int cpu)
 {
 }
 #endif
@@ -211,7 +211,7 @@ void imsic_local_sync_all(bool force_all)
        if (force_all)
                bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1);
        if (!__imsic_local_sync(lpriv))
-               __imsic_local_timer_start(lpriv);
+               __imsic_local_timer_start(lpriv, smp_processor_id());
 
        raw_spin_unlock_irqrestore(&lpriv->lock, flags);
 }
@@ -256,7 +256,7 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu
                                return;
                }
 
-               __imsic_local_timer_start(lpriv);
+               __imsic_local_timer_start(lpriv, cpu);
        }
 }
 #else