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 720fda1620f2..ea431e551c6b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -66,7 +66,7 @@ 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 */ | 69 | int polarization; /* physical polarization */ |
70 | u16 address; /* physical cpu address */ | 70 | u16 address; /* physical cpu address */ |
71 | }; | 71 | }; |
72 | 72 | ||
@@ -74,6 +74,10 @@ static u8 boot_cpu_type; | |||
74 | static u16 boot_cpu_address; | 74 | static u16 boot_cpu_address; |
75 | static struct pcpu pcpu_devices[NR_CPUS]; | 75 | static struct pcpu pcpu_devices[NR_CPUS]; |
76 | 76 | ||
77 | /* | ||
78 | * The smp_cpu_state_mutex must be held when changing the state or polarization | ||
79 | * member of a pcpu data structure within the pcpu_devices arreay. | ||
80 | */ | ||
77 | DEFINE_MUTEX(smp_cpu_state_mutex); | 81 | DEFINE_MUTEX(smp_cpu_state_mutex); |
78 | 82 | ||
79 | /* | 83 | /* |
@@ -99,7 +103,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) | |||
99 | int cc; | 103 | int cc; |
100 | 104 | ||
101 | while (1) { | 105 | while (1) { |
102 | cc = __pcpu_sigp(addr, order, parm, status); | 106 | cc = __pcpu_sigp(addr, order, parm, NULL); |
103 | if (cc != SIGP_CC_BUSY) | 107 | if (cc != SIGP_CC_BUSY) |
104 | return cc; | 108 | return cc; |
105 | cpu_relax(); | 109 | cpu_relax(); |
@@ -111,7 +115,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
111 | int cc, retry; | 115 | int cc, retry; |
112 | 116 | ||
113 | for (retry = 0; ; retry++) { | 117 | for (retry = 0; ; retry++) { |
114 | cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); | 118 | cc = __pcpu_sigp(pcpu->address, order, parm, NULL); |
115 | if (cc != SIGP_CC_BUSY) | 119 | if (cc != SIGP_CC_BUSY) |
116 | break; | 120 | break; |
117 | if (retry >= 3) | 121 | if (retry >= 3) |
@@ -122,16 +126,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
122 | 126 | ||
123 | static inline int pcpu_stopped(struct pcpu *pcpu) | 127 | static inline int pcpu_stopped(struct pcpu *pcpu) |
124 | { | 128 | { |
129 | u32 uninitialized_var(status); | ||
130 | |||
125 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, | 131 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, |
126 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 132 | 0, &status) != SIGP_CC_STATUS_STORED) |
127 | return 0; | 133 | return 0; |
128 | return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); | 134 | return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); |
129 | } | 135 | } |
130 | 136 | ||
131 | static inline int pcpu_running(struct pcpu *pcpu) | 137 | static inline int pcpu_running(struct pcpu *pcpu) |
132 | { | 138 | { |
133 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, | 139 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, |
134 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 140 | 0, NULL) != SIGP_CC_STATUS_STORED) |
135 | return 1; | 141 | return 1; |
136 | /* Status stored condition code is equivalent to cpu not running. */ | 142 | /* Status stored condition code is equivalent to cpu not running. */ |
137 | return 0; | 143 | return 0; |
@@ -586,6 +592,16 @@ static inline void smp_get_save_area(int cpu, u16 address) { } | |||
586 | 592 | ||
587 | #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ | 593 | #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ |
588 | 594 | ||
595 | void smp_cpu_set_polarization(int cpu, int val) | ||
596 | { | ||
597 | pcpu_devices[cpu].polarization = val; | ||
598 | } | ||
599 | |||
600 | int smp_cpu_get_polarization(int cpu) | ||
601 | { | ||
602 | return pcpu_devices[cpu].polarization; | ||
603 | } | ||
604 | |||
589 | static struct sclp_cpu_info *smp_get_cpu_info(void) | 605 | static struct sclp_cpu_info *smp_get_cpu_info(void) |
590 | { | 606 | { |
591 | static int use_sigp_detection; | 607 | static int use_sigp_detection; |
@@ -628,7 +644,7 @@ static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info, | |||
628 | pcpu->address = info->cpu[i].address; | 644 | pcpu->address = info->cpu[i].address; |
629 | pcpu->state = (cpu >= info->configured) ? | 645 | pcpu->state = (cpu >= info->configured) ? |
630 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; | 646 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; |
631 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 647 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
632 | set_cpu_present(cpu, true); | 648 | set_cpu_present(cpu, true); |
633 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) | 649 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) |
634 | set_cpu_present(cpu, false); | 650 | set_cpu_present(cpu, false); |
@@ -796,7 +812,7 @@ void __init smp_prepare_boot_cpu(void) | |||
796 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; | 812 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; |
797 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; | 813 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; |
798 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 814 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
799 | cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 815 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
800 | set_cpu_present(0, true); | 816 | set_cpu_present(0, true); |
801 | set_cpu_online(0, true); | 817 | set_cpu_online(0, true); |
802 | } | 818 | } |
@@ -862,7 +878,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
862 | if (rc) | 878 | if (rc) |
863 | break; | 879 | break; |
864 | pcpu->state = CPU_STATE_STANDBY; | 880 | pcpu->state = CPU_STATE_STANDBY; |
865 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 881 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
866 | topology_expect_change(); | 882 | topology_expect_change(); |
867 | break; | 883 | break; |
868 | case 1: | 884 | case 1: |
@@ -872,7 +888,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
872 | if (rc) | 888 | if (rc) |
873 | break; | 889 | break; |
874 | pcpu->state = CPU_STATE_CONFIGURED; | 890 | pcpu->state = CPU_STATE_CONFIGURED; |
875 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 891 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
876 | topology_expect_change(); | 892 | topology_expect_change(); |
877 | break; | 893 | break; |
878 | default: | 894 | default: |
@@ -959,23 +975,17 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, | |||
959 | struct device *s = &c->dev; | 975 | struct device *s = &c->dev; |
960 | int err = 0; | 976 | int err = 0; |
961 | 977 | ||
962 | switch (action) { | 978 | switch (action & ~CPU_TASKS_FROZEN) { |
963 | case CPU_ONLINE: | 979 | case CPU_ONLINE: |
964 | case CPU_ONLINE_FROZEN: | ||
965 | err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); | 980 | err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); |
966 | break; | 981 | break; |
967 | case CPU_DEAD: | 982 | case CPU_DEAD: |
968 | case CPU_DEAD_FROZEN: | ||
969 | sysfs_remove_group(&s->kobj, &cpu_online_attr_group); | 983 | sysfs_remove_group(&s->kobj, &cpu_online_attr_group); |
970 | break; | 984 | break; |
971 | } | 985 | } |
972 | return notifier_from_errno(err); | 986 | return notifier_from_errno(err); |
973 | } | 987 | } |
974 | 988 | ||
975 | static struct notifier_block __cpuinitdata smp_cpu_nb = { | ||
976 | .notifier_call = smp_cpu_notify, | ||
977 | }; | ||
978 | |||
979 | static int __devinit smp_add_present_cpu(int cpu) | 989 | static int __devinit smp_add_present_cpu(int cpu) |
980 | { | 990 | { |
981 | struct cpu *c = &pcpu_devices[cpu].cpu; | 991 | struct cpu *c = &pcpu_devices[cpu].cpu; |
@@ -1050,7 +1060,7 @@ static int __init s390_smp_init(void) | |||
1050 | { | 1060 | { |
1051 | int cpu, rc; | 1061 | int cpu, rc; |
1052 | 1062 | ||
1053 | register_cpu_notifier(&smp_cpu_nb); | 1063 | hotcpu_notifier(smp_cpu_notify, 0); |
1054 | #ifdef CONFIG_HOTPLUG_CPU | 1064 | #ifdef CONFIG_HOTPLUG_CPU |
1055 | rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); | 1065 | rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); |
1056 | if (rc) | 1066 | if (rc) |