Commit 51dce386 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

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: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 1b25fda0
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/uaccess.h>
#include <linux/sysctl.h>
#include <linux/cpuset.h> #include <linux/cpuset.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/export.h> #include <linux/export.h>
...@@ -207,10 +209,8 @@ static void topology_update_polarization_simple(void) ...@@ -207,10 +209,8 @@ static void topology_update_polarization_simple(void)
{ {
int cpu; int cpu;
mutex_lock(&smp_cpu_state_mutex);
for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
smp_cpu_set_polarization(cpu, POLARIZATION_HRZ); smp_cpu_set_polarization(cpu, POLARIZATION_HRZ);
mutex_unlock(&smp_cpu_state_mutex);
} }
static int ptf(unsigned long fc) static int ptf(unsigned long fc)
...@@ -278,6 +278,7 @@ static int __arch_update_cpu_topology(void) ...@@ -278,6 +278,7 @@ static int __arch_update_cpu_topology(void)
struct sysinfo_15_1_x *info = tl_info; struct sysinfo_15_1_x *info = tl_info;
int rc = 0; int rc = 0;
mutex_lock(&smp_cpu_state_mutex);
cpumask_clear(&cpus_with_topology); cpumask_clear(&cpus_with_topology);
if (MACHINE_HAS_TOPOLOGY) { if (MACHINE_HAS_TOPOLOGY) {
rc = 1; rc = 1;
...@@ -287,6 +288,7 @@ static int __arch_update_cpu_topology(void) ...@@ -287,6 +288,7 @@ static int __arch_update_cpu_topology(void)
update_cpu_masks(); update_cpu_masks();
if (!MACHINE_HAS_TOPOLOGY) if (!MACHINE_HAS_TOPOLOGY)
topology_update_polarization_simple(); topology_update_polarization_simple();
mutex_unlock(&smp_cpu_state_mutex);
return rc; return rc;
} }
...@@ -313,6 +315,11 @@ void topology_schedule_update(void) ...@@ -313,6 +315,11 @@ void topology_schedule_update(void)
schedule_work(&topology_work); schedule_work(&topology_work);
} }
static void topology_flush_work(void)
{
flush_work(&topology_work);
}
static void topology_timer_fn(unsigned long ignored) static void topology_timer_fn(unsigned long ignored)
{ {
if (ptf(PTF_CHECK)) if (ptf(PTF_CHECK))
...@@ -511,6 +518,11 @@ static inline int topology_get_mode(int enabled) ...@@ -511,6 +518,11 @@ static inline int topology_get_mode(int enabled)
return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE; return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE;
} }
static inline int topology_is_enabled(void)
{
return topology_mode != TOPOLOGY_MODE_SINGLE;
}
static int __init topology_setup(char *str) static int __init topology_setup(char *str)
{ {
bool enabled; bool enabled;
...@@ -524,12 +536,72 @@ static int __init topology_setup(char *str) ...@@ -524,12 +536,72 @@ static int __init topology_setup(char *str)
} }
early_param("topology", topology_setup); early_param("topology", topology_setup);
static int topology_ctl_handler(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
unsigned int len;
int new_mode;
char buf[2];
if (!*lenp || *ppos) {
*lenp = 0;
return 0;
}
if (!write) {
strncpy(buf, topology_is_enabled() ? "1\n" : "0\n",
ARRAY_SIZE(buf));
len = strnlen(buf, ARRAY_SIZE(buf));
if (len > *lenp)
len = *lenp;
if (copy_to_user(buffer, buf, len))
return -EFAULT;
goto out;
}
len = *lenp;
if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
return -EFAULT;
if (buf[0] != '0' && buf[0] != '1')
return -EINVAL;
mutex_lock(&smp_cpu_state_mutex);
new_mode = topology_get_mode(buf[0] == '1');
if (topology_mode != new_mode) {
topology_mode = new_mode;
topology_schedule_update();
}
mutex_unlock(&smp_cpu_state_mutex);
topology_flush_work();
out:
*lenp = len;
*ppos += len;
return 0;
}
static struct ctl_table topology_ctl_table[] = {
{
.procname = "topology",
.mode = 0644,
.proc_handler = topology_ctl_handler,
},
{ },
};
static struct ctl_table topology_dir_table[] = {
{
.procname = "s390",
.maxlen = 0,
.mode = 0555,
.child = topology_ctl_table,
},
{ },
};
static int __init topology_init(void) static int __init topology_init(void)
{ {
if (MACHINE_HAS_TOPOLOGY) if (MACHINE_HAS_TOPOLOGY)
set_topology_timer(); set_topology_timer();
else else
topology_update_polarization_simple(); topology_update_polarization_simple();
register_sysctl_table(topology_dir_table);
return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
} }
device_initcall(topology_init); device_initcall(topology_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment