Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / include / asm-mips / spinlock.h
index 4d0135b..4c1a1b5 100644 (file)
@@ -9,17 +9,16 @@
 #ifndef _ASM_SPINLOCK_H
 #define _ASM_SPINLOCK_H
 
-#include <linux/config.h>
 #include <asm/war.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  */
 
-#define __raw_spin_is_locked(x)        ((x)->lock != 0)
+#define __raw_spin_is_locked(x)       ((x)->lock != 0)
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 #define __raw_spin_unlock_wait(x) \
-               do { cpu_relax(); } while ((x)->lock)
+       do { cpu_relax(); } while ((x)->lock)
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
@@ -119,6 +118,18 @@ static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
  * read-locks.
  */
 
+/*
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define __raw_read_can_lock(rw)        ((rw)->lock >= 0)
+
+/*
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define __raw_write_can_lock(rw)       (!(rw)->lock)
+
 static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
        unsigned int tmp;
@@ -197,8 +208,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
-               "        nop                                            \n"
-               "       sync                                            \n"
+               "        sync                                           \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -211,8 +221,7 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
                "       beqz    %1, 1b                                  \n"
-               "        nop                                            \n"
-               "       sync                                            \n"
+               "        sync                                           \n"
                "       .set    reorder                                 \n"
                : "=m" (rw->lock), "=&r" (tmp)
                : "m" (rw->lock)
@@ -230,7 +239,51 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
        : "memory");
 }
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+       unsigned int tmp;
+       int ret;
+
+       if (R10000_LLSC_WAR) {
+               __asm__ __volatile__(
+               "       .set    noreorder       # __raw_read_trylock    \n"
+               "       li      %2, 0                                   \n"
+               "1:     ll      %1, %3                                  \n"
+               "       bnez    %1, 2f                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       sc      %1, %0                                  \n"
+               "       beqzl   %1, 1b                                  \n"
+               "       .set    reorder                                 \n"
+#ifdef CONFIG_SMP
+               "        sync                                           \n"
+#endif
+               "       li      %2, 1                                   \n"
+               "2:                                                     \n"
+               : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+               : "m" (rw->lock)
+               : "memory");
+       } else {
+               __asm__ __volatile__(
+               "       .set    noreorder       # __raw_read_trylock    \n"
+               "       li      %2, 0                                   \n"
+               "1:     ll      %1, %3                                  \n"
+               "       bnez    %1, 2f                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       sc      %1, %0                                  \n"
+               "       beqz    %1, 1b                                  \n"
+               "       .set    reorder                                 \n"
+#ifdef CONFIG_SMP
+               "        sync                                           \n"
+#endif
+               "       li      %2, 1                                   \n"
+               "2:                                                     \n"
+               : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+               : "m" (rw->lock)
+               : "memory");
+       }
+
+       return ret;
+}
 
 static inline int __raw_write_trylock(raw_rwlock_t *rw)
 {
@@ -246,8 +299,7 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
                "        lui    %1, 0x8000                              \n"
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
-               "        nop                                            \n"
-               "       sync                                            \n"
+               "        sync                                           \n"
                "       li      %2, 1                                   \n"
                "       .set    reorder                                 \n"
                "2:                                                     \n"
@@ -275,4 +327,5 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
        return ret;
 }
 
+
 #endif /* _ASM_SPINLOCK_H */