18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __ASM_SH_CMPXCHG_H 38c2ecf20Sopenharmony_ci#define __ASM_SH_CMPXCHG_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * Atomic operations that C can't guarantee us. Useful for 78c2ecf20Sopenharmony_ci * resource counting etc.. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/compiler.h> 118c2ecf20Sopenharmony_ci#include <linux/types.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#if defined(CONFIG_GUSA_RB) 148c2ecf20Sopenharmony_ci#include <asm/cmpxchg-grb.h> 158c2ecf20Sopenharmony_ci#elif defined(CONFIG_CPU_SH4A) 168c2ecf20Sopenharmony_ci#include <asm/cmpxchg-llsc.h> 178c2ecf20Sopenharmony_ci#elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP) 188c2ecf20Sopenharmony_ci#include <asm/cmpxchg-cas.h> 198c2ecf20Sopenharmony_ci#else 208c2ecf20Sopenharmony_ci#include <asm/cmpxchg-irq.h> 218c2ecf20Sopenharmony_ci#endif 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciextern void __xchg_called_with_bad_pointer(void); 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define __xchg(ptr, x, size) \ 268c2ecf20Sopenharmony_ci({ \ 278c2ecf20Sopenharmony_ci unsigned long __xchg__res; \ 288c2ecf20Sopenharmony_ci volatile void *__xchg_ptr = (ptr); \ 298c2ecf20Sopenharmony_ci switch (size) { \ 308c2ecf20Sopenharmony_ci case 4: \ 318c2ecf20Sopenharmony_ci __xchg__res = xchg_u32(__xchg_ptr, x); \ 328c2ecf20Sopenharmony_ci break; \ 338c2ecf20Sopenharmony_ci case 2: \ 348c2ecf20Sopenharmony_ci __xchg__res = xchg_u16(__xchg_ptr, x); \ 358c2ecf20Sopenharmony_ci break; \ 368c2ecf20Sopenharmony_ci case 1: \ 378c2ecf20Sopenharmony_ci __xchg__res = xchg_u8(__xchg_ptr, x); \ 388c2ecf20Sopenharmony_ci break; \ 398c2ecf20Sopenharmony_ci default: \ 408c2ecf20Sopenharmony_ci __xchg_called_with_bad_pointer(); \ 418c2ecf20Sopenharmony_ci __xchg__res = x; \ 428c2ecf20Sopenharmony_ci break; \ 438c2ecf20Sopenharmony_ci } \ 448c2ecf20Sopenharmony_ci \ 458c2ecf20Sopenharmony_ci __xchg__res; \ 468c2ecf20Sopenharmony_ci}) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define xchg(ptr,x) \ 498c2ecf20Sopenharmony_ci ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr)))) 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* This function doesn't exist, so you'll get a linker error 528c2ecf20Sopenharmony_ci * if something tries to do an invalid cmpxchg(). */ 538c2ecf20Sopenharmony_ciextern void __cmpxchg_called_with_bad_pointer(void); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old, 568c2ecf20Sopenharmony_ci unsigned long new, int size) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci switch (size) { 598c2ecf20Sopenharmony_ci case 4: 608c2ecf20Sopenharmony_ci return __cmpxchg_u32(ptr, old, new); 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci __cmpxchg_called_with_bad_pointer(); 638c2ecf20Sopenharmony_ci return old; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define cmpxchg(ptr,o,n) \ 678c2ecf20Sopenharmony_ci ({ \ 688c2ecf20Sopenharmony_ci __typeof__(*(ptr)) _o_ = (o); \ 698c2ecf20Sopenharmony_ci __typeof__(*(ptr)) _n_ = (n); \ 708c2ecf20Sopenharmony_ci (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ 718c2ecf20Sopenharmony_ci (unsigned long)_n_, sizeof(*(ptr))); \ 728c2ecf20Sopenharmony_ci }) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#endif /* __ASM_SH_CMPXCHG_H */ 75