19f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifndef __ASM_ARM_CMPXCHG_H
29f97da78bf018206fb623cd351d454af2f105fe0David Howells#define __ASM_ARM_CMPXCHG_H
39f97da78bf018206fb623cd351d454af2f105fe0David Howells
49f97da78bf018206fb623cd351d454af2f105fe0David Howells#include <linux/irqflags.h>
5c32ffce0f66e5d1d4856254516e24f5ef275cd00Will Deacon#include <linux/prefetch.h>
69f97da78bf018206fb623cd351d454af2f105fe0David Howells#include <asm/barrier.h>
79f97da78bf018206fb623cd351d454af2f105fe0David Howells
89f97da78bf018206fb623cd351d454af2f105fe0David Howells#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
99f97da78bf018206fb623cd351d454af2f105fe0David Howells/*
109f97da78bf018206fb623cd351d454af2f105fe0David Howells * On the StrongARM, "swp" is terminally broken since it bypasses the
119f97da78bf018206fb623cd351d454af2f105fe0David Howells * cache totally.  This means that the cache becomes inconsistent, and,
129f97da78bf018206fb623cd351d454af2f105fe0David Howells * since we use normal loads/stores as well, this is really bad.
139f97da78bf018206fb623cd351d454af2f105fe0David Howells * Typically, this causes oopsen in filp_close, but could have other,
149f97da78bf018206fb623cd351d454af2f105fe0David Howells * more disastrous effects.  There are two work-arounds:
159f97da78bf018206fb623cd351d454af2f105fe0David Howells *  1. Disable interrupts and emulate the atomic swap
169f97da78bf018206fb623cd351d454af2f105fe0David Howells *  2. Clean the cache, perform atomic swap, flush the cache
179f97da78bf018206fb623cd351d454af2f105fe0David Howells *
189f97da78bf018206fb623cd351d454af2f105fe0David Howells * We choose (1) since its the "easiest" to achieve here and is not
199f97da78bf018206fb623cd351d454af2f105fe0David Howells * dependent on the processor type.
209f97da78bf018206fb623cd351d454af2f105fe0David Howells *
219f97da78bf018206fb623cd351d454af2f105fe0David Howells * NOTE that this solution won't work on an SMP system, so explcitly
229f97da78bf018206fb623cd351d454af2f105fe0David Howells * forbid it here.
239f97da78bf018206fb623cd351d454af2f105fe0David Howells */
249f97da78bf018206fb623cd351d454af2f105fe0David Howells#define swp_is_buggy
259f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
269f97da78bf018206fb623cd351d454af2f105fe0David Howells
279f97da78bf018206fb623cd351d454af2f105fe0David Howellsstatic inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
289f97da78bf018206fb623cd351d454af2f105fe0David Howells{
299f97da78bf018206fb623cd351d454af2f105fe0David Howells	extern void __bad_xchg(volatile void *, int);
309f97da78bf018206fb623cd351d454af2f105fe0David Howells	unsigned long ret;
319f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifdef swp_is_buggy
329f97da78bf018206fb623cd351d454af2f105fe0David Howells	unsigned long flags;
339f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
349f97da78bf018206fb623cd351d454af2f105fe0David Howells#if __LINUX_ARM_ARCH__ >= 6
359f97da78bf018206fb623cd351d454af2f105fe0David Howells	unsigned int tmp;
369f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
379f97da78bf018206fb623cd351d454af2f105fe0David Howells
389f97da78bf018206fb623cd351d454af2f105fe0David Howells	smp_mb();
39c32ffce0f66e5d1d4856254516e24f5ef275cd00Will Deacon	prefetchw((const void *)ptr);
409f97da78bf018206fb623cd351d454af2f105fe0David Howells
419f97da78bf018206fb623cd351d454af2f105fe0David Howells	switch (size) {
429f97da78bf018206fb623cd351d454af2f105fe0David Howells#if __LINUX_ARM_ARCH__ >= 6
439f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 1:
449f97da78bf018206fb623cd351d454af2f105fe0David Howells		asm volatile("@	__xchg1\n"
459f97da78bf018206fb623cd351d454af2f105fe0David Howells		"1:	ldrexb	%0, [%3]\n"
469f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	strexb	%1, %2, [%3]\n"
479f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	teq	%1, #0\n"
489f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	bne	1b"
499f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "=&r" (ret), "=&r" (tmp)
509f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "r" (x), "r" (ptr)
519f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "memory", "cc");
529f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
539f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 4:
549f97da78bf018206fb623cd351d454af2f105fe0David Howells		asm volatile("@	__xchg4\n"
559f97da78bf018206fb623cd351d454af2f105fe0David Howells		"1:	ldrex	%0, [%3]\n"
569f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	strex	%1, %2, [%3]\n"
579f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	teq	%1, #0\n"
589f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	bne	1b"
599f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "=&r" (ret), "=&r" (tmp)
609f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "r" (x), "r" (ptr)
619f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "memory", "cc");
629f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
639f97da78bf018206fb623cd351d454af2f105fe0David Howells#elif defined(swp_is_buggy)
649f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifdef CONFIG_SMP
659f97da78bf018206fb623cd351d454af2f105fe0David Howells#error SMP is not supported on this platform
669f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
679f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 1:
689f97da78bf018206fb623cd351d454af2f105fe0David Howells		raw_local_irq_save(flags);
699f97da78bf018206fb623cd351d454af2f105fe0David Howells		ret = *(volatile unsigned char *)ptr;
709f97da78bf018206fb623cd351d454af2f105fe0David Howells		*(volatile unsigned char *)ptr = x;
719f97da78bf018206fb623cd351d454af2f105fe0David Howells		raw_local_irq_restore(flags);
729f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
739f97da78bf018206fb623cd351d454af2f105fe0David Howells
749f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 4:
759f97da78bf018206fb623cd351d454af2f105fe0David Howells		raw_local_irq_save(flags);
769f97da78bf018206fb623cd351d454af2f105fe0David Howells		ret = *(volatile unsigned long *)ptr;
779f97da78bf018206fb623cd351d454af2f105fe0David Howells		*(volatile unsigned long *)ptr = x;
789f97da78bf018206fb623cd351d454af2f105fe0David Howells		raw_local_irq_restore(flags);
799f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
809f97da78bf018206fb623cd351d454af2f105fe0David Howells#else
819f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 1:
829f97da78bf018206fb623cd351d454af2f105fe0David Howells		asm volatile("@	__xchg1\n"
839f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	swpb	%0, %1, [%2]"
849f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "=&r" (ret)
859f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "r" (x), "r" (ptr)
869f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "memory", "cc");
879f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
889f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 4:
899f97da78bf018206fb623cd351d454af2f105fe0David Howells		asm volatile("@	__xchg4\n"
909f97da78bf018206fb623cd351d454af2f105fe0David Howells		"	swp	%0, %1, [%2]"
919f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "=&r" (ret)
929f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "r" (x), "r" (ptr)
939f97da78bf018206fb623cd351d454af2f105fe0David Howells			: "memory", "cc");
949f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
959f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
969f97da78bf018206fb623cd351d454af2f105fe0David Howells	default:
979f97da78bf018206fb623cd351d454af2f105fe0David Howells		__bad_xchg(ptr, size), ret = 0;
989f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
999f97da78bf018206fb623cd351d454af2f105fe0David Howells	}
1009f97da78bf018206fb623cd351d454af2f105fe0David Howells	smp_mb();
1019f97da78bf018206fb623cd351d454af2f105fe0David Howells
1029f97da78bf018206fb623cd351d454af2f105fe0David Howells	return ret;
1039f97da78bf018206fb623cd351d454af2f105fe0David Howells}
1049f97da78bf018206fb623cd351d454af2f105fe0David Howells
1059f97da78bf018206fb623cd351d454af2f105fe0David Howells#define xchg(ptr,x) \
1069f97da78bf018206fb623cd351d454af2f105fe0David Howells	((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
1079f97da78bf018206fb623cd351d454af2f105fe0David Howells
1089f97da78bf018206fb623cd351d454af2f105fe0David Howells#include <asm-generic/cmpxchg-local.h>
1099f97da78bf018206fb623cd351d454af2f105fe0David Howells
1109f97da78bf018206fb623cd351d454af2f105fe0David Howells#if __LINUX_ARM_ARCH__ < 6
1119f97da78bf018206fb623cd351d454af2f105fe0David Howells/* min ARCH < ARMv6 */
1129f97da78bf018206fb623cd351d454af2f105fe0David Howells
1139f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifdef CONFIG_SMP
1149f97da78bf018206fb623cd351d454af2f105fe0David Howells#error "SMP is not supported on this platform"
1159f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
1169f97da78bf018206fb623cd351d454af2f105fe0David Howells
1179f97da78bf018206fb623cd351d454af2f105fe0David Howells/*
1189f97da78bf018206fb623cd351d454af2f105fe0David Howells * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
1199f97da78bf018206fb623cd351d454af2f105fe0David Howells * them available.
1209f97da78bf018206fb623cd351d454af2f105fe0David Howells */
1219f97da78bf018206fb623cd351d454af2f105fe0David Howells#define cmpxchg_local(ptr, o, n)				  	       \
1229f97da78bf018206fb623cd351d454af2f105fe0David Howells	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
1239f97da78bf018206fb623cd351d454af2f105fe0David Howells			(unsigned long)(n), sizeof(*(ptr))))
1249f97da78bf018206fb623cd351d454af2f105fe0David Howells#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
1259f97da78bf018206fb623cd351d454af2f105fe0David Howells
1269f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifndef CONFIG_SMP
1279f97da78bf018206fb623cd351d454af2f105fe0David Howells#include <asm-generic/cmpxchg.h>
1289f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
1299f97da78bf018206fb623cd351d454af2f105fe0David Howells
1309f97da78bf018206fb623cd351d454af2f105fe0David Howells#else	/* min ARCH >= ARMv6 */
1319f97da78bf018206fb623cd351d454af2f105fe0David Howells
1329f97da78bf018206fb623cd351d454af2f105fe0David Howellsextern void __bad_cmpxchg(volatile void *ptr, int size);
1339f97da78bf018206fb623cd351d454af2f105fe0David Howells
1349f97da78bf018206fb623cd351d454af2f105fe0David Howells/*
1359f97da78bf018206fb623cd351d454af2f105fe0David Howells * cmpxchg only support 32-bits operands on ARMv6.
1369f97da78bf018206fb623cd351d454af2f105fe0David Howells */
1379f97da78bf018206fb623cd351d454af2f105fe0David Howells
1389f97da78bf018206fb623cd351d454af2f105fe0David Howellsstatic inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
1399f97da78bf018206fb623cd351d454af2f105fe0David Howells				      unsigned long new, int size)
1409f97da78bf018206fb623cd351d454af2f105fe0David Howells{
1419f97da78bf018206fb623cd351d454af2f105fe0David Howells	unsigned long oldval, res;
1429f97da78bf018206fb623cd351d454af2f105fe0David Howells
143c32ffce0f66e5d1d4856254516e24f5ef275cd00Will Deacon	prefetchw((const void *)ptr);
144c32ffce0f66e5d1d4856254516e24f5ef275cd00Will Deacon
1459f97da78bf018206fb623cd351d454af2f105fe0David Howells	switch (size) {
1469f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifndef CONFIG_CPU_V6	/* min ARCH >= ARMv6K */
1479f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 1:
1489f97da78bf018206fb623cd351d454af2f105fe0David Howells		do {
1499f97da78bf018206fb623cd351d454af2f105fe0David Howells			asm volatile("@ __cmpxchg1\n"
1509f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	ldrexb	%1, [%2]\n"
1519f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	mov	%0, #0\n"
1529f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	teq	%1, %3\n"
1539f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	strexbeq %0, %4, [%2]\n"
1549f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "=&r" (res), "=&r" (oldval)
1559f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "r" (ptr), "Ir" (old), "r" (new)
1569f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "memory", "cc");
1579f97da78bf018206fb623cd351d454af2f105fe0David Howells		} while (res);
1589f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
1599f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 2:
1609f97da78bf018206fb623cd351d454af2f105fe0David Howells		do {
1619f97da78bf018206fb623cd351d454af2f105fe0David Howells			asm volatile("@ __cmpxchg1\n"
1629f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	ldrexh	%1, [%2]\n"
1639f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	mov	%0, #0\n"
1649f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	teq	%1, %3\n"
1659f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	strexheq %0, %4, [%2]\n"
1669f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "=&r" (res), "=&r" (oldval)
1679f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "r" (ptr), "Ir" (old), "r" (new)
1689f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "memory", "cc");
1699f97da78bf018206fb623cd351d454af2f105fe0David Howells		} while (res);
1709f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
1719f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
1729f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 4:
1739f97da78bf018206fb623cd351d454af2f105fe0David Howells		do {
1749f97da78bf018206fb623cd351d454af2f105fe0David Howells			asm volatile("@ __cmpxchg4\n"
1759f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	ldrex	%1, [%2]\n"
1769f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	mov	%0, #0\n"
1779f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	teq	%1, %3\n"
1789f97da78bf018206fb623cd351d454af2f105fe0David Howells			"	strexeq %0, %4, [%2]\n"
1799f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "=&r" (res), "=&r" (oldval)
1809f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "r" (ptr), "Ir" (old), "r" (new)
1819f97da78bf018206fb623cd351d454af2f105fe0David Howells				: "memory", "cc");
1829f97da78bf018206fb623cd351d454af2f105fe0David Howells		} while (res);
1839f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
1849f97da78bf018206fb623cd351d454af2f105fe0David Howells	default:
1859f97da78bf018206fb623cd351d454af2f105fe0David Howells		__bad_cmpxchg(ptr, size);
1869f97da78bf018206fb623cd351d454af2f105fe0David Howells		oldval = 0;
1879f97da78bf018206fb623cd351d454af2f105fe0David Howells	}
1889f97da78bf018206fb623cd351d454af2f105fe0David Howells
1899f97da78bf018206fb623cd351d454af2f105fe0David Howells	return oldval;
1909f97da78bf018206fb623cd351d454af2f105fe0David Howells}
1919f97da78bf018206fb623cd351d454af2f105fe0David Howells
1929f97da78bf018206fb623cd351d454af2f105fe0David Howellsstatic inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
1939f97da78bf018206fb623cd351d454af2f105fe0David Howells					 unsigned long new, int size)
1949f97da78bf018206fb623cd351d454af2f105fe0David Howells{
1959f97da78bf018206fb623cd351d454af2f105fe0David Howells	unsigned long ret;
1969f97da78bf018206fb623cd351d454af2f105fe0David Howells
1979f97da78bf018206fb623cd351d454af2f105fe0David Howells	smp_mb();
1989f97da78bf018206fb623cd351d454af2f105fe0David Howells	ret = __cmpxchg(ptr, old, new, size);
1999f97da78bf018206fb623cd351d454af2f105fe0David Howells	smp_mb();
2009f97da78bf018206fb623cd351d454af2f105fe0David Howells
2019f97da78bf018206fb623cd351d454af2f105fe0David Howells	return ret;
2029f97da78bf018206fb623cd351d454af2f105fe0David Howells}
2039f97da78bf018206fb623cd351d454af2f105fe0David Howells
2049f97da78bf018206fb623cd351d454af2f105fe0David Howells#define cmpxchg(ptr,o,n)						\
2059f97da78bf018206fb623cd351d454af2f105fe0David Howells	((__typeof__(*(ptr)))__cmpxchg_mb((ptr),			\
2069f97da78bf018206fb623cd351d454af2f105fe0David Howells					  (unsigned long)(o),		\
2079f97da78bf018206fb623cd351d454af2f105fe0David Howells					  (unsigned long)(n),		\
2089f97da78bf018206fb623cd351d454af2f105fe0David Howells					  sizeof(*(ptr))))
2099f97da78bf018206fb623cd351d454af2f105fe0David Howells
2109f97da78bf018206fb623cd351d454af2f105fe0David Howellsstatic inline unsigned long __cmpxchg_local(volatile void *ptr,
2119f97da78bf018206fb623cd351d454af2f105fe0David Howells					    unsigned long old,
2129f97da78bf018206fb623cd351d454af2f105fe0David Howells					    unsigned long new, int size)
2139f97da78bf018206fb623cd351d454af2f105fe0David Howells{
2149f97da78bf018206fb623cd351d454af2f105fe0David Howells	unsigned long ret;
2159f97da78bf018206fb623cd351d454af2f105fe0David Howells
2169f97da78bf018206fb623cd351d454af2f105fe0David Howells	switch (size) {
2179f97da78bf018206fb623cd351d454af2f105fe0David Howells#ifdef CONFIG_CPU_V6	/* min ARCH == ARMv6 */
2189f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 1:
2199f97da78bf018206fb623cd351d454af2f105fe0David Howells	case 2:
2209f97da78bf018206fb623cd351d454af2f105fe0David Howells		ret = __cmpxchg_local_generic(ptr, old, new, size);
2219f97da78bf018206fb623cd351d454af2f105fe0David Howells		break;
2229f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif
2239f97da78bf018206fb623cd351d454af2f105fe0David Howells	default:
2249f97da78bf018206fb623cd351d454af2f105fe0David Howells		ret = __cmpxchg(ptr, old, new, size);
2259f97da78bf018206fb623cd351d454af2f105fe0David Howells	}
2269f97da78bf018206fb623cd351d454af2f105fe0David Howells
2279f97da78bf018206fb623cd351d454af2f105fe0David Howells	return ret;
2289f97da78bf018206fb623cd351d454af2f105fe0David Howells}
2299f97da78bf018206fb623cd351d454af2f105fe0David Howells
2302523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deaconstatic inline unsigned long long __cmpxchg64(unsigned long long *ptr,
2312523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon					     unsigned long long old,
2322523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon					     unsigned long long new)
2332523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon{
2342523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	unsigned long long oldval;
2352523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	unsigned long res;
2362523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon
237c32ffce0f66e5d1d4856254516e24f5ef275cd00Will Deacon	prefetchw(ptr);
238c32ffce0f66e5d1d4856254516e24f5ef275cd00Will Deacon
2392523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	__asm__ __volatile__(
2402523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"1:	ldrexd		%1, %H1, [%3]\n"
2412523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"	teq		%1, %4\n"
2422523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"	teqeq		%H1, %H4\n"
2432523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"	bne		2f\n"
2442523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"	strexd		%0, %5, %H5, [%3]\n"
2452523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"	teq		%0, #0\n"
2462523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"	bne		1b\n"
2472523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon"2:"
2482523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	: "=&r" (res), "=&r" (oldval), "+Qo" (*ptr)
2492523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	: "r" (ptr), "r" (old), "r" (new)
2502523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	: "cc");
2512523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon
2522523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	return oldval;
2532523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon}
2542523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon
2552523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deaconstatic inline unsigned long long __cmpxchg64_mb(unsigned long long *ptr,
2562523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon						unsigned long long old,
2572523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon						unsigned long long new)
2582523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon{
2592523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	unsigned long long ret;
2602523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon
2612523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	smp_mb();
2622523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	ret = __cmpxchg64(ptr, old, new);
2632523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	smp_mb();
2642523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon
2652523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	return ret;
2662523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon}
2672523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon
2689f97da78bf018206fb623cd351d454af2f105fe0David Howells#define cmpxchg_local(ptr,o,n)						\
2699f97da78bf018206fb623cd351d454af2f105fe0David Howells	((__typeof__(*(ptr)))__cmpxchg_local((ptr),			\
2709f97da78bf018206fb623cd351d454af2f105fe0David Howells				       (unsigned long)(o),		\
2719f97da78bf018206fb623cd351d454af2f105fe0David Howells				       (unsigned long)(n),		\
2729f97da78bf018206fb623cd351d454af2f105fe0David Howells				       sizeof(*(ptr))))
2739f97da78bf018206fb623cd351d454af2f105fe0David Howells
2743e0f5a15f5003f4576c35498814f0f1567860449Will Deacon#define cmpxchg64(ptr, o, n)						\
2752523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	((__typeof__(*(ptr)))__cmpxchg64_mb((ptr),			\
2762523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon					(unsigned long long)(o),	\
2772523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon					(unsigned long long)(n)))
2783e0f5a15f5003f4576c35498814f0f1567860449Will Deacon
279775ebcc16b940ebf61bf54d6054a5e639f68b9d6Will Deacon#define cmpxchg64_relaxed(ptr, o, n)					\
2802523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon	((__typeof__(*(ptr)))__cmpxchg64((ptr),				\
2812523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon					(unsigned long long)(o),	\
2822523c67bb6962f98193dce1c73b6efb65a6ea92cWill Deacon					(unsigned long long)(n)))
2839f97da78bf018206fb623cd351d454af2f105fe0David Howells
284775ebcc16b940ebf61bf54d6054a5e639f68b9d6Will Deacon#define cmpxchg64_local(ptr, o, n)	cmpxchg64_relaxed((ptr), (o), (n))
285775ebcc16b940ebf61bf54d6054a5e639f68b9d6Will Deacon
2869f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif	/* __LINUX_ARM_ARCH__ >= 6 */
2879f97da78bf018206fb623cd351d454af2f105fe0David Howells
2889f97da78bf018206fb623cd351d454af2f105fe0David Howells#endif /* __ASM_ARM_CMPXCHG_H */
289