diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 720fda1620f..ea431e551c6 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -66,7 +66,7 @@ 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 */ + int polarization; /* physical polarization */ u16 address; /* physical cpu address */ }; @@ -74,6 +74,10 @@ static u8 boot_cpu_type; static u16 boot_cpu_address; static struct pcpu pcpu_devices[NR_CPUS]; +/* + * The smp_cpu_state_mutex must be held when changing the state or polarization + * member of a pcpu data structure within the pcpu_devices arreay. + */ DEFINE_MUTEX(smp_cpu_state_mutex); /* @@ -99,7 +103,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 +115,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 +126,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) static inline int pcpu_stopped(struct pcpu *pcpu) { + u32 uninitialized_var(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; @@ -586,6 +592,16 @@ static inline void smp_get_save_area(int cpu, u16 address) { } #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ +void smp_cpu_set_polarization(int cpu, int val) +{ + pcpu_devices[cpu].polarization = val; +} + +int smp_cpu_get_polarization(int cpu) +{ + return pcpu_devices[cpu].polarization; +} + static struct sclp_cpu_info *smp_get_cpu_info(void) { static int use_sigp_detection; @@ -628,7 +644,7 @@ static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info, pcpu->address = info->cpu[i].address; pcpu->state = (cpu >= info->configured) ? CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; - cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); set_cpu_present(cpu, true); if (sysfs_add && smp_add_present_cpu(cpu) != 0) set_cpu_present(cpu, false); @@ -796,7 +812,7 @@ void __init smp_prepare_boot_cpu(void) pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; S390_lowcore.percpu_offset = __per_cpu_offset[0]; - cpu_set_polarization(0, POLARIZATION_UNKNOWN); + smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); set_cpu_present(0, true); set_cpu_online(0, true); } @@ -862,7 +878,7 @@ static ssize_t cpu_configure_store(struct device *dev, if (rc) break; pcpu->state = CPU_STATE_STANDBY; - cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); topology_expect_change(); break; case 1: @@ -872,7 +888,7 @@ static ssize_t cpu_configure_store(struct device *dev, if (rc) break; pcpu->state = CPU_STATE_CONFIGURED; - cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); + smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); topology_expect_change(); break; default: @@ -959,23 +975,17 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, struct device *s = &c->dev; int err = 0; - switch (action) { + switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: sysfs_remove_group(&s->kobj, &cpu_online_attr_group); break; } return notifier_from_errno(err); } -static struct notifier_block __cpuinitdata smp_cpu_nb = { - .notifier_call = smp_cpu_notify, -}; - static int __devinit smp_add_present_cpu(int cpu) { struct cpu *c = &pcpu_devices[cpu].cpu; @@ -1050,7 +1060,7 @@ static int __init s390_smp_init(void) { int cpu, rc; - register_cpu_notifier(&smp_cpu_nb); + hotcpu_notifier(smp_cpu_notify, 0); #ifdef CONFIG_HOTPLUG_CPU rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); if (rc) |