aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/topology.c')
-rw-r--r--arch/s390/kernel/topology.c172
1 files changed, 117 insertions, 55 deletions
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index fdb5b8cb260f..621f89e36c8a 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -6,17 +6,17 @@
6#define KMSG_COMPONENT "cpu" 6#define KMSG_COMPONENT "cpu"
7#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 7#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
8 8
9#include <linux/kernel.h> 9#include <linux/workqueue.h>
10#include <linux/mm.h>
11#include <linux/init.h>
12#include <linux/device.h>
13#include <linux/bootmem.h> 10#include <linux/bootmem.h>
11#include <linux/cpuset.h>
12#include <linux/device.h>
13#include <linux/kernel.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/workqueue.h> 15#include <linux/init.h>
16#include <linux/delay.h>
16#include <linux/cpu.h> 17#include <linux/cpu.h>
17#include <linux/smp.h> 18#include <linux/smp.h>
18#include <linux/cpuset.h> 19#include <linux/mm.h>
19#include <asm/delay.h>
20 20
21#define PTF_HORIZONTAL (0UL) 21#define PTF_HORIZONTAL (0UL)
22#define PTF_VERTICAL (1UL) 22#define PTF_VERTICAL (1UL)
@@ -41,11 +41,12 @@ static struct mask_info core_info;
41cpumask_t cpu_core_map[NR_CPUS]; 41cpumask_t cpu_core_map[NR_CPUS];
42unsigned char cpu_core_id[NR_CPUS]; 42unsigned char cpu_core_id[NR_CPUS];
43 43
44#ifdef CONFIG_SCHED_BOOK
45static struct mask_info book_info; 44static struct mask_info book_info;
46cpumask_t cpu_book_map[NR_CPUS]; 45cpumask_t cpu_book_map[NR_CPUS];
47unsigned char cpu_book_id[NR_CPUS]; 46unsigned char cpu_book_id[NR_CPUS];
48#endif 47
48/* smp_cpu_state_mutex must be held when accessing this array */
49int cpu_polarization[NR_CPUS];
49 50
50static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) 51static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
51{ 52{
@@ -85,10 +86,8 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
85 for_each_present_cpu(lcpu) { 86 for_each_present_cpu(lcpu) {
86 if (cpu_logical_map(lcpu) != rcpu) 87 if (cpu_logical_map(lcpu) != rcpu)
87 continue; 88 continue;
88#ifdef CONFIG_SCHED_BOOK
89 cpumask_set_cpu(lcpu, &book->mask); 89 cpumask_set_cpu(lcpu, &book->mask);
90 cpu_book_id[lcpu] = book->id; 90 cpu_book_id[lcpu] = book->id;
91#endif
92 cpumask_set_cpu(lcpu, &core->mask); 91 cpumask_set_cpu(lcpu, &core->mask);
93 if (z10) { 92 if (z10) {
94 cpu_core_id[lcpu] = rcpu; 93 cpu_core_id[lcpu] = rcpu;
@@ -96,7 +95,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
96 } else { 95 } else {
97 cpu_core_id[lcpu] = core->id; 96 cpu_core_id[lcpu] = core->id;
98 } 97 }
99 smp_cpu_polarization[lcpu] = tl_cpu->pp; 98 cpu_set_polarization(lcpu, tl_cpu->pp);
100 } 99 }
101 } 100 }
102 return core; 101 return core;
@@ -111,13 +110,11 @@ static void clear_masks(void)
111 cpumask_clear(&info->mask); 110 cpumask_clear(&info->mask);
112 info = info->next; 111 info = info->next;
113 } 112 }
114#ifdef CONFIG_SCHED_BOOK
115 info = &book_info; 113 info = &book_info;
116 while (info) { 114 while (info) {
117 cpumask_clear(&info->mask); 115 cpumask_clear(&info->mask);
118 info = info->next; 116 info = info->next;
119 } 117 }
120#endif
121} 118}
122 119
123static union topology_entry *next_tle(union topology_entry *tle) 120static union topology_entry *next_tle(union topology_entry *tle)
@@ -129,26 +126,19 @@ static union topology_entry *next_tle(union topology_entry *tle)
129 126
130static void tl_to_cores(struct sysinfo_15_1_x *info) 127static void tl_to_cores(struct sysinfo_15_1_x *info)
131{ 128{
132#ifdef CONFIG_SCHED_BOOK
133 struct mask_info *book = &book_info;
134 struct cpuid cpu_id;
135#else
136 struct mask_info *book = NULL;
137#endif
138 struct mask_info *core = &core_info; 129 struct mask_info *core = &core_info;
130 struct mask_info *book = &book_info;
139 union topology_entry *tle, *end; 131 union topology_entry *tle, *end;
132 struct cpuid cpu_id;
140 int z10 = 0; 133 int z10 = 0;
141 134
142#ifdef CONFIG_SCHED_BOOK
143 get_cpu_id(&cpu_id); 135 get_cpu_id(&cpu_id);
144 z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098; 136 z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098;
145#endif
146 spin_lock_irq(&topology_lock); 137 spin_lock_irq(&topology_lock);
147 clear_masks(); 138 clear_masks();
148 tle = info->tle; 139 tle = info->tle;
149 end = (union topology_entry *)((unsigned long)info + info->length); 140 end = (union topology_entry *)((unsigned long)info + info->length);
150 while (tle < end) { 141 while (tle < end) {
151#ifdef CONFIG_SCHED_BOOK
152 if (z10) { 142 if (z10) {
153 switch (tle->nl) { 143 switch (tle->nl) {
154 case 1: 144 case 1:
@@ -165,14 +155,11 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
165 tle = next_tle(tle); 155 tle = next_tle(tle);
166 continue; 156 continue;
167 } 157 }
168#endif
169 switch (tle->nl) { 158 switch (tle->nl) {
170#ifdef CONFIG_SCHED_BOOK
171 case 2: 159 case 2:
172 book = book->next; 160 book = book->next;
173 book->id = tle->container.id; 161 book->id = tle->container.id;
174 break; 162 break;
175#endif
176 case 1: 163 case 1:
177 core = core->next; 164 core = core->next;
178 core->id = tle->container.id; 165 core->id = tle->container.id;
@@ -196,7 +183,7 @@ static void topology_update_polarization_simple(void)
196 183
197 mutex_lock(&smp_cpu_state_mutex); 184 mutex_lock(&smp_cpu_state_mutex);
198 for_each_possible_cpu(cpu) 185 for_each_possible_cpu(cpu)
199 smp_cpu_polarization[cpu] = POLARIZATION_HRZ; 186 cpu_set_polarization(cpu, POLARIZATION_HRZ);
200 mutex_unlock(&smp_cpu_state_mutex); 187 mutex_unlock(&smp_cpu_state_mutex);
201} 188}
202 189
@@ -215,8 +202,7 @@ static int ptf(unsigned long fc)
215 202
216int topology_set_cpu_management(int fc) 203int topology_set_cpu_management(int fc)
217{ 204{
218 int cpu; 205 int cpu, rc;
219 int rc;
220 206
221 if (!MACHINE_HAS_TOPOLOGY) 207 if (!MACHINE_HAS_TOPOLOGY)
222 return -EOPNOTSUPP; 208 return -EOPNOTSUPP;
@@ -227,7 +213,7 @@ int topology_set_cpu_management(int fc)
227 if (rc) 213 if (rc)
228 return -EBUSY; 214 return -EBUSY;
229 for_each_possible_cpu(cpu) 215 for_each_possible_cpu(cpu)
230 smp_cpu_polarization[cpu] = POLARIZATION_UNKNWN; 216 cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
231 return rc; 217 return rc;
232} 218}
233 219
@@ -239,22 +225,18 @@ static void update_cpu_core_map(void)
239 spin_lock_irqsave(&topology_lock, flags); 225 spin_lock_irqsave(&topology_lock, flags);
240 for_each_possible_cpu(cpu) { 226 for_each_possible_cpu(cpu) {
241 cpu_core_map[cpu] = cpu_group_map(&core_info, cpu); 227 cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
242#ifdef CONFIG_SCHED_BOOK
243 cpu_book_map[cpu] = cpu_group_map(&book_info, cpu); 228 cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
244#endif
245 } 229 }
246 spin_unlock_irqrestore(&topology_lock, flags); 230 spin_unlock_irqrestore(&topology_lock, flags);
247} 231}
248 232
249void store_topology(struct sysinfo_15_1_x *info) 233void store_topology(struct sysinfo_15_1_x *info)
250{ 234{
251#ifdef CONFIG_SCHED_BOOK
252 int rc; 235 int rc;
253 236
254 rc = stsi(info, 15, 1, 3); 237 rc = stsi(info, 15, 1, 3);
255 if (rc != -ENOSYS) 238 if (rc != -ENOSYS)
256 return; 239 return;
257#endif
258 stsi(info, 15, 1, 2); 240 stsi(info, 15, 1, 2);
259} 241}
260 242
@@ -313,23 +295,6 @@ static int __init early_parse_topology(char *p)
313} 295}
314early_param("topology", early_parse_topology); 296early_param("topology", early_parse_topology);
315 297
316static int __init init_topology_update(void)
317{
318 int rc;
319
320 rc = 0;
321 if (!MACHINE_HAS_TOPOLOGY) {
322 topology_update_polarization_simple();
323 goto out;
324 }
325 init_timer_deferrable(&topology_timer);
326 set_topology_timer();
327out:
328 update_cpu_core_map();
329 return rc;
330}
331__initcall(init_topology_update);
332
333static void __init alloc_masks(struct sysinfo_15_1_x *info, 298static void __init alloc_masks(struct sysinfo_15_1_x *info,
334 struct mask_info *mask, int offset) 299 struct mask_info *mask, int offset)
335{ 300{
@@ -357,10 +322,107 @@ void __init s390_init_cpu_topology(void)
357 store_topology(info); 322 store_topology(info);
358 pr_info("The CPU configuration topology of the machine is:"); 323 pr_info("The CPU configuration topology of the machine is:");
359 for (i = 0; i < TOPOLOGY_NR_MAG; i++) 324 for (i = 0; i < TOPOLOGY_NR_MAG; i++)
360 printk(" %d", info->mag[i]); 325 printk(KERN_CONT " %d", info->mag[i]);
361 printk(" / %d\n", info->mnest); 326 printk(KERN_CONT " / %d\n", info->mnest);
362 alloc_masks(info, &core_info, 1); 327 alloc_masks(info, &core_info, 1);
363#ifdef CONFIG_SCHED_BOOK
364 alloc_masks(info, &book_info, 2); 328 alloc_masks(info, &book_info, 2);
365#endif
366} 329}
330
331static int cpu_management;
332
333static ssize_t dispatching_show(struct sysdev_class *class,
334 struct sysdev_class_attribute *attr,
335 char *buf)
336{
337 ssize_t count;
338
339 mutex_lock(&smp_cpu_state_mutex);
340 count = sprintf(buf, "%d\n", cpu_management);
341 mutex_unlock(&smp_cpu_state_mutex);
342 return count;
343}
344
345static ssize_t dispatching_store(struct sysdev_class *dev,
346 struct sysdev_class_attribute *attr,
347 const char *buf,
348 size_t count)
349{
350 int val, rc;
351 char delim;
352
353 if (sscanf(buf, "%d %c", &val, &delim) != 1)
354 return -EINVAL;
355 if (val != 0 && val != 1)
356 return -EINVAL;
357 rc = 0;
358 get_online_cpus();
359 mutex_lock(&smp_cpu_state_mutex);
360 if (cpu_management == val)
361 goto out;
362 rc = topology_set_cpu_management(val);
363 if (!rc)
364 cpu_management = val;
365out:
366 mutex_unlock(&smp_cpu_state_mutex);
367 put_online_cpus();
368 return rc ? rc : count;
369}
370static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show,
371 dispatching_store);
372
373static ssize_t cpu_polarization_show(struct sys_device *dev,
374 struct sysdev_attribute *attr, char *buf)
375{
376 int cpu = dev->id;
377 ssize_t count;
378
379 mutex_lock(&smp_cpu_state_mutex);
380 switch (cpu_read_polarization(cpu)) {
381 case POLARIZATION_HRZ:
382 count = sprintf(buf, "horizontal\n");
383 break;
384 case POLARIZATION_VL:
385 count = sprintf(buf, "vertical:low\n");
386 break;
387 case POLARIZATION_VM:
388 count = sprintf(buf, "vertical:medium\n");
389 break;
390 case POLARIZATION_VH:
391 count = sprintf(buf, "vertical:high\n");
392 break;
393 default:
394 count = sprintf(buf, "unknown\n");
395 break;
396 }
397 mutex_unlock(&smp_cpu_state_mutex);
398 return count;
399}
400static SYSDEV_ATTR(polarization, 0444, cpu_polarization_show, NULL);
401
402static struct attribute *topology_cpu_attrs[] = {
403 &attr_polarization.attr,
404 NULL,
405};
406
407static struct attribute_group topology_cpu_attr_group = {
408 .attrs = topology_cpu_attrs,
409};
410
411int topology_cpu_init(struct cpu *cpu)
412{
413 return sysfs_create_group(&cpu->sysdev.kobj, &topology_cpu_attr_group);
414}
415
416static int __init topology_init(void)
417{
418 if (!MACHINE_HAS_TOPOLOGY) {
419 topology_update_polarization_simple();
420 goto out;
421 }
422 init_timer_deferrable(&topology_timer);
423 set_topology_timer();
424out:
425 update_cpu_core_map();
426 return sysdev_class_create_file(&cpu_sysdev_class, &attr_dispatching);
427}
428device_initcall(topology_init);