diff options
author | Mathieu Desnoyers <compudj@krystal.dyndns.org> | 2008-02-08 18:00:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 18:33:32 -0500 |
commit | 6784fd5931a58559673f500a333030ceaadb69bb (patch) | |
tree | 911673988500ab7c923b210220a462286741c485 /include/asm-frv/bitops.h | |
parent | b55fcb22d445a7460cbbc138ceae096d5617715a (diff) |
Fix FRV cmpxchg_local
Fix the FRV cmpxchg_local by breaking the following header dependency loop :
linux/kernel.h -> linux/bitops.h -> asm-frv/bitops.h -> asm-frv/atomic.h
-> asm-frv/system.h ->
asm-generic/cmpxchg_local.h -> typecheck() defined in linux/kernel.h
and
linux/kernel.h -> linux/bitops.h -> asm-frv/bitops.h -> asm-frv/atomic.h ->
asm-generic/cmpxchg_local.h -> typecheck() defined in linux/kernel.h
In order to fix this :
- Move the atomic_test_and_ *_mask inlines from asm-frv/atomic.h (why are they
there at all anyway ? They are not touching atomic_t variables!) to
asm-frv/bitops.h.
Also fix a build issue with cmpxchg : it does not cast to (unsigned long *)
like other architectures, to deal with it in the cmpxchg_local macro.
FRV builds fine with this patch.
Thanks to Adrian Bunk <bunk@kernel.org> for spotting this bug.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Adrian Bunk <bunk@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/asm-frv/bitops.h')
-rw-r--r-- | include/asm-frv/bitops.h | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h index 5f86b876b298..39456ba0ec17 100644 --- a/include/asm-frv/bitops.h +++ b/include/asm-frv/bitops.h | |||
@@ -16,8 +16,6 @@ | |||
16 | 16 | ||
17 | #include <linux/compiler.h> | 17 | #include <linux/compiler.h> |
18 | #include <asm/byteorder.h> | 18 | #include <asm/byteorder.h> |
19 | #include <asm/system.h> | ||
20 | #include <asm/atomic.h> | ||
21 | 19 | ||
22 | #ifdef __KERNEL__ | 20 | #ifdef __KERNEL__ |
23 | 21 | ||
@@ -33,6 +31,87 @@ | |||
33 | #define smp_mb__before_clear_bit() barrier() | 31 | #define smp_mb__before_clear_bit() barrier() |
34 | #define smp_mb__after_clear_bit() barrier() | 32 | #define smp_mb__after_clear_bit() barrier() |
35 | 33 | ||
34 | #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS | ||
35 | static inline | ||
36 | unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v) | ||
37 | { | ||
38 | unsigned long old, tmp; | ||
39 | |||
40 | asm volatile( | ||
41 | "0: \n" | ||
42 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
43 | " ckeq icc3,cc7 \n" | ||
44 | " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */ | ||
45 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
46 | " and%I3 %1,%3,%2 \n" | ||
47 | " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */ | ||
48 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */ | ||
49 | " beq icc3,#0,0b \n" | ||
50 | : "+U"(*v), "=&r"(old), "=r"(tmp) | ||
51 | : "NPr"(~mask) | ||
52 | : "memory", "cc7", "cc3", "icc3" | ||
53 | ); | ||
54 | |||
55 | return old; | ||
56 | } | ||
57 | |||
58 | static inline | ||
59 | unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v) | ||
60 | { | ||
61 | unsigned long old, tmp; | ||
62 | |||
63 | asm volatile( | ||
64 | "0: \n" | ||
65 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
66 | " ckeq icc3,cc7 \n" | ||
67 | " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */ | ||
68 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
69 | " or%I3 %1,%3,%2 \n" | ||
70 | " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */ | ||
71 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */ | ||
72 | " beq icc3,#0,0b \n" | ||
73 | : "+U"(*v), "=&r"(old), "=r"(tmp) | ||
74 | : "NPr"(mask) | ||
75 | : "memory", "cc7", "cc3", "icc3" | ||
76 | ); | ||
77 | |||
78 | return old; | ||
79 | } | ||
80 | |||
81 | static inline | ||
82 | unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v) | ||
83 | { | ||
84 | unsigned long old, tmp; | ||
85 | |||
86 | asm volatile( | ||
87 | "0: \n" | ||
88 | " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ | ||
89 | " ckeq icc3,cc7 \n" | ||
90 | " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */ | ||
91 | " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ | ||
92 | " xor%I3 %1,%3,%2 \n" | ||
93 | " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */ | ||
94 | " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */ | ||
95 | " beq icc3,#0,0b \n" | ||
96 | : "+U"(*v), "=&r"(old), "=r"(tmp) | ||
97 | : "NPr"(mask) | ||
98 | : "memory", "cc7", "cc3", "icc3" | ||
99 | ); | ||
100 | |||
101 | return old; | ||
102 | } | ||
103 | |||
104 | #else | ||
105 | |||
106 | extern unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v); | ||
107 | extern unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v); | ||
108 | extern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v); | ||
109 | |||
110 | #endif | ||
111 | |||
112 | #define atomic_clear_mask(mask, v) atomic_test_and_ANDNOT_mask((mask), (v)) | ||
113 | #define atomic_set_mask(mask, v) atomic_test_and_OR_mask((mask), (v)) | ||
114 | |||
36 | static inline int test_and_clear_bit(int nr, volatile void *addr) | 115 | static inline int test_and_clear_bit(int nr, volatile void *addr) |
37 | { | 116 | { |
38 | volatile unsigned long *ptr = addr; | 117 | volatile unsigned long *ptr = addr; |