summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/smp.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2012-08-30 14:24:42 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 15:45:04 +0200
commitc5e3acd666543544d402c83d24d44e487fb51f11 (patch)
treea73b7dea31241de6e379660bcd6fca6a39b9482b /arch/s390/kernel/smp.c
parents390/processor: use ARRAY_SIZE instead of hard coded value (diff)
downloadlinux-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>
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r--arch/s390/kernel/smp.c13
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;