diff options
Diffstat (limited to 'arch/s390/kernel/topology.c')
-rw-r--r-- | arch/s390/kernel/topology.c | 134 |
1 files changed, 64 insertions, 70 deletions
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 24ee33f1af24..14da43b801d9 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -7,14 +7,14 @@ | |||
7 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 7 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
8 | 8 | ||
9 | #include <linux/workqueue.h> | 9 | #include <linux/workqueue.h> |
10 | #include <linux/bootmem.h> | ||
11 | #include <linux/cpuset.h> | 10 | #include <linux/cpuset.h> |
12 | #include <linux/device.h> | 11 | #include <linux/device.h> |
13 | #include <linux/export.h> | 12 | #include <linux/export.h> |
14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
15 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/init.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/cpu.h> | 18 | #include <linux/cpu.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
@@ -42,8 +42,8 @@ static DEFINE_SPINLOCK(topology_lock); | |||
42 | static struct mask_info socket_info; | 42 | static struct mask_info socket_info; |
43 | static struct mask_info book_info; | 43 | static struct mask_info book_info; |
44 | 44 | ||
45 | struct cpu_topology_s390 cpu_topology[NR_CPUS]; | 45 | DEFINE_PER_CPU(struct cpu_topology_s390, cpu_topology); |
46 | EXPORT_SYMBOL_GPL(cpu_topology); | 46 | EXPORT_PER_CPU_SYMBOL_GPL(cpu_topology); |
47 | 47 | ||
48 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | 48 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) |
49 | { | 49 | { |
@@ -90,15 +90,15 @@ static struct mask_info *add_cpus_to_mask(struct topology_core *tl_core, | |||
90 | if (lcpu < 0) | 90 | if (lcpu < 0) |
91 | continue; | 91 | continue; |
92 | for (i = 0; i <= smp_cpu_mtid; i++) { | 92 | for (i = 0; i <= smp_cpu_mtid; i++) { |
93 | cpu_topology[lcpu + i].book_id = book->id; | 93 | per_cpu(cpu_topology, lcpu + i).book_id = book->id; |
94 | cpu_topology[lcpu + i].core_id = rcore; | 94 | per_cpu(cpu_topology, lcpu + i).core_id = rcore; |
95 | cpu_topology[lcpu + i].thread_id = lcpu + i; | 95 | per_cpu(cpu_topology, lcpu + i).thread_id = lcpu + i; |
96 | cpumask_set_cpu(lcpu + i, &book->mask); | 96 | cpumask_set_cpu(lcpu + i, &book->mask); |
97 | cpumask_set_cpu(lcpu + i, &socket->mask); | 97 | cpumask_set_cpu(lcpu + i, &socket->mask); |
98 | if (one_socket_per_cpu) | 98 | if (one_socket_per_cpu) |
99 | cpu_topology[lcpu + i].socket_id = rcore; | 99 | per_cpu(cpu_topology, lcpu + i).socket_id = rcore; |
100 | else | 100 | else |
101 | cpu_topology[lcpu + i].socket_id = socket->id; | 101 | per_cpu(cpu_topology, lcpu + i).socket_id = socket->id; |
102 | smp_cpu_set_polarization(lcpu + i, tl_core->pp); | 102 | smp_cpu_set_polarization(lcpu + i, tl_core->pp); |
103 | } | 103 | } |
104 | if (one_socket_per_cpu) | 104 | if (one_socket_per_cpu) |
@@ -249,14 +249,14 @@ static void update_cpu_masks(void) | |||
249 | 249 | ||
250 | spin_lock_irqsave(&topology_lock, flags); | 250 | spin_lock_irqsave(&topology_lock, flags); |
251 | for_each_possible_cpu(cpu) { | 251 | for_each_possible_cpu(cpu) { |
252 | cpu_topology[cpu].thread_mask = cpu_thread_map(cpu); | 252 | per_cpu(cpu_topology, cpu).thread_mask = cpu_thread_map(cpu); |
253 | cpu_topology[cpu].core_mask = cpu_group_map(&socket_info, cpu); | 253 | per_cpu(cpu_topology, cpu).core_mask = cpu_group_map(&socket_info, cpu); |
254 | cpu_topology[cpu].book_mask = cpu_group_map(&book_info, cpu); | 254 | per_cpu(cpu_topology, cpu).book_mask = cpu_group_map(&book_info, cpu); |
255 | if (!MACHINE_HAS_TOPOLOGY) { | 255 | if (!MACHINE_HAS_TOPOLOGY) { |
256 | cpu_topology[cpu].thread_id = cpu; | 256 | per_cpu(cpu_topology, cpu).thread_id = cpu; |
257 | cpu_topology[cpu].core_id = cpu; | 257 | per_cpu(cpu_topology, cpu).core_id = cpu; |
258 | cpu_topology[cpu].socket_id = cpu; | 258 | per_cpu(cpu_topology, cpu).socket_id = cpu; |
259 | cpu_topology[cpu].book_id = cpu; | 259 | per_cpu(cpu_topology, cpu).book_id = cpu; |
260 | } | 260 | } |
261 | } | 261 | } |
262 | spin_unlock_irqrestore(&topology_lock, flags); | 262 | spin_unlock_irqrestore(&topology_lock, flags); |
@@ -334,50 +334,6 @@ void topology_expect_change(void) | |||
334 | set_topology_timer(); | 334 | set_topology_timer(); |
335 | } | 335 | } |
336 | 336 | ||
337 | static int __init early_parse_topology(char *p) | ||
338 | { | ||
339 | if (strncmp(p, "off", 3)) | ||
340 | return 0; | ||
341 | topology_enabled = 0; | ||
342 | return 0; | ||
343 | } | ||
344 | early_param("topology", early_parse_topology); | ||
345 | |||
346 | static void __init alloc_masks(struct sysinfo_15_1_x *info, | ||
347 | struct mask_info *mask, int offset) | ||
348 | { | ||
349 | int i, nr_masks; | ||
350 | |||
351 | nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; | ||
352 | for (i = 0; i < info->mnest - offset; i++) | ||
353 | nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; | ||
354 | nr_masks = max(nr_masks, 1); | ||
355 | for (i = 0; i < nr_masks; i++) { | ||
356 | mask->next = alloc_bootmem_align( | ||
357 | roundup_pow_of_two(sizeof(struct mask_info)), | ||
358 | roundup_pow_of_two(sizeof(struct mask_info))); | ||
359 | mask = mask->next; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | void __init s390_init_cpu_topology(void) | ||
364 | { | ||
365 | struct sysinfo_15_1_x *info; | ||
366 | int i; | ||
367 | |||
368 | if (!MACHINE_HAS_TOPOLOGY) | ||
369 | return; | ||
370 | tl_info = alloc_bootmem_pages(PAGE_SIZE); | ||
371 | info = tl_info; | ||
372 | store_topology(info); | ||
373 | pr_info("The CPU configuration topology of the machine is:"); | ||
374 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | ||
375 | printk(KERN_CONT " %d", info->mag[i]); | ||
376 | printk(KERN_CONT " / %d\n", info->mnest); | ||
377 | alloc_masks(info, &socket_info, 1); | ||
378 | alloc_masks(info, &book_info, 2); | ||
379 | } | ||
380 | |||
381 | static int cpu_management; | 337 | static int cpu_management; |
382 | 338 | ||
383 | static ssize_t dispatching_show(struct device *dev, | 339 | static ssize_t dispatching_show(struct device *dev, |
@@ -467,20 +423,29 @@ int topology_cpu_init(struct cpu *cpu) | |||
467 | 423 | ||
468 | const struct cpumask *cpu_thread_mask(int cpu) | 424 | const struct cpumask *cpu_thread_mask(int cpu) |
469 | { | 425 | { |
470 | return &cpu_topology[cpu].thread_mask; | 426 | return &per_cpu(cpu_topology, cpu).thread_mask; |
471 | } | 427 | } |
472 | 428 | ||
473 | 429 | ||
474 | const struct cpumask *cpu_coregroup_mask(int cpu) | 430 | const struct cpumask *cpu_coregroup_mask(int cpu) |
475 | { | 431 | { |
476 | return &cpu_topology[cpu].core_mask; | 432 | return &per_cpu(cpu_topology, cpu).core_mask; |
477 | } | 433 | } |
478 | 434 | ||
479 | static const struct cpumask *cpu_book_mask(int cpu) | 435 | static const struct cpumask *cpu_book_mask(int cpu) |
480 | { | 436 | { |
481 | return &cpu_topology[cpu].book_mask; | 437 | return &per_cpu(cpu_topology, cpu).book_mask; |
482 | } | 438 | } |
483 | 439 | ||
440 | static int __init early_parse_topology(char *p) | ||
441 | { | ||
442 | if (strncmp(p, "off", 3)) | ||
443 | return 0; | ||
444 | topology_enabled = 0; | ||
445 | return 0; | ||
446 | } | ||
447 | early_param("topology", early_parse_topology); | ||
448 | |||
484 | static struct sched_domain_topology_level s390_topology[] = { | 449 | static struct sched_domain_topology_level s390_topology[] = { |
485 | { cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, | 450 | { cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, |
486 | { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, | 451 | { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, |
@@ -489,6 +454,42 @@ static struct sched_domain_topology_level s390_topology[] = { | |||
489 | { NULL, }, | 454 | { NULL, }, |
490 | }; | 455 | }; |
491 | 456 | ||
457 | static void __init alloc_masks(struct sysinfo_15_1_x *info, | ||
458 | struct mask_info *mask, int offset) | ||
459 | { | ||
460 | int i, nr_masks; | ||
461 | |||
462 | nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; | ||
463 | for (i = 0; i < info->mnest - offset; i++) | ||
464 | nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; | ||
465 | nr_masks = max(nr_masks, 1); | ||
466 | for (i = 0; i < nr_masks; i++) { | ||
467 | mask->next = kzalloc(sizeof(*mask->next), GFP_KERNEL); | ||
468 | mask = mask->next; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | static int __init s390_topology_init(void) | ||
473 | { | ||
474 | struct sysinfo_15_1_x *info; | ||
475 | int i; | ||
476 | |||
477 | if (!MACHINE_HAS_TOPOLOGY) | ||
478 | return 0; | ||
479 | tl_info = (struct sysinfo_15_1_x *)__get_free_page(GFP_KERNEL); | ||
480 | info = tl_info; | ||
481 | store_topology(info); | ||
482 | pr_info("The CPU configuration topology of the machine is:"); | ||
483 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | ||
484 | printk(KERN_CONT " %d", info->mag[i]); | ||
485 | printk(KERN_CONT " / %d\n", info->mnest); | ||
486 | alloc_masks(info, &socket_info, 1); | ||
487 | alloc_masks(info, &book_info, 2); | ||
488 | set_sched_topology(s390_topology); | ||
489 | return 0; | ||
490 | } | ||
491 | early_initcall(s390_topology_init); | ||
492 | |||
492 | static int __init topology_init(void) | 493 | static int __init topology_init(void) |
493 | { | 494 | { |
494 | if (MACHINE_HAS_TOPOLOGY) | 495 | if (MACHINE_HAS_TOPOLOGY) |
@@ -498,10 +499,3 @@ static int __init topology_init(void) | |||
498 | return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); | 499 | return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); |
499 | } | 500 | } |
500 | device_initcall(topology_init); | 501 | device_initcall(topology_init); |
501 | |||
502 | static int __init early_topology_init(void) | ||
503 | { | ||
504 | set_sched_topology(s390_topology); | ||
505 | return 0; | ||
506 | } | ||
507 | early_initcall(early_topology_init); | ||