Skip to content

Commit 4854649

Browse files
committed
cpufreq/sched: Move cpufreq-specific EAS checks to cpufreq
Doing cpufreq-specific EAS checks that require accessing policy internals directly from sched_is_eas_possible() is a bit unfortunate, so introduce cpufreq_ready_for_eas() in cpufreq, move those checks into that new function and make sched_is_eas_possible() call it. While at it, address a possible race between the EAS governor check and governor change by doing the former under the policy rwsem. Signed-off-by: Rafael J. Wysocki <[email protected]> Reviewed-by: Christian Loehle <[email protected]> Tested-by: Christian Loehle <[email protected]> Reviewed-by: Dietmar Eggemann <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent f42c855 commit 4854649

File tree

3 files changed

+39
-20
lines changed

3 files changed

+39
-20
lines changed

drivers/cpufreq/cpufreq.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,6 +3056,38 @@ static int __init cpufreq_core_init(void)
30563056

30573057
return 0;
30583058
}
3059+
3060+
static bool cpufreq_policy_is_good_for_eas(unsigned int cpu)
3061+
{
3062+
struct cpufreq_policy *policy __free(put_cpufreq_policy);
3063+
3064+
policy = cpufreq_cpu_get(cpu);
3065+
if (!policy) {
3066+
pr_debug("cpufreq policy not set for CPU: %d\n", cpu);
3067+
return false;
3068+
}
3069+
3070+
guard(cpufreq_policy_read)(policy);
3071+
3072+
return sugov_is_governor(policy);
3073+
}
3074+
3075+
bool cpufreq_ready_for_eas(const struct cpumask *cpu_mask)
3076+
{
3077+
unsigned int cpu;
3078+
3079+
/* Do not attempt EAS if schedutil is not being used. */
3080+
for_each_cpu(cpu, cpu_mask) {
3081+
if (!cpufreq_policy_is_good_for_eas(cpu)) {
3082+
pr_debug("rd %*pbl: schedutil is mandatory for EAS\n",
3083+
cpumask_pr_args(cpu_mask));
3084+
return false;
3085+
}
3086+
}
3087+
3088+
return true;
3089+
}
3090+
30593091
module_param(off, int, 0444);
30603092
module_param_string(default_governor, default_governor, CPUFREQ_NAME_LEN, 0444);
30613093
core_initcall(cpufreq_core_init);

include/linux/cpufreq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,8 @@ void cpufreq_generic_init(struct cpufreq_policy *policy,
12371237
struct cpufreq_frequency_table *table,
12381238
unsigned int transition_latency);
12391239

1240+
bool cpufreq_ready_for_eas(const struct cpumask *cpu_mask);
1241+
12401242
static inline void cpufreq_register_em_with_opp(struct cpufreq_policy *policy)
12411243
{
12421244
dev_pm_opp_of_register_em(get_cpu_device(policy->cpu),

kernel/sched/topology.c

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,6 @@ static bool sched_energy_update;
212212
static bool sched_is_eas_possible(const struct cpumask *cpu_mask)
213213
{
214214
bool any_asym_capacity = false;
215-
struct cpufreq_policy *policy;
216-
bool policy_is_ready;
217215
int i;
218216

219217
/* EAS is enabled for asymmetric CPU capacity topologies. */
@@ -248,25 +246,12 @@ static bool sched_is_eas_possible(const struct cpumask *cpu_mask)
248246
return false;
249247
}
250248

251-
/* Do not attempt EAS if schedutil is not being used. */
252-
for_each_cpu(i, cpu_mask) {
253-
policy = cpufreq_cpu_get(i);
254-
if (!policy) {
255-
if (sched_debug()) {
256-
pr_info("rd %*pbl: Checking EAS, cpufreq policy not set for CPU: %d",
257-
cpumask_pr_args(cpu_mask), i);
258-
}
259-
return false;
260-
}
261-
policy_is_ready = sugov_is_governor(policy);
262-
cpufreq_cpu_put(policy);
263-
if (!policy_is_ready) {
264-
if (sched_debug()) {
265-
pr_info("rd %*pbl: Checking EAS, schedutil is mandatory\n",
266-
cpumask_pr_args(cpu_mask));
267-
}
268-
return false;
249+
if (!cpufreq_ready_for_eas(cpu_mask)) {
250+
if (sched_debug()) {
251+
pr_info("rd %*pbl: Checking EAS: cpufreq is not ready\n",
252+
cpumask_pr_args(cpu_mask));
269253
}
254+
return false;
270255
}
271256

272257
return true;

0 commit comments

Comments
 (0)