diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2012-08-30 14:24:42 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-09-26 15:45:04 +0200 |
commit | c5e3acd666543544d402c83d24d44e487fb51f11 (patch) | |
tree | a73b7dea31241de6e379660bcd6fca6a39b9482b | |
parent | s390/processor: use ARRAY_SIZE instead of hard coded value (diff) | |
download | linux-c5e3acd666543544d402c83d24d44e487fb51f11.tar.xz linux-c5e3acd666543544d402c83d24d44e487fb51f11.zip |
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>
-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 { unsigned long panic_stack; /* panic stack for the cpu */ unsigned long ec_mask; /* bit mask for ec_xxx functions */ int state; /* physical cpu state */ - u32 status; /* last status received via sigp */ u16 address; /* physical cpu address */ }; @@ -99,7 +98,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) int cc; while (1) { - cc = __pcpu_sigp(addr, order, parm, status); + cc = __pcpu_sigp(addr, order, parm, NULL); if (cc != SIGP_CC_BUSY) return cc; cpu_relax(); @@ -111,7 +110,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) int cc, retry; for (retry = 0; ; retry++) { - cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); + cc = __pcpu_sigp(pcpu->address, order, parm, NULL); if (cc != SIGP_CC_BUSY) break; if (retry >= 3) @@ -122,16 +121,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) static inline int pcpu_stopped(struct pcpu *pcpu) { + u32 status; + if (__pcpu_sigp(pcpu->address, SIGP_SENSE, - 0, &pcpu->status) != SIGP_CC_STATUS_STORED) + 0, &status) != SIGP_CC_STATUS_STORED) return 0; - return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); + return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); } static inline int pcpu_running(struct pcpu *pcpu) { if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, - 0, &pcpu->status) != SIGP_CC_STATUS_STORED) + 0, NULL) != SIGP_CC_STATUS_STORED) return 1; /* Status stored condition code is equivalent to cpu not running. */ return 0; |