1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _ASM_POWERPC_QSPINLOCK_H 3#define _ASM_POWERPC_QSPINLOCK_H 4 5#include <asm-generic/qspinlock_types.h> 6#include <asm/paravirt.h> 7 8#define _Q_PENDING_LOOPS (1 << 9) /* not tuned */ 9 10#ifdef CONFIG_PARAVIRT_SPINLOCKS 11extern void native_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val); 12extern void __pv_queued_spin_lock_slowpath(struct qspinlock *lock, u32 val); 13extern void __pv_queued_spin_unlock(struct qspinlock *lock); 14 15static __always_inline void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) 16{ 17 if (!is_shared_processor()) 18 native_queued_spin_lock_slowpath(lock, val); 19 else 20 __pv_queued_spin_lock_slowpath(lock, val); 21} 22 23#define queued_spin_unlock queued_spin_unlock 24static inline void queued_spin_unlock(struct qspinlock *lock) 25{ 26 if (!is_shared_processor()) 27 smp_store_release(&lock->locked, 0); 28 else 29 __pv_queued_spin_unlock(lock); 30} 31 32#else 33extern void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val); 34#endif 35 36static __always_inline void queued_spin_lock(struct qspinlock *lock) 37{ 38 u32 val = 0; 39 40 if (likely(atomic_try_cmpxchg_lock(&lock->val, &val, _Q_LOCKED_VAL))) 41 return; 42 43 queued_spin_lock_slowpath(lock, val); 44} 45#define queued_spin_lock queued_spin_lock 46 47#define smp_mb__after_spinlock() smp_mb() 48 49static __always_inline int queued_spin_is_locked(struct qspinlock *lock) 50{ 51 /* 52 * This barrier was added to simple spinlocks by commit 51d7d5205d338, 53 * but it should now be possible to remove it, asm arm64 has done with 54 * commit c6f5d02b6a0f. 55 */ 56 smp_mb(); 57 return atomic_read(&lock->val); 58} 59#define queued_spin_is_locked queued_spin_is_locked 60 61#ifdef CONFIG_PARAVIRT_SPINLOCKS 62#define SPIN_THRESHOLD (1<<15) /* not tuned */ 63 64static __always_inline void pv_wait(u8 *ptr, u8 val) 65{ 66 if (*ptr != val) 67 return; 68 yield_to_any(); 69 /* 70 * We could pass in a CPU here if waiting in the queue and yield to 71 * the previous CPU in the queue. 72 */ 73} 74 75static __always_inline void pv_kick(int cpu) 76{ 77 prod_cpu(cpu); 78} 79 80extern void __pv_init_lock_hash(void); 81 82static inline void pv_spinlocks_init(void) 83{ 84 __pv_init_lock_hash(); 85} 86 87#endif 88 89#include <asm-generic/qspinlock.h> 90 91#endif /* _ASM_POWERPC_QSPINLOCK_H */ 92