diff options
Diffstat (limited to 'arch/s390/kernel/topology.c')
-rw-r--r-- | arch/s390/kernel/topology.c | 72 |
1 files changed, 57 insertions, 15 deletions
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 369dc1c3bd10..12b39b3d9c38 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/topology.c | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | 2 | * Copyright IBM Corp. 2007 |
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | 3 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> |
6 | */ | 4 | */ |
@@ -19,9 +17,17 @@ | |||
19 | #include <asm/sysinfo.h> | 17 | #include <asm/sysinfo.h> |
20 | 18 | ||
21 | #define CPU_BITS 64 | 19 | #define CPU_BITS 64 |
20 | #define NR_MAG 6 | ||
21 | |||
22 | #define PTF_HORIZONTAL (0UL) | ||
23 | #define PTF_VERTICAL (1UL) | ||
24 | #define PTF_CHECK (2UL) | ||
22 | 25 | ||
23 | struct tl_cpu { | 26 | struct tl_cpu { |
24 | unsigned char reserved[6]; | 27 | unsigned char reserved0[4]; |
28 | unsigned char :6; | ||
29 | unsigned char pp:2; | ||
30 | unsigned char reserved1; | ||
25 | unsigned short origin; | 31 | unsigned short origin; |
26 | unsigned long mask[CPU_BITS / BITS_PER_LONG]; | 32 | unsigned long mask[CPU_BITS / BITS_PER_LONG]; |
27 | }; | 33 | }; |
@@ -36,8 +42,6 @@ union tl_entry { | |||
36 | struct tl_container container; | 42 | struct tl_container container; |
37 | }; | 43 | }; |
38 | 44 | ||
39 | #define NR_MAG 6 | ||
40 | |||
41 | struct tl_info { | 45 | struct tl_info { |
42 | unsigned char reserved0[2]; | 46 | unsigned char reserved0[2]; |
43 | unsigned short length; | 47 | unsigned short length; |
@@ -96,8 +100,10 @@ static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core) | |||
96 | 100 | ||
97 | rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin; | 101 | rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin; |
98 | for_each_present_cpu(lcpu) { | 102 | for_each_present_cpu(lcpu) { |
99 | if (__cpu_logical_map[lcpu] == rcpu) | 103 | if (__cpu_logical_map[lcpu] == rcpu) { |
100 | cpu_set(lcpu, core->mask); | 104 | cpu_set(lcpu, core->mask); |
105 | smp_cpu_polarization[lcpu] = tl_cpu->pp; | ||
106 | } | ||
101 | } | 107 | } |
102 | } | 108 | } |
103 | } | 109 | } |
@@ -127,7 +133,7 @@ static void tl_to_cores(struct tl_info *info) | |||
127 | 133 | ||
128 | mutex_lock(&smp_cpu_state_mutex); | 134 | mutex_lock(&smp_cpu_state_mutex); |
129 | clear_cores(); | 135 | clear_cores(); |
130 | tle = (union tl_entry *)&info->tle; | 136 | tle = info->tle; |
131 | end = (union tl_entry *)((unsigned long)info + info->length); | 137 | end = (union tl_entry *)((unsigned long)info + info->length); |
132 | while (tle < end) { | 138 | while (tle < end) { |
133 | switch (tle->nl) { | 139 | switch (tle->nl) { |
@@ -152,7 +158,17 @@ static void tl_to_cores(struct tl_info *info) | |||
152 | mutex_unlock(&smp_cpu_state_mutex); | 158 | mutex_unlock(&smp_cpu_state_mutex); |
153 | } | 159 | } |
154 | 160 | ||
155 | static int ptf(void) | 161 | static void topology_update_polarization_simple(void) |
162 | { | ||
163 | int cpu; | ||
164 | |||
165 | mutex_lock(&smp_cpu_state_mutex); | ||
166 | for_each_present_cpu(cpu) | ||
167 | smp_cpu_polarization[cpu] = POLARIZATION_HRZ; | ||
168 | mutex_unlock(&smp_cpu_state_mutex); | ||
169 | } | ||
170 | |||
171 | static int ptf(unsigned long fc) | ||
156 | { | 172 | { |
157 | int rc; | 173 | int rc; |
158 | 174 | ||
@@ -161,7 +177,25 @@ static int ptf(void) | |||
161 | " ipm %0\n" | 177 | " ipm %0\n" |
162 | " srl %0,28\n" | 178 | " srl %0,28\n" |
163 | : "=d" (rc) | 179 | : "=d" (rc) |
164 | : "d" (2UL) : "cc"); | 180 | : "d" (fc) : "cc"); |
181 | return rc; | ||
182 | } | ||
183 | |||
184 | int topology_set_cpu_management(int fc) | ||
185 | { | ||
186 | int cpu; | ||
187 | int rc; | ||
188 | |||
189 | if (!machine_has_topology) | ||
190 | return -EOPNOTSUPP; | ||
191 | if (fc) | ||
192 | rc = ptf(PTF_VERTICAL); | ||
193 | else | ||
194 | rc = ptf(PTF_HORIZONTAL); | ||
195 | if (rc) | ||
196 | return -EBUSY; | ||
197 | for_each_present_cpu(cpu) | ||
198 | smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN; | ||
165 | return rc; | 199 | return rc; |
166 | } | 200 | } |
167 | 201 | ||
@@ -171,9 +205,10 @@ void arch_update_cpu_topology(void) | |||
171 | struct sys_device *sysdev; | 205 | struct sys_device *sysdev; |
172 | int cpu; | 206 | int cpu; |
173 | 207 | ||
174 | if (!machine_has_topology) | 208 | if (!machine_has_topology) { |
209 | topology_update_polarization_simple(); | ||
175 | return; | 210 | return; |
176 | ptf(); | 211 | } |
177 | stsi(info, 15, 1, 2); | 212 | stsi(info, 15, 1, 2); |
178 | tl_to_cores(info); | 213 | tl_to_cores(info); |
179 | for_each_online_cpu(cpu) { | 214 | for_each_online_cpu(cpu) { |
@@ -187,10 +222,15 @@ static void topology_work_fn(struct work_struct *work) | |||
187 | arch_reinit_sched_domains(); | 222 | arch_reinit_sched_domains(); |
188 | } | 223 | } |
189 | 224 | ||
225 | void topology_schedule_update(void) | ||
226 | { | ||
227 | schedule_work(&topology_work); | ||
228 | } | ||
229 | |||
190 | static void topology_timer_fn(unsigned long ignored) | 230 | static void topology_timer_fn(unsigned long ignored) |
191 | { | 231 | { |
192 | if (ptf()) | 232 | if (ptf(PTF_CHECK)) |
193 | schedule_work(&topology_work); | 233 | topology_schedule_update(); |
194 | set_topology_timer(); | 234 | set_topology_timer(); |
195 | } | 235 | } |
196 | 236 | ||
@@ -211,9 +251,11 @@ static int __init init_topology_update(void) | |||
211 | { | 251 | { |
212 | int rc; | 252 | int rc; |
213 | 253 | ||
214 | if (!machine_has_topology) | 254 | if (!machine_has_topology) { |
255 | topology_update_polarization_simple(); | ||
215 | return 0; | 256 | return 0; |
216 | init_timer(&topology_timer); | 257 | } |
258 | init_timer_deferrable(&topology_timer); | ||
217 | if (machine_has_topology_irq) { | 259 | if (machine_has_topology_irq) { |
218 | rc = register_external_interrupt(0x2005, topology_interrupt); | 260 | rc = register_external_interrupt(0x2005, topology_interrupt); |
219 | if (rc) | 261 | if (rc) |