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)  |