summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-03-27 18:07:02 +0100
committerRalf Baechle <ralf@linux-mips.org>2009-03-30 14:49:39 +0200
commit0e6826c73c9aa785ec58b52613df7699fb31af9a (patch)
treea85de8026984bbe94bf8ebc49873fcf0367782d9
parentMIPS: Forward declare struct task_struct to avoid potencial warning. (diff)
downloadlinux-0e6826c73c9aa785ec58b52613df7699fb31af9a.tar.xz
linux-0e6826c73c9aa785ec58b52613df7699fb31af9a.zip
MIPS: __raw_spin_lock() may spin forever on ticket wrap.
If the lock is not acquired and has to spin *and* the second attempt to acquire the lock fails, the delay time is not masked by the ticket range mask. If the ticket number wraps around to zero, the result is that the lock sampling delay is essentially infinite (due to casting -1 to an unsigned int). The fix: Always mask the difference between my_ticket and the current ticket value before calculating the delay. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/spinlock.h8
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/mips/include/asm/spinlock.h b/arch/mips/include/asm/spinlock.h
index 0884947ebe27..10e82441b496 100644
--- a/arch/mips/include/asm/spinlock.h
+++ b/arch/mips/include/asm/spinlock.h
@@ -76,7 +76,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
"2: \n"
" .subsection 2 \n"
"4: andi %[ticket], %[ticket], 0x1fff \n"
- "5: sll %[ticket], 5 \n"
+ " sll %[ticket], 5 \n"
" \n"
"6: bnez %[ticket], 6b \n"
" subu %[ticket], 1 \n"
@@ -85,7 +85,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
" andi %[ticket], %[ticket], 0x1fff \n"
" beq %[ticket], %[my_ticket], 2b \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
- " b 5b \n"
+ " b 4b \n"
" subu %[ticket], %[ticket], 1 \n"
" .previous \n"
" .set pop \n"
@@ -113,7 +113,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
" ll %[ticket], %[ticket_ptr] \n"
" \n"
"4: andi %[ticket], %[ticket], 0x1fff \n"
- "5: sll %[ticket], 5 \n"
+ " sll %[ticket], 5 \n"
" \n"
"6: bnez %[ticket], 6b \n"
" subu %[ticket], 1 \n"
@@ -122,7 +122,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
" andi %[ticket], %[ticket], 0x1fff \n"
" beq %[ticket], %[my_ticket], 2b \n"
" subu %[ticket], %[my_ticket], %[ticket] \n"
- " b 5b \n"
+ " b 4b \n"
" subu %[ticket], %[ticket], 1 \n"
" .previous \n"
" .set pop \n"