Files
android_kernel_fxtec_sm6115/kernel/sched/boost.c
Pavankumar Kondeti 3307b2de2c sched: Improve the scheduler
This change is for general scheduler improvement.

Change-Id: Ia43c01e7e368186399b9d021a6761545c7da0c18
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
[satyap@codeaurora.org: fix trivial merge conflict]
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
2019-01-18 13:23:02 -08:00

218 lines
5.3 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*/
#include "sched.h"
#include "walt.h"
#include <linux/of.h>
#include <linux/sched/core_ctl.h>
#include <trace/events/sched.h>
/*
* Scheduler boost is a mechanism to temporarily place tasks on CPUs
* with higher capacity than those where a task would have normally
* ended up with their load characteristics. Any entity enabling
* boost is responsible for disabling it as well.
*/
unsigned int sysctl_sched_boost;
static enum sched_boost_policy boost_policy;
static enum sched_boost_policy boost_policy_dt = SCHED_BOOST_NONE;
static DEFINE_MUTEX(boost_mutex);
static int boost_refcount[MAX_NUM_BOOST_TYPE];
/*
* Scheduler boost type and boost policy might at first seem unrelated,
* however, there exists a connection between them that will allow us
* to use them interchangeably during placement decisions. We'll explain
* the connection here in one possible way so that the implications are
* clear when looking at placement policies.
*
* When policy = SCHED_BOOST_NONE, type is either none or RESTRAINED
* When policy = SCHED_BOOST_ON_ALL or SCHED_BOOST_ON_BIG, type can
* neither be none nor RESTRAINED.
*/
static void set_boost_policy(int type)
{
if (type == NO_BOOST || type == RESTRAINED_BOOST) {
boost_policy = SCHED_BOOST_NONE;
return;
}
if (boost_policy_dt) {
boost_policy = boost_policy_dt;
return;
}
if (min_possible_efficiency != max_possible_efficiency) {
boost_policy = SCHED_BOOST_ON_BIG;
return;
}
boost_policy = SCHED_BOOST_ON_ALL;
}
enum sched_boost_policy sched_boost_policy(void)
{
return boost_policy;
}
static bool verify_boost_params(int type)
{
return type >= RESTRAINED_BOOST_DISABLE && type <= RESTRAINED_BOOST;
}
static void _sched_set_boost(int type)
{
switch (type) {
case NO_BOOST: /* All boost clear */
if (boost_refcount[FULL_THROTTLE_BOOST] > 0) {
core_ctl_set_boost(false);
walt_enable_frequency_aggregation(false);
boost_refcount[FULL_THROTTLE_BOOST] = 0;
}
if (boost_refcount[CONSERVATIVE_BOOST] > 0) {
restore_cgroup_boost_settings();
boost_refcount[CONSERVATIVE_BOOST] = 0;
}
if (boost_refcount[RESTRAINED_BOOST] > 0) {
walt_enable_frequency_aggregation(false);
boost_refcount[RESTRAINED_BOOST] = 0;
}
break;
case FULL_THROTTLE_BOOST:
boost_refcount[FULL_THROTTLE_BOOST]++;
if (boost_refcount[FULL_THROTTLE_BOOST] == 1) {
core_ctl_set_boost(true);
restore_cgroup_boost_settings();
if (!boost_refcount[RESTRAINED_BOOST])
walt_enable_frequency_aggregation(true);
}
break;
case CONSERVATIVE_BOOST:
boost_refcount[CONSERVATIVE_BOOST]++;
if ((boost_refcount[CONSERVATIVE_BOOST] == 1) &&
!boost_refcount[FULL_THROTTLE_BOOST])
update_cgroup_boost_settings();
break;
case RESTRAINED_BOOST:
boost_refcount[RESTRAINED_BOOST]++;
if (boost_refcount[RESTRAINED_BOOST] == 1 &&
!boost_refcount[FULL_THROTTLE_BOOST])
walt_enable_frequency_aggregation(true);
break;
case FULL_THROTTLE_BOOST_DISABLE:
if (boost_refcount[FULL_THROTTLE_BOOST] >= 1) {
boost_refcount[FULL_THROTTLE_BOOST]--;
if (!boost_refcount[FULL_THROTTLE_BOOST]) {
core_ctl_set_boost(false);
if (boost_refcount[CONSERVATIVE_BOOST] >= 1)
update_cgroup_boost_settings();
if (!boost_refcount[RESTRAINED_BOOST])
walt_enable_frequency_aggregation(
false);
}
}
break;
case CONSERVATIVE_BOOST_DISABLE:
if (boost_refcount[CONSERVATIVE_BOOST] >= 1) {
boost_refcount[CONSERVATIVE_BOOST]--;
if (!boost_refcount[CONSERVATIVE_BOOST])
restore_cgroup_boost_settings();
}
break;
case RESTRAINED_BOOST_DISABLE:
if (boost_refcount[RESTRAINED_BOOST] >= 1) {
boost_refcount[RESTRAINED_BOOST]--;
if (!boost_refcount[RESTRAINED_BOOST] &&
!boost_refcount[FULL_THROTTLE_BOOST])
walt_enable_frequency_aggregation(false);
}
break;
default:
WARN_ON(1);
return;
}
/* Aggregate final boost type */
if (boost_refcount[FULL_THROTTLE_BOOST] >= 1)
type = FULL_THROTTLE_BOOST;
else if (boost_refcount[CONSERVATIVE_BOOST] >= 1)
type = CONSERVATIVE_BOOST;
else if (boost_refcount[RESTRAINED_BOOST] >= 1)
type = RESTRAINED_BOOST;
else
type = NO_BOOST;
set_boost_policy(type);
sysctl_sched_boost = type;
trace_sched_set_boost(type);
}
void sched_boost_parse_dt(void)
{
struct device_node *sn;
const char *boost_policy;
sn = of_find_node_by_path("/sched-hmp");
if (!sn)
return;
if (!of_property_read_string(sn, "boost-policy", &boost_policy)) {
if (!strcmp(boost_policy, "boost-on-big"))
boost_policy_dt = SCHED_BOOST_ON_BIG;
else if (!strcmp(boost_policy, "boost-on-all"))
boost_policy_dt = SCHED_BOOST_ON_ALL;
}
}
int sched_set_boost(int type)
{
int ret = 0;
mutex_lock(&boost_mutex);
if (verify_boost_params(type))
_sched_set_boost(type);
else
ret = -EINVAL;
mutex_unlock(&boost_mutex);
return ret;
}
int sched_boost_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp,
loff_t *ppos)
{
int ret;
unsigned int *data = (unsigned int *)table->data;
mutex_lock(&boost_mutex);
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (ret || !write)
goto done;
if (verify_boost_params(*data))
_sched_set_boost(*data);
else
ret = -EINVAL;
done:
mutex_unlock(&boost_mutex);
return ret;
}
int sched_boost(void)
{
return sysctl_sched_boost;
}