18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Spin and read/write lock operations.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
68c2ecf20Sopenharmony_ci * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
78c2ecf20Sopenharmony_ci * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
88c2ecf20Sopenharmony_ci *   Rework to support virtual processors
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
138c2ecf20Sopenharmony_ci#include <linux/export.h>
148c2ecf20Sopenharmony_ci#include <linux/smp.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/* waiting for a spinlock... */
178c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_SPLPAR)
188c2ecf20Sopenharmony_ci#include <asm/hvcall.h>
198c2ecf20Sopenharmony_ci#include <asm/smp.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_civoid splpar_spin_yield(arch_spinlock_t *lock)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	unsigned int lock_value, holder_cpu, yield_count;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	lock_value = lock->slock;
268c2ecf20Sopenharmony_ci	if (lock_value == 0)
278c2ecf20Sopenharmony_ci		return;
288c2ecf20Sopenharmony_ci	holder_cpu = lock_value & 0xffff;
298c2ecf20Sopenharmony_ci	BUG_ON(holder_cpu >= NR_CPUS);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	yield_count = yield_count_of(holder_cpu);
328c2ecf20Sopenharmony_ci	if ((yield_count & 1) == 0)
338c2ecf20Sopenharmony_ci		return;		/* virtual cpu is currently running */
348c2ecf20Sopenharmony_ci	rmb();
358c2ecf20Sopenharmony_ci	if (lock->slock != lock_value)
368c2ecf20Sopenharmony_ci		return;		/* something has changed */
378c2ecf20Sopenharmony_ci	yield_to_preempted(holder_cpu, yield_count);
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(splpar_spin_yield);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci/*
428c2ecf20Sopenharmony_ci * Waiting for a read lock or a write lock on a rwlock...
438c2ecf20Sopenharmony_ci * This turns out to be the same for read and write locks, since
448c2ecf20Sopenharmony_ci * we only know the holder if it is write-locked.
458c2ecf20Sopenharmony_ci */
468c2ecf20Sopenharmony_civoid splpar_rw_yield(arch_rwlock_t *rw)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	int lock_value;
498c2ecf20Sopenharmony_ci	unsigned int holder_cpu, yield_count;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	lock_value = rw->lock;
528c2ecf20Sopenharmony_ci	if (lock_value >= 0)
538c2ecf20Sopenharmony_ci		return;		/* no write lock at present */
548c2ecf20Sopenharmony_ci	holder_cpu = lock_value & 0xffff;
558c2ecf20Sopenharmony_ci	BUG_ON(holder_cpu >= NR_CPUS);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	yield_count = yield_count_of(holder_cpu);
588c2ecf20Sopenharmony_ci	if ((yield_count & 1) == 0)
598c2ecf20Sopenharmony_ci		return;		/* virtual cpu is currently running */
608c2ecf20Sopenharmony_ci	rmb();
618c2ecf20Sopenharmony_ci	if (rw->lock != lock_value)
628c2ecf20Sopenharmony_ci		return;		/* something has changed */
638c2ecf20Sopenharmony_ci	yield_to_preempted(holder_cpu, yield_count);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci#endif
66