aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/head64.S3
-rw-r--r--arch/s390/kernel/setup.c6
-rw-r--r--arch/s390/lib/Makefile4
-rw-r--r--arch/s390/lib/spinlock.c133
4 files changed, 135 insertions, 11 deletions
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index f525c0c21250..28c50bdf7d40 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -658,10 +658,8 @@ startup:basr %r13,0 # get base
658# 658#
659 la %r1,0f-.LPG1(%r13) # set program check address 659 la %r1,0f-.LPG1(%r13) # set program check address
660 stg %r1,__LC_PGM_NEW_PSW+8 660 stg %r1,__LC_PGM_NEW_PSW+8
661 mvc __LC_DIAG44_OPCODE(8),.Lnop-.LPG1(%r13)
662 diag 0,0,0x44 # test diag 0x44 661 diag 0,0,0x44 # test diag 0x44
663 oi 7(%r12),32 # set diag44 flag 662 oi 7(%r12),32 # set diag44 flag
664 mvc __LC_DIAG44_OPCODE(8),.Ldiag44-.LPG1(%r13)
6650: 6630:
666 664
667# 665#
@@ -702,7 +700,6 @@ startup:basr %r13,0 # get base
702.L4malign:.quad 0xffffffffffc00000 700.L4malign:.quad 0xffffffffffc00000
703.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 701.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
704.Lnop: .long 0x07000700 702.Lnop: .long 0x07000700
705.Ldiag44:.long 0x83000044
706 703
707 .org PARMAREA-64 704 .org PARMAREA-64
708.Lduct: .long 0,0,0,0,0,0,0,0 705.Lduct: .long 0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index a12183989a79..5ba5a5485da9 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -431,12 +431,6 @@ setup_lowcore(void)
431 ctl_set_bit(14, 29); 431 ctl_set_bit(14, 29);
432 } 432 }
433#endif 433#endif
434#ifdef CONFIG_ARCH_S390X
435 if (MACHINE_HAS_DIAG44)
436 lc->diag44_opcode = 0x83000044;
437 else
438 lc->diag44_opcode = 0x07000700;
439#endif /* CONFIG_ARCH_S390X */
440 set_prefix((u32)(unsigned long) lc); 434 set_prefix((u32)(unsigned long) lc);
441} 435}
442 436
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index a8758b1d20a9..b701efa1f00e 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -5,5 +5,5 @@
5EXTRA_AFLAGS := -traditional 5EXTRA_AFLAGS := -traditional
6 6
7lib-y += delay.o string.o 7lib-y += delay.o string.o
8lib-$(CONFIG_ARCH_S390_31) += uaccess.o 8lib-$(CONFIG_ARCH_S390_31) += uaccess.o spinlock.o
9lib-$(CONFIG_ARCH_S390X) += uaccess64.o 9lib-$(CONFIG_ARCH_S390X) += uaccess64.o spinlock.o
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
new file mode 100644
index 000000000000..888b5596c195
--- /dev/null
+++ b/arch/s390/lib/spinlock.c
@@ -0,0 +1,133 @@
1/*
2 * arch/s390/lib/spinlock.c
3 * Out of line spinlock code.
4 *
5 * S390 version
6 * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
8 */
9
10#include <linux/types.h>
11#include <linux/module.h>
12#include <linux/spinlock.h>
13#include <linux/init.h>
14#include <asm/io.h>
15
16atomic_t spin_retry_counter;
17int spin_retry = 1000;
18
19/**
20 * spin_retry= parameter
21 */
22static int __init spin_retry_setup(char *str)
23{
24 spin_retry = simple_strtoul(str, &str, 0);
25 return 1;
26}
27__setup("spin_retry=", spin_retry_setup);
28
29static inline void
30_diag44(void)
31{
32#ifdef __s390x__
33 if (MACHINE_HAS_DIAG44)
34#endif
35 asm volatile("diag 0,0,0x44");
36}
37
38void
39_raw_spin_lock_wait(spinlock_t *lp, unsigned int pc)
40{
41 int count = spin_retry;
42
43 while (1) {
44 if (count-- <= 0) {
45 _diag44();
46 count = spin_retry;
47 }
48 atomic_inc(&spin_retry_counter);
49 if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
50 return;
51 }
52}
53EXPORT_SYMBOL(_raw_spin_lock_wait);
54
55int
56_raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc)
57{
58 int count = spin_retry;
59
60 while (count-- > 0) {
61 atomic_inc(&spin_retry_counter);
62 if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
63 return 1;
64 }
65 return 0;
66}
67EXPORT_SYMBOL(_raw_spin_trylock_retry);
68
69void
70_raw_read_lock_wait(rwlock_t *rw)
71{
72 unsigned int old;
73 int count = spin_retry;
74
75 while (1) {
76 if (count-- <= 0) {
77 _diag44();
78 count = spin_retry;
79 }
80 atomic_inc(&spin_retry_counter);
81 old = rw->lock & 0x7fffffffU;
82 if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
83 return;
84 }
85}
86EXPORT_SYMBOL(_raw_read_lock_wait);
87
88int
89_raw_read_trylock_retry(rwlock_t *rw)
90{
91 unsigned int old;
92 int count = spin_retry;
93
94 while (count-- > 0) {
95 atomic_inc(&spin_retry_counter);
96 old = rw->lock & 0x7fffffffU;
97 if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
98 return 1;
99 }
100 return 0;
101}
102EXPORT_SYMBOL(_raw_read_trylock_retry);
103
104void
105_raw_write_lock_wait(rwlock_t *rw)
106{
107 int count = spin_retry;
108
109 while (1) {
110 if (count-- <= 0) {
111 _diag44();
112 count = spin_retry;
113 }
114 atomic_inc(&spin_retry_counter);
115 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
116 return;
117 }
118}
119EXPORT_SYMBOL(_raw_write_lock_wait);
120
121int
122_raw_write_trylock_retry(rwlock_t *rw)
123{
124 int count = spin_retry;
125
126 while (count-- > 0) {
127 atomic_inc(&spin_retry_counter);
128 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
129 return 1;
130 }
131 return 0;
132}
133EXPORT_SYMBOL(_raw_write_trylock_retry);