^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef __ARCH_M68K_CMPXCHG__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define __ARCH_M68K_CMPXCHG__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/irqflags.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) struct __xchg_dummy { unsigned long a[100]; };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define __xg(x) ((volatile struct __xchg_dummy *)(x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #ifndef CONFIG_RMW_INSNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) unsigned long flags, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) tmp = *(u8 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *(u8 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) x = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) tmp = *(u16 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *(u16 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) x = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) tmp = *(u32 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *(u32 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) x = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) tmp = __invalid_xchg_size(x, ptr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) __asm__ __volatile__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ("moveb %2,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) "1:\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) "casb %0,%1,%2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) "jne 1b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) __asm__ __volatile__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ("movew %2,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "1:\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) "casw %0,%1,%2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "jne 1b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) __asm__ __volatile__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ("movel %2,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) "1:\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) "casl %0,%1,%2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "jne 1b"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) x = __invalid_xchg_size(x, ptr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <asm-generic/cmpxchg-local.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) extern unsigned long __invalid_cmpxchg_size(volatile void *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned long, unsigned long, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Atomic compare and exchange. Compare OLD with MEM, if identical,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * store NEW in MEM. Return the initial value in MEM. Success is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * indicated by comparing RETURN with OLD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #ifdef CONFIG_RMW_INSNS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned long new, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) __asm__ __volatile__ ("casb %0,%2,%1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) : "=d" (old), "=m" (*(char *)p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) : "d" (new), "0" (old), "m" (*(char *)p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __asm__ __volatile__ ("casw %0,%2,%1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) : "=d" (old), "=m" (*(short *)p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) : "d" (new), "0" (old), "m" (*(short *)p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) __asm__ __volatile__ ("casl %0,%2,%1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) : "=d" (old), "=m" (*(int *)p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) : "d" (new), "0" (old), "m" (*(int *)p));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) old = __invalid_cmpxchg_size(p, old, new, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return old;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define cmpxchg(ptr, o, n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) (unsigned long)(n), sizeof(*(ptr))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define cmpxchg_local(ptr, o, n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) (unsigned long)(n), sizeof(*(ptr))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #include <asm-generic/cmpxchg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #endif /* __ARCH_M68K_CMPXCHG__ */