]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
MIPS: __raw_spin_lock() may spin forever on ticket wrap.
authorDavid Daney <ddaney@caviumnetworks.com>
Fri, 27 Mar 2009 17:07:02 +0000 (10:07 -0700)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 30 Mar 2009 12:49:39 +0000 (14:49 +0200)
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>
arch/mips/include/asm/spinlock.h

index 0884947ebe270c404bb293b2acac0b067e7fd9d7..10e82441b49612ddf057618e56520df8e9fdce67 100644 (file)
@@ -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"