aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/setup.h3
-rw-r--r--arch/s390/kernel/early.c18
-rw-r--r--arch/s390/lib/spinlock.c52
3 files changed, 66 insertions, 7 deletions
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 7736fdd72595..b8d1e54b4733 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -57,6 +57,7 @@ extern void detect_memory_memblock(void);
57#define MACHINE_FLAG_TE (1UL << 15) 57#define MACHINE_FLAG_TE (1UL << 15)
58#define MACHINE_FLAG_TLB_LC (1UL << 17) 58#define MACHINE_FLAG_TLB_LC (1UL << 17)
59#define MACHINE_FLAG_VX (1UL << 18) 59#define MACHINE_FLAG_VX (1UL << 18)
60#define MACHINE_FLAG_CAD (1UL << 19)
60 61
61#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) 62#define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
62#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) 63#define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -80,6 +81,7 @@ extern void detect_memory_memblock(void);
80#define MACHINE_HAS_TE (0) 81#define MACHINE_HAS_TE (0)
81#define MACHINE_HAS_TLB_LC (0) 82#define MACHINE_HAS_TLB_LC (0)
82#define MACHINE_HAS_VX (0) 83#define MACHINE_HAS_VX (0)
84#define MACHINE_HAS_CAD (0)
83#else /* CONFIG_64BIT */ 85#else /* CONFIG_64BIT */
84#define MACHINE_HAS_IEEE (1) 86#define MACHINE_HAS_IEEE (1)
85#define MACHINE_HAS_CSP (1) 87#define MACHINE_HAS_CSP (1)
@@ -93,6 +95,7 @@ extern void detect_memory_memblock(void);
93#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) 95#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
94#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC) 96#define MACHINE_HAS_TLB_LC (S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC)
95#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX) 97#define MACHINE_HAS_VX (S390_lowcore.machine_flags & MACHINE_FLAG_VX)
98#define MACHINE_HAS_CAD (S390_lowcore.machine_flags & MACHINE_FLAG_CAD)
96#endif /* CONFIG_64BIT */ 99#endif /* CONFIG_64BIT */
97 100
98/* 101/*
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 302ac1f7f8e7..70a329450901 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -393,9 +393,27 @@ static __init void detect_machine_facilities(void)
393 S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; 393 S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
394 if (test_facility(129)) 394 if (test_facility(129))
395 S390_lowcore.machine_flags |= MACHINE_FLAG_VX; 395 S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
396 if (test_facility(128))
397 S390_lowcore.machine_flags |= MACHINE_FLAG_CAD;
396#endif 398#endif
397} 399}
398 400
401static int __init nocad_setup(char *str)
402{
403 S390_lowcore.machine_flags &= ~MACHINE_FLAG_CAD;
404 return 0;
405}
406early_param("nocad", nocad_setup);
407
408static int __init cad_init(void)
409{
410 if (MACHINE_HAS_CAD)
411 /* Enable problem state CAD. */
412 __ctl_set_bit(2, 3);
413 return 0;
414}
415early_initcall(cad_init);
416
399static __init void rescue_initrd(void) 417static __init void rescue_initrd(void)
400{ 418{
401#ifdef CONFIG_BLK_DEV_INITRD 419#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 034a35a3e9c1..d6c9991f7797 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -12,7 +12,15 @@
12#include <linux/smp.h> 12#include <linux/smp.h>
13#include <asm/io.h> 13#include <asm/io.h>
14 14
15int spin_retry = 1000; 15int spin_retry = -1;
16
17static int __init spin_retry_init(void)
18{
19 if (spin_retry < 0)
20 spin_retry = MACHINE_HAS_CAD ? 10 : 1000;
21 return 0;
22}
23early_initcall(spin_retry_init);
16 24
17/** 25/**
18 * spin_retry= parameter 26 * spin_retry= parameter
@@ -24,6 +32,11 @@ static int __init spin_retry_setup(char *str)
24} 32}
25__setup("spin_retry=", spin_retry_setup); 33__setup("spin_retry=", spin_retry_setup);
26 34
35static inline void _raw_compare_and_delay(unsigned int *lock, unsigned int old)
36{
37 asm(".insn rsy,0xeb0000000022,%0,0,%1" : : "d" (old), "Q" (*lock));
38}
39
27void arch_spin_lock_wait(arch_spinlock_t *lp) 40void arch_spin_lock_wait(arch_spinlock_t *lp)
28{ 41{
29 unsigned int cpu = SPINLOCK_LOCKVAL; 42 unsigned int cpu = SPINLOCK_LOCKVAL;
@@ -46,6 +59,8 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
46 /* Loop for a while on the lock value. */ 59 /* Loop for a while on the lock value. */
47 count = spin_retry; 60 count = spin_retry;
48 do { 61 do {
62 if (MACHINE_HAS_CAD)
63 _raw_compare_and_delay(&lp->lock, owner);
49 owner = ACCESS_ONCE(lp->lock); 64 owner = ACCESS_ONCE(lp->lock);
50 } while (owner && count-- > 0); 65 } while (owner && count-- > 0);
51 if (!owner) 66 if (!owner)
@@ -84,6 +99,8 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
84 /* Loop for a while on the lock value. */ 99 /* Loop for a while on the lock value. */
85 count = spin_retry; 100 count = spin_retry;
86 do { 101 do {
102 if (MACHINE_HAS_CAD)
103 _raw_compare_and_delay(&lp->lock, owner);
87 owner = ACCESS_ONCE(lp->lock); 104 owner = ACCESS_ONCE(lp->lock);
88 } while (owner && count-- > 0); 105 } while (owner && count-- > 0);
89 if (!owner) 106 if (!owner)
@@ -100,11 +117,19 @@ EXPORT_SYMBOL(arch_spin_lock_wait_flags);
100 117
101int arch_spin_trylock_retry(arch_spinlock_t *lp) 118int arch_spin_trylock_retry(arch_spinlock_t *lp)
102{ 119{
120 unsigned int cpu = SPINLOCK_LOCKVAL;
121 unsigned int owner;
103 int count; 122 int count;
104 123
105 for (count = spin_retry; count > 0; count--) 124 for (count = spin_retry; count > 0; count--) {
106 if (arch_spin_trylock_once(lp)) 125 owner = ACCESS_ONCE(lp->lock);
107 return 1; 126 /* Try to get the lock if it is free. */
127 if (!owner) {
128 if (_raw_compare_and_swap(&lp->lock, 0, cpu))
129 return 1;
130 } else if (MACHINE_HAS_CAD)
131 _raw_compare_and_delay(&lp->lock, owner);
132 }
108 return 0; 133 return 0;
109} 134}
110EXPORT_SYMBOL(arch_spin_trylock_retry); 135EXPORT_SYMBOL(arch_spin_trylock_retry);
@@ -126,8 +151,11 @@ void _raw_read_lock_wait(arch_rwlock_t *rw)
126 } 151 }
127 old = ACCESS_ONCE(rw->lock); 152 old = ACCESS_ONCE(rw->lock);
128 owner = ACCESS_ONCE(rw->owner); 153 owner = ACCESS_ONCE(rw->owner);
129 if ((int) old < 0) 154 if ((int) old < 0) {
155 if (MACHINE_HAS_CAD)
156 _raw_compare_and_delay(&rw->lock, old);
130 continue; 157 continue;
158 }
131 if (_raw_compare_and_swap(&rw->lock, old, old + 1)) 159 if (_raw_compare_and_swap(&rw->lock, old, old + 1))
132 return; 160 return;
133 } 161 }
@@ -141,8 +169,11 @@ int _raw_read_trylock_retry(arch_rwlock_t *rw)
141 169
142 while (count-- > 0) { 170 while (count-- > 0) {
143 old = ACCESS_ONCE(rw->lock); 171 old = ACCESS_ONCE(rw->lock);
144 if ((int) old < 0) 172 if ((int) old < 0) {
173 if (MACHINE_HAS_CAD)
174 _raw_compare_and_delay(&rw->lock, old);
145 continue; 175 continue;
176 }
146 if (_raw_compare_and_swap(&rw->lock, old, old + 1)) 177 if (_raw_compare_and_swap(&rw->lock, old, old + 1))
147 return 1; 178 return 1;
148 } 179 }
@@ -173,6 +204,8 @@ void _raw_write_lock_wait(arch_rwlock_t *rw, unsigned int prev)
173 } 204 }
174 if ((old & 0x7fffffff) == 0 && (int) prev >= 0) 205 if ((old & 0x7fffffff) == 0 && (int) prev >= 0)
175 break; 206 break;
207 if (MACHINE_HAS_CAD)
208 _raw_compare_and_delay(&rw->lock, old);
176 } 209 }
177} 210}
178EXPORT_SYMBOL(_raw_write_lock_wait); 211EXPORT_SYMBOL(_raw_write_lock_wait);
@@ -201,6 +234,8 @@ void _raw_write_lock_wait(arch_rwlock_t *rw)
201 smp_rmb(); 234 smp_rmb();
202 if ((old & 0x7fffffff) == 0 && (int) prev >= 0) 235 if ((old & 0x7fffffff) == 0 && (int) prev >= 0)
203 break; 236 break;
237 if (MACHINE_HAS_CAD)
238 _raw_compare_and_delay(&rw->lock, old);
204 } 239 }
205} 240}
206EXPORT_SYMBOL(_raw_write_lock_wait); 241EXPORT_SYMBOL(_raw_write_lock_wait);
@@ -214,8 +249,11 @@ int _raw_write_trylock_retry(arch_rwlock_t *rw)
214 249
215 while (count-- > 0) { 250 while (count-- > 0) {
216 old = ACCESS_ONCE(rw->lock); 251 old = ACCESS_ONCE(rw->lock);
217 if (old) 252 if (old) {
253 if (MACHINE_HAS_CAD)
254 _raw_compare_and_delay(&rw->lock, old);
218 continue; 255 continue;
256 }
219 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) 257 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000))
220 return 1; 258 return 1;
221 } 259 }