aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2017-09-14 08:42:32 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-09-20 07:47:55 -0400
commit51dce3867c6c63c7500332e5448c2ba76808d6b5 (patch)
tree5d2d0902c2a4ebf9975dd0d70c54b7776dd487e8
parent1b25fda0533462c9cee3a22e8a7bea68fa670af2 (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.c76
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
216static int ptf(unsigned long fc) 216static 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
318static void topology_flush_work(void)
319{
320 flush_work(&topology_work);
321}
322
316static void topology_timer_fn(unsigned long ignored) 323static 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
521static inline int topology_is_enabled(void)
522{
523 return topology_mode != TOPOLOGY_MODE_SINGLE;
524}
525
514static int __init topology_setup(char *str) 526static 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}
525early_param("topology", topology_setup); 537early_param("topology", topology_setup);
526 538
539static 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();
573out:
574 *lenp = len;
575 *ppos += len;
576 return 0;
577}
578
579static struct ctl_table topology_ctl_table[] = {
580 {
581 .procname = "topology",
582 .mode = 0644,
583 .proc_handler = topology_ctl_handler,
584 },
585 { },
586};
587
588static 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
527static int __init topology_init(void) 598static 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}
535device_initcall(topology_init); 607device_initcall(topology_init);