18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 32-bit atomic xchg() and cmpxchg() definitions. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 1996 David S. Miller (davem@davemloft.net) 58c2ecf20Sopenharmony_ci * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au) 68c2ecf20Sopenharmony_ci * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org) 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Additions by Keith M Wesolowski (wesolows@foobazco.org) based 98c2ecf20Sopenharmony_ci * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifndef __ARCH_SPARC_CMPXCHG__ 138c2ecf20Sopenharmony_ci#define __ARCH_SPARC_CMPXCHG__ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ciunsigned long __xchg_u32(volatile u32 *m, u32 new); 168c2ecf20Sopenharmony_civoid __xchg_called_with_bad_pointer(void); 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci switch (size) { 218c2ecf20Sopenharmony_ci case 4: 228c2ecf20Sopenharmony_ci return __xchg_u32(ptr, x); 238c2ecf20Sopenharmony_ci } 248c2ecf20Sopenharmony_ci __xchg_called_with_bad_pointer(); 258c2ecf20Sopenharmony_ci return x; 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* Emulate cmpxchg() the same way we emulate atomics, 318c2ecf20Sopenharmony_ci * by hashing the object address and indexing into an array 328c2ecf20Sopenharmony_ci * of spinlocks to get a bit of performance... 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * See arch/sparc/lib/atomic32.c for implementation. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci * Cribbed from <asm-parisc/atomic.h> 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* bug catcher for when unsupported size is used - won't link */ 408c2ecf20Sopenharmony_civoid __cmpxchg_called_with_bad_pointer(void); 418c2ecf20Sopenharmony_ci/* we only need to support cmpxchg of a u32 on sparc */ 428c2ecf20Sopenharmony_ciunsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* don't worry...optimizer will get rid of most of this */ 458c2ecf20Sopenharmony_cistatic inline unsigned long 468c2ecf20Sopenharmony_ci__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci switch (size) { 498c2ecf20Sopenharmony_ci case 4: 508c2ecf20Sopenharmony_ci return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_); 518c2ecf20Sopenharmony_ci default: 528c2ecf20Sopenharmony_ci __cmpxchg_called_with_bad_pointer(); 538c2ecf20Sopenharmony_ci break; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci return old; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define cmpxchg(ptr, o, n) \ 598c2ecf20Sopenharmony_ci({ \ 608c2ecf20Sopenharmony_ci __typeof__(*(ptr)) _o_ = (o); \ 618c2ecf20Sopenharmony_ci __typeof__(*(ptr)) _n_ = (n); \ 628c2ecf20Sopenharmony_ci (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 638c2ecf20Sopenharmony_ci (unsigned long)_n_, sizeof(*(ptr))); \ 648c2ecf20Sopenharmony_ci}) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciu64 __cmpxchg_u64(u64 *ptr, u64 old, u64 new); 678c2ecf20Sopenharmony_ci#define cmpxchg64(ptr, old, new) __cmpxchg_u64(ptr, old, new) 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#include <asm-generic/cmpxchg-local.h> 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* 728c2ecf20Sopenharmony_ci * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make 738c2ecf20Sopenharmony_ci * them available. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci#define cmpxchg_local(ptr, o, n) \ 768c2ecf20Sopenharmony_ci ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ 778c2ecf20Sopenharmony_ci (unsigned long)(n), sizeof(*(ptr)))) 788c2ecf20Sopenharmony_ci#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#endif /* __ARCH_SPARC_CMPXCHG__ */ 81