| /* |
| * 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); |
| |