Skip to content

Commit 84e81e5

Browse files
committed
drivers: dwc_otg: add ticket-based spinlock for ARM64
The ARM64 architecture uses qspinlock which has a fast and slow path. This isn't ideal for all claimers of a lock operating in interrupt context. Add a ticket-based lock similar to the armv6/7 implementation. Based on an upstream patch that was abandoned in favour of qspinlock. Link: https://patchwork.kernel.org/project/linux-arm-kernel/patch/[email protected]/ Signed-off-by: Jonathan Bell <[email protected]>
1 parent 4338bda commit 84e81e5

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,6 @@ enum fiq_debug_level {
129129
FIQDBG_PORTHUB = (1 << 3),
130130
};
131131

132-
#ifdef CONFIG_ARM64
133-
134-
typedef spinlock_t fiq_lock_t;
135-
136-
#else
137-
138132
#define TICKET_SHIFT 16
139133
typedef struct {
140134
union {
@@ -146,18 +140,45 @@ typedef struct {
146140
};
147141
} __aligned(4) fiq_lock_t;
148142

149-
#endif
150-
151-
#ifdef CONFIG_ARM64
152-
143+
#if defined(CONFIG_ARM64)
153144
static inline void fiq_fsm_spin_lock(fiq_lock_t *lock)
154145
{
155-
spin_lock((spinlock_t *)lock);
146+
unsigned int tmp;
147+
fiq_lock_t lockval, newval;
148+
149+
asm volatile(
150+
/* Atomically increment the next ticket. */
151+
" prfm pstl1strm, %3\n"
152+
"1: ldaxr %w0, %3\n"
153+
" add %w1, %w0, %w5\n"
154+
" stxr %w2, %w1, %3\n"
155+
" cbnz %w2, 1b\n"
156+
/* Did we get the lock? */
157+
" eor %w1, %w0, %w0, ror #16\n"
158+
" cbz %w1, 3f\n"
159+
/*
160+
* No: spin on the owner. Send a local event to avoid missing an
161+
* unlock before the exclusive load.
162+
*/
163+
" sevl\n"
164+
"2: wfe\n"
165+
" ldaxrh %w2, %4\n"
166+
" eor %w1, %w2, %w0, lsr #16\n"
167+
" cbnz %w1, 2b\n"
168+
/* We got the lock. Critical section starts here. */
169+
"3:"
170+
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp), "+Q" (*lock)
171+
: "Q" (lock->tickets.owner), "I" (1 << TICKET_SHIFT)
172+
: "memory");
156173
}
157174

158175
static inline void fiq_fsm_spin_unlock(fiq_lock_t *lock)
159176
{
160-
spin_unlock((spinlock_t *)lock);
177+
asm volatile(
178+
" stlrh %w1, %0\n"
179+
: "=Q" (lock->tickets.owner)
180+
: "r" (lock->tickets.owner + 1)
181+
: "memory");
161182
}
162183

163184
#else

drivers/usb/host/dwc_otg/dwc_otg_hcd.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,10 +1044,6 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
10441044
}
10451045
DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels)));
10461046

1047-
#ifdef CONFIG_ARM64
1048-
spin_lock_init(&hcd->fiq_state->lock);
1049-
#endif
1050-
10511047
hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16,
10521048
&hcd->fiq_state->dummy_send_dma);
10531049

0 commit comments

Comments
 (0)