Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / include / asm-arm / locks.h
1 /*
2  *  linux/include/asm-arm/locks.h
3  *
4  *  Copyright (C) 2000 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  *  Interrupt safe locking assembler. 
11  */
12 #ifndef __ASM_PROC_LOCKS_H
13 #define __ASM_PROC_LOCKS_H
14
15 #if __LINUX_ARM_ARCH__ >= 6
16
17 #define __down_op(ptr,fail)                     \
18         ({                                      \
19         __asm__ __volatile__(                   \
20         "@ down_op\n"                           \
21 "1:     ldrex   lr, [%0]\n"                     \
22 "       sub     lr, lr, %1\n"                   \
23 "       strex   ip, lr, [%0]\n"                 \
24 "       teq     ip, #0\n"                       \
25 "       bne     1b\n"                           \
26 "       teq     lr, #0\n"                       \
27 "       movmi   ip, %0\n"                       \
28 "       blmi    " #fail                         \
29         :                                       \
30         : "r" (ptr), "I" (1)                    \
31         : "ip", "lr", "cc");                    \
32         smp_mb();                               \
33         })
34
35 #define __down_op_ret(ptr,fail)                 \
36         ({                                      \
37                 unsigned int ret;               \
38         __asm__ __volatile__(                   \
39         "@ down_op_ret\n"                       \
40 "1:     ldrex   lr, [%1]\n"                     \
41 "       sub     lr, lr, %2\n"                   \
42 "       strex   ip, lr, [%1]\n"                 \
43 "       teq     ip, #0\n"                       \
44 "       bne     1b\n"                           \
45 "       teq     lr, #0\n"                       \
46 "       movmi   ip, %1\n"                       \
47 "       movpl   ip, #0\n"                       \
48 "       blmi    " #fail "\n"                    \
49 "       mov     %0, ip"                         \
50         : "=&r" (ret)                           \
51         : "r" (ptr), "I" (1)                    \
52         : "ip", "lr", "cc");                    \
53         smp_mb();                               \
54         ret;                                    \
55         })
56
57 #define __up_op(ptr,wake)                       \
58         ({                                      \
59         smp_mb();                               \
60         __asm__ __volatile__(                   \
61         "@ up_op\n"                             \
62 "1:     ldrex   lr, [%0]\n"                     \
63 "       add     lr, lr, %1\n"                   \
64 "       strex   ip, lr, [%0]\n"                 \
65 "       teq     ip, #0\n"                       \
66 "       bne     1b\n"                           \
67 "       cmp     lr, #0\n"                       \
68 "       movle   ip, %0\n"                       \
69 "       blle    " #wake                         \
70         :                                       \
71         : "r" (ptr), "I" (1)                    \
72         : "ip", "lr", "cc");                    \
73         })
74
75 /*
76  * The value 0x01000000 supports up to 128 processors and
77  * lots of processes.  BIAS must be chosen such that sub'ing
78  * BIAS once per CPU will result in the long remaining
79  * negative.
80  */
81 #define RW_LOCK_BIAS      0x01000000
82 #define RW_LOCK_BIAS_STR "0x01000000"
83
84 #define __down_op_write(ptr,fail)               \
85         ({                                      \
86         __asm__ __volatile__(                   \
87         "@ down_op_write\n"                     \
88 "1:     ldrex   lr, [%0]\n"                     \
89 "       sub     lr, lr, %1\n"                   \
90 "       strex   ip, lr, [%0]\n"                 \
91 "       teq     ip, #0\n"                       \
92 "       bne     1b\n"                           \
93 "       teq     lr, #0\n"                       \
94 "       movne   ip, %0\n"                       \
95 "       blne    " #fail                         \
96         :                                       \
97         : "r" (ptr), "I" (RW_LOCK_BIAS)         \
98         : "ip", "lr", "cc");                    \
99         smp_mb();                               \
100         })
101
102 #define __up_op_write(ptr,wake)                 \
103         ({                                      \
104         smp_mb();                               \
105         __asm__ __volatile__(                   \
106         "@ up_op_write\n"                       \
107 "1:     ldrex   lr, [%0]\n"                     \
108 "       adds    lr, lr, %1\n"                   \
109 "       strex   ip, lr, [%0]\n"                 \
110 "       teq     ip, #0\n"                       \
111 "       bne     1b\n"                           \
112 "       movcs   ip, %0\n"                       \
113 "       blcs    " #wake                         \
114         :                                       \
115         : "r" (ptr), "I" (RW_LOCK_BIAS)         \
116         : "ip", "lr", "cc");                    \
117         })
118
119 #define __down_op_read(ptr,fail)                \
120         __down_op(ptr, fail)
121
122 #define __up_op_read(ptr,wake)                  \
123         ({                                      \
124         smp_mb();                               \
125         __asm__ __volatile__(                   \
126         "@ up_op_read\n"                        \
127 "1:     ldrex   lr, [%0]\n"                     \
128 "       add     lr, lr, %1\n"                   \
129 "       strex   ip, lr, [%0]\n"                 \
130 "       teq     ip, #0\n"                       \
131 "       bne     1b\n"                           \
132 "       teq     lr, #0\n"                       \
133 "       moveq   ip, %0\n"                       \
134 "       bleq    " #wake                         \
135         :                                       \
136         : "r" (ptr), "I" (1)                    \
137         : "ip", "lr", "cc");                    \
138         })
139
140 #else
141
142 #define __down_op(ptr,fail)                     \
143         ({                                      \
144         __asm__ __volatile__(                   \
145         "@ down_op\n"                           \
146 "       mrs     ip, cpsr\n"                     \
147 "       orr     lr, ip, #128\n"                 \
148 "       msr     cpsr_c, lr\n"                   \
149 "       ldr     lr, [%0]\n"                     \
150 "       subs    lr, lr, %1\n"                   \
151 "       str     lr, [%0]\n"                     \
152 "       msr     cpsr_c, ip\n"                   \
153 "       movmi   ip, %0\n"                       \
154 "       blmi    " #fail                         \
155         :                                       \
156         : "r" (ptr), "I" (1)                    \
157         : "ip", "lr", "cc");                    \
158         smp_mb();                               \
159         })
160
161 #define __down_op_ret(ptr,fail)                 \
162         ({                                      \
163                 unsigned int ret;               \
164         __asm__ __volatile__(                   \
165         "@ down_op_ret\n"                       \
166 "       mrs     ip, cpsr\n"                     \
167 "       orr     lr, ip, #128\n"                 \
168 "       msr     cpsr_c, lr\n"                   \
169 "       ldr     lr, [%1]\n"                     \
170 "       subs    lr, lr, %2\n"                   \
171 "       str     lr, [%1]\n"                     \
172 "       msr     cpsr_c, ip\n"                   \
173 "       movmi   ip, %1\n"                       \
174 "       movpl   ip, #0\n"                       \
175 "       blmi    " #fail "\n"                    \
176 "       mov     %0, ip"                         \
177         : "=&r" (ret)                           \
178         : "r" (ptr), "I" (1)                    \
179         : "ip", "lr", "cc");                    \
180         smp_mb();                               \
181         ret;                                    \
182         })
183
184 #define __up_op(ptr,wake)                       \
185         ({                                      \
186         smp_mb();                               \
187         __asm__ __volatile__(                   \
188         "@ up_op\n"                             \
189 "       mrs     ip, cpsr\n"                     \
190 "       orr     lr, ip, #128\n"                 \
191 "       msr     cpsr_c, lr\n"                   \
192 "       ldr     lr, [%0]\n"                     \
193 "       adds    lr, lr, %1\n"                   \
194 "       str     lr, [%0]\n"                     \
195 "       msr     cpsr_c, ip\n"                   \
196 "       movle   ip, %0\n"                       \
197 "       blle    " #wake                         \
198         :                                       \
199         : "r" (ptr), "I" (1)                    \
200         : "ip", "lr", "cc");                    \
201         })
202
203 /*
204  * The value 0x01000000 supports up to 128 processors and
205  * lots of processes.  BIAS must be chosen such that sub'ing
206  * BIAS once per CPU will result in the long remaining
207  * negative.
208  */
209 #define RW_LOCK_BIAS      0x01000000
210 #define RW_LOCK_BIAS_STR "0x01000000"
211
212 #define __down_op_write(ptr,fail)               \
213         ({                                      \
214         __asm__ __volatile__(                   \
215         "@ down_op_write\n"                     \
216 "       mrs     ip, cpsr\n"                     \
217 "       orr     lr, ip, #128\n"                 \
218 "       msr     cpsr_c, lr\n"                   \
219 "       ldr     lr, [%0]\n"                     \
220 "       subs    lr, lr, %1\n"                   \
221 "       str     lr, [%0]\n"                     \
222 "       msr     cpsr_c, ip\n"                   \
223 "       movne   ip, %0\n"                       \
224 "       blne    " #fail                         \
225         :                                       \
226         : "r" (ptr), "I" (RW_LOCK_BIAS)         \
227         : "ip", "lr", "cc");                    \
228         smp_mb();                               \
229         })
230
231 #define __up_op_write(ptr,wake)                 \
232         ({                                      \
233         __asm__ __volatile__(                   \
234         "@ up_op_write\n"                       \
235 "       mrs     ip, cpsr\n"                     \
236 "       orr     lr, ip, #128\n"                 \
237 "       msr     cpsr_c, lr\n"                   \
238 "       ldr     lr, [%0]\n"                     \
239 "       adds    lr, lr, %1\n"                   \
240 "       str     lr, [%0]\n"                     \
241 "       msr     cpsr_c, ip\n"                   \
242 "       movcs   ip, %0\n"                       \
243 "       blcs    " #wake                         \
244         :                                       \
245         : "r" (ptr), "I" (RW_LOCK_BIAS)         \
246         : "ip", "lr", "cc");                    \
247         smp_mb();                               \
248         })
249
250 #define __down_op_read(ptr,fail)                \
251         __down_op(ptr, fail)
252
253 #define __up_op_read(ptr,wake)                  \
254         ({                                      \
255         smp_mb();                               \
256         __asm__ __volatile__(                   \
257         "@ up_op_read\n"                        \
258 "       mrs     ip, cpsr\n"                     \
259 "       orr     lr, ip, #128\n"                 \
260 "       msr     cpsr_c, lr\n"                   \
261 "       ldr     lr, [%0]\n"                     \
262 "       adds    lr, lr, %1\n"                   \
263 "       str     lr, [%0]\n"                     \
264 "       msr     cpsr_c, ip\n"                   \
265 "       moveq   ip, %0\n"                       \
266 "       bleq    " #wake                         \
267         :                                       \
268         : "r" (ptr), "I" (1)                    \
269         : "ip", "lr", "cc");                    \
270         })
271
272 #endif
273
274 #endif