diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-08-30 08:24:42 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-09-26 09:45:04 -0400 |
commit | c5e3acd666543544d402c83d24d44e487fb51f11 (patch) | |
tree | a73b7dea31241de6e379660bcd6fca6a39b9482b /arch | |
parent | fbf3c54239f77a82218002e0c511819e274e7cd4 (diff) |
s390/smp: avoid concurrent write to sigp status field
When a sigp instruction is issued it may store a status. This status is
currently stored in a per cpu field of the target cpu.
If multiple cpus issue a sigp instruction with the same target cpu
and a status is stored the result is not necessarily as expected.
Currently this is not an issue:
- on cpu hotplug no sigps, except "restart" and "sense" are sent to the
target cpu.
- on external call we don't look at the status if it is stored
- on sense running the condition code "status stored" is sufficient to
tell if a cpu is running or not
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/kernel/smp.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 87be1024d91b..c88fe8569e62 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -66,7 +66,6 @@ struct pcpu { | |||
66 | unsigned long panic_stack; /* panic stack for the cpu */ | 66 | unsigned long panic_stack; /* panic stack for the cpu */ |
67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ | 67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ |
68 | int state; /* physical cpu state */ | 68 | int state; /* physical cpu state */ |
69 | u32 status; /* last status received via sigp */ | ||
70 | u16 address; /* physical cpu address */ | 69 | u16 address; /* physical cpu address */ |
71 | }; | 70 | }; |
72 | 71 | ||
@@ -99,7 +98,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) | |||
99 | int cc; | 98 | int cc; |
100 | 99 | ||
101 | while (1) { | 100 | while (1) { |
102 | cc = __pcpu_sigp(addr, order, parm, status); | 101 | cc = __pcpu_sigp(addr, order, parm, NULL); |
103 | if (cc != SIGP_CC_BUSY) | 102 | if (cc != SIGP_CC_BUSY) |
104 | return cc; | 103 | return cc; |
105 | cpu_relax(); | 104 | cpu_relax(); |
@@ -111,7 +110,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
111 | int cc, retry; | 110 | int cc, retry; |
112 | 111 | ||
113 | for (retry = 0; ; retry++) { | 112 | for (retry = 0; ; retry++) { |
114 | cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); | 113 | cc = __pcpu_sigp(pcpu->address, order, parm, NULL); |
115 | if (cc != SIGP_CC_BUSY) | 114 | if (cc != SIGP_CC_BUSY) |
116 | break; | 115 | break; |
117 | if (retry >= 3) | 116 | if (retry >= 3) |
@@ -122,16 +121,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
122 | 121 | ||
123 | static inline int pcpu_stopped(struct pcpu *pcpu) | 122 | static inline int pcpu_stopped(struct pcpu *pcpu) |
124 | { | 123 | { |
124 | u32 status; | ||
125 | |||
125 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, | 126 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, |
126 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 127 | 0, &status) != SIGP_CC_STATUS_STORED) |
127 | return 0; | 128 | return 0; |
128 | return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); | 129 | return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); |
129 | } | 130 | } |
130 | 131 | ||
131 | static inline int pcpu_running(struct pcpu *pcpu) | 132 | static inline int pcpu_running(struct pcpu *pcpu) |
132 | { | 133 | { |
133 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, | 134 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, |
134 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 135 | 0, NULL) != SIGP_CC_STATUS_STORED) |
135 | return 1; | 136 | return 1; |
136 | /* Status stored condition code is equivalent to cpu not running. */ | 137 | /* Status stored condition code is equivalent to cpu not running. */ |
137 | return 0; | 138 | return 0; |