[SPARC]: Make bitops use same spinlocks as atomics.
authorDavid S. Miller <davem@sunset.davemloft.net>
Mon, 18 Dec 2006 00:18:47 +0000 (16:18 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 18 Dec 2006 00:18:47 +0000 (16:18 -0800)
Recent workqueue changes basically make this a formal requirement.

Also, move atomic32.o from lib-y to obj-y since it exports symbols
to modules.

Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc/kernel/sparc_ksyms.c
arch/sparc/kernel/time.c
arch/sparc/lib/Makefile
arch/sparc/lib/atomic32.c
arch/sparc/lib/bitops.S [deleted file]
include/asm-sparc/bitops.h

index 33dadd9..d8e008a 100644 (file)
@@ -83,9 +83,6 @@ extern int __divdi3(int, int);
 /* Private functions with odd calling conventions. */
 extern void ___atomic24_add(void);
 extern void ___atomic24_sub(void);
-extern void ___set_bit(void);
-extern void ___clear_bit(void);
-extern void ___change_bit(void);
 extern void ___rw_read_enter(void);
 extern void ___rw_read_try(void);
 extern void ___rw_read_exit(void);
@@ -125,11 +122,6 @@ EXPORT_SYMBOL(pfn_base);
 EXPORT_SYMBOL(___atomic24_add);
 EXPORT_SYMBOL(___atomic24_sub);
 
-/* Bit operations. */
-EXPORT_SYMBOL(___set_bit);
-EXPORT_SYMBOL(___clear_bit);
-EXPORT_SYMBOL(___change_bit);
-
 /* Per-CPU information table */
 EXPORT_PER_CPU_SYMBOL(__cpu_data);
 
index 6c7aa51..2fcce00 100644 (file)
@@ -78,7 +78,6 @@ unsigned long profile_pc(struct pt_regs *regs)
        extern char __copy_user_begin[], __copy_user_end[];
        extern char __atomic_begin[], __atomic_end[];
        extern char __bzero_begin[], __bzero_end[];
-       extern char __bitops_begin[], __bitops_end[];
 
        unsigned long pc = regs->pc;
 
@@ -88,9 +87,7 @@ unsigned long profile_pc(struct pt_regs *regs)
            (pc >= (unsigned long) __atomic_begin &&
             pc < (unsigned long) __atomic_end) ||
            (pc >= (unsigned long) __bzero_begin &&
-            pc < (unsigned long) __bzero_end) ||
-           (pc >= (unsigned long) __bitops_begin &&
-            pc < (unsigned long) __bitops_end))
+            pc < (unsigned long) __bzero_end))
                pc = regs->u_regs[UREG_RETPC];
        return pc;
 }
index 5db7e1d..9ddc5b9 100644 (file)
@@ -7,7 +7,7 @@ EXTRA_AFLAGS := -ansi -DST_DIV0=0x02
 lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
          strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
         strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
-        copy_user.o locks.o atomic.o atomic32.o bitops.o \
+        copy_user.o locks.o atomic.o \
         lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
 
-obj-y += iomap.o
+obj-y += iomap.o atomic32.o
index de84f85..53ddcd9 100644 (file)
@@ -76,3 +76,42 @@ void atomic_set(atomic_t *v, int i)
        spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
 }
 EXPORT_SYMBOL(atomic_set);
+
+unsigned long ___set_bit(unsigned long *addr, unsigned long mask)
+{
+       unsigned long old, flags;
+
+       spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+       old = *addr;
+       *addr = old | mask;
+       spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+
+       return old & mask;
+}
+EXPORT_SYMBOL(___set_bit);
+
+unsigned long ___clear_bit(unsigned long *addr, unsigned long mask)
+{
+       unsigned long old, flags;
+
+       spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+       old = *addr;
+       *addr = old & ~mask;
+       spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+
+       return old & mask;
+}
+EXPORT_SYMBOL(___clear_bit);
+
+unsigned long ___change_bit(unsigned long *addr, unsigned long mask)
+{
+       unsigned long old, flags;
+
+       spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+       old = *addr;
+       *addr = old ^ mask;
+       spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+
+       return old & mask;
+}
+EXPORT_SYMBOL(___change_bit);
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S
deleted file mode 100644 (file)
index cb7fb66..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* bitops.S: Low level assembler bit operations.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/ptrace.h>
-#include <asm/psr.h>
-
-       .text
-       .align  4
-
-       .globl  __bitops_begin
-__bitops_begin:
-
-       /* Take bits in %g2 and set them in word at %g1,
-        * return whether bits were set in original value
-        * in %g2.  %g4 holds value to restore into %o7
-        * in delay slot of jmpl return, %g3 + %g5 + %g7 can be
-        * used as temporaries and thus is considered clobbered
-        * by all callers.
-        */
-       .globl  ___set_bit
-___set_bit:
-       rd      %psr, %g3
-       nop; nop; nop;
-       or      %g3, PSR_PIL, %g5
-       wr      %g5, 0x0, %psr
-       nop; nop; nop
-#ifdef CONFIG_SMP
-       set     bitops_spinlock, %g5
-2:     ldstub  [%g5], %g7              ! Spin on the byte lock for SMP.
-       orcc    %g7, 0x0, %g0           ! Did we get it?
-       bne     2b                      ! Nope...
-#endif
-        ld     [%g1], %g7
-       or      %g7, %g2, %g5
-       and     %g7, %g2, %g2
-#ifdef CONFIG_SMP
-       st      %g5, [%g1]
-       set     bitops_spinlock, %g5
-       stb     %g0, [%g5]
-#else
-       st      %g5, [%g1]
-#endif
-       wr      %g3, 0x0, %psr
-       nop; nop; nop
-       jmpl    %o7, %g0
-        mov    %g4, %o7
-
-       /* Same as above, but clears the bits from %g2 instead. */
-       .globl  ___clear_bit
-___clear_bit:
-       rd      %psr, %g3
-       nop; nop; nop
-       or      %g3, PSR_PIL, %g5
-       wr      %g5, 0x0, %psr
-       nop; nop; nop
-#ifdef CONFIG_SMP
-       set     bitops_spinlock, %g5
-2:     ldstub  [%g5], %g7              ! Spin on the byte lock for SMP.
-       orcc    %g7, 0x0, %g0           ! Did we get it?
-       bne     2b                      ! Nope...
-#endif
-        ld     [%g1], %g7
-       andn    %g7, %g2, %g5
-       and     %g7, %g2, %g2
-#ifdef CONFIG_SMP
-       st      %g5, [%g1]
-       set     bitops_spinlock, %g5
-       stb     %g0, [%g5]
-#else
-       st      %g5, [%g1]
-#endif
-       wr      %g3, 0x0, %psr
-       nop; nop; nop
-       jmpl    %o7, %g0
-        mov    %g4, %o7
-
-       /* Same thing again, but this time toggles the bits from %g2. */
-       .globl  ___change_bit
-___change_bit:
-       rd      %psr, %g3
-       nop; nop; nop
-       or      %g3, PSR_PIL, %g5
-       wr      %g5, 0x0, %psr
-       nop; nop; nop
-#ifdef CONFIG_SMP
-       set     bitops_spinlock, %g5
-2:     ldstub  [%g5], %g7              ! Spin on the byte lock for SMP.
-       orcc    %g7, 0x0, %g0           ! Did we get it?
-       bne     2b                      ! Nope...
-#endif
-        ld     [%g1], %g7
-       xor     %g7, %g2, %g5
-       and     %g7, %g2, %g2
-#ifdef CONFIG_SMP
-       st      %g5, [%g1]
-       set     bitops_spinlock, %g5
-       stb     %g0, [%g5]
-#else
-       st      %g5, [%g1]
-#endif
-       wr      %g3, 0x0, %psr
-       nop; nop; nop
-       jmpl    %o7, %g0
-        mov    %g4, %o7
-
-       .globl  __bitops_end
-__bitops_end:
index 04aa331..329e696 100644 (file)
 
 #ifdef __KERNEL__
 
+extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
+extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
+extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask);
+
 /*
  * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
  * is in the highest of the four bytes and bit '31' is the high bit
  */
 static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       register unsigned long mask asm("g2");
-       register unsigned long *ADDR asm("g1");
-       register int tmp1 asm("g3");
-       register int tmp2 asm("g4");
-       register int tmp3 asm("g5");
-       register int tmp4 asm("g7");
+       unsigned long *ADDR, mask;
 
        ADDR = ((unsigned long *) addr) + (nr >> 5);
        mask = 1 << (nr & 31);
 
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___set_bit\n\t"
-       " add   %%o7, 8, %%o7\n"
-       : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
-       : "0" (mask), "r" (ADDR)
-       : "memory", "cc");
-
-       return mask != 0;
+       return ___set_bit(ADDR, mask) != 0;
 }
 
 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       register unsigned long mask asm("g2");
-       register unsigned long *ADDR asm("g1");
-       register int tmp1 asm("g3");
-       register int tmp2 asm("g4");
-       register int tmp3 asm("g5");
-       register int tmp4 asm("g7");
+       unsigned long *ADDR, mask;
 
        ADDR = ((unsigned long *) addr) + (nr >> 5);
        mask = 1 << (nr & 31);
 
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___set_bit\n\t"
-       " add   %%o7, 8, %%o7\n"
-       : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
-       : "0" (mask), "r" (ADDR)
-       : "memory", "cc");
+       (void) ___set_bit(ADDR, mask);
 }
 
 static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       register unsigned long mask asm("g2");
-       register unsigned long *ADDR asm("g1");
-       register int tmp1 asm("g3");
-       register int tmp2 asm("g4");
-       register int tmp3 asm("g5");
-       register int tmp4 asm("g7");
+       unsigned long *ADDR, mask;
 
        ADDR = ((unsigned long *) addr) + (nr >> 5);
        mask = 1 << (nr & 31);
 
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___clear_bit\n\t"
-       " add   %%o7, 8, %%o7\n"
-       : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
-       : "0" (mask), "r" (ADDR)
-       : "memory", "cc");
-
-       return mask != 0;
+       return ___clear_bit(ADDR, mask) != 0;
 }
 
 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       register unsigned long mask asm("g2");
-       register unsigned long *ADDR asm("g1");
-       register int tmp1 asm("g3");
-       register int tmp2 asm("g4");
-       register int tmp3 asm("g5");
-       register int tmp4 asm("g7");
+       unsigned long *ADDR, mask;
 
        ADDR = ((unsigned long *) addr) + (nr >> 5);
        mask = 1 << (nr & 31);
 
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___clear_bit\n\t"
-       " add   %%o7, 8, %%o7\n"
-       : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
-       : "0" (mask), "r" (ADDR)
-       : "memory", "cc");
+       (void) ___clear_bit(ADDR, mask);
 }
 
 static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       register unsigned long mask asm("g2");
-       register unsigned long *ADDR asm("g1");
-       register int tmp1 asm("g3");
-       register int tmp2 asm("g4");
-       register int tmp3 asm("g5");
-       register int tmp4 asm("g7");
+       unsigned long *ADDR, mask;
 
        ADDR = ((unsigned long *) addr) + (nr >> 5);
        mask = 1 << (nr & 31);
 
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___change_bit\n\t"
-       " add   %%o7, 8, %%o7\n"
-       : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
-       : "0" (mask), "r" (ADDR)
-       : "memory", "cc");
-
-       return mask != 0;
+       return ___change_bit(ADDR, mask) != 0;
 }
 
 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       register unsigned long mask asm("g2");
-       register unsigned long *ADDR asm("g1");
-       register int tmp1 asm("g3");
-       register int tmp2 asm("g4");
-       register int tmp3 asm("g5");
-       register int tmp4 asm("g7");
+       unsigned long *ADDR, mask;
 
        ADDR = ((unsigned long *) addr) + (nr >> 5);
        mask = 1 << (nr & 31);
 
-       __asm__ __volatile__(
-       "mov    %%o7, %%g4\n\t"
-       "call   ___change_bit\n\t"
-       " add   %%o7, 8, %%o7\n"
-       : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
-       : "0" (mask), "r" (ADDR)
-       : "memory", "cc");
+       (void) ___change_bit(ADDR, mask);
 }
 
 #include <asm-generic/bitops/non-atomic.h>