1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2024b246eSLinus Torvalds #ifndef _ALPHA_SPINLOCK_H 3024b246eSLinus Torvalds #define _ALPHA_SPINLOCK_H 4024b246eSLinus Torvalds 5024b246eSLinus Torvalds #include <linux/kernel.h> 6024b246eSLinus Torvalds #include <asm/current.h> 7726328d9SPeter Zijlstra #include <asm/barrier.h> 8726328d9SPeter Zijlstra #include <asm/processor.h> 9024b246eSLinus Torvalds 10024b246eSLinus Torvalds /* 11024b246eSLinus Torvalds * Simple spin lock operations. There are two variants, one clears IRQ's 12024b246eSLinus Torvalds * on the local processor, one does not. 13024b246eSLinus Torvalds * 14024b246eSLinus Torvalds * We make no fairness assumptions. They have a cost. 15024b246eSLinus Torvalds */ 16024b246eSLinus Torvalds 170199c4e6SThomas Gleixner #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) 180199c4e6SThomas Gleixner #define arch_spin_is_locked(x) ((x)->lock != 0) 19726328d9SPeter Zijlstra 208f8dcb3fSMatt Turner static inline int arch_spin_value_unlocked(arch_spinlock_t lock) 218f8dcb3fSMatt Turner { 228f8dcb3fSMatt Turner return lock.lock == 0; 238f8dcb3fSMatt Turner } 248f8dcb3fSMatt Turner 250199c4e6SThomas Gleixner static inline void arch_spin_unlock(arch_spinlock_t * lock) 26024b246eSLinus Torvalds { 27024b246eSLinus Torvalds mb(); 28024b246eSLinus Torvalds lock->lock = 0; 29024b246eSLinus Torvalds } 30024b246eSLinus Torvalds 310199c4e6SThomas Gleixner static inline void arch_spin_lock(arch_spinlock_t * lock) 32024b246eSLinus Torvalds { 33024b246eSLinus Torvalds long tmp; 34024b246eSLinus Torvalds 35024b246eSLinus Torvalds __asm__ __volatile__( 36024b246eSLinus Torvalds "1: ldl_l %0,%1\n" 37024b246eSLinus Torvalds " bne %0,2f\n" 38024b246eSLinus Torvalds " lda %0,1\n" 39024b246eSLinus Torvalds " stl_c %0,%1\n" 40024b246eSLinus Torvalds " beq %0,2f\n" 41024b246eSLinus Torvalds " mb\n" 42024b246eSLinus Torvalds ".subsection 2\n" 43024b246eSLinus Torvalds "2: ldl %0,%1\n" 44024b246eSLinus Torvalds " bne %0,2b\n" 45024b246eSLinus Torvalds " br 1b\n" 46024b246eSLinus Torvalds ".previous" 47024b246eSLinus Torvalds : "=&r" (tmp), "=m" (lock->lock) 48024b246eSLinus Torvalds : "m"(lock->lock) : "memory"); 49024b246eSLinus Torvalds } 50024b246eSLinus Torvalds 510199c4e6SThomas Gleixner static inline int arch_spin_trylock(arch_spinlock_t *lock) 52024b246eSLinus Torvalds { 53024b246eSLinus Torvalds return !test_and_set_bit(0, &lock->lock); 54024b246eSLinus Torvalds } 55024b246eSLinus Torvalds 56024b246eSLinus Torvalds /***********************************************************/ 57024b246eSLinus Torvalds 58e5931943SThomas Gleixner static inline int arch_read_can_lock(arch_rwlock_t *lock) 59024b246eSLinus Torvalds { 60024b246eSLinus Torvalds return (lock->lock & 1) == 0; 61024b246eSLinus Torvalds } 62024b246eSLinus Torvalds 63e5931943SThomas Gleixner static inline int arch_write_can_lock(arch_rwlock_t *lock) 64024b246eSLinus Torvalds { 65024b246eSLinus Torvalds return lock->lock == 0; 66024b246eSLinus Torvalds } 67024b246eSLinus Torvalds 68e5931943SThomas Gleixner static inline void arch_read_lock(arch_rwlock_t *lock) 69024b246eSLinus Torvalds { 70024b246eSLinus Torvalds long regx; 71024b246eSLinus Torvalds 72024b246eSLinus Torvalds __asm__ __volatile__( 73024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 74024b246eSLinus Torvalds " blbs %1,6f\n" 75024b246eSLinus Torvalds " subl %1,2,%1\n" 76024b246eSLinus Torvalds " stl_c %1,%0\n" 77024b246eSLinus Torvalds " beq %1,6f\n" 78024b246eSLinus Torvalds " mb\n" 79024b246eSLinus Torvalds ".subsection 2\n" 80024b246eSLinus Torvalds "6: ldl %1,%0\n" 81024b246eSLinus Torvalds " blbs %1,6b\n" 82024b246eSLinus Torvalds " br 1b\n" 83024b246eSLinus Torvalds ".previous" 84024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 85024b246eSLinus Torvalds : "m" (*lock) : "memory"); 86024b246eSLinus Torvalds } 87024b246eSLinus Torvalds 88e5931943SThomas Gleixner static inline void arch_write_lock(arch_rwlock_t *lock) 89024b246eSLinus Torvalds { 90024b246eSLinus Torvalds long regx; 91024b246eSLinus Torvalds 92024b246eSLinus Torvalds __asm__ __volatile__( 93024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 94024b246eSLinus Torvalds " bne %1,6f\n" 95024b246eSLinus Torvalds " lda %1,1\n" 96024b246eSLinus Torvalds " stl_c %1,%0\n" 97024b246eSLinus Torvalds " beq %1,6f\n" 98024b246eSLinus Torvalds " mb\n" 99024b246eSLinus Torvalds ".subsection 2\n" 100024b246eSLinus Torvalds "6: ldl %1,%0\n" 101024b246eSLinus Torvalds " bne %1,6b\n" 102024b246eSLinus Torvalds " br 1b\n" 103024b246eSLinus Torvalds ".previous" 104024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 105024b246eSLinus Torvalds : "m" (*lock) : "memory"); 106024b246eSLinus Torvalds } 107024b246eSLinus Torvalds 108e5931943SThomas Gleixner static inline int arch_read_trylock(arch_rwlock_t * lock) 109024b246eSLinus Torvalds { 110024b246eSLinus Torvalds long regx; 111024b246eSLinus Torvalds int success; 112024b246eSLinus Torvalds 113024b246eSLinus Torvalds __asm__ __volatile__( 114024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 115024b246eSLinus Torvalds " lda %2,0\n" 116024b246eSLinus Torvalds " blbs %1,2f\n" 117024b246eSLinus Torvalds " subl %1,2,%2\n" 118024b246eSLinus Torvalds " stl_c %2,%0\n" 119024b246eSLinus Torvalds " beq %2,6f\n" 120024b246eSLinus Torvalds "2: mb\n" 121024b246eSLinus Torvalds ".subsection 2\n" 122024b246eSLinus Torvalds "6: br 1b\n" 123024b246eSLinus Torvalds ".previous" 124024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx), "=&r" (success) 125024b246eSLinus Torvalds : "m" (*lock) : "memory"); 126024b246eSLinus Torvalds 127024b246eSLinus Torvalds return success; 128024b246eSLinus Torvalds } 129024b246eSLinus Torvalds 130e5931943SThomas Gleixner static inline int arch_write_trylock(arch_rwlock_t * lock) 131024b246eSLinus Torvalds { 132024b246eSLinus Torvalds long regx; 133024b246eSLinus Torvalds int success; 134024b246eSLinus Torvalds 135024b246eSLinus Torvalds __asm__ __volatile__( 136024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 137024b246eSLinus Torvalds " lda %2,0\n" 138024b246eSLinus Torvalds " bne %1,2f\n" 139024b246eSLinus Torvalds " lda %2,1\n" 140024b246eSLinus Torvalds " stl_c %2,%0\n" 141024b246eSLinus Torvalds " beq %2,6f\n" 142024b246eSLinus Torvalds "2: mb\n" 143024b246eSLinus Torvalds ".subsection 2\n" 144024b246eSLinus Torvalds "6: br 1b\n" 145024b246eSLinus Torvalds ".previous" 146024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx), "=&r" (success) 147024b246eSLinus Torvalds : "m" (*lock) : "memory"); 148024b246eSLinus Torvalds 149024b246eSLinus Torvalds return success; 150024b246eSLinus Torvalds } 151024b246eSLinus Torvalds 152e5931943SThomas Gleixner static inline void arch_read_unlock(arch_rwlock_t * lock) 153024b246eSLinus Torvalds { 154024b246eSLinus Torvalds long regx; 155024b246eSLinus Torvalds __asm__ __volatile__( 156024b246eSLinus Torvalds " mb\n" 157024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 158024b246eSLinus Torvalds " addl %1,2,%1\n" 159024b246eSLinus Torvalds " stl_c %1,%0\n" 160024b246eSLinus Torvalds " beq %1,6f\n" 161024b246eSLinus Torvalds ".subsection 2\n" 162024b246eSLinus Torvalds "6: br 1b\n" 163024b246eSLinus Torvalds ".previous" 164024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 165024b246eSLinus Torvalds : "m" (*lock) : "memory"); 166024b246eSLinus Torvalds } 167024b246eSLinus Torvalds 168e5931943SThomas Gleixner static inline void arch_write_unlock(arch_rwlock_t * lock) 169024b246eSLinus Torvalds { 170024b246eSLinus Torvalds mb(); 171024b246eSLinus Torvalds lock->lock = 0; 172024b246eSLinus Torvalds } 173024b246eSLinus Torvalds 174e5931943SThomas Gleixner #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) 175e5931943SThomas Gleixner #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) 176f5f7eac4SRobin Holt 177024b246eSLinus Torvalds #endif /* _ALPHA_SPINLOCK_H */ 178