linux-m68k.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] m68k: coldfire: Prevent spurious interrupts when masking IMR
@ 2025-02-04 18:38 Jean-Michel Hautbois
  2025-02-04 19:27 ` Geert Uytterhoeven
  0 siblings, 1 reply; 11+ messages in thread
From: Jean-Michel Hautbois @ 2025-02-04 18:38 UTC (permalink / raw)
  To: Greg Ungerer, Geert Uytterhoeven
  Cc: linux-m68k, linux-kernel, Jean-Michel Hautbois

The ColdFire interrupt controller can generate spurious interrupts if an
interrupt source is masked in the IMR while the CPU interrupt priority
mask (SR[I]) is set lower than the interrupt level.

The reference manual states:

To avoid this situation for interrupts sources with levels 1-6, first
write a higher level interrupt mask to the status register, before
setting the mask in the IMR or the module’s interrupt mask register.
After the mask is set, return the interrupt mask in the status register
to its previous value.

It can be tested like this:
- Prepare a iperf3 server on the coldfire target (iperf3 -s -D)
- Start a high priority cyclictest:
    cyclictest --secaligned -m -p 99 -i 2500 -q
- Start iperf3 -c $COLDFIRE_IP -t 0

After a few seconds the dmesg may display:
[   84.784301] irq 24, desc: dbc502da, depth: 1, count: 0, unhandled: 0
[   84.784455] ->handle_irq():  0ba0aca3, handle_bad_irq+0x0/0x1e0
[   84.784610] ->irq_data.chip(): c6779d4f, 0x41652544
[   84.784719] ->action(): 00000000
[   84.784770] unexpected IRQ trap at vector 18

With this patch, I never saw it in a few hours testing.

Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>
---
 arch/m68k/coldfire/intc-simr.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/m68k/coldfire/intc-simr.c b/arch/m68k/coldfire/intc-simr.c
index f7c2c41b31564defe47b1edd63b9a51c27b2db8b..17aae7524c4e999083795a769219556f151eeeb3 100644
--- a/arch/m68k/coldfire/intc-simr.c
+++ b/arch/m68k/coldfire/intc-simr.c
@@ -58,6 +58,14 @@ static inline unsigned int irq2ebit(unsigned int irq)
 
 #endif
 
+static inline void intc_irq_setlevel(unsigned long level)
+{
+	asm volatile ("move.w %0,%%sr"
+		      : /* no outputs */
+		      : "d" (0x2000 | ((level) << 8))
+		      : "memory");
+}
+
 /*
  *	There maybe one, two or three interrupt control units, each has 64
  *	interrupts. If there is no second or third unit then MCFINTC1_* or
@@ -67,13 +75,17 @@ static inline unsigned int irq2ebit(unsigned int irq)
 static void intc_irq_mask(struct irq_data *d)
 {
 	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long flags = arch_local_save_flags();
 
+	intc_irq_setlevel(7);
 	if (MCFINTC2_SIMR && (irq > 127))
 		__raw_writeb(irq - 128, MCFINTC2_SIMR);
 	else if (MCFINTC1_SIMR && (irq > 63))
 		__raw_writeb(irq - 64, MCFINTC1_SIMR);
 	else
 		__raw_writeb(irq, MCFINTC0_SIMR);
+
+	arch_local_irq_restore(flags);
 }
 
 static void intc_irq_unmask(struct irq_data *d)

---
base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
change-id: 20250204-coldfire-spurious-irq-97d8a4f8e6d8

Best regards,
-- 
Jean-Michel Hautbois <jeanmichel.hautbois@yoseli.org>


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-02-18 13:30 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-04 18:38 [PATCH] m68k: coldfire: Prevent spurious interrupts when masking IMR Jean-Michel Hautbois
2025-02-04 19:27 ` Geert Uytterhoeven
2025-02-04 20:14   ` Jean-Michel Hautbois
2025-02-04 20:17   ` Jean-Michel Hautbois
2025-02-05  7:07   ` Jean-Michel Hautbois
2025-02-05  8:14     ` Geert Uytterhoeven
2025-02-05  9:34       ` Jean-Michel Hautbois
2025-02-05 11:26       ` Jean-Michel Hautbois
2025-02-12 12:47         ` Greg Ungerer
2025-02-18 13:17           ` Jean-Michel Hautbois
2025-02-18 13:30             ` Greg Ungerer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).