1 #ifndef __ASM_SH_CMPXCHG_XCHG_H
2 #define __ASM_SH_CMPXCHG_XCHG_H
5 * Copyright (C) 2016 Red Hat, Inc.
6 * Author: Michael S. Tsirkin <mst@redhat.com>
8 * This work is licensed under the terms of the GNU GPL, version 2. See the
9 * file "COPYING" in the main directory of this archive for more details.
11 #include <linux/bits.h>
12 #include <linux/compiler.h>
13 #include <asm/byteorder.h>
16 * Portable implementations of 1 and 2 byte xchg using a 4 byte cmpxchg.
17 * Note: this header isn't self-contained: before including it, __cmpxchg_u32
18 * must be defined first.
20 static inline u32
__xchg_cmpxchg(volatile void *ptr
, u32 x
, int size
)
22 int off
= (unsigned long)ptr
% sizeof(u32
);
23 volatile u32
*p
= ptr
- off
;
25 int bitoff
= (sizeof(u32
) - size
- off
) * BITS_PER_BYTE
;
27 int bitoff
= off
* BITS_PER_BYTE
;
29 u32 bitmask
= ((0x1 << size
* BITS_PER_BYTE
) - 1) << bitoff
;
35 ret
= (oldv
& bitmask
) >> bitoff
;
36 newv
= (oldv
& ~bitmask
) | (x
<< bitoff
);
37 } while (__cmpxchg_u32(p
, oldv
, newv
) != oldv
);
42 static inline unsigned long xchg_u16(volatile u16
*m
, unsigned long val
)
44 return __xchg_cmpxchg(m
, val
, sizeof *m
);
47 static inline unsigned long xchg_u8(volatile u8
*m
, unsigned long val
)
49 return __xchg_cmpxchg(m
, val
, sizeof *m
);
52 #endif /* __ASM_SH_CMPXCHG_XCHG_H */