Преглед на файлове

[SPARC]: Make bitops use same spinlocks as atomics.

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>
David S. Miller преди 18 години
родител
ревизия
8a8b836b91
променени са 6 файла, в които са добавени 58 реда и са изтрити 207 реда
  1. 0 8
      arch/sparc/kernel/sparc_ksyms.c
  2. 1 4
      arch/sparc/kernel/time.c
  3. 2 2
      arch/sparc/lib/Makefile
  4. 39 0
      arch/sparc/lib/atomic32.c
  5. 0 109
      arch/sparc/lib/bitops.S
  6. 16 84
      include/asm-sparc/bitops.h

+ 0 - 8
arch/sparc/kernel/sparc_ksyms.c

@@ -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);
 

+ 1 - 4
arch/sparc/kernel/time.c

@@ -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;
 }

+ 2 - 2
arch/sparc/lib/Makefile

@@ -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

+ 39 - 0
arch/sparc/lib/atomic32.c

@@ -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);

+ 0 - 109
arch/sparc/lib/bitops.S

@@ -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:

+ 16 - 84
include/asm-sparc/bitops.h

@@ -14,6 +14,10 @@
 
 #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
@@ -22,134 +26,62 @@
  */
 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>