1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_SH_CMPXCHG_XCHG_H
3 #define __ASM_SH_CMPXCHG_XCHG_H
6 * Copyright (C) 2016 Red Hat, Inc.
7 * Author: Michael S. Tsirkin <mst@redhat.com>
9 #include <linux/bits.h>
10 #include <linux/compiler.h>
11 #include <asm/byteorder.h>
14 * Portable implementations of 1 and 2 byte xchg using a 4 byte cmpxchg.
15 * Note: this header isn't self-contained: before including it, __cmpxchg_u32
16 * must be defined first.
18 static inline u32
__xchg_cmpxchg(volatile void *ptr
, u32 x
, int size
)
20 int off
= (unsigned long)ptr
% sizeof(u32
);
21 volatile u32
*p
= ptr
- off
;
23 int bitoff
= (sizeof(u32
) - size
- off
) * BITS_PER_BYTE
;
25 int bitoff
= off
* BITS_PER_BYTE
;
27 u32 bitmask
= ((0x1 << size
* BITS_PER_BYTE
) - 1) << bitoff
;
33 ret
= (oldv
& bitmask
) >> bitoff
;
34 newv
= (oldv
& ~bitmask
) | (x
<< bitoff
);
35 } while (__cmpxchg_u32(p
, oldv
, newv
) != oldv
);
40 static inline unsigned long xchg_u16(volatile u16
*m
, unsigned long val
)
42 return __xchg_cmpxchg(m
, val
, sizeof *m
);
45 static inline unsigned long xchg_u8(volatile u8
*m
, unsigned long val
)
47 return __xchg_cmpxchg(m
, val
, sizeof *m
);
50 #endif /* __ASM_SH_CMPXCHG_XCHG_H */