Merge tag 'nfs-for-3.8-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[firefly-linux-kernel-4.4.55.git] / include / linux / hwspinlock.h
1 /*
2  * Hardware spinlock public header
3  *
4  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
5  *
6  * Contact: Ohad Ben-Cohen <ohad@wizery.com>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License version 2 as published
10  * by the Free Software Foundation.
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
18 #ifndef __LINUX_HWSPINLOCK_H
19 #define __LINUX_HWSPINLOCK_H
20
21 #include <linux/err.h>
22 #include <linux/sched.h>
23
24 /* hwspinlock mode argument */
25 #define HWLOCK_IRQSTATE 0x01    /* Disable interrupts, save state */
26 #define HWLOCK_IRQ      0x02    /* Disable interrupts, don't save state */
27
28 struct device;
29 struct hwspinlock;
30 struct hwspinlock_device;
31 struct hwspinlock_ops;
32
33 /**
34  * struct hwspinlock_pdata - platform data for hwspinlock drivers
35  * @base_id: base id for this hwspinlock device
36  *
37  * hwspinlock devices provide system-wide hardware locks that are used
38  * by remote processors that have no other way to achieve synchronization.
39  *
40  * To achieve that, each physical lock must have a system-wide id number
41  * that is agreed upon, otherwise remote processors can't possibly assume
42  * they're using the same hardware lock.
43  *
44  * Usually boards have a single hwspinlock device, which provides several
45  * hwspinlocks, and in this case, they can be trivially numbered 0 to
46  * (num-of-locks - 1).
47  *
48  * In case boards have several hwspinlocks devices, a different base id
49  * should be used for each hwspinlock device (they can't all use 0 as
50  * a starting id!).
51  *
52  * This platform data structure should be used to provide the base id
53  * for each device (which is trivially 0 when only a single hwspinlock
54  * device exists). It can be shared between different platforms, hence
55  * its location.
56  */
57 struct hwspinlock_pdata {
58         int base_id;
59 };
60
61 #if defined(CONFIG_HWSPINLOCK) || defined(CONFIG_HWSPINLOCK_MODULE)
62
63 int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
64                 const struct hwspinlock_ops *ops, int base_id, int num_locks);
65 int hwspin_lock_unregister(struct hwspinlock_device *bank);
66 struct hwspinlock *hwspin_lock_request(void);
67 struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
68 int hwspin_lock_free(struct hwspinlock *hwlock);
69 int hwspin_lock_get_id(struct hwspinlock *hwlock);
70 int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int,
71                                                         unsigned long *);
72 int __hwspin_trylock(struct hwspinlock *, int, unsigned long *);
73 void __hwspin_unlock(struct hwspinlock *, int, unsigned long *);
74
75 #else /* !CONFIG_HWSPINLOCK */
76
77 /*
78  * We don't want these functions to fail if CONFIG_HWSPINLOCK is not
79  * enabled. We prefer to silently succeed in this case, and let the
80  * code path get compiled away. This way, if CONFIG_HWSPINLOCK is not
81  * required on a given setup, users will still work.
82  *
83  * The only exception is hwspin_lock_register/hwspin_lock_unregister, with which
84  * we _do_ want users to fail (no point in registering hwspinlock instances if
85  * the framework is not available).
86  *
87  * Note: ERR_PTR(-ENODEV) will still be considered a success for NULL-checking
88  * users. Others, which care, can still check this with IS_ERR.
89  */
90 static inline struct hwspinlock *hwspin_lock_request(void)
91 {
92         return ERR_PTR(-ENODEV);
93 }
94
95 static inline struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
96 {
97         return ERR_PTR(-ENODEV);
98 }
99
100 static inline int hwspin_lock_free(struct hwspinlock *hwlock)
101 {
102         return 0;
103 }
104
105 static inline
106 int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to,
107                                         int mode, unsigned long *flags)
108 {
109         return 0;
110 }
111
112 static inline
113 int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
114 {
115         return 0;
116 }
117
118 static inline
119 void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
120 {
121 }
122
123 static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
124 {
125         return 0;
126 }
127
128 #endif /* !CONFIG_HWSPINLOCK */
129
130 /**
131  * hwspin_trylock_irqsave() - try to lock an hwspinlock, disable interrupts
132  * @hwlock: an hwspinlock which we want to trylock
133  * @flags: a pointer to where the caller's interrupt state will be saved at
134  *
135  * This function attempts to lock the underlying hwspinlock, and will
136  * immediately fail if the hwspinlock is already locked.
137  *
138  * Upon a successful return from this function, preemption and local
139  * interrupts are disabled (previous interrupts state is saved at @flags),
140  * so the caller must not sleep, and is advised to release the hwspinlock
141  * as soon as possible.
142  *
143  * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
144  * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
145  */
146 static inline
147 int hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags)
148 {
149         return __hwspin_trylock(hwlock, HWLOCK_IRQSTATE, flags);
150 }
151
152 /**
153  * hwspin_trylock_irq() - try to lock an hwspinlock, disable interrupts
154  * @hwlock: an hwspinlock which we want to trylock
155  *
156  * This function attempts to lock the underlying hwspinlock, and will
157  * immediately fail if the hwspinlock is already locked.
158  *
159  * Upon a successful return from this function, preemption and local
160  * interrupts are disabled, so the caller must not sleep, and is advised
161  * to release the hwspinlock as soon as possible.
162  *
163  * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
164  * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
165  */
166 static inline int hwspin_trylock_irq(struct hwspinlock *hwlock)
167 {
168         return __hwspin_trylock(hwlock, HWLOCK_IRQ, NULL);
169 }
170
171 /**
172  * hwspin_trylock() - attempt to lock a specific hwspinlock
173  * @hwlock: an hwspinlock which we want to trylock
174  *
175  * This function attempts to lock an hwspinlock, and will immediately fail
176  * if the hwspinlock is already taken.
177  *
178  * Upon a successful return from this function, preemption is disabled,
179  * so the caller must not sleep, and is advised to release the hwspinlock
180  * as soon as possible. This is required in order to minimize remote cores
181  * polling on the hardware interconnect.
182  *
183  * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
184  * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
185  */
186 static inline int hwspin_trylock(struct hwspinlock *hwlock)
187 {
188         return __hwspin_trylock(hwlock, 0, NULL);
189 }
190
191 /**
192  * hwspin_lock_timeout_irqsave() - lock hwspinlock, with timeout, disable irqs
193  * @hwlock: the hwspinlock to be locked
194  * @to: timeout value in msecs
195  * @flags: a pointer to where the caller's interrupt state will be saved at
196  *
197  * This function locks the underlying @hwlock. If the @hwlock
198  * is already taken, the function will busy loop waiting for it to
199  * be released, but give up when @timeout msecs have elapsed.
200  *
201  * Upon a successful return from this function, preemption and local interrupts
202  * are disabled (plus previous interrupt state is saved), so the caller must
203  * not sleep, and is advised to release the hwspinlock as soon as possible.
204  *
205  * Returns 0 when the @hwlock was successfully taken, and an appropriate
206  * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
207  * busy after @timeout msecs). The function will never sleep.
208  */
209 static inline int hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock,
210                                 unsigned int to, unsigned long *flags)
211 {
212         return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQSTATE, flags);
213 }
214
215 /**
216  * hwspin_lock_timeout_irq() - lock hwspinlock, with timeout, disable irqs
217  * @hwlock: the hwspinlock to be locked
218  * @to: timeout value in msecs
219  *
220  * This function locks the underlying @hwlock. If the @hwlock
221  * is already taken, the function will busy loop waiting for it to
222  * be released, but give up when @timeout msecs have elapsed.
223  *
224  * Upon a successful return from this function, preemption and local interrupts
225  * are disabled so the caller must not sleep, and is advised to release the
226  * hwspinlock as soon as possible.
227  *
228  * Returns 0 when the @hwlock was successfully taken, and an appropriate
229  * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
230  * busy after @timeout msecs). The function will never sleep.
231  */
232 static inline
233 int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int to)
234 {
235         return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQ, NULL);
236 }
237
238 /**
239  * hwspin_lock_timeout() - lock an hwspinlock with timeout limit
240  * @hwlock: the hwspinlock to be locked
241  * @to: timeout value in msecs
242  *
243  * This function locks the underlying @hwlock. If the @hwlock
244  * is already taken, the function will busy loop waiting for it to
245  * be released, but give up when @timeout msecs have elapsed.
246  *
247  * Upon a successful return from this function, preemption is disabled
248  * so the caller must not sleep, and is advised to release the hwspinlock
249  * as soon as possible.
250  * This is required in order to minimize remote cores polling on the
251  * hardware interconnect.
252  *
253  * Returns 0 when the @hwlock was successfully taken, and an appropriate
254  * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
255  * busy after @timeout msecs). The function will never sleep.
256  */
257 static inline
258 int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to)
259 {
260         return __hwspin_lock_timeout(hwlock, to, 0, NULL);
261 }
262
263 /**
264  * hwspin_unlock_irqrestore() - unlock hwspinlock, restore irq state
265  * @hwlock: a previously-acquired hwspinlock which we want to unlock
266  * @flags: previous caller's interrupt state to restore
267  *
268  * This function will unlock a specific hwspinlock, enable preemption and
269  * restore the previous state of the local interrupts. It should be used
270  * to undo, e.g., hwspin_trylock_irqsave().
271  *
272  * @hwlock must be already locked before calling this function: it is a bug
273  * to call unlock on a @hwlock that is already unlocked.
274  */
275 static inline void hwspin_unlock_irqrestore(struct hwspinlock *hwlock,
276                                                         unsigned long *flags)
277 {
278         __hwspin_unlock(hwlock, HWLOCK_IRQSTATE, flags);
279 }
280
281 /**
282  * hwspin_unlock_irq() - unlock hwspinlock, enable interrupts
283  * @hwlock: a previously-acquired hwspinlock which we want to unlock
284  *
285  * This function will unlock a specific hwspinlock, enable preemption and
286  * enable local interrupts. Should be used to undo hwspin_lock_irq().
287  *
288  * @hwlock must be already locked (e.g. by hwspin_trylock_irq()) before
289  * calling this function: it is a bug to call unlock on a @hwlock that is
290  * already unlocked.
291  */
292 static inline void hwspin_unlock_irq(struct hwspinlock *hwlock)
293 {
294         __hwspin_unlock(hwlock, HWLOCK_IRQ, NULL);
295 }
296
297 /**
298  * hwspin_unlock() - unlock hwspinlock
299  * @hwlock: a previously-acquired hwspinlock which we want to unlock
300  *
301  * This function will unlock a specific hwspinlock and enable preemption
302  * back.
303  *
304  * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling
305  * this function: it is a bug to call unlock on a @hwlock that is already
306  * unlocked.
307  */
308 static inline void hwspin_unlock(struct hwspinlock *hwlock)
309 {
310         __hwspin_unlock(hwlock, 0, NULL);
311 }
312
313 #endif /* __LINUX_HWSPINLOCK_H */