^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Generic UP xchg and cmpxchg using interrupt disablement. Does not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * support SMP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #ifndef __ASM_GENERIC_CMPXCHG_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define __ASM_GENERIC_CMPXCHG_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #error "Cannot use generic cmpxchg on SMP"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/irqflags.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #ifndef xchg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * This function doesn't exist, so you'll get a linker error if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * something tries to do an invalidly-sized xchg().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) extern void __xchg_called_with_bad_pointer(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long ret, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #ifdef __xchg_u8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return __xchg_u8(x, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ret = *(volatile u8 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *(volatile u8 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #endif /* __xchg_u8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #ifdef __xchg_u16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return __xchg_u16(x, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ret = *(volatile u16 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *(volatile u16 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #endif /* __xchg_u16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #ifdef __xchg_u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return __xchg_u32(x, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ret = *(volatile u32 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *(volatile u32 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #endif /* __xchg_u32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #ifdef __xchg_u64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return __xchg_u64(x, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = *(volatile u64 *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *(volatile u64 *)ptr = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #endif /* __xchg_u64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #endif /* CONFIG_64BIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) __xchg_called_with_bad_pointer();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define xchg(ptr, x) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ((__typeof__(*(ptr))) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #endif /* xchg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Atomic compare and exchange.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #include <asm-generic/cmpxchg-local.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #ifndef cmpxchg_local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define cmpxchg_local(ptr, o, n) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) (unsigned long)(n), sizeof(*(ptr)))); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #ifndef cmpxchg64_local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define cmpxchg(ptr, o, n) cmpxchg_local((ptr), (o), (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #endif /* __ASM_GENERIC_CMPXCHG_H */