diff options
Diffstat (limited to 'include/asm-arm/system.h')
-rw-r--r-- | include/asm-arm/system.h | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index 2f44b2044214..8efa4ebdcacb 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h | |||
@@ -139,7 +139,12 @@ extern unsigned int user_debug; | |||
139 | #define vectors_high() (0) | 139 | #define vectors_high() (0) |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | #if __LINUX_ARM_ARCH__ >= 6 | ||
143 | #define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ | ||
144 | : : "r" (0) : "memory") | ||
145 | #else | ||
142 | #define mb() __asm__ __volatile__ ("" : : : "memory") | 146 | #define mb() __asm__ __volatile__ ("" : : : "memory") |
147 | #endif | ||
143 | #define rmb() mb() | 148 | #define rmb() mb() |
144 | #define wmb() mb() | 149 | #define wmb() mb() |
145 | #define read_barrier_depends() do { } while(0) | 150 | #define read_barrier_depends() do { } while(0) |
@@ -323,12 +328,8 @@ do { \ | |||
323 | * NOTE that this solution won't work on an SMP system, so explcitly | 328 | * NOTE that this solution won't work on an SMP system, so explcitly |
324 | * forbid it here. | 329 | * forbid it here. |
325 | */ | 330 | */ |
326 | #ifdef CONFIG_SMP | ||
327 | #error SMP is not supported on SA1100/SA110 | ||
328 | #else | ||
329 | #define swp_is_buggy | 331 | #define swp_is_buggy |
330 | #endif | 332 | #endif |
331 | #endif | ||
332 | 333 | ||
333 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) | 334 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size) |
334 | { | 335 | { |
@@ -337,35 +338,68 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size | |||
337 | #ifdef swp_is_buggy | 338 | #ifdef swp_is_buggy |
338 | unsigned long flags; | 339 | unsigned long flags; |
339 | #endif | 340 | #endif |
341 | #if __LINUX_ARM_ARCH__ >= 6 | ||
342 | unsigned int tmp; | ||
343 | #endif | ||
340 | 344 | ||
341 | switch (size) { | 345 | switch (size) { |
342 | #ifdef swp_is_buggy | 346 | #if __LINUX_ARM_ARCH__ >= 6 |
343 | case 1: | 347 | case 1: |
344 | local_irq_save(flags); | 348 | asm volatile("@ __xchg1\n" |
345 | ret = *(volatile unsigned char *)ptr; | 349 | "1: ldrexb %0, [%3]\n" |
346 | *(volatile unsigned char *)ptr = x; | 350 | " strexb %1, %2, [%3]\n" |
347 | local_irq_restore(flags); | 351 | " teq %1, #0\n" |
348 | break; | 352 | " bne 1b" |
349 | 353 | : "=&r" (ret), "=&r" (tmp) | |
350 | case 4: | 354 | : "r" (x), "r" (ptr) |
351 | local_irq_save(flags); | 355 | : "memory", "cc"); |
352 | ret = *(volatile unsigned long *)ptr; | 356 | break; |
353 | *(volatile unsigned long *)ptr = x; | 357 | case 4: |
354 | local_irq_restore(flags); | 358 | asm volatile("@ __xchg4\n" |
355 | break; | 359 | "1: ldrex %0, [%3]\n" |
360 | " strex %1, %2, [%3]\n" | ||
361 | " teq %1, #0\n" | ||
362 | " bne 1b" | ||
363 | : "=&r" (ret), "=&r" (tmp) | ||
364 | : "r" (x), "r" (ptr) | ||
365 | : "memory", "cc"); | ||
366 | break; | ||
367 | #elif defined(swp_is_buggy) | ||
368 | #ifdef CONFIG_SMP | ||
369 | #error SMP is not supported on this platform | ||
370 | #endif | ||
371 | case 1: | ||
372 | local_irq_save(flags); | ||
373 | ret = *(volatile unsigned char *)ptr; | ||
374 | *(volatile unsigned char *)ptr = x; | ||
375 | local_irq_restore(flags); | ||
376 | break; | ||
377 | |||
378 | case 4: | ||
379 | local_irq_save(flags); | ||
380 | ret = *(volatile unsigned long *)ptr; | ||
381 | *(volatile unsigned long *)ptr = x; | ||
382 | local_irq_restore(flags); | ||
383 | break; | ||
356 | #else | 384 | #else |
357 | case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]" | 385 | case 1: |
358 | : "=&r" (ret) | 386 | asm volatile("@ __xchg1\n" |
359 | : "r" (x), "r" (ptr) | 387 | " swpb %0, %1, [%2]" |
360 | : "memory", "cc"); | 388 | : "=&r" (ret) |
361 | break; | 389 | : "r" (x), "r" (ptr) |
362 | case 4: __asm__ __volatile__ ("swp %0, %1, [%2]" | 390 | : "memory", "cc"); |
363 | : "=&r" (ret) | 391 | break; |
364 | : "r" (x), "r" (ptr) | 392 | case 4: |
365 | : "memory", "cc"); | 393 | asm volatile("@ __xchg4\n" |
366 | break; | 394 | " swp %0, %1, [%2]" |
395 | : "=&r" (ret) | ||
396 | : "r" (x), "r" (ptr) | ||
397 | : "memory", "cc"); | ||
398 | break; | ||
367 | #endif | 399 | #endif |
368 | default: __bad_xchg(ptr, size), ret = 0; | 400 | default: |
401 | __bad_xchg(ptr, size), ret = 0; | ||
402 | break; | ||
369 | } | 403 | } |
370 | 404 | ||
371 | return ret; | 405 | return ret; |