|
@@ -56,174 +56,102 @@
|
|
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
|
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
|
#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
|
|
#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
|
|
|
|
|
|
|
|
+/* Macro for generating the ***_bits() functions */
|
|
|
|
+#define DEFINE_BITOP(fn, op, prefix, postfix) \
|
|
|
|
+static __inline__ void fn(unsigned long mask, \
|
|
|
|
+ volatile unsigned long *_p) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned long old; \
|
|
|
|
+ unsigned long *p = (unsigned long *)_p; \
|
|
|
|
+ __asm__ __volatile__ ( \
|
|
|
|
+ prefix \
|
|
|
|
+"1:" PPC_LLARX "%0,0,%3\n" \
|
|
|
|
+ stringify_in_c(op) "%0,%0,%2\n" \
|
|
|
|
+ PPC405_ERR77(0,%3) \
|
|
|
|
+ PPC_STLCX "%0,0,%3\n" \
|
|
|
|
+ "bne- 1b\n" \
|
|
|
|
+ postfix \
|
|
|
|
+ : "=&r" (old), "+m" (*p) \
|
|
|
|
+ : "r" (mask), "r" (p) \
|
|
|
|
+ : "cc", "memory"); \
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+DEFINE_BITOP(set_bits, or, "", "")
|
|
|
|
+DEFINE_BITOP(clear_bits, andc, "", "")
|
|
|
|
+DEFINE_BITOP(clear_bits_unlock, andc, LWSYNC_ON_SMP, "")
|
|
|
|
+DEFINE_BITOP(change_bits, xor, "", "")
|
|
|
|
+
|
|
static __inline__ void set_bit(int nr, volatile unsigned long *addr)
|
|
static __inline__ void set_bit(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__(
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # set_bit\n"
|
|
|
|
- "or %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" );
|
|
|
|
|
|
+ set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
|
|
}
|
|
}
|
|
|
|
|
|
static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
|
|
static __inline__ void clear_bit(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__(
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # clear_bit\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" );
|
|
|
|
|
|
+ clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
|
|
}
|
|
}
|
|
|
|
|
|
static __inline__ void clear_bit_unlock(int nr, volatile unsigned long *addr)
|
|
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");
|
|
|
|
|
|
+ clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr));
|
|
}
|
|
}
|
|
|
|
|
|
static __inline__ void change_bit(int nr, volatile unsigned long *addr)
|
|
static __inline__ void change_bit(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__(
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # change_bit\n"
|
|
|
|
- "xor %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" );
|
|
|
|
|
|
+ change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output
|
|
|
|
+ * operands. */
|
|
|
|
+#define DEFINE_TESTOP(fn, op, prefix, postfix) \
|
|
|
|
+static __inline__ unsigned long fn( \
|
|
|
|
+ unsigned long mask, \
|
|
|
|
+ volatile unsigned long *_p) \
|
|
|
|
+{ \
|
|
|
|
+ unsigned long old, t; \
|
|
|
|
+ unsigned long *p = (unsigned long *)_p; \
|
|
|
|
+ __asm__ __volatile__ ( \
|
|
|
|
+ prefix \
|
|
|
|
+"1:" PPC_LLARX "%0,0,%3\n" \
|
|
|
|
+ stringify_in_c(op) "%1,%0,%2\n" \
|
|
|
|
+ PPC405_ERR77(0,%3) \
|
|
|
|
+ PPC_STLCX "%1,0,%3\n" \
|
|
|
|
+ "bne- 1b\n" \
|
|
|
|
+ postfix \
|
|
|
|
+ : "=&r" (old), "=&r" (t) \
|
|
|
|
+ : "r" (mask), "r" (p) \
|
|
|
|
+ : "cc", "memory"); \
|
|
|
|
+ return (old & mask); \
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+DEFINE_TESTOP(test_and_set_bits, or, LWSYNC_ON_SMP, ISYNC_ON_SMP)
|
|
|
|
+DEFINE_TESTOP(test_and_set_bits_lock, or, "", ISYNC_ON_SMP)
|
|
|
|
+DEFINE_TESTOP(test_and_clear_bits, andc, LWSYNC_ON_SMP, ISYNC_ON_SMP)
|
|
|
|
+DEFINE_TESTOP(test_and_change_bits, xor, LWSYNC_ON_SMP, ISYNC_ON_SMP)
|
|
|
|
+
|
|
static __inline__ int test_and_set_bit(unsigned long nr,
|
|
static __inline__ int test_and_set_bit(unsigned long nr,
|
|
volatile unsigned long *addr)
|
|
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__(
|
|
|
|
- LWSYNC_ON_SMP
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\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;
|
|
|
|
|
|
+ return test_and_set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
|
|
}
|
|
}
|
|
|
|
|
|
static __inline__ int test_and_set_bit_lock(unsigned long nr,
|
|
static __inline__ int test_and_set_bit_lock(unsigned long nr,
|
|
volatile unsigned long *addr)
|
|
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;
|
|
|
|
|
|
+ return test_and_set_bits_lock(BITOP_MASK(nr),
|
|
|
|
+ addr + BITOP_WORD(nr)) != 0;
|
|
}
|
|
}
|
|
|
|
|
|
static __inline__ int test_and_clear_bit(unsigned long nr,
|
|
static __inline__ int test_and_clear_bit(unsigned long nr,
|
|
volatile unsigned long *addr)
|
|
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__(
|
|
|
|
- LWSYNC_ON_SMP
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n"
|
|
|
|
- "andc %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;
|
|
|
|
|
|
+ return test_and_clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
|
|
}
|
|
}
|
|
|
|
|
|
static __inline__ int test_and_change_bit(unsigned long nr,
|
|
static __inline__ int test_and_change_bit(unsigned long nr,
|
|
volatile unsigned long *addr)
|
|
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__(
|
|
|
|
- LWSYNC_ON_SMP
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n"
|
|
|
|
- "xor %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__ void set_bits(unsigned long mask, unsigned long *addr)
|
|
|
|
-{
|
|
|
|
- unsigned long old;
|
|
|
|
-
|
|
|
|
- __asm__ __volatile__(
|
|
|
|
-"1:" PPC_LLARX "%0,0,%3 # set_bits\n"
|
|
|
|
- "or %0,%0,%2\n"
|
|
|
|
- PPC_STLCX "%0,0,%3\n"
|
|
|
|
- "bne- 1b"
|
|
|
|
- : "=&r" (old), "+m" (*addr)
|
|
|
|
- : "r" (mask), "r" (addr)
|
|
|
|
- : "cc");
|
|
|
|
|
|
+ return test_and_change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
|
|
}
|
|
}
|
|
|
|
|
|
#include <asm-generic/bitops/non-atomic.h>
|
|
#include <asm-generic/bitops/non-atomic.h>
|