提交 d6bd0e6b 编写于 作者: R Ralf Baechle

[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: NRalf Baechle <ralf@linux-mips.org>
上级 966f4406
...@@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned long j; unsigned long j;
unsigned int count; unsigned int count;
write_seqlock(&xtime_lock);
count = mips_hpt_read(); count = mips_hpt_read();
mips_timer_ack(); mips_timer_ack();
...@@ -441,7 +443,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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 * 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. * called as close as possible to 500 ms before the new second starts.
*/ */
write_seqlock(&xtime_lock);
if (ntp_synced() && if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 && xtime.tv_sec > last_rtc_update + 660 &&
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && (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) ...@@ -453,7 +454,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
last_rtc_update = xtime.tv_sec - 600; last_rtc_update = xtime.tv_sec - 600;
} }
} }
write_sequnlock(&xtime_lock);
/* /*
* If jiffies has overflown in this timer_interrupt, we must * 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) ...@@ -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 * In UP mode, we call local_timer_interrupt() to do profiling
* and process accouting. * and process accouting.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册