diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2018-12-01 11:53:10 +1100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-01-27 14:51:23 +0100 |
commit | a825e9a7ced544fafc7fdf23cc19ff7216d518ac (patch) | |
tree | 02446b368099653a2e143cbd3a4124d433cbc0e3 /arch/m68k/mac | |
parent | 283163a39a7923da0509270139f6bd48fc82cca9 (diff) | |
download | linux-stable-a825e9a7ced544fafc7fdf23cc19ff7216d518ac.tar.gz linux-stable-a825e9a7ced544fafc7fdf23cc19ff7216d518ac.tar.bz2 linux-stable-a825e9a7ced544fafc7fdf23cc19ff7216d518ac.zip |
m68k: Call timer_interrupt() with interrupts disabled
[ Upstream commit 1efdd4bd254311498123a15fa0acd565f454da97 ]
Some platforms execute their timer handler with the interrupt priority
level set below 6. That means the handler could be interrupted by another
driver and this could lead to re-entry of the timer core.
Avoid this by use of local_irq_save/restore for timer interrupt dispatch.
This provides mutual exclusion around the timer interrupt flag access
which is needed later in this series for the clocksource conversion.
Reported-by: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/alpine.DEB.2.21.1811131407120.2697@nanos.tec.linutronix.de
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'arch/m68k/mac')
-rw-r--r-- | arch/m68k/mac/via.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 288ec3aa5b57..038d5a1c4d48 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -387,6 +387,8 @@ void via_nubus_irq_shutdown(int irq) * via6522.c :-), disable/pending masks added. */ +#define VIA_TIMER_1_INT BIT(6) + void via1_irq(struct irq_desc *desc) { int irq_num; @@ -396,6 +398,21 @@ void via1_irq(struct irq_desc *desc) if (!events) return; + irq_num = IRQ_MAC_TIMER_1; + irq_bit = VIA_TIMER_1_INT; + if (events & irq_bit) { + unsigned long flags; + + local_irq_save(flags); + via1[vIFR] = irq_bit; + generic_handle_irq(irq_num); + local_irq_restore(flags); + + events &= ~irq_bit; + if (!events) + return; + } + irq_num = VIA1_SOURCE_BASE; irq_bit = 1; do { |