162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Spin and read/write lock operations. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM 662306a36Sopenharmony_ci * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM 762306a36Sopenharmony_ci * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM 862306a36Sopenharmony_ci * Rework to support virtual processors 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/spinlock.h> 1362306a36Sopenharmony_ci#include <linux/export.h> 1462306a36Sopenharmony_ci#include <linux/smp.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* waiting for a spinlock... */ 1762306a36Sopenharmony_ci#if defined(CONFIG_PPC_SPLPAR) 1862306a36Sopenharmony_ci#include <asm/hvcall.h> 1962306a36Sopenharmony_ci#include <asm/smp.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_civoid splpar_spin_yield(arch_spinlock_t *lock) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci unsigned int lock_value, holder_cpu, yield_count; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci lock_value = lock->slock; 2662306a36Sopenharmony_ci if (lock_value == 0) 2762306a36Sopenharmony_ci return; 2862306a36Sopenharmony_ci holder_cpu = lock_value & 0xffff; 2962306a36Sopenharmony_ci BUG_ON(holder_cpu >= NR_CPUS); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci yield_count = yield_count_of(holder_cpu); 3262306a36Sopenharmony_ci if ((yield_count & 1) == 0) 3362306a36Sopenharmony_ci return; /* virtual cpu is currently running */ 3462306a36Sopenharmony_ci rmb(); 3562306a36Sopenharmony_ci if (lock->slock != lock_value) 3662306a36Sopenharmony_ci return; /* something has changed */ 3762306a36Sopenharmony_ci yield_to_preempted(holder_cpu, yield_count); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(splpar_spin_yield); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * Waiting for a read lock or a write lock on a rwlock... 4362306a36Sopenharmony_ci * This turns out to be the same for read and write locks, since 4462306a36Sopenharmony_ci * we only know the holder if it is write-locked. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_civoid splpar_rw_yield(arch_rwlock_t *rw) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci int lock_value; 4962306a36Sopenharmony_ci unsigned int holder_cpu, yield_count; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci lock_value = rw->lock; 5262306a36Sopenharmony_ci if (lock_value >= 0) 5362306a36Sopenharmony_ci return; /* no write lock at present */ 5462306a36Sopenharmony_ci holder_cpu = lock_value & 0xffff; 5562306a36Sopenharmony_ci BUG_ON(holder_cpu >= NR_CPUS); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci yield_count = yield_count_of(holder_cpu); 5862306a36Sopenharmony_ci if ((yield_count & 1) == 0) 5962306a36Sopenharmony_ci return; /* virtual cpu is currently running */ 6062306a36Sopenharmony_ci rmb(); 6162306a36Sopenharmony_ci if (rw->lock != lock_value) 6262306a36Sopenharmony_ci return; /* something has changed */ 6362306a36Sopenharmony_ci yield_to_preempted(holder_cpu, yield_count); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci#endif 66