diff options
author | Graf Yang <graf.yang@analog.com> | 2009-01-07 10:14:39 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 10:14:39 -0500 |
commit | 6b3087c64a92a36ae20d33479b4df6d7afc910d4 (patch) | |
tree | 95984fc623658ebf150d0d912a7f6c5a0301a5a9 /arch/blackfin/include | |
parent | c51b4488cd5bff08ed5690a8f303ff7f0894da2a (diff) |
Blackfin arch: SMP supporting patchset: Blackfin header files and machine common code
Blackfin dual core BF561 processor can support SMP like features.
https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like
In this patch, we provide SMP extend to Blackfin header files
and machine common code
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/include')
-rw-r--r-- | arch/blackfin/include/asm/atomic.h | 119 | ||||
-rw-r--r-- | arch/blackfin/include/asm/bfin-global.h | 5 | ||||
-rw-r--r-- | arch/blackfin/include/asm/bitops.h | 189 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cache.h | 29 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cacheflush.h | 20 | ||||
-rw-r--r-- | arch/blackfin/include/asm/context.S | 6 | ||||
-rw-r--r-- | arch/blackfin/include/asm/cpu.h | 42 | ||||
-rw-r--r-- | arch/blackfin/include/asm/l1layout.h | 3 | ||||
-rw-r--r-- | arch/blackfin/include/asm/mutex-dec.h | 112 | ||||
-rw-r--r-- | arch/blackfin/include/asm/mutex.h | 63 | ||||
-rw-r--r-- | arch/blackfin/include/asm/pda.h | 70 | ||||
-rw-r--r-- | arch/blackfin/include/asm/percpu.h | 12 | ||||
-rw-r--r-- | arch/blackfin/include/asm/processor.h | 7 | ||||
-rw-r--r-- | arch/blackfin/include/asm/rwlock.h | 6 | ||||
-rw-r--r-- | arch/blackfin/include/asm/smp.h | 42 | ||||
-rw-r--r-- | arch/blackfin/include/asm/spinlock.h | 87 | ||||
-rw-r--r-- | arch/blackfin/include/asm/spinlock_types.h | 22 | ||||
-rw-r--r-- | arch/blackfin/include/asm/system.h | 116 |
18 files changed, 829 insertions, 121 deletions
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h index 25776c19064b..d76275e5638c 100644 --- a/arch/blackfin/include/asm/atomic.h +++ b/arch/blackfin/include/asm/atomic.h | |||
@@ -15,11 +15,80 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define ATOMIC_INIT(i) { (i) } | 17 | #define ATOMIC_INIT(i) { (i) } |
18 | |||
19 | #define atomic_read(v) ((v)->counter) | ||
20 | #define atomic_set(v, i) (((v)->counter) = i) | 18 | #define atomic_set(v, i) (((v)->counter) = i) |
21 | 19 | ||
22 | static __inline__ void atomic_add(int i, atomic_t * v) | 20 | #ifdef CONFIG_SMP |
21 | |||
22 | #define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter) | ||
23 | |||
24 | asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr); | ||
25 | |||
26 | asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value); | ||
27 | |||
28 | asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value); | ||
29 | |||
30 | asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value); | ||
31 | |||
32 | asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value); | ||
33 | |||
34 | asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value); | ||
35 | |||
36 | static inline void atomic_add(int i, atomic_t *v) | ||
37 | { | ||
38 | __raw_atomic_update_asm(&v->counter, i); | ||
39 | } | ||
40 | |||
41 | static inline void atomic_sub(int i, atomic_t *v) | ||
42 | { | ||
43 | __raw_atomic_update_asm(&v->counter, -i); | ||
44 | } | ||
45 | |||
46 | static inline int atomic_add_return(int i, atomic_t *v) | ||
47 | { | ||
48 | return __raw_atomic_update_asm(&v->counter, i); | ||
49 | } | ||
50 | |||
51 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
52 | { | ||
53 | return __raw_atomic_update_asm(&v->counter, -i); | ||
54 | } | ||
55 | |||
56 | static inline void atomic_inc(volatile atomic_t *v) | ||
57 | { | ||
58 | __raw_atomic_update_asm(&v->counter, 1); | ||
59 | } | ||
60 | |||
61 | static inline void atomic_dec(volatile atomic_t *v) | ||
62 | { | ||
63 | __raw_atomic_update_asm(&v->counter, -1); | ||
64 | } | ||
65 | |||
66 | static inline void atomic_clear_mask(int mask, atomic_t *v) | ||
67 | { | ||
68 | __raw_atomic_clear_asm(&v->counter, mask); | ||
69 | } | ||
70 | |||
71 | static inline void atomic_set_mask(int mask, atomic_t *v) | ||
72 | { | ||
73 | __raw_atomic_set_asm(&v->counter, mask); | ||
74 | } | ||
75 | |||
76 | static inline int atomic_test_mask(int mask, atomic_t *v) | ||
77 | { | ||
78 | return __raw_atomic_test_asm(&v->counter, mask); | ||
79 | } | ||
80 | |||
81 | /* Atomic operations are already serializing */ | ||
82 | #define smp_mb__before_atomic_dec() barrier() | ||
83 | #define smp_mb__after_atomic_dec() barrier() | ||
84 | #define smp_mb__before_atomic_inc() barrier() | ||
85 | #define smp_mb__after_atomic_inc() barrier() | ||
86 | |||
87 | #else /* !CONFIG_SMP */ | ||
88 | |||
89 | #define atomic_read(v) ((v)->counter) | ||
90 | |||
91 | static inline void atomic_add(int i, atomic_t *v) | ||
23 | { | 92 | { |
24 | long flags; | 93 | long flags; |
25 | 94 | ||
@@ -28,7 +97,7 @@ static __inline__ void atomic_add(int i, atomic_t * v) | |||
28 | local_irq_restore(flags); | 97 | local_irq_restore(flags); |
29 | } | 98 | } |
30 | 99 | ||
31 | static __inline__ void atomic_sub(int i, atomic_t * v) | 100 | static inline void atomic_sub(int i, atomic_t *v) |
32 | { | 101 | { |
33 | long flags; | 102 | long flags; |
34 | 103 | ||
@@ -38,7 +107,7 @@ static __inline__ void atomic_sub(int i, atomic_t * v) | |||
38 | 107 | ||
39 | } | 108 | } |
40 | 109 | ||
41 | static inline int atomic_add_return(int i, atomic_t * v) | 110 | static inline int atomic_add_return(int i, atomic_t *v) |
42 | { | 111 | { |
43 | int __temp = 0; | 112 | int __temp = 0; |
44 | long flags; | 113 | long flags; |
@@ -52,8 +121,7 @@ static inline int atomic_add_return(int i, atomic_t * v) | |||
52 | return __temp; | 121 | return __temp; |
53 | } | 122 | } |
54 | 123 | ||
55 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) | 124 | static inline int atomic_sub_return(int i, atomic_t *v) |
56 | static inline int atomic_sub_return(int i, atomic_t * v) | ||
57 | { | 125 | { |
58 | int __temp = 0; | 126 | int __temp = 0; |
59 | long flags; | 127 | long flags; |
@@ -66,7 +134,7 @@ static inline int atomic_sub_return(int i, atomic_t * v) | |||
66 | return __temp; | 134 | return __temp; |
67 | } | 135 | } |
68 | 136 | ||
69 | static __inline__ void atomic_inc(volatile atomic_t * v) | 137 | static inline void atomic_inc(volatile atomic_t *v) |
70 | { | 138 | { |
71 | long flags; | 139 | long flags; |
72 | 140 | ||
@@ -75,20 +143,7 @@ static __inline__ void atomic_inc(volatile atomic_t * v) | |||
75 | local_irq_restore(flags); | 143 | local_irq_restore(flags); |
76 | } | 144 | } |
77 | 145 | ||
78 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | 146 | static inline void atomic_dec(volatile atomic_t *v) |
79 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | ||
80 | |||
81 | #define atomic_add_unless(v, a, u) \ | ||
82 | ({ \ | ||
83 | int c, old; \ | ||
84 | c = atomic_read(v); \ | ||
85 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
86 | c = old; \ | ||
87 | c != (u); \ | ||
88 | }) | ||
89 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
90 | |||
91 | static __inline__ void atomic_dec(volatile atomic_t * v) | ||
92 | { | 147 | { |
93 | long flags; | 148 | long flags; |
94 | 149 | ||
@@ -97,7 +152,7 @@ static __inline__ void atomic_dec(volatile atomic_t * v) | |||
97 | local_irq_restore(flags); | 152 | local_irq_restore(flags); |
98 | } | 153 | } |
99 | 154 | ||
100 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t * v) | 155 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
101 | { | 156 | { |
102 | long flags; | 157 | long flags; |
103 | 158 | ||
@@ -106,7 +161,7 @@ static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t * v) | |||
106 | local_irq_restore(flags); | 161 | local_irq_restore(flags); |
107 | } | 162 | } |
108 | 163 | ||
109 | static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v) | 164 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) |
110 | { | 165 | { |
111 | long flags; | 166 | long flags; |
112 | 167 | ||
@@ -121,9 +176,25 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v) | |||
121 | #define smp_mb__before_atomic_inc() barrier() | 176 | #define smp_mb__before_atomic_inc() barrier() |
122 | #define smp_mb__after_atomic_inc() barrier() | 177 | #define smp_mb__after_atomic_inc() barrier() |
123 | 178 | ||
179 | #endif /* !CONFIG_SMP */ | ||
180 | |||
181 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) | ||
124 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 182 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
125 | #define atomic_inc_return(v) atomic_add_return(1,(v)) | 183 | #define atomic_inc_return(v) atomic_add_return(1,(v)) |
126 | 184 | ||
185 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
186 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | ||
187 | |||
188 | #define atomic_add_unless(v, a, u) \ | ||
189 | ({ \ | ||
190 | int c, old; \ | ||
191 | c = atomic_read(v); \ | ||
192 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
193 | c = old; \ | ||
194 | c != (u); \ | ||
195 | }) | ||
196 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
197 | |||
127 | /* | 198 | /* |
128 | * atomic_inc_and_test - increment and test | 199 | * atomic_inc_and_test - increment and test |
129 | * @v: pointer of type atomic_t | 200 | * @v: pointer of type atomic_t |
diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index 77295666c34b..1dd08058bc90 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h | |||
@@ -47,6 +47,9 @@ | |||
47 | # define DMA_UNCACHED_REGION (0) | 47 | # define DMA_UNCACHED_REGION (0) |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | extern void bfin_setup_caches(unsigned int cpu); | ||
51 | extern void bfin_setup_cpudata(unsigned int cpu); | ||
52 | |||
50 | extern unsigned long get_cclk(void); | 53 | extern unsigned long get_cclk(void); |
51 | extern unsigned long get_sclk(void); | 54 | extern unsigned long get_sclk(void); |
52 | extern unsigned long sclk_to_usecs(unsigned long sclk); | 55 | extern unsigned long sclk_to_usecs(unsigned long sclk); |
@@ -58,8 +61,6 @@ extern void dump_bfin_trace_buffer(void); | |||
58 | 61 | ||
59 | /* init functions only */ | 62 | /* init functions only */ |
60 | extern int init_arch_irq(void); | 63 | extern int init_arch_irq(void); |
61 | extern void bfin_icache_init(void); | ||
62 | extern void bfin_dcache_init(void); | ||
63 | extern void init_exception_vectors(void); | 64 | extern void init_exception_vectors(void); |
64 | extern void program_IAR(void); | 65 | extern void program_IAR(void); |
65 | 66 | ||
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h index c428e4106f89..9964e17232e9 100644 --- a/arch/blackfin/include/asm/bitops.h +++ b/arch/blackfin/include/asm/bitops.h | |||
@@ -7,7 +7,6 @@ | |||
7 | 7 | ||
8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
9 | #include <asm/byteorder.h> /* swab32 */ | 9 | #include <asm/byteorder.h> /* swab32 */ |
10 | #include <asm/system.h> /* save_flags */ | ||
11 | 10 | ||
12 | #ifdef __KERNEL__ | 11 | #ifdef __KERNEL__ |
13 | 12 | ||
@@ -20,36 +19,71 @@ | |||
20 | #include <asm-generic/bitops/sched.h> | 19 | #include <asm-generic/bitops/sched.h> |
21 | #include <asm-generic/bitops/ffz.h> | 20 | #include <asm-generic/bitops/ffz.h> |
22 | 21 | ||
23 | static __inline__ void set_bit(int nr, volatile unsigned long *addr) | 22 | #ifdef CONFIG_SMP |
23 | |||
24 | #include <linux/linkage.h> | ||
25 | |||
26 | asmlinkage int __raw_bit_set_asm(volatile unsigned long *addr, int nr); | ||
27 | |||
28 | asmlinkage int __raw_bit_clear_asm(volatile unsigned long *addr, int nr); | ||
29 | |||
30 | asmlinkage int __raw_bit_toggle_asm(volatile unsigned long *addr, int nr); | ||
31 | |||
32 | asmlinkage int __raw_bit_test_set_asm(volatile unsigned long *addr, int nr); | ||
33 | |||
34 | asmlinkage int __raw_bit_test_clear_asm(volatile unsigned long *addr, int nr); | ||
35 | |||
36 | asmlinkage int __raw_bit_test_toggle_asm(volatile unsigned long *addr, int nr); | ||
37 | |||
38 | asmlinkage int __raw_bit_test_asm(const volatile unsigned long *addr, int nr); | ||
39 | |||
40 | static inline void set_bit(int nr, volatile unsigned long *addr) | ||
24 | { | 41 | { |
25 | int *a = (int *)addr; | 42 | volatile unsigned long *a = addr + (nr >> 5); |
26 | int mask; | 43 | __raw_bit_set_asm(a, nr & 0x1f); |
27 | unsigned long flags; | 44 | } |
28 | 45 | ||
29 | a += nr >> 5; | 46 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
30 | mask = 1 << (nr & 0x1f); | 47 | { |
31 | local_irq_save(flags); | 48 | volatile unsigned long *a = addr + (nr >> 5); |
32 | *a |= mask; | 49 | __raw_bit_clear_asm(a, nr & 0x1f); |
33 | local_irq_restore(flags); | ||
34 | } | 50 | } |
35 | 51 | ||
36 | static __inline__ void __set_bit(int nr, volatile unsigned long *addr) | 52 | static inline void change_bit(int nr, volatile unsigned long *addr) |
37 | { | 53 | { |
38 | int *a = (int *)addr; | 54 | volatile unsigned long *a = addr + (nr >> 5); |
39 | int mask; | 55 | __raw_bit_toggle_asm(a, nr & 0x1f); |
56 | } | ||
40 | 57 | ||
41 | a += nr >> 5; | 58 | static inline int test_bit(int nr, const volatile unsigned long *addr) |
42 | mask = 1 << (nr & 0x1f); | 59 | { |
43 | *a |= mask; | 60 | volatile const unsigned long *a = addr + (nr >> 5); |
61 | return __raw_bit_test_asm(a, nr & 0x1f) != 0; | ||
44 | } | 62 | } |
45 | 63 | ||
46 | /* | 64 | static inline int test_and_set_bit(int nr, volatile unsigned long *addr) |
47 | * clear_bit() doesn't provide any barrier for the compiler. | 65 | { |
48 | */ | 66 | volatile unsigned long *a = addr + (nr >> 5); |
49 | #define smp_mb__before_clear_bit() barrier() | 67 | return __raw_bit_test_set_asm(a, nr & 0x1f); |
50 | #define smp_mb__after_clear_bit() barrier() | 68 | } |
51 | 69 | ||
52 | static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | 70 | static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) |
71 | { | ||
72 | volatile unsigned long *a = addr + (nr >> 5); | ||
73 | return __raw_bit_test_clear_asm(a, nr & 0x1f); | ||
74 | } | ||
75 | |||
76 | static inline int test_and_change_bit(int nr, volatile unsigned long *addr) | ||
77 | { | ||
78 | volatile unsigned long *a = addr + (nr >> 5); | ||
79 | return __raw_bit_test_toggle_asm(a, nr & 0x1f); | ||
80 | } | ||
81 | |||
82 | #else /* !CONFIG_SMP */ | ||
83 | |||
84 | #include <asm/system.h> /* save_flags */ | ||
85 | |||
86 | static inline void set_bit(int nr, volatile unsigned long *addr) | ||
53 | { | 87 | { |
54 | int *a = (int *)addr; | 88 | int *a = (int *)addr; |
55 | int mask; | 89 | int mask; |
@@ -57,21 +91,23 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | |||
57 | a += nr >> 5; | 91 | a += nr >> 5; |
58 | mask = 1 << (nr & 0x1f); | 92 | mask = 1 << (nr & 0x1f); |
59 | local_irq_save(flags); | 93 | local_irq_save(flags); |
60 | *a &= ~mask; | 94 | *a |= mask; |
61 | local_irq_restore(flags); | 95 | local_irq_restore(flags); |
62 | } | 96 | } |
63 | 97 | ||
64 | static __inline__ void __clear_bit(int nr, volatile unsigned long *addr) | 98 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
65 | { | 99 | { |
66 | int *a = (int *)addr; | 100 | int *a = (int *)addr; |
67 | int mask; | 101 | int mask; |
68 | 102 | unsigned long flags; | |
69 | a += nr >> 5; | 103 | a += nr >> 5; |
70 | mask = 1 << (nr & 0x1f); | 104 | mask = 1 << (nr & 0x1f); |
105 | local_irq_save(flags); | ||
71 | *a &= ~mask; | 106 | *a &= ~mask; |
107 | local_irq_restore(flags); | ||
72 | } | 108 | } |
73 | 109 | ||
74 | static __inline__ void change_bit(int nr, volatile unsigned long *addr) | 110 | static inline void change_bit(int nr, volatile unsigned long *addr) |
75 | { | 111 | { |
76 | int mask, flags; | 112 | int mask, flags; |
77 | unsigned long *ADDR = (unsigned long *)addr; | 113 | unsigned long *ADDR = (unsigned long *)addr; |
@@ -83,17 +119,7 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr) | |||
83 | local_irq_restore(flags); | 119 | local_irq_restore(flags); |
84 | } | 120 | } |
85 | 121 | ||
86 | static __inline__ void __change_bit(int nr, volatile unsigned long *addr) | 122 | static inline int test_and_set_bit(int nr, volatile unsigned long *addr) |
87 | { | ||
88 | int mask; | ||
89 | unsigned long *ADDR = (unsigned long *)addr; | ||
90 | |||
91 | ADDR += nr >> 5; | ||
92 | mask = 1 << (nr & 31); | ||
93 | *ADDR ^= mask; | ||
94 | } | ||
95 | |||
96 | static __inline__ int test_and_set_bit(int nr, void *addr) | ||
97 | { | 123 | { |
98 | int mask, retval; | 124 | int mask, retval; |
99 | volatile unsigned int *a = (volatile unsigned int *)addr; | 125 | volatile unsigned int *a = (volatile unsigned int *)addr; |
@@ -109,19 +135,23 @@ static __inline__ int test_and_set_bit(int nr, void *addr) | |||
109 | return retval; | 135 | return retval; |
110 | } | 136 | } |
111 | 137 | ||
112 | static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr) | 138 | static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) |
113 | { | 139 | { |
114 | int mask, retval; | 140 | int mask, retval; |
115 | volatile unsigned int *a = (volatile unsigned int *)addr; | 141 | volatile unsigned int *a = (volatile unsigned int *)addr; |
142 | unsigned long flags; | ||
116 | 143 | ||
117 | a += nr >> 5; | 144 | a += nr >> 5; |
118 | mask = 1 << (nr & 0x1f); | 145 | mask = 1 << (nr & 0x1f); |
146 | local_irq_save(flags); | ||
119 | retval = (mask & *a) != 0; | 147 | retval = (mask & *a) != 0; |
120 | *a |= mask; | 148 | *a &= ~mask; |
149 | local_irq_restore(flags); | ||
150 | |||
121 | return retval; | 151 | return retval; |
122 | } | 152 | } |
123 | 153 | ||
124 | static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) | 154 | static inline int test_and_change_bit(int nr, volatile unsigned long *addr) |
125 | { | 155 | { |
126 | int mask, retval; | 156 | int mask, retval; |
127 | volatile unsigned int *a = (volatile unsigned int *)addr; | 157 | volatile unsigned int *a = (volatile unsigned int *)addr; |
@@ -131,13 +161,50 @@ static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) | |||
131 | mask = 1 << (nr & 0x1f); | 161 | mask = 1 << (nr & 0x1f); |
132 | local_irq_save(flags); | 162 | local_irq_save(flags); |
133 | retval = (mask & *a) != 0; | 163 | retval = (mask & *a) != 0; |
134 | *a &= ~mask; | 164 | *a ^= mask; |
135 | local_irq_restore(flags); | 165 | local_irq_restore(flags); |
136 | |||
137 | return retval; | 166 | return retval; |
138 | } | 167 | } |
139 | 168 | ||
140 | static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) | 169 | #endif /* CONFIG_SMP */ |
170 | |||
171 | /* | ||
172 | * clear_bit() doesn't provide any barrier for the compiler. | ||
173 | */ | ||
174 | #define smp_mb__before_clear_bit() barrier() | ||
175 | #define smp_mb__after_clear_bit() barrier() | ||
176 | |||
177 | static inline void __set_bit(int nr, volatile unsigned long *addr) | ||
178 | { | ||
179 | int *a = (int *)addr; | ||
180 | int mask; | ||
181 | |||
182 | a += nr >> 5; | ||
183 | mask = 1 << (nr & 0x1f); | ||
184 | *a |= mask; | ||
185 | } | ||
186 | |||
187 | static inline void __clear_bit(int nr, volatile unsigned long *addr) | ||
188 | { | ||
189 | int *a = (int *)addr; | ||
190 | int mask; | ||
191 | |||
192 | a += nr >> 5; | ||
193 | mask = 1 << (nr & 0x1f); | ||
194 | *a &= ~mask; | ||
195 | } | ||
196 | |||
197 | static inline void __change_bit(int nr, volatile unsigned long *addr) | ||
198 | { | ||
199 | int mask; | ||
200 | unsigned long *ADDR = (unsigned long *)addr; | ||
201 | |||
202 | ADDR += nr >> 5; | ||
203 | mask = 1 << (nr & 31); | ||
204 | *ADDR ^= mask; | ||
205 | } | ||
206 | |||
207 | static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) | ||
141 | { | 208 | { |
142 | int mask, retval; | 209 | int mask, retval; |
143 | volatile unsigned int *a = (volatile unsigned int *)addr; | 210 | volatile unsigned int *a = (volatile unsigned int *)addr; |
@@ -145,26 +212,23 @@ static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) | |||
145 | a += nr >> 5; | 212 | a += nr >> 5; |
146 | mask = 1 << (nr & 0x1f); | 213 | mask = 1 << (nr & 0x1f); |
147 | retval = (mask & *a) != 0; | 214 | retval = (mask & *a) != 0; |
148 | *a &= ~mask; | 215 | *a |= mask; |
149 | return retval; | 216 | return retval; |
150 | } | 217 | } |
151 | 218 | ||
152 | static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr) | 219 | static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) |
153 | { | 220 | { |
154 | int mask, retval; | 221 | int mask, retval; |
155 | volatile unsigned int *a = (volatile unsigned int *)addr; | 222 | volatile unsigned int *a = (volatile unsigned int *)addr; |
156 | unsigned long flags; | ||
157 | 223 | ||
158 | a += nr >> 5; | 224 | a += nr >> 5; |
159 | mask = 1 << (nr & 0x1f); | 225 | mask = 1 << (nr & 0x1f); |
160 | local_irq_save(flags); | ||
161 | retval = (mask & *a) != 0; | 226 | retval = (mask & *a) != 0; |
162 | *a ^= mask; | 227 | *a &= ~mask; |
163 | local_irq_restore(flags); | ||
164 | return retval; | 228 | return retval; |
165 | } | 229 | } |
166 | 230 | ||
167 | static __inline__ int __test_and_change_bit(int nr, | 231 | static inline int __test_and_change_bit(int nr, |
168 | volatile unsigned long *addr) | 232 | volatile unsigned long *addr) |
169 | { | 233 | { |
170 | int mask, retval; | 234 | int mask, retval; |
@@ -177,16 +241,7 @@ static __inline__ int __test_and_change_bit(int nr, | |||
177 | return retval; | 241 | return retval; |
178 | } | 242 | } |
179 | 243 | ||
180 | /* | 244 | static inline int __test_bit(int nr, const void *addr) |
181 | * This routine doesn't need to be atomic. | ||
182 | */ | ||
183 | static __inline__ int __constant_test_bit(int nr, const void *addr) | ||
184 | { | ||
185 | return ((1UL << (nr & 31)) & | ||
186 | (((const volatile unsigned int *)addr)[nr >> 5])) != 0; | ||
187 | } | ||
188 | |||
189 | static __inline__ int __test_bit(int nr, const void *addr) | ||
190 | { | 245 | { |
191 | int *a = (int *)addr; | 246 | int *a = (int *)addr; |
192 | int mask; | 247 | int mask; |
@@ -196,10 +251,16 @@ static __inline__ int __test_bit(int nr, const void *addr) | |||
196 | return ((mask & *a) != 0); | 251 | return ((mask & *a) != 0); |
197 | } | 252 | } |
198 | 253 | ||
199 | #define test_bit(nr,addr) \ | 254 | #ifndef CONFIG_SMP |
200 | (__builtin_constant_p(nr) ? \ | 255 | /* |
201 | __constant_test_bit((nr),(addr)) : \ | 256 | * This routine doesn't need irq save and restore ops in UP |
202 | __test_bit((nr),(addr))) | 257 | * context. |
258 | */ | ||
259 | static inline int test_bit(int nr, const void *addr) | ||
260 | { | ||
261 | return __test_bit(nr, addr); | ||
262 | } | ||
263 | #endif | ||
203 | 264 | ||
204 | #include <asm-generic/bitops/find.h> | 265 | #include <asm-generic/bitops/find.h> |
205 | #include <asm-generic/bitops/hweight.h> | 266 | #include <asm-generic/bitops/hweight.h> |
diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h index 023d72133b5a..86637814cf25 100644 --- a/arch/blackfin/include/asm/cache.h +++ b/arch/blackfin/include/asm/cache.h | |||
@@ -12,6 +12,11 @@ | |||
12 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | 12 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
13 | #define SMP_CACHE_BYTES L1_CACHE_BYTES | 13 | #define SMP_CACHE_BYTES L1_CACHE_BYTES |
14 | 14 | ||
15 | #ifdef CONFIG_SMP | ||
16 | #define __cacheline_aligned | ||
17 | #else | ||
18 | #define ____cacheline_aligned | ||
19 | |||
15 | /* | 20 | /* |
16 | * Put cacheline_aliged data to L1 data memory | 21 | * Put cacheline_aliged data to L1 data memory |
17 | */ | 22 | */ |
@@ -21,9 +26,33 @@ | |||
21 | __section__(".data_l1.cacheline_aligned"))) | 26 | __section__(".data_l1.cacheline_aligned"))) |
22 | #endif | 27 | #endif |
23 | 28 | ||
29 | #endif | ||
30 | |||
24 | /* | 31 | /* |
25 | * largest L1 which this arch supports | 32 | * largest L1 which this arch supports |
26 | */ | 33 | */ |
27 | #define L1_CACHE_SHIFT_MAX 5 | 34 | #define L1_CACHE_SHIFT_MAX 5 |
28 | 35 | ||
36 | #if defined(CONFIG_SMP) && \ | ||
37 | !defined(CONFIG_BFIN_CACHE_COHERENT) && \ | ||
38 | defined(CONFIG_BFIN_DCACHE) | ||
39 | #define __ARCH_SYNC_CORE_DCACHE | ||
40 | #ifndef __ASSEMBLY__ | ||
41 | asmlinkage void __raw_smp_mark_barrier_asm(void); | ||
42 | asmlinkage void __raw_smp_check_barrier_asm(void); | ||
43 | |||
44 | static inline void smp_mark_barrier(void) | ||
45 | { | ||
46 | __raw_smp_mark_barrier_asm(); | ||
47 | } | ||
48 | static inline void smp_check_barrier(void) | ||
49 | { | ||
50 | __raw_smp_check_barrier_asm(); | ||
51 | } | ||
52 | |||
53 | void resync_core_dcache(void); | ||
54 | #endif | ||
55 | #endif | ||
56 | |||
57 | |||
29 | #endif | 58 | #endif |
diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 4403415583fa..1b040f5b4feb 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h | |||
@@ -35,6 +35,7 @@ extern void blackfin_icache_flush_range(unsigned long start_address, unsigned lo | |||
35 | extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address); | 35 | extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address); |
36 | extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); | 36 | extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); |
37 | extern void blackfin_dflush_page(void *page); | 37 | extern void blackfin_dflush_page(void *page); |
38 | extern void blackfin_invalidate_entire_dcache(void); | ||
38 | 39 | ||
39 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 40 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
40 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 41 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
@@ -44,12 +45,20 @@ extern void blackfin_dflush_page(void *page); | |||
44 | #define flush_cache_vmap(start, end) do { } while (0) | 45 | #define flush_cache_vmap(start, end) do { } while (0) |
45 | #define flush_cache_vunmap(start, end) do { } while (0) | 46 | #define flush_cache_vunmap(start, end) do { } while (0) |
46 | 47 | ||
48 | #ifdef CONFIG_SMP | ||
49 | #define flush_icache_range_others(start, end) \ | ||
50 | smp_icache_flush_range_others((start), (end)) | ||
51 | #else | ||
52 | #define flush_icache_range_others(start, end) do { } while (0) | ||
53 | #endif | ||
54 | |||
47 | static inline void flush_icache_range(unsigned start, unsigned end) | 55 | static inline void flush_icache_range(unsigned start, unsigned end) |
48 | { | 56 | { |
49 | #if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE) | 57 | #if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE) |
50 | 58 | ||
51 | # if defined(CONFIG_BFIN_WT) | 59 | # if defined(CONFIG_BFIN_WT) |
52 | blackfin_icache_flush_range((start), (end)); | 60 | blackfin_icache_flush_range((start), (end)); |
61 | flush_icache_range_others(start, end); | ||
53 | # else | 62 | # else |
54 | blackfin_icache_dcache_flush_range((start), (end)); | 63 | blackfin_icache_dcache_flush_range((start), (end)); |
55 | # endif | 64 | # endif |
@@ -58,6 +67,7 @@ static inline void flush_icache_range(unsigned start, unsigned end) | |||
58 | 67 | ||
59 | # if defined(CONFIG_BFIN_ICACHE) | 68 | # if defined(CONFIG_BFIN_ICACHE) |
60 | blackfin_icache_flush_range((start), (end)); | 69 | blackfin_icache_flush_range((start), (end)); |
70 | flush_icache_range_others(start, end); | ||
61 | # endif | 71 | # endif |
62 | # if defined(CONFIG_BFIN_DCACHE) | 72 | # if defined(CONFIG_BFIN_DCACHE) |
63 | blackfin_dcache_flush_range((start), (end)); | 73 | blackfin_dcache_flush_range((start), (end)); |
@@ -66,10 +76,12 @@ static inline void flush_icache_range(unsigned start, unsigned end) | |||
66 | #endif | 76 | #endif |
67 | } | 77 | } |
68 | 78 | ||
69 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 79 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ |
70 | do { memcpy(dst, src, len); \ | 80 | do { memcpy(dst, src, len); \ |
71 | flush_icache_range ((unsigned) (dst), (unsigned) (dst) + (len)); \ | 81 | flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ |
82 | flush_icache_range_others((unsigned long) (dst), (unsigned long) (dst) + (len));\ | ||
72 | } while (0) | 83 | } while (0) |
84 | |||
73 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len) | 85 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len) |
74 | 86 | ||
75 | #if defined(CONFIG_BFIN_DCACHE) | 87 | #if defined(CONFIG_BFIN_DCACHE) |
@@ -82,7 +94,7 @@ do { memcpy(dst, src, len); \ | |||
82 | # define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) | 94 | # define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) |
83 | #else | 95 | #else |
84 | # define flush_dcache_range(start,end) do { } while (0) | 96 | # define flush_dcache_range(start,end) do { } while (0) |
85 | # define flush_dcache_page(page) do { } while (0) | 97 | # define flush_dcache_page(page) do { } while (0) |
86 | #endif | 98 | #endif |
87 | 99 | ||
88 | extern unsigned long reserved_mem_dcache_on; | 100 | extern unsigned long reserved_mem_dcache_on; |
diff --git a/arch/blackfin/include/asm/context.S b/arch/blackfin/include/asm/context.S index c0e630edfb9a..40d20b4a9b1f 100644 --- a/arch/blackfin/include/asm/context.S +++ b/arch/blackfin/include/asm/context.S | |||
@@ -303,9 +303,14 @@ | |||
303 | RETI = [sp++]; | 303 | RETI = [sp++]; |
304 | RETS = [sp++]; | 304 | RETS = [sp++]; |
305 | 305 | ||
306 | #ifdef CONFIG_SMP | ||
307 | GET_PDA(p0, r0); | ||
308 | r0 = [p0 + PDA_IRQFLAGS]; | ||
309 | #else | ||
306 | p0.h = _irq_flags; | 310 | p0.h = _irq_flags; |
307 | p0.l = _irq_flags; | 311 | p0.l = _irq_flags; |
308 | r0 = [p0]; | 312 | r0 = [p0]; |
313 | #endif | ||
309 | sti r0; | 314 | sti r0; |
310 | 315 | ||
311 | sp += 4; /* Skip Reserved */ | 316 | sp += 4; /* Skip Reserved */ |
@@ -352,4 +357,3 @@ | |||
352 | SYSCFG = [sp++]; | 357 | SYSCFG = [sp++]; |
353 | csync; | 358 | csync; |
354 | .endm | 359 | .endm |
355 | |||
diff --git a/arch/blackfin/include/asm/cpu.h b/arch/blackfin/include/asm/cpu.h new file mode 100644 index 000000000000..9b7aefe7eb2d --- /dev/null +++ b/arch/blackfin/include/asm/cpu.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/include/asm/cpu.h. | ||
3 | * Author: Philippe Gerum <rpm@xenomai.org> | ||
4 | * | ||
5 | * Copyright 2007 Analog Devices Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, see the file COPYING, or write | ||
19 | * to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef __ASM_BLACKFIN_CPU_H | ||
24 | #define __ASM_BLACKFIN_CPU_H | ||
25 | |||
26 | #include <linux/percpu.h> | ||
27 | |||
28 | struct task_struct; | ||
29 | |||
30 | struct blackfin_cpudata { | ||
31 | struct cpu cpu; | ||
32 | struct task_struct *idle; | ||
33 | unsigned long cclk; | ||
34 | unsigned int imemctl; | ||
35 | unsigned int dmemctl; | ||
36 | unsigned long loops_per_jiffy; | ||
37 | unsigned long dcache_invld_count; | ||
38 | }; | ||
39 | |||
40 | DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data); | ||
41 | |||
42 | #endif | ||
diff --git a/arch/blackfin/include/asm/l1layout.h b/arch/blackfin/include/asm/l1layout.h index c13ded777828..06bb37f6c788 100644 --- a/arch/blackfin/include/asm/l1layout.h +++ b/arch/blackfin/include/asm/l1layout.h | |||
@@ -24,7 +24,8 @@ struct l1_scratch_task_info | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | /* A pointer to the structure in memory. */ | 26 | /* A pointer to the structure in memory. */ |
27 | #define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)L1_SCRATCH_START) | 27 | #define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)\ |
28 | get_l1_scratch_start()) | ||
28 | 29 | ||
29 | #endif | 30 | #endif |
30 | 31 | ||
diff --git a/arch/blackfin/include/asm/mutex-dec.h b/arch/blackfin/include/asm/mutex-dec.h new file mode 100644 index 000000000000..0134151656af --- /dev/null +++ b/arch/blackfin/include/asm/mutex-dec.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * include/asm-generic/mutex-dec.h | ||
3 | * | ||
4 | * Generic implementation of the mutex fastpath, based on atomic | ||
5 | * decrement/increment. | ||
6 | */ | ||
7 | #ifndef _ASM_GENERIC_MUTEX_DEC_H | ||
8 | #define _ASM_GENERIC_MUTEX_DEC_H | ||
9 | |||
10 | /** | ||
11 | * __mutex_fastpath_lock - try to take the lock by moving the count | ||
12 | * from 1 to a 0 value | ||
13 | * @count: pointer of type atomic_t | ||
14 | * @fail_fn: function to call if the original value was not 1 | ||
15 | * | ||
16 | * Change the count from 1 to a value lower than 1, and call <fail_fn> if | ||
17 | * it wasn't 1 originally. This function MUST leave the value lower than | ||
18 | * 1 even when the "1" assertion wasn't true. | ||
19 | */ | ||
20 | static inline void | ||
21 | __mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) | ||
22 | { | ||
23 | if (unlikely(atomic_dec_return(count) < 0)) | ||
24 | fail_fn(count); | ||
25 | else | ||
26 | smp_mb(); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * __mutex_fastpath_lock_retval - try to take the lock by moving the count | ||
31 | * from 1 to a 0 value | ||
32 | * @count: pointer of type atomic_t | ||
33 | * @fail_fn: function to call if the original value was not 1 | ||
34 | * | ||
35 | * Change the count from 1 to a value lower than 1, and call <fail_fn> if | ||
36 | * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, | ||
37 | * or anything the slow path function returns. | ||
38 | */ | ||
39 | static inline int | ||
40 | __mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *)) | ||
41 | { | ||
42 | if (unlikely(atomic_dec_return(count) < 0)) | ||
43 | return fail_fn(count); | ||
44 | else { | ||
45 | smp_mb(); | ||
46 | return 0; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * __mutex_fastpath_unlock - try to promote the count from 0 to 1 | ||
52 | * @count: pointer of type atomic_t | ||
53 | * @fail_fn: function to call if the original value was not 0 | ||
54 | * | ||
55 | * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>. | ||
56 | * In the failure case, this function is allowed to either set the value to | ||
57 | * 1, or to set it to a value lower than 1. | ||
58 | * | ||
59 | * If the implementation sets it to a value of lower than 1, then the | ||
60 | * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs | ||
61 | * to return 0 otherwise. | ||
62 | */ | ||
63 | static inline void | ||
64 | __mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) | ||
65 | { | ||
66 | smp_mb(); | ||
67 | if (unlikely(atomic_inc_return(count) <= 0)) | ||
68 | fail_fn(count); | ||
69 | } | ||
70 | |||
71 | #define __mutex_slowpath_needs_to_unlock() 1 | ||
72 | |||
73 | /** | ||
74 | * __mutex_fastpath_trylock - try to acquire the mutex, without waiting | ||
75 | * | ||
76 | * @count: pointer of type atomic_t | ||
77 | * @fail_fn: fallback function | ||
78 | * | ||
79 | * Change the count from 1 to a value lower than 1, and return 0 (failure) | ||
80 | * if it wasn't 1 originally, or return 1 (success) otherwise. This function | ||
81 | * MUST leave the value lower than 1 even when the "1" assertion wasn't true. | ||
82 | * Additionally, if the value was < 0 originally, this function must not leave | ||
83 | * it to 0 on failure. | ||
84 | * | ||
85 | * If the architecture has no effective trylock variant, it should call the | ||
86 | * <fail_fn> spinlock-based trylock variant unconditionally. | ||
87 | */ | ||
88 | static inline int | ||
89 | __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
90 | { | ||
91 | /* | ||
92 | * We have two variants here. The cmpxchg based one is the best one | ||
93 | * because it never induce a false contention state. It is included | ||
94 | * here because architectures using the inc/dec algorithms over the | ||
95 | * xchg ones are much more likely to support cmpxchg natively. | ||
96 | * | ||
97 | * If not we fall back to the spinlock based variant - that is | ||
98 | * just as efficient (and simpler) as a 'destructive' probing of | ||
99 | * the mutex state would be. | ||
100 | */ | ||
101 | #ifdef __HAVE_ARCH_CMPXCHG | ||
102 | if (likely(atomic_cmpxchg(count, 1, 0) == 1)) { | ||
103 | smp_mb(); | ||
104 | return 1; | ||
105 | } | ||
106 | return 0; | ||
107 | #else | ||
108 | return fail_fn(count); | ||
109 | #endif | ||
110 | } | ||
111 | |||
112 | #endif | ||
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h index 458c1f7fbc18..5d399256bf06 100644 --- a/arch/blackfin/include/asm/mutex.h +++ b/arch/blackfin/include/asm/mutex.h | |||
@@ -6,4 +6,67 @@ | |||
6 | * implementation. (see asm-generic/mutex-xchg.h for details) | 6 | * implementation. (see asm-generic/mutex-xchg.h for details) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _ASM_MUTEX_H | ||
10 | #define _ASM_MUTEX_H | ||
11 | |||
12 | #ifndef CONFIG_SMP | ||
9 | #include <asm-generic/mutex-dec.h> | 13 | #include <asm-generic/mutex-dec.h> |
14 | #else | ||
15 | |||
16 | static inline void | ||
17 | __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||
18 | { | ||
19 | if (unlikely(atomic_dec_return(count) < 0)) | ||
20 | fail_fn(count); | ||
21 | else | ||
22 | smp_mb(); | ||
23 | } | ||
24 | |||
25 | static inline int | ||
26 | __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
27 | { | ||
28 | if (unlikely(atomic_dec_return(count) < 0)) | ||
29 | return fail_fn(count); | ||
30 | else { | ||
31 | smp_mb(); | ||
32 | return 0; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | static inline void | ||
37 | __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||
38 | { | ||
39 | smp_mb(); | ||
40 | if (unlikely(atomic_inc_return(count) <= 0)) | ||
41 | fail_fn(count); | ||
42 | } | ||
43 | |||
44 | #define __mutex_slowpath_needs_to_unlock() 1 | ||
45 | |||
46 | static inline int | ||
47 | __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
48 | { | ||
49 | /* | ||
50 | * We have two variants here. The cmpxchg based one is the best one | ||
51 | * because it never induce a false contention state. It is included | ||
52 | * here because architectures using the inc/dec algorithms over the | ||
53 | * xchg ones are much more likely to support cmpxchg natively. | ||
54 | * | ||
55 | * If not we fall back to the spinlock based variant - that is | ||
56 | * just as efficient (and simpler) as a 'destructive' probing of | ||
57 | * the mutex state would be. | ||
58 | */ | ||
59 | #ifdef __HAVE_ARCH_CMPXCHG | ||
60 | if (likely(atomic_cmpxchg(count, 1, 0) == 1)) { | ||
61 | smp_mb(); | ||
62 | return 1; | ||
63 | } | ||
64 | return 0; | ||
65 | #else | ||
66 | return fail_fn(count); | ||
67 | #endif | ||
68 | } | ||
69 | |||
70 | #endif | ||
71 | |||
72 | #endif | ||
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h new file mode 100644 index 000000000000..a24d130c30f0 --- /dev/null +++ b/arch/blackfin/include/asm/pda.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/include/asm/pda.h | ||
3 | * Author: Philippe Gerum <rpm@xenomai.org> | ||
4 | * | ||
5 | * Copyright 2007 Analog Devices Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, see the file COPYING, or write | ||
19 | * to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef _ASM_BLACKFIN_PDA_H | ||
24 | #define _ASM_BLACKFIN_PDA_H | ||
25 | |||
26 | #include <asm/mem_map.h> | ||
27 | |||
28 | #ifndef __ASSEMBLY__ | ||
29 | |||
30 | struct blackfin_pda { /* Per-processor Data Area */ | ||
31 | struct blackfin_pda *next; | ||
32 | |||
33 | unsigned long syscfg; | ||
34 | #ifdef CONFIG_SMP | ||
35 | unsigned long imask; /* Current IMASK value */ | ||
36 | #endif | ||
37 | |||
38 | unsigned long *ipdt; /* Start of switchable I-CPLB table */ | ||
39 | unsigned long *ipdt_swapcount; /* Number of swaps in ipdt */ | ||
40 | unsigned long *dpdt; /* Start of switchable D-CPLB table */ | ||
41 | unsigned long *dpdt_swapcount; /* Number of swaps in dpdt */ | ||
42 | |||
43 | /* | ||
44 | * Single instructions can have multiple faults, which | ||
45 | * need to be handled by traps.c, in irq5. We store | ||
46 | * the exception cause to ensure we don't miss a | ||
47 | * double fault condition | ||
48 | */ | ||
49 | unsigned long ex_iptr; | ||
50 | unsigned long ex_optr; | ||
51 | unsigned long ex_buf[4]; | ||
52 | unsigned long ex_imask; /* Saved imask from exception */ | ||
53 | unsigned long *ex_stack; /* Exception stack space */ | ||
54 | |||
55 | #ifdef ANOMALY_05000261 | ||
56 | unsigned long last_cplb_fault_retx; | ||
57 | #endif | ||
58 | unsigned long dcplb_fault_addr; | ||
59 | unsigned long icplb_fault_addr; | ||
60 | unsigned long retx; | ||
61 | unsigned long seqstat; | ||
62 | }; | ||
63 | |||
64 | extern struct blackfin_pda cpu_pda[]; | ||
65 | |||
66 | void reserve_pda(void); | ||
67 | |||
68 | #endif /* __ASSEMBLY__ */ | ||
69 | |||
70 | #endif /* _ASM_BLACKFIN_PDA_H */ | ||
diff --git a/arch/blackfin/include/asm/percpu.h b/arch/blackfin/include/asm/percpu.h index 78dd61f6b39f..797c0c165069 100644 --- a/arch/blackfin/include/asm/percpu.h +++ b/arch/blackfin/include/asm/percpu.h | |||
@@ -3,4 +3,14 @@ | |||
3 | 3 | ||
4 | #include <asm-generic/percpu.h> | 4 | #include <asm-generic/percpu.h> |
5 | 5 | ||
6 | #endif /* __ARCH_BLACKFIN_PERCPU__ */ | 6 | #ifdef CONFIG_MODULES |
7 | #define PERCPU_MODULE_RESERVE 8192 | ||
8 | #else | ||
9 | #define PERCPU_MODULE_RESERVE 0 | ||
10 | #endif | ||
11 | |||
12 | #define PERCPU_ENOUGH_ROOM \ | ||
13 | (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \ | ||
14 | PERCPU_MODULE_RESERVE) | ||
15 | |||
16 | #endif /* __ARCH_BLACKFIN_PERCPU__ */ | ||
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index e3e9b41fa8db..30703c75030c 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h | |||
@@ -106,7 +106,8 @@ unsigned long get_wchan(struct task_struct *p); | |||
106 | eip; }) | 106 | eip; }) |
107 | #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) | 107 | #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) |
108 | 108 | ||
109 | #define cpu_relax() barrier() | 109 | #define cpu_relax() smp_mb() |
110 | |||
110 | 111 | ||
111 | /* Get the Silicon Revision of the chip */ | 112 | /* Get the Silicon Revision of the chip */ |
112 | static inline uint32_t __pure bfin_revid(void) | 113 | static inline uint32_t __pure bfin_revid(void) |
@@ -137,7 +138,11 @@ static inline uint32_t __pure bfin_revid(void) | |||
137 | static inline uint16_t __pure bfin_cpuid(void) | 138 | static inline uint16_t __pure bfin_cpuid(void) |
138 | { | 139 | { |
139 | return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12; | 140 | return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12; |
141 | } | ||
140 | 142 | ||
143 | static inline uint32_t __pure bfin_dspid(void) | ||
144 | { | ||
145 | return bfin_read_DSPID(); | ||
141 | } | 146 | } |
142 | 147 | ||
143 | static inline uint32_t __pure bfin_compiled_revid(void) | 148 | static inline uint32_t __pure bfin_compiled_revid(void) |
diff --git a/arch/blackfin/include/asm/rwlock.h b/arch/blackfin/include/asm/rwlock.h new file mode 100644 index 000000000000..4a724b378971 --- /dev/null +++ b/arch/blackfin/include/asm/rwlock.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _ASM_BLACKFIN_RWLOCK_H | ||
2 | #define _ASM_BLACKFIN_RWLOCK_H | ||
3 | |||
4 | #define RW_LOCK_BIAS 0x01000000 | ||
5 | |||
6 | #endif | ||
diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h new file mode 100644 index 000000000000..233cb8c3cfb7 --- /dev/null +++ b/arch/blackfin/include/asm/smp.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/include/asm/smp.h | ||
3 | * Author: Philippe Gerum <rpm@xenomai.org> | ||
4 | * | ||
5 | * Copyright 2007 Analog Devices Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, see the file COPYING, or write | ||
19 | * to the Free Software Foundation, Inc., | ||
20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef __ASM_BLACKFIN_SMP_H | ||
24 | #define __ASM_BLACKFIN_SMP_H | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/threads.h> | ||
28 | #include <linux/cpumask.h> | ||
29 | #include <linux/cache.h> | ||
30 | #include <asm/blackfin.h> | ||
31 | #include <mach/smp.h> | ||
32 | |||
33 | #define raw_smp_processor_id() blackfin_core_id() | ||
34 | |||
35 | struct corelock_slot { | ||
36 | int lock; | ||
37 | }; | ||
38 | |||
39 | void smp_icache_flush_range_others(unsigned long start, | ||
40 | unsigned long end); | ||
41 | |||
42 | #endif /* !__ASM_BLACKFIN_SMP_H */ | ||
diff --git a/arch/blackfin/include/asm/spinlock.h b/arch/blackfin/include/asm/spinlock.h index 64e908a50646..0249ac319476 100644 --- a/arch/blackfin/include/asm/spinlock.h +++ b/arch/blackfin/include/asm/spinlock.h | |||
@@ -1,6 +1,89 @@ | |||
1 | #ifndef __BFIN_SPINLOCK_H | 1 | #ifndef __BFIN_SPINLOCK_H |
2 | #define __BFIN_SPINLOCK_H | 2 | #define __BFIN_SPINLOCK_H |
3 | 3 | ||
4 | #error blackfin architecture does not support SMP spin lock yet | 4 | #include <asm/atomic.h> |
5 | 5 | ||
6 | #endif | 6 | asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr); |
7 | asmlinkage void __raw_spin_lock_asm(volatile int *ptr); | ||
8 | asmlinkage int __raw_spin_trylock_asm(volatile int *ptr); | ||
9 | asmlinkage void __raw_spin_unlock_asm(volatile int *ptr); | ||
10 | asmlinkage void __raw_read_lock_asm(volatile int *ptr); | ||
11 | asmlinkage int __raw_read_trylock_asm(volatile int *ptr); | ||
12 | asmlinkage void __raw_read_unlock_asm(volatile int *ptr); | ||
13 | asmlinkage void __raw_write_lock_asm(volatile int *ptr); | ||
14 | asmlinkage int __raw_write_trylock_asm(volatile int *ptr); | ||
15 | asmlinkage void __raw_write_unlock_asm(volatile int *ptr); | ||
16 | |||
17 | static inline int __raw_spin_is_locked(raw_spinlock_t *lock) | ||
18 | { | ||
19 | return __raw_spin_is_locked_asm(&lock->lock); | ||
20 | } | ||
21 | |||
22 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | ||
23 | { | ||
24 | __raw_spin_lock_asm(&lock->lock); | ||
25 | } | ||
26 | |||
27 | #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) | ||
28 | |||
29 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | ||
30 | { | ||
31 | return __raw_spin_trylock_asm(&lock->lock); | ||
32 | } | ||
33 | |||
34 | static inline void __raw_spin_unlock(raw_spinlock_t *lock) | ||
35 | { | ||
36 | __raw_spin_unlock_asm(&lock->lock); | ||
37 | } | ||
38 | |||
39 | static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock) | ||
40 | { | ||
41 | while (__raw_spin_is_locked(lock)) | ||
42 | cpu_relax(); | ||
43 | } | ||
44 | |||
45 | static inline int __raw_read_can_lock(raw_rwlock_t *rw) | ||
46 | { | ||
47 | return __raw_uncached_fetch_asm(&rw->lock) > 0; | ||
48 | } | ||
49 | |||
50 | static inline int __raw_write_can_lock(raw_rwlock_t *rw) | ||
51 | { | ||
52 | return __raw_uncached_fetch_asm(&rw->lock) == RW_LOCK_BIAS; | ||
53 | } | ||
54 | |||
55 | static inline void __raw_read_lock(raw_rwlock_t *rw) | ||
56 | { | ||
57 | __raw_read_lock_asm(&rw->lock); | ||
58 | } | ||
59 | |||
60 | static inline int __raw_read_trylock(raw_rwlock_t *rw) | ||
61 | { | ||
62 | return __raw_read_trylock_asm(&rw->lock); | ||
63 | } | ||
64 | |||
65 | static inline void __raw_read_unlock(raw_rwlock_t *rw) | ||
66 | { | ||
67 | __raw_read_unlock_asm(&rw->lock); | ||
68 | } | ||
69 | |||
70 | static inline void __raw_write_lock(raw_rwlock_t *rw) | ||
71 | { | ||
72 | __raw_write_lock_asm(&rw->lock); | ||
73 | } | ||
74 | |||
75 | static inline int __raw_write_trylock(raw_rwlock_t *rw) | ||
76 | { | ||
77 | return __raw_write_trylock_asm(&rw->lock); | ||
78 | } | ||
79 | |||
80 | static inline void __raw_write_unlock(raw_rwlock_t *rw) | ||
81 | { | ||
82 | __raw_write_unlock_asm(&rw->lock); | ||
83 | } | ||
84 | |||
85 | #define _raw_spin_relax(lock) cpu_relax() | ||
86 | #define _raw_read_relax(lock) cpu_relax() | ||
87 | #define _raw_write_relax(lock) cpu_relax() | ||
88 | |||
89 | #endif /* !__BFIN_SPINLOCK_H */ | ||
diff --git a/arch/blackfin/include/asm/spinlock_types.h b/arch/blackfin/include/asm/spinlock_types.h new file mode 100644 index 000000000000..b1e3c4c7b382 --- /dev/null +++ b/arch/blackfin/include/asm/spinlock_types.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef __ASM_SPINLOCK_TYPES_H | ||
2 | #define __ASM_SPINLOCK_TYPES_H | ||
3 | |||
4 | #ifndef __LINUX_SPINLOCK_TYPES_H | ||
5 | # error "please don't include this file directly" | ||
6 | #endif | ||
7 | |||
8 | #include <asm/rwlock.h> | ||
9 | |||
10 | typedef struct { | ||
11 | volatile unsigned int lock; | ||
12 | } raw_spinlock_t; | ||
13 | |||
14 | #define __RAW_SPIN_LOCK_UNLOCKED { 0 } | ||
15 | |||
16 | typedef struct { | ||
17 | volatile unsigned int lock; | ||
18 | } raw_rwlock_t; | ||
19 | |||
20 | #define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } | ||
21 | |||
22 | #endif | ||
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h index 8f1627d8bf09..6b368faf30c3 100644 --- a/arch/blackfin/include/asm/system.h +++ b/arch/blackfin/include/asm/system.h | |||
@@ -37,20 +37,16 @@ | |||
37 | #include <linux/linkage.h> | 37 | #include <linux/linkage.h> |
38 | #include <linux/compiler.h> | 38 | #include <linux/compiler.h> |
39 | #include <mach/anomaly.h> | 39 | #include <mach/anomaly.h> |
40 | #include <asm/pda.h> | ||
41 | #include <asm/processor.h> | ||
42 | |||
43 | /* Forward decl needed due to cdef inter dependencies */ | ||
44 | static inline uint32_t __pure bfin_dspid(void); | ||
45 | #define blackfin_core_id() (bfin_dspid() & 0xff) | ||
40 | 46 | ||
41 | /* | 47 | /* |
42 | * Interrupt configuring macros. | 48 | * Interrupt configuring macros. |
43 | */ | 49 | */ |
44 | |||
45 | extern unsigned long irq_flags; | ||
46 | |||
47 | #define local_irq_enable() \ | ||
48 | __asm__ __volatile__( \ | ||
49 | "sti %0;" \ | ||
50 | : \ | ||
51 | : "d" (irq_flags) \ | ||
52 | ) | ||
53 | |||
54 | #define local_irq_disable() \ | 50 | #define local_irq_disable() \ |
55 | do { \ | 51 | do { \ |
56 | int __tmp_dummy; \ | 52 | int __tmp_dummy; \ |
@@ -66,6 +62,18 @@ extern unsigned long irq_flags; | |||
66 | # define NOP_PAD_ANOMALY_05000244 | 62 | # define NOP_PAD_ANOMALY_05000244 |
67 | #endif | 63 | #endif |
68 | 64 | ||
65 | #ifdef CONFIG_SMP | ||
66 | # define irq_flags cpu_pda[blackfin_core_id()].imask | ||
67 | #else | ||
68 | extern unsigned long irq_flags; | ||
69 | #endif | ||
70 | |||
71 | #define local_irq_enable() \ | ||
72 | __asm__ __volatile__( \ | ||
73 | "sti %0;" \ | ||
74 | : \ | ||
75 | : "d" (irq_flags) \ | ||
76 | ) | ||
69 | #define idle_with_irq_disabled() \ | 77 | #define idle_with_irq_disabled() \ |
70 | __asm__ __volatile__( \ | 78 | __asm__ __volatile__( \ |
71 | NOP_PAD_ANOMALY_05000244 \ | 79 | NOP_PAD_ANOMALY_05000244 \ |
@@ -129,22 +137,85 @@ extern unsigned long irq_flags; | |||
129 | #define rmb() asm volatile ("" : : :"memory") | 137 | #define rmb() asm volatile ("" : : :"memory") |
130 | #define wmb() asm volatile ("" : : :"memory") | 138 | #define wmb() asm volatile ("" : : :"memory") |
131 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) | 139 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) |
132 | |||
133 | #define read_barrier_depends() do { } while(0) | 140 | #define read_barrier_depends() do { } while(0) |
134 | 141 | ||
135 | #ifdef CONFIG_SMP | 142 | #ifdef CONFIG_SMP |
136 | #define smp_mb() mb() | 143 | asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value); |
137 | #define smp_rmb() rmb() | 144 | asmlinkage unsigned long __raw_xchg_2_asm(volatile void *ptr, unsigned long value); |
138 | #define smp_wmb() wmb() | 145 | asmlinkage unsigned long __raw_xchg_4_asm(volatile void *ptr, unsigned long value); |
139 | #define smp_read_barrier_depends() read_barrier_depends() | 146 | asmlinkage unsigned long __raw_cmpxchg_1_asm(volatile void *ptr, |
147 | unsigned long new, unsigned long old); | ||
148 | asmlinkage unsigned long __raw_cmpxchg_2_asm(volatile void *ptr, | ||
149 | unsigned long new, unsigned long old); | ||
150 | asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr, | ||
151 | unsigned long new, unsigned long old); | ||
152 | |||
153 | #ifdef __ARCH_SYNC_CORE_DCACHE | ||
154 | # define smp_mb() do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0) | ||
155 | # define smp_rmb() do { barrier(); smp_check_barrier(); } while (0) | ||
156 | # define smp_wmb() do { barrier(); smp_mark_barrier(); } while (0) | ||
140 | #else | 157 | #else |
158 | # define smp_mb() barrier() | ||
159 | # define smp_rmb() barrier() | ||
160 | # define smp_wmb() barrier() | ||
161 | #endif | ||
162 | |||
163 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | ||
164 | int size) | ||
165 | { | ||
166 | unsigned long tmp; | ||
167 | |||
168 | switch (size) { | ||
169 | case 1: | ||
170 | tmp = __raw_xchg_1_asm(ptr, x); | ||
171 | break; | ||
172 | case 2: | ||
173 | tmp = __raw_xchg_2_asm(ptr, x); | ||
174 | break; | ||
175 | case 4: | ||
176 | tmp = __raw_xchg_4_asm(ptr, x); | ||
177 | break; | ||
178 | } | ||
179 | |||
180 | return tmp; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | ||
185 | * store NEW in MEM. Return the initial value in MEM. Success is | ||
186 | * indicated by comparing RETURN with OLD. | ||
187 | */ | ||
188 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | ||
189 | unsigned long new, int size) | ||
190 | { | ||
191 | unsigned long tmp; | ||
192 | |||
193 | switch (size) { | ||
194 | case 1: | ||
195 | tmp = __raw_cmpxchg_1_asm(ptr, new, old); | ||
196 | break; | ||
197 | case 2: | ||
198 | tmp = __raw_cmpxchg_2_asm(ptr, new, old); | ||
199 | break; | ||
200 | case 4: | ||
201 | tmp = __raw_cmpxchg_4_asm(ptr, new, old); | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | return tmp; | ||
206 | } | ||
207 | #define cmpxchg(ptr, o, n) \ | ||
208 | ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ | ||
209 | (unsigned long)(n), sizeof(*(ptr)))) | ||
210 | |||
211 | #define smp_read_barrier_depends() smp_check_barrier() | ||
212 | |||
213 | #else /* !CONFIG_SMP */ | ||
214 | |||
141 | #define smp_mb() barrier() | 215 | #define smp_mb() barrier() |
142 | #define smp_rmb() barrier() | 216 | #define smp_rmb() barrier() |
143 | #define smp_wmb() barrier() | 217 | #define smp_wmb() barrier() |
144 | #define smp_read_barrier_depends() do { } while(0) | 218 | #define smp_read_barrier_depends() do { } while(0) |
145 | #endif | ||
146 | |||
147 | #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
148 | 219 | ||
149 | struct __xchg_dummy { | 220 | struct __xchg_dummy { |
150 | unsigned long a[100]; | 221 | unsigned long a[100]; |
@@ -194,9 +265,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | |||
194 | (unsigned long)(n), sizeof(*(ptr)))) | 265 | (unsigned long)(n), sizeof(*(ptr)))) |
195 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) | 266 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) |
196 | 267 | ||
197 | #ifndef CONFIG_SMP | ||
198 | #include <asm-generic/cmpxchg.h> | 268 | #include <asm-generic/cmpxchg.h> |
199 | #endif | 269 | |
270 | #endif /* !CONFIG_SMP */ | ||
271 | |||
272 | #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) | ||
273 | #define tas(ptr) ((void)xchg((ptr), 1)) | ||
200 | 274 | ||
201 | #define prepare_to_switch() do { } while(0) | 275 | #define prepare_to_switch() do { } while(0) |
202 | 276 | ||
@@ -218,4 +292,4 @@ do { \ | |||
218 | (last) = resume (prev, next); \ | 292 | (last) = resume (prev, next); \ |
219 | } while (0) | 293 | } while (0) |
220 | 294 | ||
221 | #endif /* _BLACKFIN_SYSTEM_H */ | 295 | #endif /* _BLACKFIN_SYSTEM_H */ |