summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-03-15 00:46:58 +0100
committerRalf Baechle <ralf@linux-mips.org>2006-03-18 17:59:29 +0100
commitd6bd0e6b32ea72be91e5789b1e838c244f8a05d9 (patch)
tree2eb5551533165cb7772ffdef3d8cbdbac1050cb6 /arch
parent[MIPS] Work around bad code generation for <asm/io.h>. (diff)
downloadlinux-d6bd0e6b32ea72be91e5789b1e838c244f8a05d9.tar.xz
linux-d6bd0e6b32ea72be91e5789b1e838c244f8a05d9.zip
[MIPS] Protect more of timer_interrupt() by xtime_lock.
From Dave Johnson <djohnson+linuxmips@sw.starentnetworks.com>: * do_timer() expects the arch-specific handler to take the lock as it modifies jiffies[_64] and xtime. * writing timerhi/lo in timer_interrupt() will mess up fixed_rate_gettimeoffset() which reads timerhi/lo. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/kernel/time.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 42c94c771afb..51273b7297a7 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned long j;
unsigned int count;
+ write_seqlock(&xtime_lock);
+
count = mips_hpt_read();
mips_timer_ack();
@@ -441,7 +443,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
* called as close as possible to 500 ms before the new second starts.
*/
- write_seqlock(&xtime_lock);
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
@@ -453,7 +454,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
last_rtc_update = xtime.tv_sec - 600;
}
}
- write_sequnlock(&xtime_lock);
/*
* If jiffies has overflown in this timer_interrupt, we must
@@ -496,6 +496,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
+ write_sequnlock(&xtime_lock);
+
/*
* In UP mode, we call local_timer_interrupt() to do profiling
* and process accouting.