169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifndef __ARCH_M68K_ATOMIC__ 269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define __ARCH_M68K_ATOMIC__ 369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#include <linux/types.h> 5803f69144f0d48863c68f9d111b56849c7cef5bbDavid Howells#include <linux/irqflags.h> 67224c0d1045327d637dab2c90777b6d5ec6d6804Greg Ungerer#include <asm/cmpxchg.h> 72db56e8606016e33903c64feaed989ffecd66a1bPeter Zijlstra#include <asm/barrier.h> 869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* 1069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * Atomic operations that C can't guarantee us. Useful for 1169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * resource counting etc.. 1269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */ 1369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 1469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* 1569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * We do not have SMP m68k systems, so we don't have to deal with that. 1669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */ 1769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 1869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ATOMIC_INIT(i) { (i) } 1969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 202291059c852706c6f5ffb400366042b7625066cdPranith Kumar#define atomic_read(v) ACCESS_ONCE((v)->counter) 2169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_set(v, i) (((v)->counter) = i) 2269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 2369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer/* 2469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * The ColdFire parts cannot do some immediate to memory operations, 2569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer * so for them we do not specify the "i" asm constraint. 2669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer */ 2769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifdef CONFIG_COLDFIRE 2869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ASM_DI "d" 2949148020bcb6910ce71417bd990a5ce7017f9bd3Sam Ravnborg#else 3069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define ASM_DI "di" 3149148020bcb6910ce71417bd990a5ce7017f9bd3Sam Ravnborg#endif 32b417b717093085e45867770b29b9a97692cf132aGeert Uytterhoeven 33d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#define ATOMIC_OP(op, c_op, asm_op) \ 34d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstrastatic inline void atomic_##op(int i, atomic_t *v) \ 35d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra{ \ 36d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra __asm__ __volatile__(#asm_op "l %1,%0" : "+m" (*v) : ASM_DI (i));\ 37d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra} \ 38d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 39d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#ifdef CONFIG_RMW_INSNS 40d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 41d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#define ATOMIC_OP_RETURN(op, c_op, asm_op) \ 42d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstrastatic inline int atomic_##op##_return(int i, atomic_t *v) \ 43d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra{ \ 44d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra int t, tmp; \ 45d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra \ 46d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra __asm__ __volatile__( \ 47d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra "1: movel %2,%1\n" \ 48d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra " " #asm_op "l %3,%1\n" \ 49d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra " casl %2,%1,%0\n" \ 50d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra " jne 1b" \ 51d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra : "+m" (*v), "=&d" (t), "=&d" (tmp) \ 52d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra : "g" (i), "2" (atomic_read(v))); \ 53d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra return t; \ 5469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 5569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 56d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#else 57d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 58d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#define ATOMIC_OP_RETURN(op, c_op, asm_op) \ 59d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstrastatic inline int atomic_##op##_return(int i, atomic_t * v) \ 60d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra{ \ 61d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra unsigned long flags; \ 62d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra int t; \ 63d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra \ 64d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra local_irq_save(flags); \ 65d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra t = (v->counter c_op i); \ 66d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra local_irq_restore(flags); \ 67d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra \ 68d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra return t; \ 6969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 7069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 71d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#endif /* CONFIG_RMW_INSNS */ 72d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 73d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#define ATOMIC_OPS(op, c_op, asm_op) \ 74d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra ATOMIC_OP(op, c_op, asm_op) \ 75d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra ATOMIC_OP_RETURN(op, c_op, asm_op) 76d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 77d839bae4269aea46bff4133066a411cfba5c7c46Peter ZijlstraATOMIC_OPS(add, +=, add) 78d839bae4269aea46bff4133066a411cfba5c7c46Peter ZijlstraATOMIC_OPS(sub, -=, sub) 79d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 80d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#undef ATOMIC_OPS 81d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#undef ATOMIC_OP_RETURN 82d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra#undef ATOMIC_OP 83d839bae4269aea46bff4133066a411cfba5c7c46Peter Zijlstra 8469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_inc(atomic_t *v) 8569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 8669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addql #1,%0" : "+m" (*v)); 8769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 8869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 8969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_dec(atomic_t *v) 9069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 9169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subql #1,%0" : "+m" (*v)); 9269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 9369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 9469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_dec_and_test(atomic_t *v) 9569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 9669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 9769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "+m" (*v)); 9869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 9969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 10069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 10183b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungererstatic inline int atomic_dec_and_test_lt(atomic_t *v) 10283b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer{ 10383b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer char c; 10483b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer __asm__ __volatile__( 10583b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer "subql #1,%1; slt %0" 10683b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer : "=d" (c), "=m" (*v) 10783b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer : "m" (*v)); 10883b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer return c != 0; 10983b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer} 11083b73d6cb8301df32d9887c16c83490c4fd1f55fGreg Ungerer 11169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_inc_and_test(atomic_t *v) 11269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 11369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 11469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addql #1,%1; seq %0" : "=d" (c), "+m" (*v)); 11569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 11669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 11769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 11869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#ifdef CONFIG_RMW_INSNS 11969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 12069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) 12169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) 12269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 12369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#else /* !CONFIG_RMW_INSNS */ 12469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 12569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_cmpxchg(atomic_t *v, int old, int new) 12669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 12769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer unsigned long flags; 12869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int prev; 12969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 13069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_save(flags); 13169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer prev = atomic_read(v); 13269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer if (prev == old) 13369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer atomic_set(v, new); 13469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_restore(flags); 13569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return prev; 13669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 13769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 13869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_xchg(atomic_t *v, int new) 13969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 14069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer unsigned long flags; 14169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int prev; 14269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 14369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_save(flags); 14469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer prev = atomic_read(v); 14569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer atomic_set(v, new); 14669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer local_irq_restore(flags); 14769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return prev; 14869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 14969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 15069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#endif /* !CONFIG_RMW_INSNS */ 15169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 15269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_dec_return(v) atomic_sub_return(1, (v)) 15369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#define atomic_inc_return(v) atomic_add_return(1, (v)) 15469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 15569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_sub_and_test(int i, atomic_t *v) 15669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 15769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 15869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("subl %2,%1; seq %0" 15969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "=d" (c), "+m" (*v) 16069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : ASM_DI (i)); 16169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 16269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 16369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 16469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline int atomic_add_negative(int i, atomic_t *v) 16569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 16669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer char c; 16769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer __asm__ __volatile__("addl %2,%1; smi %0" 16869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer : "=d" (c), "+m" (*v) 16935de674982aa13de98cf470c640895164017563eGreg Ungerer : ASM_DI (i)); 17069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer return c != 0; 17169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 17269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 17369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_clear_mask(unsigned long mask, unsigned long *v) 17469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 17535de674982aa13de98cf470c640895164017563eGreg Ungerer __asm__ __volatile__("andl %1,%0" : "+m" (*v) : ASM_DI (~(mask))); 17669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 17769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 17869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungererstatic inline void atomic_set_mask(unsigned long mask, unsigned long *v) 17969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 18035de674982aa13de98cf470c640895164017563eGreg Ungerer __asm__ __volatile__("orl %1,%0" : "+m" (*v) : ASM_DI (mask)); 18169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 18269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 183f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharmastatic __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) 18469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer{ 18569f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer int c, old; 18669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer c = atomic_read(v); 18769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer for (;;) { 18869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer if (unlikely(c == (u))) 18969f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer break; 19069f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer old = atomic_cmpxchg((v), c, c + (a)); 19169f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer if (likely(old == c)) 19269f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer break; 19369f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer c = old; 19469f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer } 195f24219b4e90cf70ec4a211b17fbabc725a0ddf3cArun Sharma return c; 19669f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer} 19769f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer 19869f99746a2cfd88b9caed8e320ad86405b228adaGreg Ungerer#endif /* __ARCH_M68K_ATOMIC __ */ 199