]> err.no Git - linux-2.6/blobdiff - include/asm-powerpc/bitops.h
[POWERPC] Fix swapper_pg_dir size when CONFIG_PTE_64BIT=y on FSL_BOOKE
[linux-2.6] / include / asm-powerpc / bitops.h
index c341063d08049b0dfbf4050617c013c46daff0ab..733b4af7f4f1e7e49269b17856bbf7e47924d7b6 100644 (file)
 
 #ifdef __KERNEL__
 
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
 #include <linux/compiler.h>
-#include <asm/atomic.h>
 #include <asm/asm-compat.h>
 #include <asm/synch.h>
 
@@ -87,6 +90,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;
@@ -126,6 +147,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)
 {
@@ -186,11 +228,18 @@ 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.
  */
-static __inline__ int __ilog2(unsigned long x)
+static __inline__ __attribute__((const))
+int __ilog2(unsigned long x)
 {
        int lz;
 
@@ -198,6 +247,24 @@ static __inline__ int __ilog2(unsigned long x)
        return BITS_PER_LONG - 1 - lz;
 }
 
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+       int bit;
+       asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n));
+       return 31 - bit;
+}
+
+#ifdef __powerpc64__
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+       int bit;
+       asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n));
+       return 63 - bit;
+}
+#endif
+
 /*
  * Determines the bit position of the least significant 0 bit in the
  * specified double word. The returned bit position will be