diff options
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r-- | include/asm-powerpc/atomic.h | 7 | ||||
-rw-r--r-- | include/asm-powerpc/bitops.h | 1 | ||||
-rw-r--r-- | include/asm-powerpc/kdebug.h | 19 | ||||
-rw-r--r-- | include/asm-powerpc/kexec.h | 2 | ||||
-rw-r--r-- | include/asm-powerpc/local.h | 201 | ||||
-rw-r--r-- | include/asm-powerpc/parport.h | 5 | ||||
-rw-r--r-- | include/asm-powerpc/system.h | 130 |
7 files changed, 331 insertions, 34 deletions
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h index 2ce4b6b7b348..c44810b9d322 100644 --- a/include/asm-powerpc/atomic.h +++ b/include/asm-powerpc/atomic.h | |||
@@ -11,6 +11,7 @@ typedef struct { volatile int counter; } atomic_t; | |||
11 | #include <linux/compiler.h> | 11 | #include <linux/compiler.h> |
12 | #include <asm/synch.h> | 12 | #include <asm/synch.h> |
13 | #include <asm/asm-compat.h> | 13 | #include <asm/asm-compat.h> |
14 | #include <asm/system.h> | ||
14 | 15 | ||
15 | #define ATOMIC_INIT(i) { (i) } | 16 | #define ATOMIC_INIT(i) { (i) } |
16 | 17 | ||
@@ -165,8 +166,7 @@ static __inline__ int atomic_dec_return(atomic_t *v) | |||
165 | return t; | 166 | return t; |
166 | } | 167 | } |
167 | 168 | ||
168 | #define atomic_cmpxchg(v, o, n) \ | 169 | #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) |
169 | ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) | ||
170 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | 170 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) |
171 | 171 | ||
172 | /** | 172 | /** |
@@ -414,8 +414,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v) | |||
414 | return t; | 414 | return t; |
415 | } | 415 | } |
416 | 416 | ||
417 | #define atomic64_cmpxchg(v, o, n) \ | 417 | #define atomic64_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) |
418 | ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) | ||
419 | #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) | 418 | #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) |
420 | 419 | ||
421 | /** | 420 | /** |
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index 8f757f6246e4..8144a2788db6 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h | |||
@@ -39,7 +39,6 @@ | |||
39 | #ifdef __KERNEL__ | 39 | #ifdef __KERNEL__ |
40 | 40 | ||
41 | #include <linux/compiler.h> | 41 | #include <linux/compiler.h> |
42 | #include <asm/atomic.h> | ||
43 | #include <asm/asm-compat.h> | 42 | #include <asm/asm-compat.h> |
44 | #include <asm/synch.h> | 43 | #include <asm/synch.h> |
45 | 44 | ||
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h index df996b933def..295f0162c608 100644 --- a/include/asm-powerpc/kdebug.h +++ b/include/asm-powerpc/kdebug.h | |||
@@ -6,19 +6,6 @@ | |||
6 | 6 | ||
7 | #include <linux/notifier.h> | 7 | #include <linux/notifier.h> |
8 | 8 | ||
9 | struct pt_regs; | ||
10 | |||
11 | struct die_args { | ||
12 | struct pt_regs *regs; | ||
13 | const char *str; | ||
14 | long err; | ||
15 | int trapnr; | ||
16 | int signr; | ||
17 | }; | ||
18 | |||
19 | extern int register_die_notifier(struct notifier_block *); | ||
20 | extern int unregister_die_notifier(struct notifier_block *); | ||
21 | |||
22 | /* | 9 | /* |
23 | * These are only here because kprobes.c wants them to implement a | 10 | * These are only here because kprobes.c wants them to implement a |
24 | * blatant layering violation. Will hopefully go away soon once all | 11 | * blatant layering violation. Will hopefully go away soon once all |
@@ -43,11 +30,5 @@ enum die_val { | |||
43 | DIE_SSTEP, | 30 | DIE_SSTEP, |
44 | }; | 31 | }; |
45 | 32 | ||
46 | static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) | ||
47 | { | ||
48 | struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; | ||
49 | return atomic_notifier_call_chain(&powerpc_die_chain, val, &args); | ||
50 | } | ||
51 | |||
52 | #endif /* __KERNEL__ */ | 33 | #endif /* __KERNEL__ */ |
53 | #endif /* _ASM_POWERPC_KDEBUG_H */ | 34 | #endif /* _ASM_POWERPC_KDEBUG_H */ |
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index 11cbdf81fd2e..b6f817b8ba3d 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h | |||
@@ -108,8 +108,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs, | |||
108 | struct pt_regs *oldregs) { } | 108 | struct pt_regs *oldregs) { } |
109 | #endif /* !__powerpc64 __ */ | 109 | #endif /* !__powerpc64 __ */ |
110 | 110 | ||
111 | #define MAX_NOTE_BYTES 1024 | ||
112 | |||
113 | extern void kexec_smp_wait(void); /* get and clear naca physid, wait for | 111 | extern void kexec_smp_wait(void); /* get and clear naca physid, wait for |
114 | master to copy new code to 0 */ | 112 | master to copy new code to 0 */ |
115 | extern int crashing_cpu; | 113 | extern int crashing_cpu; |
diff --git a/include/asm-powerpc/local.h b/include/asm-powerpc/local.h index c11c530f74d0..612d83276653 100644 --- a/include/asm-powerpc/local.h +++ b/include/asm-powerpc/local.h | |||
@@ -1 +1,200 @@ | |||
1 | #include <asm-generic/local.h> | 1 | #ifndef _ARCH_POWERPC_LOCAL_H |
2 | #define _ARCH_POWERPC_LOCAL_H | ||
3 | |||
4 | #include <linux/percpu.h> | ||
5 | #include <asm/atomic.h> | ||
6 | |||
7 | typedef struct | ||
8 | { | ||
9 | atomic_long_t a; | ||
10 | } local_t; | ||
11 | |||
12 | #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } | ||
13 | |||
14 | #define local_read(l) atomic_long_read(&(l)->a) | ||
15 | #define local_set(l,i) atomic_long_set(&(l)->a, (i)) | ||
16 | |||
17 | #define local_add(i,l) atomic_long_add((i),(&(l)->a)) | ||
18 | #define local_sub(i,l) atomic_long_sub((i),(&(l)->a)) | ||
19 | #define local_inc(l) atomic_long_inc(&(l)->a) | ||
20 | #define local_dec(l) atomic_long_dec(&(l)->a) | ||
21 | |||
22 | static __inline__ long local_add_return(long a, local_t *l) | ||
23 | { | ||
24 | long t; | ||
25 | |||
26 | __asm__ __volatile__( | ||
27 | "1:" PPC_LLARX "%0,0,%2 # local_add_return\n\ | ||
28 | add %0,%1,%0\n" | ||
29 | PPC405_ERR77(0,%2) | ||
30 | PPC_STLCX "%0,0,%2 \n\ | ||
31 | bne- 1b" | ||
32 | : "=&r" (t) | ||
33 | : "r" (a), "r" (&(l->a.counter)) | ||
34 | : "cc", "memory"); | ||
35 | |||
36 | return t; | ||
37 | } | ||
38 | |||
39 | #define local_add_negative(a, l) (local_add_return((a), (l)) < 0) | ||
40 | |||
41 | static __inline__ long local_sub_return(long a, local_t *l) | ||
42 | { | ||
43 | long t; | ||
44 | |||
45 | __asm__ __volatile__( | ||
46 | "1:" PPC_LLARX "%0,0,%2 # local_sub_return\n\ | ||
47 | subf %0,%1,%0\n" | ||
48 | PPC405_ERR77(0,%2) | ||
49 | PPC_STLCX "%0,0,%2 \n\ | ||
50 | bne- 1b" | ||
51 | : "=&r" (t) | ||
52 | : "r" (a), "r" (&(l->a.counter)) | ||
53 | : "cc", "memory"); | ||
54 | |||
55 | return t; | ||
56 | } | ||
57 | |||
58 | static __inline__ long local_inc_return(local_t *l) | ||
59 | { | ||
60 | long t; | ||
61 | |||
62 | __asm__ __volatile__( | ||
63 | "1:" PPC_LLARX "%0,0,%1 # local_inc_return\n\ | ||
64 | addic %0,%0,1\n" | ||
65 | PPC405_ERR77(0,%1) | ||
66 | PPC_STLCX "%0,0,%1 \n\ | ||
67 | bne- 1b" | ||
68 | : "=&r" (t) | ||
69 | : "r" (&(l->a.counter)) | ||
70 | : "cc", "memory"); | ||
71 | |||
72 | return t; | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * local_inc_and_test - increment and test | ||
77 | * @l: pointer of type local_t | ||
78 | * | ||
79 | * Atomically increments @l by 1 | ||
80 | * and returns true if the result is zero, or false for all | ||
81 | * other cases. | ||
82 | */ | ||
83 | #define local_inc_and_test(l) (local_inc_return(l) == 0) | ||
84 | |||
85 | static __inline__ long local_dec_return(local_t *l) | ||
86 | { | ||
87 | long t; | ||
88 | |||
89 | __asm__ __volatile__( | ||
90 | "1:" PPC_LLARX "%0,0,%1 # local_dec_return\n\ | ||
91 | addic %0,%0,-1\n" | ||
92 | PPC405_ERR77(0,%1) | ||
93 | PPC_STLCX "%0,0,%1\n\ | ||
94 | bne- 1b" | ||
95 | : "=&r" (t) | ||
96 | : "r" (&(l->a.counter)) | ||
97 | : "cc", "memory"); | ||
98 | |||
99 | return t; | ||
100 | } | ||
101 | |||
102 | #define local_cmpxchg(l, o, n) \ | ||
103 | (cmpxchg_local(&((l)->a.counter), (o), (n))) | ||
104 | #define local_xchg(l, n) (xchg_local(&((l)->a.counter), (n))) | ||
105 | |||
106 | /** | ||
107 | * local_add_unless - add unless the number is a given value | ||
108 | * @l: pointer of type local_t | ||
109 | * @a: the amount to add to v... | ||
110 | * @u: ...unless v is equal to u. | ||
111 | * | ||
112 | * Atomically adds @a to @l, so long as it was not @u. | ||
113 | * Returns non-zero if @l was not @u, and zero otherwise. | ||
114 | */ | ||
115 | static __inline__ int local_add_unless(local_t *l, long a, long u) | ||
116 | { | ||
117 | long t; | ||
118 | |||
119 | __asm__ __volatile__ ( | ||
120 | "1:" PPC_LLARX "%0,0,%1 # local_add_unless\n\ | ||
121 | cmpw 0,%0,%3 \n\ | ||
122 | beq- 2f \n\ | ||
123 | add %0,%2,%0 \n" | ||
124 | PPC405_ERR77(0,%2) | ||
125 | PPC_STLCX "%0,0,%1 \n\ | ||
126 | bne- 1b \n" | ||
127 | " subf %0,%2,%0 \n\ | ||
128 | 2:" | ||
129 | : "=&r" (t) | ||
130 | : "r" (&(l->a.counter)), "r" (a), "r" (u) | ||
131 | : "cc", "memory"); | ||
132 | |||
133 | return t != u; | ||
134 | } | ||
135 | |||
136 | #define local_inc_not_zero(l) local_add_unless((l), 1, 0) | ||
137 | |||
138 | #define local_sub_and_test(a, l) (local_sub_return((a), (l)) == 0) | ||
139 | #define local_dec_and_test(l) (local_dec_return((l)) == 0) | ||
140 | |||
141 | /* | ||
142 | * Atomically test *l and decrement if it is greater than 0. | ||
143 | * The function returns the old value of *l minus 1. | ||
144 | */ | ||
145 | static __inline__ long local_dec_if_positive(local_t *l) | ||
146 | { | ||
147 | long t; | ||
148 | |||
149 | __asm__ __volatile__( | ||
150 | "1:" PPC_LLARX "%0,0,%1 # local_dec_if_positive\n\ | ||
151 | cmpwi %0,1\n\ | ||
152 | addi %0,%0,-1\n\ | ||
153 | blt- 2f\n" | ||
154 | PPC405_ERR77(0,%1) | ||
155 | PPC_STLCX "%0,0,%1\n\ | ||
156 | bne- 1b" | ||
157 | "\n\ | ||
158 | 2:" : "=&b" (t) | ||
159 | : "r" (&(l->a.counter)) | ||
160 | : "cc", "memory"); | ||
161 | |||
162 | return t; | ||
163 | } | ||
164 | |||
165 | /* Use these for per-cpu local_t variables: on some archs they are | ||
166 | * much more efficient than these naive implementations. Note they take | ||
167 | * a variable, not an address. | ||
168 | */ | ||
169 | |||
170 | #define __local_inc(l) ((l)->a.counter++) | ||
171 | #define __local_dec(l) ((l)->a.counter++) | ||
172 | #define __local_add(i,l) ((l)->a.counter+=(i)) | ||
173 | #define __local_sub(i,l) ((l)->a.counter-=(i)) | ||
174 | |||
175 | /* Need to disable preemption for the cpu local counters otherwise we could | ||
176 | still access a variable of a previous CPU in a non atomic way. */ | ||
177 | #define cpu_local_wrap_v(l) \ | ||
178 | ({ local_t res__; \ | ||
179 | preempt_disable(); \ | ||
180 | res__ = (l); \ | ||
181 | preempt_enable(); \ | ||
182 | res__; }) | ||
183 | #define cpu_local_wrap(l) \ | ||
184 | ({ preempt_disable(); \ | ||
185 | l; \ | ||
186 | preempt_enable(); }) \ | ||
187 | |||
188 | #define cpu_local_read(l) cpu_local_wrap_v(local_read(&__get_cpu_var(l))) | ||
189 | #define cpu_local_set(l, i) cpu_local_wrap(local_set(&__get_cpu_var(l), (i))) | ||
190 | #define cpu_local_inc(l) cpu_local_wrap(local_inc(&__get_cpu_var(l))) | ||
191 | #define cpu_local_dec(l) cpu_local_wrap(local_dec(&__get_cpu_var(l))) | ||
192 | #define cpu_local_add(i, l) cpu_local_wrap(local_add((i), &__get_cpu_var(l))) | ||
193 | #define cpu_local_sub(i, l) cpu_local_wrap(local_sub((i), &__get_cpu_var(l))) | ||
194 | |||
195 | #define __cpu_local_inc(l) cpu_local_inc(l) | ||
196 | #define __cpu_local_dec(l) cpu_local_dec(l) | ||
197 | #define __cpu_local_add(i, l) cpu_local_add((i), (l)) | ||
198 | #define __cpu_local_sub(i, l) cpu_local_sub((i), (l)) | ||
199 | |||
200 | #endif /* _ARCH_POWERPC_LOCAL_H */ | ||
diff --git a/include/asm-powerpc/parport.h b/include/asm-powerpc/parport.h index b37b81e37278..414c50e2e881 100644 --- a/include/asm-powerpc/parport.h +++ b/include/asm-powerpc/parport.h | |||
@@ -12,11 +12,6 @@ | |||
12 | 12 | ||
13 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
14 | 14 | ||
15 | extern struct parport *parport_pc_probe_port (unsigned long int base, | ||
16 | unsigned long int base_hi, | ||
17 | int irq, int dma, | ||
18 | struct pci_dev *dev); | ||
19 | |||
20 | static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) | 15 | static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) |
21 | { | 16 | { |
22 | struct device_node *np; | 17 | struct device_node *np; |
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index d3e0906ff2bc..09621f611dbc 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | 8 | ||
9 | #include <asm/hw_irq.h> | 9 | #include <asm/hw_irq.h> |
10 | #include <asm/atomic.h> | ||
11 | 10 | ||
12 | /* | 11 | /* |
13 | * Memory barrier. | 12 | * Memory barrier. |
@@ -227,6 +226,29 @@ __xchg_u32(volatile void *p, unsigned long val) | |||
227 | return prev; | 226 | return prev; |
228 | } | 227 | } |
229 | 228 | ||
229 | /* | ||
230 | * Atomic exchange | ||
231 | * | ||
232 | * Changes the memory location '*ptr' to be val and returns | ||
233 | * the previous value stored there. | ||
234 | */ | ||
235 | static __inline__ unsigned long | ||
236 | __xchg_u32_local(volatile void *p, unsigned long val) | ||
237 | { | ||
238 | unsigned long prev; | ||
239 | |||
240 | __asm__ __volatile__( | ||
241 | "1: lwarx %0,0,%2 \n" | ||
242 | PPC405_ERR77(0,%2) | ||
243 | " stwcx. %3,0,%2 \n\ | ||
244 | bne- 1b" | ||
245 | : "=&r" (prev), "+m" (*(volatile unsigned int *)p) | ||
246 | : "r" (p), "r" (val) | ||
247 | : "cc", "memory"); | ||
248 | |||
249 | return prev; | ||
250 | } | ||
251 | |||
230 | #ifdef CONFIG_PPC64 | 252 | #ifdef CONFIG_PPC64 |
231 | static __inline__ unsigned long | 253 | static __inline__ unsigned long |
232 | __xchg_u64(volatile void *p, unsigned long val) | 254 | __xchg_u64(volatile void *p, unsigned long val) |
@@ -246,6 +268,23 @@ __xchg_u64(volatile void *p, unsigned long val) | |||
246 | 268 | ||
247 | return prev; | 269 | return prev; |
248 | } | 270 | } |
271 | |||
272 | static __inline__ unsigned long | ||
273 | __xchg_u64_local(volatile void *p, unsigned long val) | ||
274 | { | ||
275 | unsigned long prev; | ||
276 | |||
277 | __asm__ __volatile__( | ||
278 | "1: ldarx %0,0,%2 \n" | ||
279 | PPC405_ERR77(0,%2) | ||
280 | " stdcx. %3,0,%2 \n\ | ||
281 | bne- 1b" | ||
282 | : "=&r" (prev), "+m" (*(volatile unsigned long *)p) | ||
283 | : "r" (p), "r" (val) | ||
284 | : "cc", "memory"); | ||
285 | |||
286 | return prev; | ||
287 | } | ||
249 | #endif | 288 | #endif |
250 | 289 | ||
251 | /* | 290 | /* |
@@ -269,13 +308,32 @@ __xchg(volatile void *ptr, unsigned long x, unsigned int size) | |||
269 | return x; | 308 | return x; |
270 | } | 309 | } |
271 | 310 | ||
311 | static __inline__ unsigned long | ||
312 | __xchg_local(volatile void *ptr, unsigned long x, unsigned int size) | ||
313 | { | ||
314 | switch (size) { | ||
315 | case 4: | ||
316 | return __xchg_u32_local(ptr, x); | ||
317 | #ifdef CONFIG_PPC64 | ||
318 | case 8: | ||
319 | return __xchg_u64_local(ptr, x); | ||
320 | #endif | ||
321 | } | ||
322 | __xchg_called_with_bad_pointer(); | ||
323 | return x; | ||
324 | } | ||
272 | #define xchg(ptr,x) \ | 325 | #define xchg(ptr,x) \ |
273 | ({ \ | 326 | ({ \ |
274 | __typeof__(*(ptr)) _x_ = (x); \ | 327 | __typeof__(*(ptr)) _x_ = (x); \ |
275 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ | 328 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ |
276 | }) | 329 | }) |
277 | 330 | ||
278 | #define tas(ptr) (xchg((ptr),1)) | 331 | #define xchg_local(ptr,x) \ |
332 | ({ \ | ||
333 | __typeof__(*(ptr)) _x_ = (x); \ | ||
334 | (__typeof__(*(ptr))) __xchg_local((ptr), \ | ||
335 | (unsigned long)_x_, sizeof(*(ptr))); \ | ||
336 | }) | ||
279 | 337 | ||
280 | /* | 338 | /* |
281 | * Compare and exchange - if *p == old, set it to new, | 339 | * Compare and exchange - if *p == old, set it to new, |
@@ -306,6 +364,28 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new) | |||
306 | return prev; | 364 | return prev; |
307 | } | 365 | } |
308 | 366 | ||
367 | static __inline__ unsigned long | ||
368 | __cmpxchg_u32_local(volatile unsigned int *p, unsigned long old, | ||
369 | unsigned long new) | ||
370 | { | ||
371 | unsigned int prev; | ||
372 | |||
373 | __asm__ __volatile__ ( | ||
374 | "1: lwarx %0,0,%2 # __cmpxchg_u32\n\ | ||
375 | cmpw 0,%0,%3\n\ | ||
376 | bne- 2f\n" | ||
377 | PPC405_ERR77(0,%2) | ||
378 | " stwcx. %4,0,%2\n\ | ||
379 | bne- 1b" | ||
380 | "\n\ | ||
381 | 2:" | ||
382 | : "=&r" (prev), "+m" (*p) | ||
383 | : "r" (p), "r" (old), "r" (new) | ||
384 | : "cc", "memory"); | ||
385 | |||
386 | return prev; | ||
387 | } | ||
388 | |||
309 | #ifdef CONFIG_PPC64 | 389 | #ifdef CONFIG_PPC64 |
310 | static __inline__ unsigned long | 390 | static __inline__ unsigned long |
311 | __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) | 391 | __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) |
@@ -328,6 +408,27 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new) | |||
328 | 408 | ||
329 | return prev; | 409 | return prev; |
330 | } | 410 | } |
411 | |||
412 | static __inline__ unsigned long | ||
413 | __cmpxchg_u64_local(volatile unsigned long *p, unsigned long old, | ||
414 | unsigned long new) | ||
415 | { | ||
416 | unsigned long prev; | ||
417 | |||
418 | __asm__ __volatile__ ( | ||
419 | "1: ldarx %0,0,%2 # __cmpxchg_u64\n\ | ||
420 | cmpd 0,%0,%3\n\ | ||
421 | bne- 2f\n\ | ||
422 | stdcx. %4,0,%2\n\ | ||
423 | bne- 1b" | ||
424 | "\n\ | ||
425 | 2:" | ||
426 | : "=&r" (prev), "+m" (*p) | ||
427 | : "r" (p), "r" (old), "r" (new) | ||
428 | : "cc", "memory"); | ||
429 | |||
430 | return prev; | ||
431 | } | ||
331 | #endif | 432 | #endif |
332 | 433 | ||
333 | /* This function doesn't exist, so you'll get a linker error | 434 | /* This function doesn't exist, so you'll get a linker error |
@@ -350,6 +451,22 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, | |||
350 | return old; | 451 | return old; |
351 | } | 452 | } |
352 | 453 | ||
454 | static __inline__ unsigned long | ||
455 | __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new, | ||
456 | unsigned int size) | ||
457 | { | ||
458 | switch (size) { | ||
459 | case 4: | ||
460 | return __cmpxchg_u32_local(ptr, old, new); | ||
461 | #ifdef CONFIG_PPC64 | ||
462 | case 8: | ||
463 | return __cmpxchg_u64_local(ptr, old, new); | ||
464 | #endif | ||
465 | } | ||
466 | __cmpxchg_called_with_bad_pointer(); | ||
467 | return old; | ||
468 | } | ||
469 | |||
353 | #define cmpxchg(ptr,o,n) \ | 470 | #define cmpxchg(ptr,o,n) \ |
354 | ({ \ | 471 | ({ \ |
355 | __typeof__(*(ptr)) _o_ = (o); \ | 472 | __typeof__(*(ptr)) _o_ = (o); \ |
@@ -358,6 +475,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, | |||
358 | (unsigned long)_n_, sizeof(*(ptr))); \ | 475 | (unsigned long)_n_, sizeof(*(ptr))); \ |
359 | }) | 476 | }) |
360 | 477 | ||
478 | |||
479 | #define cmpxchg_local(ptr,o,n) \ | ||
480 | ({ \ | ||
481 | __typeof__(*(ptr)) _o_ = (o); \ | ||
482 | __typeof__(*(ptr)) _n_ = (n); \ | ||
483 | (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ | ||
484 | (unsigned long)_n_, sizeof(*(ptr))); \ | ||
485 | }) | ||
486 | |||
361 | #ifdef CONFIG_PPC64 | 487 | #ifdef CONFIG_PPC64 |
362 | /* | 488 | /* |
363 | * We handle most unaligned accesses in hardware. On the other hand | 489 | * We handle most unaligned accesses in hardware. On the other hand |