diff options
47 files changed, 1032 insertions, 979 deletions
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index fa9aaf7144b7..1d4706114a45 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h | |||
| @@ -15,23 +15,29 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/compiler.h> | 16 | #include <linux/compiler.h> |
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <asm/barrier.h> | ||
| 18 | #include <asm/cmpxchg.h> | 19 | #include <asm/cmpxchg.h> |
| 19 | 20 | ||
| 20 | #define ATOMIC_INIT(i) { (i) } | 21 | #define ATOMIC_INIT(i) { (i) } |
| 21 | 22 | ||
| 23 | #define __ATOMIC_NO_BARRIER "\n" | ||
| 24 | |||
| 22 | #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES | 25 | #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES |
| 23 | 26 | ||
| 24 | #define __ATOMIC_OR "lao" | 27 | #define __ATOMIC_OR "lao" |
| 25 | #define __ATOMIC_AND "lan" | 28 | #define __ATOMIC_AND "lan" |
| 26 | #define __ATOMIC_ADD "laa" | 29 | #define __ATOMIC_ADD "laa" |
| 30 | #define __ATOMIC_BARRIER "bcr 14,0\n" | ||
| 27 | 31 | ||
| 28 | #define __ATOMIC_LOOP(ptr, op_val, op_string) \ | 32 | #define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier) \ |
| 29 | ({ \ | 33 | ({ \ |
| 30 | int old_val; \ | 34 | int old_val; \ |
| 31 | \ | 35 | \ |
| 32 | typecheck(atomic_t *, ptr); \ | 36 | typecheck(atomic_t *, ptr); \ |
| 33 | asm volatile( \ | 37 | asm volatile( \ |
| 38 | __barrier \ | ||
| 34 | op_string " %0,%2,%1\n" \ | 39 | op_string " %0,%2,%1\n" \ |
| 40 | __barrier \ | ||
| 35 | : "=d" (old_val), "+Q" ((ptr)->counter) \ | 41 | : "=d" (old_val), "+Q" ((ptr)->counter) \ |
| 36 | : "d" (op_val) \ | 42 | : "d" (op_val) \ |
| 37 | : "cc", "memory"); \ | 43 | : "cc", "memory"); \ |
| @@ -43,8 +49,9 @@ | |||
| 43 | #define __ATOMIC_OR "or" | 49 | #define __ATOMIC_OR "or" |
| 44 | #define __ATOMIC_AND "nr" | 50 | #define __ATOMIC_AND "nr" |
| 45 | #define __ATOMIC_ADD "ar" | 51 | #define __ATOMIC_ADD "ar" |
| 52 | #define __ATOMIC_BARRIER "\n" | ||
| 46 | 53 | ||
| 47 | #define __ATOMIC_LOOP(ptr, op_val, op_string) \ | 54 | #define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier) \ |
| 48 | ({ \ | 55 | ({ \ |
| 49 | int old_val, new_val; \ | 56 | int old_val, new_val; \ |
| 50 | \ | 57 | \ |
| @@ -82,7 +89,7 @@ static inline void atomic_set(atomic_t *v, int i) | |||
| 82 | 89 | ||
| 83 | static inline int atomic_add_return(int i, atomic_t *v) | 90 | static inline int atomic_add_return(int i, atomic_t *v) |
| 84 | { | 91 | { |
| 85 | return __ATOMIC_LOOP(v, i, __ATOMIC_ADD) + i; | 92 | return __ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_BARRIER) + i; |
| 86 | } | 93 | } |
| 87 | 94 | ||
| 88 | static inline void atomic_add(int i, atomic_t *v) | 95 | static inline void atomic_add(int i, atomic_t *v) |
| @@ -94,12 +101,10 @@ static inline void atomic_add(int i, atomic_t *v) | |||
| 94 | : "+Q" (v->counter) | 101 | : "+Q" (v->counter) |
| 95 | : "i" (i) | 102 | : "i" (i) |
| 96 | : "cc", "memory"); | 103 | : "cc", "memory"); |
| 97 | } else { | 104 | return; |
| 98 | atomic_add_return(i, v); | ||
| 99 | } | 105 | } |
| 100 | #else | ||
| 101 | atomic_add_return(i, v); | ||
| 102 | #endif | 106 | #endif |
| 107 | __ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_NO_BARRIER); | ||
| 103 | } | 108 | } |
| 104 | 109 | ||
| 105 | #define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0) | 110 | #define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0) |
| @@ -115,12 +120,12 @@ static inline void atomic_add(int i, atomic_t *v) | |||
| 115 | 120 | ||
| 116 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | 121 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
| 117 | { | 122 | { |
| 118 | __ATOMIC_LOOP(v, ~mask, __ATOMIC_AND); | 123 | __ATOMIC_LOOP(v, ~mask, __ATOMIC_AND, __ATOMIC_NO_BARRIER); |
| 119 | } | 124 | } |
| 120 | 125 | ||
| 121 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | 126 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) |
| 122 | { | 127 | { |
| 123 | __ATOMIC_LOOP(v, mask, __ATOMIC_OR); | 128 | __ATOMIC_LOOP(v, mask, __ATOMIC_OR, __ATOMIC_NO_BARRIER); |
| 124 | } | 129 | } |
| 125 | 130 | ||
| 126 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | 131 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) |
| @@ -157,19 +162,24 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u) | |||
| 157 | 162 | ||
| 158 | #ifdef CONFIG_64BIT | 163 | #ifdef CONFIG_64BIT |
| 159 | 164 | ||
| 165 | #define __ATOMIC64_NO_BARRIER "\n" | ||
| 166 | |||
| 160 | #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES | 167 | #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES |
| 161 | 168 | ||
| 162 | #define __ATOMIC64_OR "laog" | 169 | #define __ATOMIC64_OR "laog" |
| 163 | #define __ATOMIC64_AND "lang" | 170 | #define __ATOMIC64_AND "lang" |
| 164 | #define __ATOMIC64_ADD "laag" | 171 | #define __ATOMIC64_ADD "laag" |
| 172 | #define __ATOMIC64_BARRIER "bcr 14,0\n" | ||
| 165 | 173 | ||
| 166 | #define __ATOMIC64_LOOP(ptr, op_val, op_string) \ | ||
