powerpc: lock bitops
authorNick Piggin <npiggin@suse.de>
Thu, 18 Oct 2007 10:06:53 +0000 (03:06 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 18 Oct 2007 21:37:29 +0000 (14:37 -0700)
Add non-trivial lock bitops implementation for powerpc.

Signed-off-by: Nick Piggin <npiggin@suse.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/asm-powerpc/bitops.h

index 1d4c16613d2faa06203495fa1ba918962d15131c..e85c3e078ba29be59f7d4f0425844de39d24461a 100644 (file)
@@ -86,6 +86,24 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
        : "cc" );
 }
 
+static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
+{
+       unsigned long old;
+       unsigned long mask = BITOP_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+       __asm__ __volatile__(
+       LWSYNC_ON_SMP
+"1:"   PPC_LLARX "%0,0,%3      # clear_bit_unlock\n"
+       "andc   %0,%0,%2\n"
+       PPC405_ERR77(0,%3)
+       PPC_STLCX "%0,0,%3\n"
+       "bne-   1b"
+       : "=&r" (old), "+m" (*p)
+       : "r" (mask), "r" (p)
+       : "cc", "memory");
+}
+
 static __inline__ void change_bit(int nr, volatile unsigned long *addr)
 {
        unsigned long old;
@@ -125,6 +143,27 @@ static __inline__ int test_and_set_bit(unsigned long nr,
        return (old & mask) != 0;
 }
 
+static __inline__ int test_and_set_bit_lock(unsigned long nr,
+                                      volatile unsigned long *addr)
+{
+       unsigned long old, t;
+       unsigned long mask = BITOP_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
+
+       __asm__ __volatile__(
+"1:"   PPC_LLARX "%0,0,%3              # test_and_set_bit_lock\n"
+       "or     %1,%0,%2 \n"
+       PPC405_ERR77(0,%3)
+       PPC_STLCX "%1,0,%3 \n"
+       "bne-   1b"
+       ISYNC_ON_SMP
+       : "=&r" (old), "=&r" (t)
+       : "r" (mask), "r" (p)
+       : "cc", "memory");
+
+       return (old & mask) != 0;
+}
+
 static __inline__ int test_and_clear_bit(unsigned long nr,
                                         volatile unsigned long *addr)
 {
@@ -185,6 +224,12 @@ static __inline__ void set_bits(unsigned long mask, unsigned long *addr)
 
 #include <asm-generic/bitops/non-atomic.h>
 
+static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr)
+{
+       __asm__ __volatile__(LWSYNC_ON_SMP "" ::: "memory");
+       __clear_bit(nr, addr);
+}
+
 /*
  * Return the zero-based bit position (LE, not IBM bit numbering) of
  * the most significant 1-bit in a double word.
@@ -266,7 +311,6 @@ static __inline__ int fls(unsigned int x)
 #include <asm-generic/bitops/fls64.h>
 
 #include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
 
 #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
 unsigned long find_next_zero_bit(const unsigned long *addr,