sched: walt: fix SMART_FMAX threshold based capping logic

One of the condition to remove/apply SMART_FMAX frequency capping
is based on utilization of the CPU, if CPU is busy beyond 90% at the
capped frequency then frequency capping is removed and re-applied
whenever CPU utilization falls below 90%(after hysteresis of 1 sec).

Current logic checks CPU busy time based on the current frequency
and this results in a cycle of capping and uncapping.
For Example:
If the capping frequency is 2.8GHz and cluster's max frequency is
3.1GHz, once capping is applied CPU busy time is compared with
util@2.8GHz, while once capping is removed CPU busy time is compared
with util@3.1GHz, thus if system's requirement is 2.75GHz then there
will be a continuous cycle of capping and uncapping.

Fix this by always comparing CPU busy time against the capping frequency.

While at it, remove "update_smart_fmax_capacity" function as it is
no longer used.

Change-Id: Iefaff1037339477396bd238a01c273af4c7706e6
Signed-off-by: Ashay Jaiswal <quic_ashayj@quicinc.com>
This commit is contained in:
Ashay Jaiswal 2024-02-02 11:42:03 +05:30
parent dd70fdd247
commit 073ad6710f
3 changed files with 14 additions and 22 deletions

View file

@ -2551,7 +2551,6 @@ static struct walt_sched_cluster init_cluster = {
.max_possible_freq = 1,
.aggr_grp_load = 0,
.found_ts = 0,
.smart_fmax_cap = 1,
};
static void init_clusters(void)
@ -2593,7 +2592,6 @@ static struct walt_sched_cluster *alloc_new_cluster(const struct cpumask *cpus)
raw_spin_lock_init(&cluster->load_lock);
cluster->cpus = *cpus;
cluster->found_ts = 0;
cluster->smart_fmax_cap = 1;
return cluster;
}
@ -4567,7 +4565,7 @@ void walt_rotation_checkpoint(int nr_big)
fmax_cap[HIGH_PERF_CAP][i] = FREQ_QOS_MAX_DEFAULT_VALUE;
}
update_fmax_cap_capacities(HIGH_PERF_CAP);
update_fmax_cap_capacities();
}
#define WAKEUP_CTR_THRESH 50
@ -4582,17 +4580,23 @@ bool thres_based_uncap(u64 window_start)
for (i = 0; i < num_sched_clusters; i++) {
bool cluster_high_load = false;
unsigned long fmax_capacity, tgt_cap;
cluster = sched_cluster[i];
fmax_capacity = arch_scale_cpu_capacity(cpumask_first(&cluster->cpus));
tgt_cap = mult_frac(fmax_capacity, sysctl_fmax_cap[cluster->id],
cluster->max_possible_freq);
for_each_cpu(cpu, &cluster->cpus) {
wrq = &per_cpu(walt_rq, cpu);
if (wrq->util >= mult_frac(UTIL_THRES, cluster->smart_fmax_cap, 100)) {
if (wrq->util >= mult_frac(tgt_cap, UTIL_THRES, 100)) {
cluster_high_load = true;
if (!cluster->found_ts)
cluster->found_ts = window_start;
else if ((window_start - cluster->found_ts) >= UNCAP_THRES)
return true;
break;
}
}
if (!cluster_high_load)
@ -4632,7 +4636,7 @@ void fmax_uncap_checkpoint(int nr_big, u64 window_start, u32 wakeup_ctr_sum)
}
}
update_fmax_cap_capacities(SMART_FMAX_CAP);
update_fmax_cap_capacities();
trace_sched_fmax_uncap(nr_big, window_start, wakeup_ctr_sum,
fmax_uncap_load_detected, fmax_uncap_timestamp);
@ -4669,7 +4673,7 @@ void update_freq_relation(struct walt_sched_cluster *cluster)
fmax_cap[FREQ_REL_CAP][cluster_id] = FREQ_QOS_MAX_DEFAULT_VALUE;
if (prev_cap != fmax_cap[FREQ_REL_CAP][cluster_id])
update_fmax_cap_capacities(FREQ_REL_CAP);
update_fmax_cap_capacities();
}
void walt_fill_ta_data(struct core_ctl_notif_data *data)

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _WALT_H
@ -173,7 +173,6 @@ struct walt_sched_cluster {
u64 aggr_grp_load;
unsigned long util_to_cost[1024];
u64 found_ts;
unsigned int smart_fmax_cap;
};
struct freq_relation_map {
@ -1152,24 +1151,13 @@ static inline bool has_internal_freq_limit_changed(struct walt_sched_cluster *cl
return cluster->walt_internal_freq_limit != internal_freq;
}
static inline void update_smart_fmax_capacity(struct walt_sched_cluster *cluster)
{
unsigned long fmax_capacity = arch_scale_cpu_capacity(cpumask_first(&cluster->cpus));
cluster->smart_fmax_cap = mult_frac(fmax_capacity,
fmax_cap[SMART_FMAX_CAP][cluster->id],
cluster->max_possible_freq);
}
static inline void update_fmax_cap_capacities(int type)
static inline void update_fmax_cap_capacities(void)
{
struct walt_sched_cluster *cluster;
int cpu;
for_each_sched_cluster(cluster) {
if (has_internal_freq_limit_changed(cluster)) {
if (type == SMART_FMAX_CAP)
update_smart_fmax_capacity(cluster);
for_each_cpu(cpu, &cluster->cpus)
update_cpu_capacity_helper(cpu);
}

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/cpu.h>
#include <linux/cpumask.h>
@ -288,7 +288,7 @@ void restrict_cpus_and_freq(struct cpumask *cpus)
}
}
update_fmax_cap_capacities(PARTIAL_HALT_CAP);
update_fmax_cap_capacities();
}
struct task_struct *walt_drain_thread;