Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / arch / arm / common / vlock.S
blobc5eaed5a76f067dd81e936ef6388102a5f7494b5
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * vlock.S - simple voting lock implementation for ARM
4  *
5  * Created by:  Dave Martin, 2012-08-16
6  * Copyright:   (C) 2012-2013  Linaro Limited
7  *
8  * This algorithm is described in more detail in
9  * Documentation/arch/arm/vlocks.rst.
10  */
12 #include <linux/linkage.h>
13 #include "vlock.h"
15 .arch armv7-a
17 /* Select different code if voting flags  can fit in a single word. */
18 #if VLOCK_VOTING_SIZE > 4
19 #define FEW(x...)
20 #define MANY(x...) x
21 #else
22 #define FEW(x...) x
23 #define MANY(x...)
24 #endif
26 @ voting lock for first-man coordination
28 .macro voting_begin rbase:req, rcpu:req, rscratch:req
29         mov     \rscratch, #1
30         strb    \rscratch, [\rbase, \rcpu]
31         dmb
32 .endm
34 .macro voting_end rbase:req, rcpu:req, rscratch:req
35         dmb
36         mov     \rscratch, #0
37         strb    \rscratch, [\rbase, \rcpu]
38         dsb     st
39         sev
40 .endm
43  * The vlock structure must reside in Strongly-Ordered or Device memory.
44  * This implementation deliberately eliminates most of the barriers which
45  * would be required for other memory types, and assumes that independent
46  * writes to neighbouring locations within a cacheline do not interfere
47  * with one another.
48  */
50 @ r0: lock structure base
51 @ r1: CPU ID (0-based index within cluster)
52 ENTRY(vlock_trylock)
53         add     r1, r1, #VLOCK_VOTING_OFFSET
55         voting_begin    r0, r1, r2
57         ldrb    r2, [r0, #VLOCK_OWNER_OFFSET]   @ check whether lock is held
58         cmp     r2, #VLOCK_OWNER_NONE
59         bne     trylock_fail                    @ fail if so
61         @ Control dependency implies strb not observable before previous ldrb.
63         strb    r1, [r0, #VLOCK_OWNER_OFFSET]   @ submit my vote
65         voting_end      r0, r1, r2              @ implies DMB
67         @ Wait for the current round of voting to finish:
69  MANY(  mov     r3, #VLOCK_VOTING_OFFSET                        )
71  MANY(  ldr     r2, [r0, r3]                                    )
72  FEW(   ldr     r2, [r0, #VLOCK_VOTING_OFFSET]                  )
73         cmp     r2, #0
74         wfene
75         bne     0b
76  MANY(  add     r3, r3, #4                                      )
77  MANY(  cmp     r3, #VLOCK_VOTING_OFFSET + VLOCK_VOTING_SIZE    )
78  MANY(  bne     0b                                              )
80         @ Check who won:
82         dmb
83         ldrb    r2, [r0, #VLOCK_OWNER_OFFSET]
84         eor     r0, r1, r2                      @ zero if I won, else nonzero
85         bx      lr
87 trylock_fail:
88         voting_end      r0, r1, r2
89         mov     r0, #1                          @ nonzero indicates that I lost
90         bx      lr
91 ENDPROC(vlock_trylock)
93 @ r0: lock structure base
94 ENTRY(vlock_unlock)
95         dmb
96         mov     r1, #VLOCK_OWNER_NONE
97         strb    r1, [r0, #VLOCK_OWNER_OFFSET]
98         dsb     st
99         sev
100         bx      lr
101 ENDPROC(vlock_unlock)