and changed files
[powerpc.git] / include / asm-mips / spinlock.h
index c8d5587..35e431c 100644 (file)
@@ -3,12 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000, 06 Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 
+#include <asm/barrier.h>
 #include <asm/war.h>
 
 /*
@@ -40,7 +41,6 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
                "        nop                                            \n"
-               "       sync                                            \n"
                "       .set    reorder                                 \n"
                : "=m" (lock->lock), "=&r" (tmp)
                : "m" (lock->lock)
@@ -49,23 +49,33 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
                __asm__ __volatile__(
                "       .set    noreorder       # __raw_spin_lock       \n"
                "1:     ll      %1, %2                                  \n"
-               "       bnez    %1, 1b                                  \n"
+               "       bnez    %1, 2f                                  \n"
                "        li     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
-               "        sync                                           \n"
+               "       beqz    %1, 2f                                  \n"
+               "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     ll      %1, %2                                  \n"
+               "       bnez    %1, 2b                                  \n"
+               "        li     %1, 1                                   \n"
+               "       b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (lock->lock), "=&r" (tmp)
                : "m" (lock->lock)
                : "memory");
        }
+
+       smp_mb();
 }
 
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
+       smp_mb();
+
        __asm__ __volatile__(
        "       .set    noreorder       # __raw_spin_unlock     \n"
-       "       sync                                            \n"
        "       sw      $0, %0                                  \n"
        "       .set\treorder                                   \n"
        : "=m" (lock->lock)
@@ -86,7 +96,6 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
                "       beqzl   %2, 1b                                  \n"
                "        nop                                            \n"
                "       andi    %2, %0, 1                               \n"
-               "       sync                                            \n"
                "       .set    reorder"
                : "=&r" (temp), "=m" (lock->lock), "=&r" (res)
                : "m" (lock->lock)
@@ -97,15 +106,20 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
                "1:     ll      %0, %3                                  \n"
                "       ori     %2, %0, 1                               \n"
                "       sc      %2, %1                                  \n"
-               "       beqz    %2, 1b                                  \n"
+               "       beqz    %2, 2f                                  \n"
                "        andi   %2, %0, 1                               \n"
-               "       sync                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder"
                : "=&r" (temp), "=m" (lock->lock), "=&r" (res)
                : "m" (lock->lock)
                : "memory");
        }
 
+       smp_mb();
+
        return res == 0;
 }
 
@@ -143,7 +157,6 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
                "        nop                                            \n"
-               "       sync                                            \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -152,16 +165,25 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
                __asm__ __volatile__(
                "       .set    noreorder       # __raw_read_lock       \n"
                "1:     ll      %1, %2                                  \n"
-               "       bltz    %1, 1b                                  \n"
+               "       bltz    %1, 2f                                  \n"
                "        addu   %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       beqz    %1, 1b                                  \n"
-               "        sync                                           \n"
+               "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     ll      %1, %2                                  \n"
+               "       bltz    %1, 2b                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
                : "memory");
        }
+
+       smp_mb();
 }
 
 /* Note the use of sub, not subu which will make the kernel die with an
@@ -171,13 +193,14 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
        unsigned int tmp;
 
+       smp_mb();
+
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
                "1:     ll      %1, %2          # __raw_read_unlock     \n"
                "       sub     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
-               "       sync                                            \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
                : "memory");
@@ -187,8 +210,12 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
                "1:     ll      %1, %2                                  \n"
                "       sub     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
-               "        sync                                           \n"
+               "       beqz    %1, 2f                                  \n"
+               "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -208,7 +235,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
-               "        sync                                           \n"
+               "        nop                                            \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -217,22 +244,33 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
                __asm__ __volatile__(
                "       .set    noreorder       # __raw_write_lock      \n"
                "1:     ll      %1, %2                                  \n"
-               "       bnez    %1, 1b                                  \n"
+               "       bnez    %1, 2f                                  \n"
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
-               "        sync                                           \n"
+               "       beqz    %1, 2f                                  \n"
+               "        nop                                            \n"
+               "       .subsection 2                                   \n"
+               "2:     ll      %1, %2                                  \n"
+               "       bnez    %1, 2b                                  \n"
+               "        lui    %1, 0x8000                              \n"
+               "       b       1b                                      \n"
+               "        nop                                            \n"
+               "       .previous                                       \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
                : "memory");
        }
+
+       smp_mb();
 }
 
 static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
+       smp_mb();
+
        __asm__ __volatile__(
-       "       sync                    # __raw_write_unlock    \n"
+       "                               # __raw_write_unlock    \n"
        "       sw      $0, %0                                  \n"
        : "=m" (rw->lock)
        : "m" (rw->lock)
@@ -249,14 +287,13 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
                "       .set    noreorder       # __raw_read_trylock    \n"
                "       li      %2, 0                                   \n"
                "1:     ll      %1, %3                                  \n"
-               "       bnez    %1, 2f                                  \n"
+               "       bltz    %1, 2f                                  \n"
                "        addu   %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
-               "       beqzl   %1, 1b                                  \n"
                "       .set    reorder                                 \n"
-#ifdef CONFIG_SMP
-               "        sync                                           \n"
-#endif
+               "       beqzl   %1, 1b                                  \n"
+               "        nop                                            \n"
+               __WEAK_ORDERING_MB
                "       li      %2, 1                                   \n"
                "2:                                                     \n"
                : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
@@ -267,14 +304,13 @@ static inline int __raw_read_trylock(raw_rwlock_t *rw)
                "       .set    noreorder       # __raw_read_trylock    \n"
                "       li      %2, 0                                   \n"
                "1:     ll      %1, %3                                  \n"
-               "       bnez    %1, 2f                                  \n"
+               "       bltz    %1, 2f                                  \n"
                "        addu   %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       beqz    %1, 1b                                  \n"
+               "        nop                                            \n"
                "       .set    reorder                                 \n"
-#ifdef CONFIG_SMP
-               "        sync                                           \n"
-#endif
+               __WEAK_ORDERING_MB
                "       li      %2, 1                                   \n"
                "2:                                                     \n"
                : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
@@ -299,7 +335,8 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
-               "        sync                                           \n"
+               "        nop                                            \n"
+               __WEAK_ORDERING_MB
                "       li      %2, 1                                   \n"
                "       .set    reorder                                 \n"
                "2:                                                     \n"
@@ -314,11 +351,15 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
                "       bnez    %1, 2f                                  \n"
                "       lui     %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
-               "       beqz    %1, 1b                                  \n"
-               "        sync                                           \n"
-               "       li      %2, 1                                   \n"
-               "       .set    reorder                                 \n"
+               "       beqz    %1, 3f                                  \n"
+               "        li     %2, 1                                   \n"
                "2:                                                     \n"
+               __WEAK_ORDERING_MB
+               "       .subsection 2                                   \n"
+               "3:     b       1b                                      \n"
+               "        li     %2, 0                                   \n"
+               "       .previous                                       \n"
+               "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
                : "m" (rw->lock)
                : "memory");