summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2010-11-23 10:26:44 -0800
committerRalf Baechle <ralf@linux-mips.org>2010-12-16 18:10:58 +0000
commit5878fc936aebf592cca418ca50773cd578f7daf4 (patch)
treeee9d8cec2235b737cfb2cd931e43ede7d9772a53
parent190fca3e40a65303eac35ac4fbae4f1f1342431c (diff)
downloadlinux-3.10-5878fc936aebf592cca418ca50773cd578f7daf4.tar.gz
linux-3.10-5878fc936aebf592cca418ca50773cd578f7daf4.tar.bz2
linux-3.10-5878fc936aebf592cca418ca50773cd578f7daf4.zip
MIPS: Fix CP0 COUNTER clockevent race
Consider the following test case: write_c0_compare(read_c0_count()); Even if the counter doesn't increment during execution, this might not generate an interrupt until the counter wraps around. The CPU may perform the comparison each time CP0 COUNT increments, not when CP0 COMPARE is written. If mips_next_event() is called with a very small delta, and CP0 COUNT increments during the calculation of "cnt += delta", it is possible that CP0 COMPARE will be written with the current value of CP0 COUNT. If this is detected, the function should return -ETIME, to indicate that the interrupt might not have actually gotten scheduled. Signed-off-by: Kevin Cernekee <cernekee@gmail.com> Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/1836/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/cevt-r4k.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 2f4d7a99bcc..98c5a9737c1 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,
cnt = read_c0_count();
cnt += delta;
write_c0_compare(cnt);
- res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+ res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;
return res;
}