summaryrefslogtreecommitdiffstats
path: root/arch/m68k/q40
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2018-12-01 01:53:10 +0100
committerGeert Uytterhoeven <geert@linux-m68k.org>2019-03-25 10:22:24 +0100
commit1efdd4bd254311498123a15fa0acd565f454da97 (patch)
tree6eed2d1e020561326c3754973e588c947673a5b0 /arch/m68k/q40
parentLinux 5.1-rc1 (diff)
downloadlinux-1efdd4bd254311498123a15fa0acd565f454da97.tar.xz
linux-1efdd4bd254311498123a15fa0acd565f454da97.zip
m68k: Call timer_interrupt() with interrupts disabled
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>
Diffstat (limited to 'arch/m68k/q40')
-rw-r--r--arch/m68k/q40/q40ints.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 3e7603202977..1c696906c159 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -127,10 +127,10 @@ void q40_mksound(unsigned int hz, unsigned int ticks)
sound_ticks = ticks << 1;
}
-static irq_handler_t q40_timer_routine;
-
-static irqreturn_t q40_timer_int (int irq, void * dev)
+static irqreturn_t q40_timer_int(int irq, void *dev_id)
{
+ irq_handler_t timer_routine = dev_id;
+
ql_ticks = ql_ticks ? 0 : 1;
if (sound_ticks) {
unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
@@ -139,8 +139,13 @@ static irqreturn_t q40_timer_int (int irq, void * dev)
*DAC_RIGHT=sval;
}
- if (!ql_ticks)
- q40_timer_routine(irq, dev);
+ if (!ql_ticks) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ timer_routine(0, NULL);
+ local_irq_restore(flags);
+ }
return IRQ_HANDLED;
}
@@ -148,11 +153,9 @@ void q40_sched_init (irq_handler_t timer_routine)
{
int timer_irq;
- q40_timer_routine = timer_routine;
timer_irq = Q40_IRQ_FRAME;
- if (request_irq(timer_irq, q40_timer_int, 0,
- "timer", q40_timer_int))
+ if (request_irq(timer_irq, q40_timer_int, 0, "timer", timer_routine))
panic("Couldn't register timer int");
master_outb(-1, FRAME_CLEAR_REG);