static inline u32 cmpxchg_small()

in include/asm/cmpxchg.h [59:88]


static inline u32 cmpxchg_small(volatile void *ptr, u32 old, u32 new,
				int size)
{
	int off = (unsigned long)ptr % sizeof(u32);
	volatile u32 *p = ptr - off;
#ifdef __BIG_ENDIAN
	int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE;
#else
	int bitoff = off * BITS_PER_BYTE;
#endif
	u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff;
	u32 load32, old32, new32;
	u32 ret;

	load32 = READ_ONCE(*p);

	while (true) {
		ret = (load32 & bitmask) >> bitoff;
		if (old != ret)
			return ret;

		old32 = (load32 & ~bitmask) | (old << bitoff);
		new32 = (load32 & ~bitmask) | (new << bitoff);

		/* Do 32 bit cmpxchg */
		load32 = cmpxchg_u32(p, old32, new32);
		if (load32 == old32)
			return old;
	}
}