summaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2018-12-01 11:53:10 +1100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-27 14:51:23 +0100
commita825e9a7ced544fafc7fdf23cc19ff7216d518ac (patch)
tree02446b368099653a2e143cbd3a4124d433cbc0e3 /arch/m68k/mac
parent283163a39a7923da0509270139f6bd48fc82cca9 (diff)
downloadlinux-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.c17
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 {