diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2017-09-14 08:42:32 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2017-09-20 07:47:55 -0400 |
commit | 51dce3867c6c63c7500332e5448c2ba76808d6b5 (patch) | |
tree | 5d2d0902c2a4ebf9975dd0d70c54b7776dd487e8 | |
parent | 1b25fda0533462c9cee3a22e8a7bea68fa670af2 (diff) |
s390/topology: enable / disable topology dynamically
Add a new sysctl file /proc/sys/s390/topology which displays if
topology is on (1) or off (0) as specified by the "topology=" kernel
parameter.
This allows to change topology information during runtime and
configuring it via /etc/sysctl.conf instead of using the kernel line
parameter.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/kernel/topology.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index a0ce9c83f589..ed0bdd220e1a 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -8,6 +8,8 @@ | |||
8 | 8 | ||
9 | #include <linux/workqueue.h> | 9 | #include <linux/workqueue.h> |
10 | #include <linux/bootmem.h> | 10 | #include <linux/bootmem.h> |
11 | #include <linux/uaccess.h> | ||
12 | #include <linux/sysctl.h> | ||
11 | #include <linux/cpuset.h> | 13 | #include <linux/cpuset.h> |
12 | #include <linux/device.h> | 14 | #include <linux/device.h> |
13 | #include <linux/export.h> | 15 | #include <linux/export.h> |
@@ -207,10 +209,8 @@ static void topology_update_polarization_simple(void) | |||
207 | { | 209 | { |
208 | int cpu; | 210 | int cpu; |
209 | 211 | ||
210 | mutex_lock(&smp_cpu_state_mutex); | ||
211 | for_each_possible_cpu(cpu) | 212 | for_each_possible_cpu(cpu) |
212 | smp_cpu_set_polarization(cpu, POLARIZATION_HRZ); | 213 | smp_cpu_set_polarization(cpu, POLARIZATION_HRZ); |
213 | mutex_unlock(&smp_cpu_state_mutex); | ||
214 | } | 214 | } |
215 | 215 | ||
216 | static int ptf(unsigned long fc) | 216 | static int ptf(unsigned long fc) |
@@ -278,6 +278,7 @@ static int __arch_update_cpu_topology(void) | |||
278 | struct sysinfo_15_1_x *info = tl_info; | 278 | struct sysinfo_15_1_x *info = tl_info; |
279 | int rc = 0; | 279 | int rc = 0; |
280 | 280 | ||
281 | mutex_lock(&smp_cpu_state_mutex); | ||
281 | cpumask_clear(&cpus_with_topology); | 282 | cpumask_clear(&cpus_with_topology); |
282 | if (MACHINE_HAS_TOPOLOGY) { | 283 | if (MACHINE_HAS_TOPOLOGY) { |
283 | rc = 1; | 284 | rc = 1; |
@@ -287,6 +288,7 @@ static int __arch_update_cpu_topology(void) | |||
287 | update_cpu_masks(); | 288 | update_cpu_masks(); |
288 | if (!MACHINE_HAS_TOPOLOGY) | 289 | if (!MACHINE_HAS_TOPOLOGY) |
289 | topology_update_polarization_simple(); | 290 | topology_update_polarization_simple(); |
291 | mutex_unlock(&smp_cpu_state_mutex); | ||
290 | return rc; | 292 | return rc; |
291 | } | 293 | } |
292 | 294 | ||
@@ -313,6 +315,11 @@ void topology_schedule_update(void) | |||
313 | schedule_work(&topology_work); | 315 | schedule_work(&topology_work); |
314 | } | 316 | } |
315 | 317 | ||
318 | static void topology_flush_work(void) | ||
319 | { | ||
320 | flush_work(&topology_work); | ||
321 | } | ||
322 | |||
316 | static void topology_timer_fn(unsigned long ignored) | 323 | static void topology_timer_fn(unsigned long ignored) |
317 | { | 324 | { |
318 | if (ptf(PTF_CHECK)) | 325 | if (ptf(PTF_CHECK)) |
@@ -511,6 +518,11 @@ static inline int topology_get_mode(int enabled) | |||
511 | return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE; | 518 | return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE; |
512 | } | 519 | } |
513 | 520 | ||
521 | static inline int topology_is_enabled(void) | ||
522 | { | ||
523 | return topology_mode != TOPOLOGY_MODE_SINGLE; | ||
524 | } | ||
525 | |||
514 | static int __init topology_setup(char *str) | 526 | static int __init topology_setup(char *str) |
515 | { | 527 | { |
516 | bool enabled; | 528 | bool enabled; |
@@ -524,12 +536,72 @@ static int __init topology_setup(char *str) | |||
524 | } | 536 | } |
525 | early_param("topology", topology_setup); | 537 | early_param("topology", topology_setup); |
526 | 538 | ||
539 | static int topology_ctl_handler(struct ctl_table *ctl, int write, | ||
540 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
541 | { | ||
542 | unsigned int len; | ||
543 | int new_mode; | ||
544 | char buf[2]; | ||
545 | |||
546 | if (!*lenp || *ppos) { | ||
547 | *lenp = 0; | ||
548 | return 0; | ||
549 | } | ||
550 | if (!write) { | ||
551 | strncpy(buf, topology_is_enabled() ? "1\n" : "0\n", | ||
552 | ARRAY_SIZE(buf)); | ||
553 | len = strnlen(buf, ARRAY_SIZE(buf)); | ||
554 | if (len > *lenp) | ||
555 | len = *lenp; | ||
556 | if (copy_to_user(buffer, buf, len)) | ||
557 | return -EFAULT; | ||
558 | goto out; | ||
559 | } | ||
560 | len = *lenp; | ||
561 | if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) | ||
562 | return -EFAULT; | ||
563 | if (buf[0] != '0' && buf[0] != '1') | ||
564 | return -EINVAL; | ||
565 | mutex_lock(&smp_cpu_state_mutex); | ||
566 | new_mode = topology_get_mode(buf[0] == '1'); | ||
567 | if (topology_mode != new_mode) { | ||
568 | topology_mode = new_mode; | ||
569 | topology_schedule_update(); | ||
570 | } | ||
571 | mutex_unlock(&smp_cpu_state_mutex); | ||
572 | topology_flush_work(); | ||
573 | out: | ||
574 | *lenp = len; | ||
575 | *ppos += len; | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | static struct ctl_table topology_ctl_table[] = { | ||
580 | { | ||
581 | .procname = "topology", | ||
582 | .mode = 0644, | ||
583 | .proc_handler = topology_ctl_handler, | ||
584 | }, | ||
585 | { }, | ||
586 | }; | ||
587 | |||
588 | static struct ctl_table topology_dir_table[] = { | ||
589 | { | ||
590 | .procname = "s390", | ||
591 | .maxlen = 0, | ||
592 | .mode = 0555, | ||
593 | .child = topology_ctl_table, | ||
594 | }, | ||
595 | { }, | ||
596 | }; | ||
597 | |||
527 | static int __init topology_init(void) | 598 | static int __init topology_init(void) |
528 | { | 599 | { |
529 | if (MACHINE_HAS_TOPOLOGY) | 600 | if (MACHINE_HAS_TOPOLOGY) |
530 | set_topology_timer(); | 601 | set_topology_timer(); |
531 | else | 602 | else |
532 | topology_update_polarization_simple(); | 603 | topology_update_polarization_simple(); |
604 | register_sysctl_table(topology_dir_table); | ||
533 | return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); | 605 | return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); |
534 | } | 606 | } |
535 | device_initcall(topology_init); | 607 | device_initcall(topology_init); |