Commit b9271a53 authored by Mete Durlu's avatar Mete Durlu Committed by Vasily Gorbik
Browse files

s390/hiperdispatch: Add hiperdispatch sysctl interface



Expose hiperdispatch controls via sysctl. The user can now toggle
hiperdispatch via assigning 0 or 1 to s390.hiperdispatch attribute.
When hiperdipatch is toggled on, it tries to adjust CPU capacities,
while system is in vertical polarization to gain performance benefits
from different CPU polarizations. Disabling hiperdispatch reverts the
CPU capacities to their default (HIGH_CAPACITY) and stops the dynamic
adjustments.

Introduce a kconfig option HIPERDISPATCH_ON which allows users to
use hiperdispatch by default on vertical polarization. Using the
sysctl attribute s390.hiperdispatch would overwrite this behavior.

Acked-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Signed-off-by: default avatarMete Durlu <meted@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 1e5aa12d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -521,6 +521,18 @@ config SCHED_TOPOLOGY_VERTICAL
	  Use vertical CPU polarization by default if available.
	  The default CPU polarization is horizontal.

config HIPERDISPATCH_ON
	def_bool y
	bool "Use hiperdispatch on vertical polarization by default"
	depends on SCHED_TOPOLOGY
	depends on PROC_SYSCTL
	help
	  Hiperdispatch aims to improve the CPU scheduler's decision
	  making when using vertical polarization by adjusting CPU
	  capacities dynamically. Set this option to use hiperdispatch
	  on vertical polarization by default. This can be overwritten
	  by sysctl's s390.hiperdispatch attribute later on.

source "kernel/Kconfig.hz"

config CERT_STORE
+60 −0
Original line number Diff line number Diff line
@@ -48,8 +48,10 @@
#include <linux/cpumask.h>
#include <linux/kernel_stat.h>
#include <linux/ktime.h>
#include <linux/sysctl.h>
#include <linux/workqueue.h>
#include <asm/hiperdispatch.h>
#include <asm/setup.h>
#include <asm/smp.h>
#include <asm/topology.h>

@@ -69,9 +71,21 @@ static int hd_online_cores; /* Current online CORE count */

static unsigned long hd_previous_steal;	/* Previous iteration's CPU steal timer total */

static int hd_enabled;

static void hd_capacity_work_fn(struct work_struct *work);
static DECLARE_DELAYED_WORK(hd_capacity_work, hd_capacity_work_fn);

static int hd_set_hiperdispatch_mode(int enable)
{
	if (!MACHINE_HAS_TOPOLOGY)
		enable = 0;
	if (hd_enabled == enable)
		return 0;
	hd_enabled = enable;
	return 1;
}

void hd_reset_state(void)
{
	cpumask_clear(&hd_vl_coremask);
@@ -131,6 +145,8 @@ void hd_disable_hiperdispatch(void)

int hd_enable_hiperdispatch(void)
{
	if (hd_enabled == 0)
		return 0;
	if (hd_entitled_cores == 0)
		return 0;
	if (hd_online_cores <= hd_entitled_cores)
@@ -211,3 +227,47 @@ static void hd_capacity_work_fn(struct work_struct *work)
	mutex_unlock(&smp_cpu_state_mutex);
	schedule_delayed_work(&hd_capacity_work, HD_DELAY_INTERVAL);
}

static int hiperdispatch_ctl_handler(const struct ctl_table *ctl, int write,
				     void *buffer, size_t *lenp, loff_t *ppos)
{
	int hiperdispatch;
	int rc;
	struct ctl_table ctl_entry = {
		.procname	= ctl->procname,
		.data		= &hiperdispatch,
		.maxlen		= sizeof(int),
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
	};

	hiperdispatch = hd_enabled;
	rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
	if (rc < 0 || !write)
		return rc;
	mutex_lock(&smp_cpu_state_mutex);
	if (hd_set_hiperdispatch_mode(hiperdispatch))
		topology_schedule_update();
	mutex_unlock(&smp_cpu_state_mutex);
	return 0;
}

static struct ctl_table hiperdispatch_ctl_table[] = {
	{
		.procname	= "hiperdispatch",
		.mode		= 0644,
		.proc_handler	= hiperdispatch_ctl_handler,
	},
};

static int __init hd_init(void)
{
	if (IS_ENABLED(CONFIG_HIPERDISPATCH_ON)) {
		hd_set_hiperdispatch_mode(1);
		topology_schedule_update();
	}
	if (!register_sysctl("s390", hiperdispatch_ctl_table))
		pr_warn("Failed to register s390.hiperdispatch sysctl attribute\n");
	return 0;
}
late_initcall(hd_init);