blob: f056c03b443b5f3c83778646f05d0bc21685b7c9 [file] [log] [blame]
/*
* Copyright (C) 2018 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*/
/*
* Add a system-wide over-utilization indicator which
* is updated in load-balance.
*/
#include "../../drivers/misc/mediatek/base/power/include/mtk_upower.h"
#include "energy_plus.h"
extern int cpu_eff_tp;
inline bool system_overutilized(int cpu);
#ifdef OPLUS_FEATURE_SPECIALOPT
// caichen@TECH.Kernel.Sched, 2020/09/26, add for heavy load task
inline unsigned long task_util(struct task_struct *p);
#else
static inline unsigned long task_util(struct task_struct *p);
#endif
bool is_intra_domain(int prev, int target);
static int select_max_spare_capacity(struct task_struct *p, int target);
static int init_cpu_info(void);
static unsigned int aggressive_idle_pull(int this_cpu);
bool idle_lb_enhance(struct task_struct *p, int cpu);
static int
___select_idle_sibling(struct task_struct *p, int prev_cpu, int new_cpu);
static int __find_energy_efficient_cpu(struct sched_domain *sd,
struct task_struct *p, int cpu, int prev_cpu, int sync);
extern int find_best_idle_cpu(struct task_struct *p, bool prefer_idle);
static int start_cpu(struct task_struct *p, bool prefer_idle,
bool boosted);
static int
migrate_running_task(int this_cpu, struct task_struct *p, struct rq *target);
#ifdef CONFIG_UCLAMP_TASK
static __always_inline
unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
struct task_struct *p);
#else
inline unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
struct task_struct *p)
{
return util;
}
#endif
#ifdef CONFIG_MTK_UNIFY_POWER
extern int
mtk_idle_power(int cpu_idx, int idle_state, int cpu, void *argu, int sd_level);
extern
int mtk_busy_power(int cpu_idx, int cpu, void *argu, int sd_level);
extern
const struct sched_group_energy * const cci_energy(void);
#endif
/*#define DEBUG_EENV_DECISIONS*/
#ifdef DEBUG_EENV_DECISIONS
/* max of 8 levels of sched groups traversed */
#define EAS_EENV_DEBUG_LEVELS 16
struct _eenv_debug {
unsigned long cap;
unsigned long norm_util;
unsigned long cap_energy;
unsigned long idle_energy;
unsigned long this_energy;
unsigned long this_busy_energy;
unsigned long this_idle_energy;
cpumask_t group_cpumask;
unsigned long cpu_util[1];
};
#endif
struct eenv_cpu {
/* CPU ID, must be in cpus_mask */
int cpu_id;
/*
* Index (into sched_group_energy::cap_states) of the OPP the
* CPU needs to run at if the task is placed on it.
* This includes the both active and blocked load, due to
* other tasks on this CPU, as well as the task's own
* utilization.
*/
#ifndef CONFIG_MTK_SCHED_EAS_POWER_SUPPORT
int cap_idx;
int cap;
#else
int cap_idx[3]; /* [FIXME] cluster may > 3 */
int cap[3];
#endif
/* Estimated system energy */
unsigned long energy;
/* Estimated energy variation wrt EAS_CPU_PRV */
long nrg_delta;
#ifdef DEBUG_EENV_DECISIONS
struct _eenv_debug *debug;
int debug_idx;
#endif /* DEBUG_EENV_DECISIONS */
};
struct energy_env {
/* Utilization to move */
struct task_struct *p;
unsigned long util_delta;
unsigned long util_delta_boosted;
/* Mask of CPUs candidates to evaluate */
cpumask_t cpus_mask;
/* CPU candidates to evaluate */
struct eenv_cpu *cpu;
int eenv_cpu_count;
#ifdef DEBUG_EENV_DECISIONS
/* pointer to the memory block reserved
* for debug on this CPU - there will be
* sizeof(struct _eenv_debug) *
* (EAS_CPU_CNT * EAS_EENV_DEBUG_LEVELS)
* bytes allocated here.
*/
struct _eenv_debug *debug;
#endif
/*
* Index (into energy_env::cpu) of the morst energy efficient CPU for
* the specified energy_env::task
*/
int next_idx;
int max_cpu_count;
/* Support data */
struct sched_group *sg_top;
struct sched_group *sg_cap;
struct sched_group *sg;
};
void mtk_update_new_capacity(struct energy_env *eenv);
static void select_task_prefer_cpu_fair(struct task_struct *p, int *result);
inline int valid_cpu_prefer(int task_prefer);
inline int hinted_cpu_prefer(int task_prefer);
int cpu_prefer(struct task_struct *p);
extern unsigned int hmp_cpu_is_fastest(int cpu);
static int check_freq_turning(void);
struct rq *__migrate_task(struct rq *rq, struct rq_flags *rf,
struct task_struct *p, int dest_cpu);