[PATCH] ARM SMP: Use exclusive load/store for __xchg
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
6b6a93c687
commit
9560782f9a
|
@ -323,12 +323,8 @@ do { \
|
||||||
* NOTE that this solution won't work on an SMP system, so explcitly
|
* NOTE that this solution won't work on an SMP system, so explcitly
|
||||||
* forbid it here.
|
* forbid it here.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
#error SMP is not supported on SA1100/SA110
|
|
||||||
#else
|
|
||||||
#define swp_is_buggy
|
#define swp_is_buggy
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
|
static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
|
||||||
{
|
{
|
||||||
|
@ -337,35 +333,68 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
|
||||||
#ifdef swp_is_buggy
|
#ifdef swp_is_buggy
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
#endif
|
#endif
|
||||||
|
#if __LINUX_ARM_ARCH__ >= 6
|
||||||
|
unsigned int tmp;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
#ifdef swp_is_buggy
|
#if __LINUX_ARM_ARCH__ >= 6
|
||||||
case 1:
|
case 1:
|
||||||
local_irq_save(flags);
|
asm volatile("@ __xchg1\n"
|
||||||
ret = *(volatile unsigned char *)ptr;
|
"1: ldrexb %0, [%3]\n"
|
||||||
*(volatile unsigned char *)ptr = x;
|
" strexb %1, %2, [%3]\n"
|
||||||
local_irq_restore(flags);
|
" teq %1, #0\n"
|
||||||
break;
|
" bne 1b"
|
||||||
|
: "=&r" (ret), "=&r" (tmp)
|
||||||
case 4:
|
: "r" (x), "r" (ptr)
|
||||||
local_irq_save(flags);
|
: "memory", "cc");
|
||||||
ret = *(volatile unsigned long *)ptr;
|
break;
|
||||||
*(volatile unsigned long *)ptr = x;
|
case 4:
|
||||||
local_irq_restore(flags);
|
asm volatile("@ __xchg4\n"
|
||||||
break;
|
"1: ldrex %0, [%3]\n"
|
||||||
#else
|
" strex %1, %2, [%3]\n"
|
||||||
case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]"
|
" teq %1, #0\n"
|
||||||
: "=&r" (ret)
|
" bne 1b"
|
||||||
: "r" (x), "r" (ptr)
|
: "=&r" (ret), "=&r" (tmp)
|
||||||
: "memory", "cc");
|
: "r" (x), "r" (ptr)
|
||||||
break;
|
: "memory", "cc");
|
||||||
case 4: __asm__ __volatile__ ("swp %0, %1, [%2]"
|
break;
|
||||||
: "=&r" (ret)
|
#elif defined(swp_is_buggy)
|
||||||
: "r" (x), "r" (ptr)
|
#ifdef CONFIG_SMP
|
||||||
: "memory", "cc");
|
#error SMP is not supported on this platform
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
default: __bad_xchg(ptr, size), ret = 0;
|
case 1:
|
||||||
|
local_irq_save(flags);
|
||||||
|
ret = *(volatile unsigned char *)ptr;
|
||||||
|
*(volatile unsigned char *)ptr = x;
|
||||||
|
local_irq_restore(flags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
local_irq_save(flags);
|
||||||
|
ret = *(volatile unsigned long *)ptr;
|
||||||
|
*(volatile unsigned long *)ptr = x;
|
||||||
|
local_irq_restore(flags);
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case 1:
|
||||||
|
asm volatile("@ __xchg1\n"
|
||||||
|
" swpb %0, %1, [%2]"
|
||||||
|
: "=&r" (ret)
|
||||||
|
: "r" (x), "r" (ptr)
|
||||||
|
: "memory", "cc");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
asm volatile("@ __xchg4\n"
|
||||||
|
" swp %0, %1, [%2]"
|
||||||
|
: "=&r" (ret)
|
||||||
|
: "r" (x), "r" (ptr)
|
||||||
|
: "memory", "cc");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
__bad_xchg(ptr, size), ret = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue