162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ALPHA_SPINLOCK_H 362306a36Sopenharmony_ci#define _ALPHA_SPINLOCK_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <asm/current.h> 762306a36Sopenharmony_ci#include <asm/barrier.h> 862306a36Sopenharmony_ci#include <asm/processor.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * Simple spin lock operations. There are two variants, one clears IRQ's 1262306a36Sopenharmony_ci * on the local processor, one does not. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * We make no fairness assumptions. They have a cost. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define arch_spin_is_locked(x) ((x)->lock != 0) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic inline int arch_spin_value_unlocked(arch_spinlock_t lock) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci return lock.lock == 0; 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic inline void arch_spin_unlock(arch_spinlock_t * lock) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci mb(); 2762306a36Sopenharmony_ci lock->lock = 0; 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic inline void arch_spin_lock(arch_spinlock_t * lock) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci long tmp; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci __asm__ __volatile__( 3562306a36Sopenharmony_ci "1: ldl_l %0,%1\n" 3662306a36Sopenharmony_ci " bne %0,2f\n" 3762306a36Sopenharmony_ci " lda %0,1\n" 3862306a36Sopenharmony_ci " stl_c %0,%1\n" 3962306a36Sopenharmony_ci " beq %0,2f\n" 4062306a36Sopenharmony_ci " mb\n" 4162306a36Sopenharmony_ci ".subsection 2\n" 4262306a36Sopenharmony_ci "2: ldl %0,%1\n" 4362306a36Sopenharmony_ci " bne %0,2b\n" 4462306a36Sopenharmony_ci " br 1b\n" 4562306a36Sopenharmony_ci ".previous" 4662306a36Sopenharmony_ci : "=&r" (tmp), "=m" (lock->lock) 4762306a36Sopenharmony_ci : "m"(lock->lock) : "memory"); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline int arch_spin_trylock(arch_spinlock_t *lock) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return !test_and_set_bit(0, &lock->lock); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/***********************************************************/ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic inline void arch_read_lock(arch_rwlock_t *lock) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci long regx; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci __asm__ __volatile__( 6262306a36Sopenharmony_ci "1: ldl_l %1,%0\n" 6362306a36Sopenharmony_ci " blbs %1,6f\n" 6462306a36Sopenharmony_ci " subl %1,2,%1\n" 6562306a36Sopenharmony_ci " stl_c %1,%0\n" 6662306a36Sopenharmony_ci " beq %1,6f\n" 6762306a36Sopenharmony_ci " mb\n" 6862306a36Sopenharmony_ci ".subsection 2\n" 6962306a36Sopenharmony_ci "6: ldl %1,%0\n" 7062306a36Sopenharmony_ci " blbs %1,6b\n" 7162306a36Sopenharmony_ci " br 1b\n" 7262306a36Sopenharmony_ci ".previous" 7362306a36Sopenharmony_ci : "=m" (*lock), "=&r" (regx) 7462306a36Sopenharmony_ci : "m" (*lock) : "memory"); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic inline void arch_write_lock(arch_rwlock_t *lock) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci long regx; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci __asm__ __volatile__( 8262306a36Sopenharmony_ci "1: ldl_l %1,%0\n" 8362306a36Sopenharmony_ci " bne %1,6f\n" 8462306a36Sopenharmony_ci " lda %1,1\n" 8562306a36Sopenharmony_ci " stl_c %1,%0\n" 8662306a36Sopenharmony_ci " beq %1,6f\n" 8762306a36Sopenharmony_ci " mb\n" 8862306a36Sopenharmony_ci ".subsection 2\n" 8962306a36Sopenharmony_ci "6: ldl %1,%0\n" 9062306a36Sopenharmony_ci " bne %1,6b\n" 9162306a36Sopenharmony_ci " br 1b\n" 9262306a36Sopenharmony_ci ".previous" 9362306a36Sopenharmony_ci : "=m" (*lock), "=&r" (regx) 9462306a36Sopenharmony_ci : "m" (*lock) : "memory"); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic inline int arch_read_trylock(arch_rwlock_t * lock) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci long regx; 10062306a36Sopenharmony_ci int success; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci __asm__ __volatile__( 10362306a36Sopenharmony_ci "1: ldl_l %1,%0\n" 10462306a36Sopenharmony_ci " lda %2,0\n" 10562306a36Sopenharmony_ci " blbs %1,2f\n" 10662306a36Sopenharmony_ci " subl %1,2,%2\n" 10762306a36Sopenharmony_ci " stl_c %2,%0\n" 10862306a36Sopenharmony_ci " beq %2,6f\n" 10962306a36Sopenharmony_ci "2: mb\n" 11062306a36Sopenharmony_ci ".subsection 2\n" 11162306a36Sopenharmony_ci "6: br 1b\n" 11262306a36Sopenharmony_ci ".previous" 11362306a36Sopenharmony_ci : "=m" (*lock), "=&r" (regx), "=&r" (success) 11462306a36Sopenharmony_ci : "m" (*lock) : "memory"); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci return success; 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic inline int arch_write_trylock(arch_rwlock_t * lock) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci long regx; 12262306a36Sopenharmony_ci int success; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci __asm__ __volatile__( 12562306a36Sopenharmony_ci "1: ldl_l %1,%0\n" 12662306a36Sopenharmony_ci " lda %2,0\n" 12762306a36Sopenharmony_ci " bne %1,2f\n" 12862306a36Sopenharmony_ci " lda %2,1\n" 12962306a36Sopenharmony_ci " stl_c %2,%0\n" 13062306a36Sopenharmony_ci " beq %2,6f\n" 13162306a36Sopenharmony_ci "2: mb\n" 13262306a36Sopenharmony_ci ".subsection 2\n" 13362306a36Sopenharmony_ci "6: br 1b\n" 13462306a36Sopenharmony_ci ".previous" 13562306a36Sopenharmony_ci : "=m" (*lock), "=&r" (regx), "=&r" (success) 13662306a36Sopenharmony_ci : "m" (*lock) : "memory"); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return success; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic inline void arch_read_unlock(arch_rwlock_t * lock) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci long regx; 14462306a36Sopenharmony_ci __asm__ __volatile__( 14562306a36Sopenharmony_ci " mb\n" 14662306a36Sopenharmony_ci "1: ldl_l %1,%0\n" 14762306a36Sopenharmony_ci " addl %1,2,%1\n" 14862306a36Sopenharmony_ci " stl_c %1,%0\n" 14962306a36Sopenharmony_ci " beq %1,6f\n" 15062306a36Sopenharmony_ci ".subsection 2\n" 15162306a36Sopenharmony_ci "6: br 1b\n" 15262306a36Sopenharmony_ci ".previous" 15362306a36Sopenharmony_ci : "=m" (*lock), "=&r" (regx) 15462306a36Sopenharmony_ci : "m" (*lock) : "memory"); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic inline void arch_write_unlock(arch_rwlock_t * lock) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci mb(); 16062306a36Sopenharmony_ci lock->lock = 0; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#endif /* _ALPHA_SPINLOCK_H */ 164