|
@@ -36,9 +36,9 @@
|
|
|
|
|
|
static inline int arch_spin_is_locked(arch_spinlock_t *lock)
|
|
|
{
|
|
|
- unsigned int counters = ACCESS_ONCE(lock->lock);
|
|
|
+ u32 counters = ACCESS_ONCE(lock->lock);
|
|
|
|
|
|
- return ((counters >> 14) ^ counters) & 0x1fff;
|
|
|
+ return ((counters >> 16) ^ counters) & 0xffff;
|
|
|
}
|
|
|
|
|
|
#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
|
|
@@ -47,9 +47,9 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
|
|
|
|
|
|
static inline int arch_spin_is_contended(arch_spinlock_t *lock)
|
|
|
{
|
|
|
- unsigned int counters = ACCESS_ONCE(lock->lock);
|
|
|
+ u32 counters = ACCESS_ONCE(lock->lock);
|
|
|
|
|
|
- return (((counters >> 14) - counters) & 0x1fff) > 1;
|
|
|
+ return (((counters >> 16) - counters) & 0xffff) > 1;
|
|
|
}
|
|
|
#define arch_spin_is_contended arch_spin_is_contended
|
|
|
|
|
@@ -57,6 +57,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
|
|
{
|
|
|
int my_ticket;
|
|
|
int tmp;
|
|
|
+ int inc = 0x10000;
|
|
|
|
|
|
if (R10000_LLSC_WAR) {
|
|
|
__asm__ __volatile__ (
|
|
@@ -64,25 +65,24 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
|
|
" .set noreorder \n"
|
|
|
" \n"
|
|
|
"1: ll %[ticket], %[ticket_ptr] \n"
|
|
|
- " addiu %[my_ticket], %[ticket], 0x4000 \n"
|
|
|
+ " addu %[my_ticket], %[ticket], %[inc] \n"
|
|
|
" sc %[my_ticket], %[ticket_ptr] \n"
|
|
|
" beqzl %[my_ticket], 1b \n"
|
|
|
" nop \n"
|
|
|
- " srl %[my_ticket], %[ticket], 14 \n"
|
|
|
- " andi %[my_ticket], %[my_ticket], 0x1fff \n"
|
|
|
- " andi %[ticket], %[ticket], 0x1fff \n"
|
|
|
+ " srl %[my_ticket], %[ticket], 16 \n"
|
|
|
+ " andi %[ticket], %[ticket], 0xffff \n"
|
|
|
+ " andi %[my_ticket], %[my_ticket], 0xffff \n"
|
|
|
" bne %[ticket], %[my_ticket], 4f \n"
|
|
|
" subu %[ticket], %[my_ticket], %[ticket] \n"
|
|
|
"2: \n"
|
|
|
" .subsection 2 \n"
|
|
|
- "4: andi %[ticket], %[ticket], 0x1fff \n"
|
|
|
+ "4: andi %[ticket], %[ticket], 0xffff \n"
|
|
|
" sll %[ticket], 5 \n"
|
|
|
" \n"
|
|
|
"6: bnez %[ticket], 6b \n"
|
|
|
" subu %[ticket], 1 \n"
|
|
|
" \n"
|
|
|
- " lw %[ticket], %[ticket_ptr] \n"
|
|
|
- " andi %[ticket], %[ticket], 0x1fff \n"
|
|
|
+ " lhu %[ticket], %[serving_now_ptr] \n"
|
|
|
" beq %[ticket], %[my_ticket], 2b \n"
|
|
|
" subu %[ticket], %[my_ticket], %[ticket] \n"
|
|
|
" b 4b \n"
|
|
@@ -90,36 +90,33 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
|
|
" .previous \n"
|
|
|
" .set pop \n"
|
|
|
: [ticket_ptr] "+m" (lock->lock),
|
|
|
+ [serving_now_ptr] "+m" (lock->h.serving_now),
|
|
|
[ticket] "=&r" (tmp),
|
|
|
- [my_ticket] "=&r" (my_ticket));
|
|
|
+ [my_ticket] "=&r" (my_ticket)
|
|
|
+ : [inc] "r" (inc));
|
|
|
} else {
|
|
|
__asm__ __volatile__ (
|
|
|
" .set push # arch_spin_lock \n"
|
|
|
" .set noreorder \n"
|
|
|
" \n"
|
|
|
- " ll %[ticket], %[ticket_ptr] \n"
|
|
|
- "1: addiu %[my_ticket], %[ticket], 0x4000 \n"
|
|
|
+ "1: ll %[ticket], %[ticket_ptr] \n"
|
|
|
+ " addu %[my_ticket], %[ticket], %[inc] \n"
|
|
|
" sc %[my_ticket], %[ticket_ptr] \n"
|
|
|
- " beqz %[my_ticket], 3f \n"
|
|
|
- " nop \n"
|
|
|
- " srl %[my_ticket], %[ticket], 14 \n"
|
|
|
- " andi %[my_ticket], %[my_ticket], 0x1fff \n"
|
|
|
- " andi %[ticket], %[ticket], 0x1fff \n"
|
|
|
+ " beqz %[my_ticket], 1b \n"
|
|
|
+ " srl %[my_ticket], %[ticket], 16 \n"
|
|
|
+ " andi %[ticket], %[ticket], 0xffff \n"
|
|
|
+ " andi %[my_ticket], %[my_ticket], 0xffff \n"
|
|
|
" bne %[ticket], %[my_ticket], 4f \n"
|
|
|
" subu %[ticket], %[my_ticket], %[ticket] \n"
|
|
|
"2: \n"
|
|
|
" .subsection 2 \n"
|
|
|
- "3: b 1b \n"
|
|
|
- " ll %[ticket], %[ticket_ptr] \n"
|
|
|
- " \n"
|
|
|
"4: andi %[ticket], %[ticket], 0x1fff \n"
|
|
|
" sll %[ticket], 5 \n"
|
|
|
" \n"
|
|
|
"6: bnez %[ticket], 6b \n"
|
|
|
" subu %[ticket], 1 \n"
|
|
|
" \n"
|
|
|
- " lw %[ticket], %[ticket_ptr] \n"
|
|
|
- " andi %[ticket], %[ticket], 0x1fff \n"
|
|
|
+ " lhu %[ticket], %[serving_now_ptr] \n"
|
|
|
" beq %[ticket], %[my_ticket], 2b \n"
|
|
|
" subu %[ticket], %[my_ticket], %[ticket] \n"
|
|
|
" b 4b \n"
|
|
@@ -127,8 +124,10 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
|
|
" .previous \n"
|
|
|
" .set pop \n"
|
|
|
: [ticket_ptr] "+m" (lock->lock),
|
|
|
+ [serving_now_ptr] "+m" (lock->h.serving_now),
|
|
|
[ticket] "=&r" (tmp),
|
|
|
- [my_ticket] "=&r" (my_ticket));
|
|
|
+ [my_ticket] "=&r" (my_ticket)
|
|
|
+ : [inc] "r" (inc));
|
|
|
}
|
|
|
|
|
|
smp_llsc_mb();
|
|
@@ -136,47 +135,16 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
|
|
|
|
|
|
static inline void arch_spin_unlock(arch_spinlock_t *lock)
|
|
|
{
|
|
|
- int tmp;
|
|
|
-
|
|
|
- smp_mb__before_llsc();
|
|
|
-
|
|
|
- if (R10000_LLSC_WAR) {
|
|
|
- __asm__ __volatile__ (
|
|
|
- " # arch_spin_unlock \n"
|
|
|
- "1: ll %[ticket], %[ticket_ptr] \n"
|
|
|
- " addiu %[ticket], %[ticket], 1 \n"
|
|
|
- " ori %[ticket], %[ticket], 0x2000 \n"
|
|
|
- " xori %[ticket], %[ticket], 0x2000 \n"
|
|
|
- " sc %[ticket], %[ticket_ptr] \n"
|
|
|
- " beqzl %[ticket], 1b \n"
|
|
|
- : [ticket_ptr] "+m" (lock->lock),
|
|
|
- [ticket] "=&r" (tmp));
|
|
|
- } else {
|
|
|
- __asm__ __volatile__ (
|
|
|
- " .set push # arch_spin_unlock \n"
|
|
|
- " .set noreorder \n"
|
|
|
- " \n"
|
|
|
- " ll %[ticket], %[ticket_ptr] \n"
|
|
|
- "1: addiu %[ticket], %[ticket], 1 \n"
|
|
|
- " ori %[ticket], %[ticket], 0x2000 \n"
|
|
|
- " xori %[ticket], %[ticket], 0x2000 \n"
|
|
|
- " sc %[ticket], %[ticket_ptr] \n"
|
|
|
- " beqz %[ticket], 2f \n"
|
|
|
- " nop \n"
|
|
|
- " \n"
|
|
|
- " .subsection 2 \n"
|
|
|
- "2: b 1b \n"
|
|
|
- " ll %[ticket], %[ticket_ptr] \n"
|
|
|
- " .previous \n"
|
|
|
- " .set pop \n"
|
|
|
- : [ticket_ptr] "+m" (lock->lock),
|
|
|
- [ticket] "=&r" (tmp));
|
|
|
- }
|
|
|
+ unsigned int serving_now = lock->h.serving_now + 1;
|
|
|
+ wmb();
|
|
|
+ lock->h.serving_now = (u16)serving_now;
|
|
|
+ nudge_writes();
|
|
|
}
|
|
|
|
|
|
static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
|
|
|
{
|
|
|
int tmp, tmp2, tmp3;
|
|
|
+ int inc = 0x10000;
|
|
|
|
|
|
if (R10000_LLSC_WAR) {
|
|
|
__asm__ __volatile__ (
|
|
@@ -184,11 +152,11 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
|
|
|
" .set noreorder \n"
|
|
|
" \n"
|
|
|
"1: ll %[ticket], %[ticket_ptr] \n"
|
|
|
- " srl %[my_ticket], %[ticket], 14 \n"
|
|
|
- " andi %[my_ticket], %[my_ticket], 0x1fff \n"
|
|
|
- " andi %[now_serving], %[ticket], 0x1fff \n"
|
|
|
+ " srl %[my_ticket], %[ticket], 16 \n"
|
|
|
+ " andi %[my_ticket], %[my_ticket], 0xffff \n"
|
|
|
+ " andi %[now_serving], %[ticket], 0xffff \n"
|
|
|
" bne %[my_ticket], %[now_serving], 3f \n"
|
|
|
- " addiu %[ticket], %[ticket], 0x4000 \n"
|
|
|
+ " addu %[ticket], %[ticket], %[inc] \n"
|
|
|
" sc %[ticket], %[ticket_ptr] \n"
|
|
|
" beqzl %[ticket], 1b \n"
|
|
|
" li %[ticket], 1 \n"
|
|
@@ -201,33 +169,33 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
|
|
|
: [ticket_ptr] "+m" (lock->lock),
|
|
|
[ticket] "=&r" (tmp),
|
|
|
[my_ticket] "=&r" (tmp2),
|
|
|
- [now_serving] "=&r" (tmp3));
|
|
|
+ [now_serving] "=&r" (tmp3)
|
|
|
+ : [inc] "r" (inc));
|
|
|
} else {
|
|
|
__asm__ __volatile__ (
|
|
|
" .set push # arch_spin_trylock \n"
|
|
|
" .set noreorder \n"
|
|
|
" \n"
|
|
|
- " ll %[ticket], %[ticket_ptr] \n"
|
|
|
- "1: srl %[my_ticket], %[ticket], 14 \n"
|
|
|
- " andi %[my_ticket], %[my_ticket], 0x1fff \n"
|
|
|
- " andi %[now_serving], %[ticket], 0x1fff \n"
|
|
|
+ "1: ll %[ticket], %[ticket_ptr] \n"
|
|
|
+ " srl %[my_ticket], %[ticket], 16 \n"
|
|
|
+ " andi %[my_ticket], %[my_ticket], 0xffff \n"
|
|
|
+ " andi %[now_serving], %[ticket], 0xffff \n"
|
|
|
" bne %[my_ticket], %[now_serving], 3f \n"
|
|
|
- " addiu %[ticket], %[ticket], 0x4000 \n"
|
|
|
+ " addu %[ticket], %[ticket], %[inc] \n"
|
|
|
" sc %[ticket], %[ticket_ptr] \n"
|
|
|
- " beqz %[ticket], 4f \n"
|
|
|
+ " beqz %[ticket], 1b \n"
|
|
|
" li %[ticket], 1 \n"
|
|
|
"2: \n"
|
|
|
" .subsection 2 \n"
|
|
|
"3: b 2b \n"
|
|
|
" li %[ticket], 0 \n"
|
|
|
- "4: b 1b \n"
|
|
|
- " ll %[ticket], %[ticket_ptr] \n"
|
|
|
" .previous \n"
|
|
|
" .set pop \n"
|
|
|
: [ticket_ptr] "+m" (lock->lock),
|
|
|
[ticket] "=&r" (tmp),
|
|
|
[my_ticket] "=&r" (tmp2),
|
|
|
- [now_serving] "=&r" (tmp3));
|
|
|
+ [now_serving] "=&r" (tmp3)
|
|
|
+ : [inc] "r" (inc));
|
|
|
}
|
|
|
|
|
|
smp_llsc_mb();
|