summaryrefslogtreecommitdiffstats
path: root/arch/m68k/bvme6000/config.c
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/bvme6000/config.c
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/bvme6000/config.c')
-rw-r--r--arch/m68k/bvme6000/config.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 143ee9fa3893..0e5efed4da86 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -44,11 +44,6 @@ extern int bvme6000_hwclk (int, struct rtc_time *);
extern void bvme6000_reset (void);
void bvme6000_set_vectors (void);
-/* Save tick handler routine pointer, will point to xtime_update() in
- * kernel/timer/timekeeping.c, called via bvme6000_process_int() */
-
-static irq_handler_t tick_handler;
-
int __init bvme6000_parse_bootinfo(const struct bi_record *bi)
{
@@ -157,12 +152,18 @@ irqreturn_t bvme6000_abort_int (int irq, void *dev_id)
static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
{
+ irq_handler_t timer_routine = dev_id;
+ unsigned long flags;
volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
- unsigned char msr = rtc->msr & 0xc0;
+ unsigned char msr;
+ local_irq_save(flags);
+ msr = rtc->msr & 0xc0;
rtc->msr = msr | 0x20; /* Ack the interrupt */
+ timer_routine(0, NULL);
+ local_irq_restore(flags);
- return tick_handler(irq, dev_id);
+ return IRQ_HANDLED;
}
/*
@@ -181,9 +182,8 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
rtc->msr = 0; /* Ensure timer registers accessible */
- tick_handler = timer_routine;
- if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0,
- "timer", bvme6000_timer_int))
+ if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, "timer",
+ timer_routine))
panic ("Couldn't register timer int");
rtc->t1cr_omr = 0x04; /* Mode 2, ext clk */