diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-12-17 19:18:47 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-17 19:18:47 -0500 |
| commit | 8a8b836b91aa170a383f2f360b73d3d23160d9d7 (patch) | |
| tree | 875a635f634a869b801c4efa8f145c5b7b7db8e4 /arch | |
| parent | 216da721b881838d639a3987bf8a825e6b4aacdd (diff) | |
[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>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/sparc/kernel/sparc_ksyms.c | 8 | ||||
| -rw-r--r-- | arch/sparc/kernel/time.c | 5 | ||||
| -rw-r--r-- | arch/sparc/lib/Makefile | 4 | ||||
| -rw-r--r-- | arch/sparc/lib/atomic32.c | 39 | ||||
| -rw-r--r-- | arch/sparc/lib/bitops.S | 109 |
5 files changed, 42 insertions, 123 deletions
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 33dadd9f2871..d8e008a04e2b 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c | |||
| @@ -83,9 +83,6 @@ extern int __divdi3(int, int); | |||
| 83 | /* Private functions with odd calling conventions. */ | 83 | /* Private functions with odd calling conventions. */ |
| 84 | extern void ___atomic24_add(void); | 84 | extern void ___atomic24_add(void); |
| 85 | extern void ___atomic24_sub(void); | 85 | extern void ___atomic24_sub(void); |
| 86 | extern void ___set_bit(void); | ||
| 87 | extern void ___clear_bit(void); | ||
| 88 | extern void ___change_bit(void); | ||
| 89 | extern void ___rw_read_enter(void); | 86 | extern void ___rw_read_enter(void); |
| 90 | extern void ___rw_read_try(void); | 87 | extern void ___rw_read_try(void); |
| 91 | extern void ___rw_read_exit(void); | 88 | extern void ___rw_read_exit(void); |
| @@ -125,11 +122,6 @@ EXPORT_SYMBOL(pfn_base); | |||
| 125 | EXPORT_SYMBOL(___atomic24_add); | 122 | EXPORT_SYMBOL(___atomic24_add); |
| 126 | EXPORT_SYMBOL(___atomic24_sub); | 123 | EXPORT_SYMBOL(___atomic24_sub); |
| 127 | 124 | ||
| 128 | /* Bit operations. */ | ||
| 129 | EXPORT_SYMBOL(___set_bit); | ||
| 130 | EXPORT_SYMBOL(___clear_bit); | ||
| 131 | EXPORT_SYMBOL(___change_bit); | ||
| 132 | |||
| 133 | /* Per-CPU information table */ | 125 | /* Per-CPU information table */ |
| 134 | EXPORT_PER_CPU_SYMBOL(__cpu_data); | 126 | EXPORT_PER_CPU_SYMBOL(__cpu_data); |
| 135 | 127 | ||
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 6c7aa51b590f..2fcce000d877 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c | |||
| @@ -78,7 +78,6 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
| 78 | extern char __copy_user_begin[], __copy_user_end[]; | 78 | extern char __copy_user_begin[], __copy_user_end[]; |
| 79 | extern char __atomic_begin[], __atomic_end[]; | 79 | extern char __atomic_begin[], __atomic_end[]; |
| 80 | extern char __bzero_begin[], __bzero_end[]; | 80 | extern char __bzero_begin[], __bzero_end[]; |
| 81 | extern char __bitops_begin[], __bitops_end[]; | ||
| 82 | 81 | ||
| 83 | unsigned long pc = regs->pc; | 82 | unsigned long pc = regs->pc; |
| 84 | 83 | ||
| @@ -88,9 +87,7 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
| 88 | (pc >= (unsigned long) __atomic_begin && | 87 | (pc >= (unsigned long) __atomic_begin && |
| 89 | pc < (unsigned long) __atomic_end) || | 88 | pc < (unsigned long) __atomic_end) || |
| 90 | (pc >= (unsigned long) __bzero_begin && | 89 | (pc >= (unsigned long) __bzero_begin && |
| 91 | pc < (unsigned long) __bzero_end) || | 90 | pc < (unsigned long) __bzero_end)) |
| 92 | (pc >= (unsigned long) __bitops_begin && | ||
| 93 | pc < (unsigned long) __bitops_end)) | ||
| 94 | pc = regs->u_regs[UREG_RETPC]; | 91 | pc = regs->u_regs[UREG_RETPC]; |
| 95 | return pc; | 92 | return pc; |
| 96 | } | 93 | } |
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 5db7e1d85385..9ddc5b9ce3bd 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile | |||
| @@ -7,7 +7,7 @@ EXTRA_AFLAGS := -ansi -DST_DIV0=0x02 | |||
| 7 | lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ | 7 | lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ |
| 8 | strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ | 8 | strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ |
| 9 | strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ | 9 | strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ |
| 10 | copy_user.o locks.o atomic.o atomic32.o bitops.o \ | 10 | copy_user.o locks.o atomic.o \ |
| 11 | lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o | 11 | lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o |
| 12 | 12 | ||
| 13 | obj-y += iomap.o | 13 | obj-y += iomap.o atomic32.o |
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index de84f8534bac..53ddcd9d1e60 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c | |||
| @@ -76,3 +76,42 @@ void atomic_set(atomic_t *v, int i) | |||
| 76 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | 76 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); |
| 77 | } | 77 | } |
| 78 | EXPORT_SYMBOL(atomic_set); | 78 | EXPORT_SYMBOL(atomic_set); |
| 79 | |||
| 80 | unsigned long ___set_bit(unsigned long *addr, unsigned long mask) | ||
| 81 | { | ||
| 82 | unsigned long old, flags; | ||
| 83 | |||
| 84 | spin_lock_irqsave(ATOMIC_HASH(addr), flags); | ||
| 85 | old = *addr; | ||
| 86 | *addr = old | mask; | ||
| 87 | spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); | ||
| 88 | |||
| 89 | return old & mask; | ||
| 90 | } | ||
| 91 | EXPORT_SYMBOL(___set_bit); | ||
| 92 | |||
| 93 | unsigned long ___clear_bit(unsigned long *addr, unsigned long mask) | ||
| 94 | { | ||
| 95 | unsigned long old, flags; | ||
| 96 | |||
| 97 | spin_lock_irqsave(ATOMIC_HASH(addr), flags); | ||
| 98 | old = *addr; | ||
| 99 | *addr = old & ~mask; | ||
| 100 | spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); | ||
| 101 | |||
| 102 | return old & mask; | ||
| 103 | } | ||
| 104 | EXPORT_SYMBOL(___clear_bit); | ||
| 105 | |||
| 106 | unsigned long ___change_bit(unsigned long *addr, unsigned long mask) | ||
| 107 | { | ||
| 108 | unsigned long old, flags; | ||
| 109 | |||
| 110 | spin_lock_irqsave(ATOMIC_HASH(addr), flags); | ||
| 111 | old = *addr; | ||
| 112 | *addr = old ^ mask; | ||
| 113 | spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); | ||
| 114 | |||
| 115 | return old & mask; | ||
| 116 | } | ||
| 117 | EXPORT_SYMBOL(___change_bit); | ||
diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S deleted file mode 100644 index cb7fb66a40c8..000000000000 --- a/arch/sparc/lib/bitops.S +++ /dev/null | |||
| @@ -1,109 +0,0 @@ | |||
| 1 | /* bitops.S: Low level assembler bit operations. | ||
| 2 | * | ||
| 3 | * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <asm/ptrace.h> | ||
| 7 | #include <asm/psr.h> | ||
| 8 | |||
| 9 | .text | ||
| 10 | .align 4 | ||
| 11 | |||
| 12 | .globl __bitops_begin | ||
| 13 | __bitops_begin: | ||
| 14 | |||
| 15 | /* Take bits in %g2 and set them in word at %g1, | ||
| 16 | * return whether bits were set in original value | ||
| 17 | * in %g2. %g4 holds value to restore into %o7 | ||
| 18 | * in delay slot of jmpl return, %g3 + %g5 + %g7 can be | ||
| 19 | * used as temporaries and thus is considered clobbered | ||
| 20 | * by all callers. | ||
| 21 | */ | ||
| 22 | .globl ___set_bit | ||
| 23 | ___set_bit: | ||
| 24 | rd %psr, %g3 | ||
| 25 | nop; nop; nop; | ||
| 26 | or %g3, PSR_PIL, %g5 | ||
| 27 | wr %g5, 0x0, %psr | ||
| 28 | nop; nop; nop | ||
| 29 | #ifdef CONFIG_SMP | ||
| 30 | set bitops_spinlock, %g5 | ||
| 31 | 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. | ||
| 32 | orcc %g7, 0x0, %g0 ! Did we get it? | ||
| 33 | bne 2b ! Nope... | ||
| 34 | #endif | ||
| 35 | ld [%g1], %g7 | ||
| 36 | or %g7, %g2, %g5 | ||
| 37 | and %g7, %g2, %g2 | ||
| 38 | #ifdef CONFIG_SMP | ||
| 39 | st %g5, [%g1] | ||
| 40 | set bitops_spinlock, %g5 | ||
| 41 | stb %g0, [%g5] | ||
| 42 | #else | ||
| 43 | st %g5, [%g1] | ||
| 44 | #endif | ||
| 45 | wr %g3, 0x0, %psr | ||
| 46 | nop; nop; nop | ||
| 47 | jmpl %o7, %g0 | ||
| 48 | mov %g4, %o7 | ||
| 49 | |||
| 50 | /* Same as above, but clears the bits from %g2 instead. */ | ||
| 51 | .globl ___clear_bit | ||
| 52 | ___clear_bit: | ||
| 53 | rd %psr, %g3 | ||
| 54 | nop; nop; nop | ||
| 55 | or %g3, PSR_PIL, %g5 | ||
| 56 | wr %g5, 0x0, %psr | ||
| 57 | nop; nop; nop | ||
| 58 | #ifdef CONFIG_SMP | ||
| 59 | set bitops_spinlock, %g5 | ||
| 60 | 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. | ||
| 61 | orcc %g7, 0x0, %g0 ! Did we get it? | ||
| 62 | bne 2b ! Nope... | ||
| 63 | #endif | ||
| 64 | ld [%g1], %g7 | ||
| 65 | andn %g7, %g2, %g5 | ||
| 66 | and %g7, %g2, %g2 | ||
| 67 | #ifdef CONFIG_SMP | ||
| 68 | st %g5, [%g1] | ||
| 69 | set bitops_spinlock, %g5 | ||
| 70 | stb %g0, [%g5] | ||
| 71 | #else | ||
| 72 | st %g5, [%g1] | ||
| 73 | #endif | ||
| 74 | wr %g3, 0x0, %psr | ||
| 75 | nop; nop; nop | ||
| 76 | jmpl %o7, %g0 | ||
| 77 | mov %g4, %o7 | ||
| 78 | |||
| 79 | /* Same thing again, but this time toggles the bits from %g2. */ | ||
| 80 | .globl ___change_bit | ||
| 81 | ___change_bit: | ||
| 82 | rd %psr, %g3 | ||
| 83 | nop; nop; nop | ||
| 84 | or %g3, PSR_PIL, %g5 | ||
| 85 | wr %g5, 0x0, %psr | ||
| 86 | nop; nop; nop | ||
| 87 | #ifdef CONFIG_SMP | ||
| 88 | set bitops_spinlock, %g5 | ||
| 89 | 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. | ||
| 90 | orcc %g7, 0x0, %g0 ! Did we get it? | ||
| 91 | bne 2b ! Nope... | ||
| 92 | #endif | ||
| 93 | ld [%g1], %g7 | ||
| 94 | xor %g7, %g2, %g5 | ||
| 95 | and %g7, %g2, %g2 | ||
| 96 | #ifdef CONFIG_SMP | ||
| 97 | st %g5, [%g1] | ||
| 98 | set bitops_spinlock, %g5 | ||
| 99 | stb %g0, [%g5] | ||
| 100 | #else | ||
| 101 | st %g5, [%g1] | ||
| 102 | #endif | ||
| 103 | wr %g3, 0x0, %psr | ||
| 104 | nop; nop; nop | ||
| 105 | jmpl %o7, %g0 | ||
| 106 | mov %g4, %o7 | ||
| 107 | |||
| 108 | .globl __bitops_end | ||
| 109 | __bitops_end: | ||
