Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / include / asm-arm / locks.h
blob852220eecdbc5d3147528bd6853f2a039ae91543
1 /*
2 * linux/include/asm-arm/locks.h
4 * Copyright (C) 2000 Russell King
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.
10 * Interrupt safe locking assembler.
12 #ifndef __ASM_PROC_LOCKS_H
13 #define __ASM_PROC_LOCKS_H
15 #if __LINUX_ARM_ARCH__ >= 6
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(); \
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; \
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"); \
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.
81 #define RW_LOCK_BIAS 0x01000000
82 #define RW_LOCK_BIAS_STR "0x01000000"
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(); \
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 \
115 : "r" (ptr), "I" (RW_LOCK_BIAS) \
116 : "ip", "lr", "cc"); \
119 #define __down_op_read(ptr,fail) \
120 __down_op(ptr, fail)
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 \
136 : "r" (ptr), "I" (1) \
137 : "ip", "lr", "cc"); \
140 #else
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 \
156 : "r" (ptr), "I" (1) \
157 : "ip", "lr", "cc"); \
158 smp_mb(); \
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; \
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 \
199 : "r" (ptr), "I" (1) \
200 : "ip", "lr", "cc"); \
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.
209 #define RW_LOCK_BIAS 0x01000000
210 #define RW_LOCK_BIAS_STR "0x01000000"
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 \
226 : "r" (ptr), "I" (RW_LOCK_BIAS) \
227 : "ip", "lr", "cc"); \
228 smp_mb(); \
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 \
245 : "r" (ptr), "I" (RW_LOCK_BIAS) \
246 : "ip", "lr", "cc"); \
247 smp_mb(); \
250 #define __down_op_read(ptr,fail) \
251 __down_op(ptr, fail)
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 \
268 : "r" (ptr), "I" (1) \
269 : "ip", "lr", "cc"); \
272 #endif
274 #endif