History

Merge tag 'hwlock-v5.3' of git://github.com/andersson/remoteproc

Pull hwspinlock updates from Bjorn Andersson: "This contains support for hardware spinlock TI K3 AM65x and J721E family of SoCs, support for using hwspinlocks from atomic context and better error reporting when dealing with hardware disabled in DeviceTree" * tag 'hwlock-v5.3' of git://github.com/andersson/remoteproc: hwspinlock: add the 'in_atomic' API hwspinlock: document the hwspinlock 'raw' API hwspinlock: stm32: implement the relax() ops hwspinlock: ignore disabled device hwspinlock/omap: Add a trace during probe hwspinlock/omap: Add support for TI K3 SoCs dt-bindings: hwlock: Update OMAP binding for TI K3 SoCs

Linus Torvalds committed 7 years ago

Commit 57ab5f72 parents fdcec00 360aa647 files · +206 −22Browse files

Unified · Split

7 files
  1. Documentation/devicetree/bindings/hwlock/omap-hwspinlock.txt +20 −5
  2. Documentation/hwspinlock.txt +81 −0
  3. drivers/hwspinlock/Kconfig +1 −1
  4. drivers/hwspinlock/hwspinlock_core.c +35 −13
  5. drivers/hwspinlock/omap_hwspinlock.c +4 −0
  6. drivers/hwspinlock/stm32_hwspinlock.c +7 −0
  7. include/linux/hwspinlock.h +58 −3
Documentation/devicetree/bindings/hwlock/omap-hwspinlock.txt+20−5
@@ -1,12 +1,16 @@
1OMAP4+ HwSpinlock Driver1TI HwSpinlock for OMAP and K3 based SoCs
2========================2=========================================
3 3
4Required properties:4Required properties:
5- compatible: Should be "ti,omap4-hwspinlock" for5- compatible: Should be one of the following,
6 OMAP44xx, OMAP54xx, AM33xx, AM43xx, DRA7xx SoCs6 "ti,omap4-hwspinlock" for
7 OMAP44xx, OMAP54xx, AM33xx, AM43xx, DRA7xx SoCs
8 "ti,am654-hwspinlock" for
9 K3 AM65x and J721E SoCs
7- reg: Contains the hwspinlock module register address space10- reg: Contains the hwspinlock module register address space
8 (base address and length)11 (base address and length)
9- ti,hwmods: Name of the hwmod associated with the hwspinlock device12- ti,hwmods: Name of the hwmod associated with the hwspinlock device
13 (for OMAP architecture based SoCs only)
10- #hwlock-cells: Should be 1. The OMAP hwspinlock users will use a14- #hwlock-cells: Should be 1. The OMAP hwspinlock users will use a
11 0-indexed relative hwlock number as the argument15 0-indexed relative hwlock number as the argument
12 specifier value for requesting a specific hwspinlock16 specifier value for requesting a specific hwspinlock
@@ -17,10 +21,21 @@ Please look at the generic hwlock binding for usage information for consumers, · 4 unmodified lines
17 21
18Example:22Example:
19 23
20/* OMAP4 */241. OMAP4 SoCs
21hwspinlock: spinlock@4a0f6000 {25hwspinlock: spinlock@4a0f6000 {
22 compatible = "ti,omap4-hwspinlock";26 compatible = "ti,omap4-hwspinlock";
23 reg = <0x4a0f6000 0x1000>;27 reg = <0x4a0f6000 0x1000>;
24 ti,hwmods = "spinlock";28 ti,hwmods = "spinlock";
25 #hwlock-cells = <1>;29 #hwlock-cells = <1>;
26};30};
31
322. AM65x SoCs and J721E SoCs
33&cbass_main {
34 cbass_main_navss: interconnect0 {
35 hwspinlock: spinlock@30e00000 {
36 compatible = "ti,am654-hwspinlock";
37 reg = <0x00 0x30e00000 0x00 0x1000>;
38 #hwlock-cells = <1>;
39 };
40 };
41};
Documentation/hwspinlock.txt+81−0
@@ -134,6 +134,39 @@ notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs). · 133 unmodified lines
134 134
135The function will never sleep.135The function will never sleep.
136 136
137::
138
139 int hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int timeout);
140
141Lock a previously-assigned hwspinlock with a timeout limit (specified in
142msecs). If the hwspinlock is already taken, the function will busy loop
143waiting for it to be released, but give up when the timeout elapses.
144
145Caution: User must protect the routine of getting hardware lock with mutex
146or spinlock to avoid dead-lock, that will let user can do some time-consuming
147or sleepable operations under the hardware lock.
148
149Returns 0 when successful and an appropriate error code otherwise (most
150notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
151
152The function will never sleep.
153
154::
155
156 int hwspin_lock_timeout_in_atomic(struct hwspinlock *hwlock, unsigned int to);
157
158Lock a previously-assigned hwspinlock with a timeout limit (specified in
159msecs). If the hwspinlock is already taken, the function will busy loop
160waiting for it to be released, but give up when the timeout elapses.
161
162This function shall be called only from an atomic context and the timeout
163value shall not exceed a few msecs.
164
165Returns 0 when successful and an appropriate error code otherwise (most
166notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
167
168The function will never sleep.
169
137::170::
138 171
139 int hwspin_trylock(struct hwspinlock *hwlock);172 int hwspin_trylock(struct hwspinlock *hwlock);
@@ -184,6 +217,34 @@ Returns 0 on success and an appropriate error code otherwise (most · 44 unmodified lines
184notably -EBUSY if the hwspinlock was already taken).217notably -EBUSY if the hwspinlock was already taken).
185The function will never sleep.218The function will never sleep.
186 219
220::
221
222 int hwspin_trylock_raw(struct hwspinlock *hwlock);
223
224Attempt to lock a previously-assigned hwspinlock, but immediately fail if
225it is already taken.
226
227Caution: User must protect the routine of getting hardware lock with mutex
228or spinlock to avoid dead-lock, that will let user can do some time-consuming
229or sleepable operations under the hardware lock.
230
231Returns 0 on success and an appropriate error code otherwise (most
232notably -EBUSY if the hwspinlock was already taken).
233The function will never sleep.
234
235::
236
237 int hwspin_trylock_in_atomic(struct hwspinlock *hwlock);
238
239Attempt to lock a previously-assigned hwspinlock, but immediately fail if
240it is already taken.
241
242This function shall be called only from an atomic context.
243
244Returns 0 on success and an appropriate error code otherwise (most
245notably -EBUSY if the hwspinlock was already taken).
246The function will never sleep.
247
187::248::
188 249
189 void hwspin_unlock(struct hwspinlock *hwlock);250 void hwspin_unlock(struct hwspinlock *hwlock);
@@ -220,6 +281,26 @@ Upon a successful return from this function, preemption is reenabled, · 30 unmodified lines
220and the state of the local interrupts is restored to the state saved at281and the state of the local interrupts is restored to the state saved at
221the given flags. This function will never sleep.282the given flags. This function will never sleep.
222 283
284::
285
286 void hwspin_unlock_raw(struct hwspinlock *hwlock);
287
288Unlock a previously-locked hwspinlock.
289
290The caller should **never** unlock an hwspinlock which is already unlocked.
291Doing so is considered a bug (there is no protection against this).
292This function will never sleep.
293
294::
295
296 void hwspin_unlock_in_atomic(struct hwspinlock *hwlock);
297
298Unlock a previously-locked hwspinlock.
299
300The caller should **never** unlock an hwspinlock which is already unlocked.
301Doing so is considered a bug (there is no protection against this).
302This function will never sleep.
303
223::304::
224 305
225 int hwspin_lock_get_id(struct hwspinlock *hwlock);306 int hwspin_lock_get_id(struct hwspinlock *hwlock);
drivers/hwspinlock/Kconfig+1−1
@@ -9,7 +9,7 @@ menuconfig HWSPINLOCK · 8 unmodified lines
9config HWSPINLOCK_OMAP9config HWSPINLOCK_OMAP
10 tristate "OMAP Hardware Spinlock device"10 tristate "OMAP Hardware Spinlock device"
11 depends on HWSPINLOCK11 depends on HWSPINLOCK
12 depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX12 depends on ARCH_OMAP4 || SOC_OMAP5 || SOC_DRA7XX || SOC_AM33XX || SOC_AM43XX || ARCH_K3
13 help13 help
14 Say y here to support the OMAP Hardware Spinlock device (firstly14 Say y here to support the OMAP Hardware Spinlock device (firstly
15 introduced in OMAP4).15 introduced in OMAP4).
drivers/hwspinlock/hwspinlock_core.c+35−13
@@ -9,6 +9,7 @@ · 8 unmodified lines
9 9
10#define pr_fmt(fmt) "%s: " fmt, __func__10#define pr_fmt(fmt) "%s: " fmt, __func__
11 11
12#include <linux/delay.h>
12#include <linux/kernel.h>13#include <linux/kernel.h>
13#include <linux/module.h>14#include <linux/module.h>
14#include <linux/spinlock.h>15#include <linux/spinlock.h>
@@ -23,6 +24,9 @@ · 8 unmodified lines
23 24
24#include "hwspinlock_internal.h"25#include "hwspinlock_internal.h"
25 26
27/* retry delay used in atomic context */
28#define HWSPINLOCK_RETRY_DELAY_US 100
29
26/* radix tree tags */30/* radix tree tags */
27#define HWSPINLOCK_UNUSED (0) /* tags an hwspinlock as unused */31#define HWSPINLOCK_UNUSED (0) /* tags an hwspinlock as unused */
28 32
@@ -68,11 +72,11 @@ static DEFINE_MUTEX(hwspinlock_tree_lock); · 39 unmodified lines
68 * user need some time-consuming or sleepable operations under the hardware72 * user need some time-consuming or sleepable operations under the hardware
69 * lock, they need one sleepable lock (like mutex) to protect the operations.73 * lock, they need one sleepable lock (like mutex) to protect the operations.
70 *74 *
71 * If the mode is not HWLOCK_RAW, upon a successful return from this function,75 * If the mode is neither HWLOCK_IN_ATOMIC nor HWLOCK_RAW, upon a successful
72 * preemption (and possibly interrupts) is disabled, so the caller must not76 * return from this function, preemption (and possibly interrupts) is disabled,
73 * sleep, and is advised to release the hwspinlock as soon as possible. This is77 * so the caller must not sleep, and is advised to release the hwspinlock as
74 * required in order to minimize remote cores polling on the hardware78 * soon as possible. This is required in order to minimize remote cores polling
75 * interconnect.79 * on the hardware interconnect.
76 *80 *
77 * The user decides whether local interrupts are disabled or not, and if yes,81 * The user decides whether local interrupts are disabled or not, and if yes,
78 * whether he wants their previous state to be saved. It is up to the user82 * whether he wants their previous state to be saved. It is up to the user
@@ -112,6 +116,7 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) · 33 unmodified lines
112 ret = spin_trylock_irq(&hwlock->lock);116 ret = spin_trylock_irq(&hwlock->lock);
113 break;117 break;
114 case HWLOCK_RAW:118 case HWLOCK_RAW:
119 case HWLOCK_IN_ATOMIC:
115 ret = 1;120 ret = 1;
116 break;121 break;
117 default:122 default:
@@ -136,6 +141,7 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags) · 18 unmodified lines
136 spin_unlock_irq(&hwlock->lock);141 spin_unlock_irq(&hwlock->lock);
137 break;142 break;
138 case HWLOCK_RAW:143 case HWLOCK_RAW:
144 case HWLOCK_IN_ATOMIC:
139 /* Nothing to do */145 /* Nothing to do */
140 break;146 break;
141 default:147 default:
@@ -179,11 +185,14 @@ EXPORT_SYMBOL_GPL(__hwspin_trylock); · 37 unmodified lines
179 * user need some time-consuming or sleepable operations under the hardware185 * user need some time-consuming or sleepable operations under the hardware
180 * lock, they need one sleepable lock (like mutex) to protect the operations.186 * lock, they need one sleepable lock (like mutex) to protect the operations.
181 *187 *
182 * If the mode is not HWLOCK_RAW, upon a successful return from this function,188 * If the mode is HWLOCK_IN_ATOMIC (called from an atomic context) the timeout
183 * preemption is disabled (and possibly local interrupts, too), so the caller189 * is handled with busy-waiting delays, hence shall not exceed few msecs.
184 * must not sleep, and is advised to release the hwspinlock as soon as possible.190 *
185 * This is required in order to minimize remote cores polling on the191 * If the mode is neither HWLOCK_IN_ATOMIC nor HWLOCK_RAW, upon a successful
186 * hardware interconnect.192 * return from this function, preemption (and possibly interrupts) is disabled,
193 * so the caller must not sleep, and is advised to release the hwspinlock as
194 * soon as possible. This is required in order to minimize remote cores polling
195 * on the hardware interconnect.
187 *196 *
188 * The user decides whether local interrupts are disabled or not, and if yes,197 * The user decides whether local interrupts are disabled or not, and if yes,
189 * whether he wants their previous state to be saved. It is up to the user198 * whether he wants their previous state to be saved. It is up to the user
@@ -198,7 +207,7 @@ int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to, · 8 unmodified lines
198 int mode, unsigned long *flags)207 int mode, unsigned long *flags)
199{208{
200 int ret;209 int ret;
201 unsigned long expire;210 unsigned long expire, atomic_delay = 0;
202 211
203 expire = msecs_to_jiffies(to) + jiffies;212 expire = msecs_to_jiffies(to) + jiffies;
204 213
@@ -212,8 +221,15 @@ int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to, · 7 unmodified lines
212 * The lock is already taken, let's check if the user wants221 * The lock is already taken, let's check if the user wants
213 * us to try again222 * us to try again
214 */223 */
215 if (time_is_before_eq_jiffies(expire))224 if (mode == HWLOCK_IN_ATOMIC) {
216 return -ETIMEDOUT;225 udelay(HWSPINLOCK_RETRY_DELAY_US);
226 atomic_delay += HWSPINLOCK_RETRY_DELAY_US;
227 if (atomic_delay > to * 1000)
228 return -ETIMEDOUT;
229 } else {
230 if (time_is_before_eq_jiffies(expire))
231 return -ETIMEDOUT;
232 }
217 233
218 /*234 /*
219 * Allow platform-specific relax handlers to prevent235 * Allow platform-specific relax handlers to prevent
@@ -276,6 +292,7 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags) · 56 unmodified lines
276 spin_unlock_irq(&hwlock->lock);292 spin_unlock_irq(&hwlock->lock);
277 break;293 break;
278 case HWLOCK_RAW:294 case HWLOCK_RAW:
295 case HWLOCK_IN_ATOMIC:
279 /* Nothing to do */296 /* Nothing to do */
280 break;297 break;
281 default:298 default:
@@ -333,6 +350,11 @@ int of_hwspin_lock_get_id(struct device_node *np, int index) · 51 unmodified lines
333 if (ret)350 if (ret)
334 return ret;351 return ret;
335 352
353 if (!of_device_is_available(args.np)) {
354 ret = -ENOENT;
355 goto out;
356 }
357
336 /* Find the hwspinlock device: we need its base_id */358 /* Find the hwspinlock device: we need its base_id */
337 ret = -EPROBE_DEFER;359 ret = -EPROBE_DEFER;
338 rcu_read_lock();360 rcu_read_lock();
drivers/hwspinlock/omap_hwspinlock.c+4−0
@@ -140,6 +140,9 @@ static int omap_hwspinlock_probe(struct platform_device *pdev) · 139 unmodified lines
140 if (ret)140 if (ret)
141 goto reg_fail;141 goto reg_fail;
142 142
143 dev_dbg(&pdev->dev, "Registered %d locks with HwSpinlock core\n",
144 num_locks);
145
143 return 0;146 return 0;
144 147
145reg_fail:148reg_fail:
@@ -171,6 +174,7 @@ static int omap_hwspinlock_remove(struct platform_device *pdev) · 25 unmodified lines
171 174
172static const struct of_device_id omap_hwspinlock_of_match[] = {175static const struct of_device_id omap_hwspinlock_of_match[] = {
173 { .compatible = "ti,omap4-hwspinlock", },176 { .compatible = "ti,omap4-hwspinlock", },
177 { .compatible = "ti,am654-hwspinlock", },
174 { /* end */ },178 { /* end */ },
175};179};
176MODULE_DEVICE_TABLE(of, omap_hwspinlock_of_match);180MODULE_DEVICE_TABLE(of, omap_hwspinlock_of_match);
drivers/hwspinlock/stm32_hwspinlock.c+7−0
@@ -5,6 +5,7 @@ · 4 unmodified lines
5 */5 */
6 6
7#include <linux/clk.h>7#include <linux/clk.h>
8#include <linux/delay.h>
8#include <linux/hwspinlock.h>9#include <linux/hwspinlock.h>
9#include <linux/io.h>10#include <linux/io.h>
10#include <linux/kernel.h>11#include <linux/kernel.h>
@@ -42,9 +43,15 @@ static void stm32_hwspinlock_unlock(struct hwspinlock *lock) · 31 unmodified lines
42 writel(STM32_MUTEX_COREID, lock_addr);43 writel(STM32_MUTEX_COREID, lock_addr);
43}44}
44 45
46static void stm32_hwspinlock_relax(struct hwspinlock *lock)
47{
48 ndelay(50);
49}
50
45static const struct hwspinlock_ops stm32_hwspinlock_ops = {51static const struct hwspinlock_ops stm32_hwspinlock_ops = {
46 .trylock = stm32_hwspinlock_trylock,52 .trylock = stm32_hwspinlock_trylock,
47 .unlock = stm32_hwspinlock_unlock,53 .unlock = stm32_hwspinlock_unlock,
54 .relax = stm32_hwspinlock_relax,
48};55};
49 56
50static int stm32_hwspinlock_probe(struct platform_device *pdev)57static int stm32_hwspinlock_probe(struct platform_device *pdev)
include/linux/hwspinlock.h+58−3
@@ -14,9 +14,10 @@ · 13 unmodified lines
14#include <linux/sched.h>14#include <linux/sched.h>
15 15
16/* hwspinlock mode argument */16/* hwspinlock mode argument */
17#define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */17#define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */
18#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */18#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */
19#define HWLOCK_RAW 0x0319#define HWLOCK_RAW 0x03
20#define HWLOCK_IN_ATOMIC 0x04 /* Called while in atomic context */
20 21
21struct device;22struct device;
22struct device_node;23struct device_node;
@@ -222,6 +223,23 @@ static inline int hwspin_trylock_raw(struct hwspinlock *hwlock) · 199 unmodified lines
222 return __hwspin_trylock(hwlock, HWLOCK_RAW, NULL);223 return __hwspin_trylock(hwlock, HWLOCK_RAW, NULL);
223}224}
224 225
226/**
227 * hwspin_trylock_in_atomic() - attempt to lock a specific hwspinlock
228 * @hwlock: an hwspinlock which we want to trylock
229 *
230 * This function attempts to lock an hwspinlock, and will immediately fail
231 * if the hwspinlock is already taken.
232 *
233 * This function shall be called only from an atomic context.
234 *
235 * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
236 * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
237 */
238static inline int hwspin_trylock_in_atomic(struct hwspinlock *hwlock)
239{
240 return __hwspin_trylock(hwlock, HWLOCK_IN_ATOMIC, NULL);
241}
242
225/**243/**
226 * hwspin_trylock() - attempt to lock a specific hwspinlock244 * hwspin_trylock() - attempt to lock a specific hwspinlock
227 * @hwlock: an hwspinlock which we want to trylock245 * @hwlock: an hwspinlock which we want to trylock
@@ -312,6 +330,28 @@ int hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int to) · 84 unmodified lines
312 return __hwspin_lock_timeout(hwlock, to, HWLOCK_RAW, NULL);330 return __hwspin_lock_timeout(hwlock, to, HWLOCK_RAW, NULL);
313}331}
314 332
333/**
334 * hwspin_lock_timeout_in_atomic() - lock an hwspinlock with timeout limit
335 * @hwlock: the hwspinlock to be locked
336 * @to: timeout value in msecs
337 *
338 * This function locks the underlying @hwlock. If the @hwlock
339 * is already taken, the function will busy loop waiting for it to
340 * be released, but give up when @timeout msecs have elapsed.
341 *
342 * This function shall be called only from an atomic context and the timeout
343 * value shall not exceed a few msecs.
344 *
345 * Returns 0 when the @hwlock was successfully taken, and an appropriate
346 * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
347 * busy after @timeout msecs). The function will never sleep.
348 */
349static inline
350int hwspin_lock_timeout_in_atomic(struct hwspinlock *hwlock, unsigned int to)
351{
352 return __hwspin_lock_timeout(hwlock, to, HWLOCK_IN_ATOMIC, NULL);
353}
354
315/**355/**
316 * hwspin_lock_timeout() - lock an hwspinlock with timeout limit356 * hwspin_lock_timeout() - lock an hwspinlock with timeout limit
317 * @hwlock: the hwspinlock to be locked357 * @hwlock: the hwspinlock to be locked
@@ -386,6 +426,21 @@ static inline void hwspin_unlock_raw(struct hwspinlock *hwlock) · 68 unmodified lines
386 __hwspin_unlock(hwlock, HWLOCK_RAW, NULL);426 __hwspin_unlock(hwlock, HWLOCK_RAW, NULL);
387}427}
388 428
429/**
430 * hwspin_unlock_in_atomic() - unlock hwspinlock
431 * @hwlock: a previously-acquired hwspinlock which we want to unlock
432 *
433 * This function will unlock a specific hwspinlock.
434 *
435 * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling
436 * this function: it is a bug to call unlock on a @hwlock that is already
437 * unlocked.
438 */
439static inline void hwspin_unlock_in_atomic(struct hwspinlock *hwlock)
440{
441 __hwspin_unlock(hwlock, HWLOCK_IN_ATOMIC, NULL);
442}
443
389/**444/**
390 * hwspin_unlock() - unlock hwspinlock445 * hwspin_unlock() - unlock hwspinlock
391 * @hwlock: a previously-acquired hwspinlock which we want to unlock446 * @hwlock: a previously-acquired hwspinlock which we want to unlock

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t