Skip to content

Commit 505b308

Browse files
committed
Merge branch 'pm-cpufreq'
* pm-cpufreq: cpufreq: Avoid leaving stale IRQ work items during CPU offline
2 parents 4c84515 + 85572c2 commit 505b308

File tree

4 files changed

+24
-16
lines changed

4 files changed

+24
-16
lines changed

include/linux/cpufreq.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -595,17 +595,6 @@ struct governor_attr {
595595
size_t count);
596596
};
597597

598-
static inline bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
599-
{
600-
/*
601-
* Allow remote callbacks if:
602-
* - dvfs_possible_from_any_cpu flag is set
603-
* - the local and remote CPUs share cpufreq policy
604-
*/
605-
return policy->dvfs_possible_from_any_cpu ||
606-
cpumask_test_cpu(smp_processor_id(), policy->cpus);
607-
}
608-
609598
/*********************************************************************
610599
* FREQUENCY TABLE HELPERS *
611600
*********************************************************************/

include/linux/sched/cpufreq.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#define SCHED_CPUFREQ_MIGRATION (1U << 1)
1313

1414
#ifdef CONFIG_CPU_FREQ
15+
struct cpufreq_policy;
16+
1517
struct update_util_data {
1618
void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
1719
};
@@ -20,6 +22,7 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
2022
void (*func)(struct update_util_data *data, u64 time,
2123
unsigned int flags));
2224
void cpufreq_remove_update_util_hook(int cpu);
25+
bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy);
2326

2427
static inline unsigned long map_util_freq(unsigned long util,
2528
unsigned long freq, unsigned long cap)

kernel/sched/cpufreq.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Copyright (C) 2016, Intel Corporation
66
* Author: Rafael J. Wysocki <[email protected]>
77
*/
8+
#include <linux/cpufreq.h>
9+
810
#include "sched.h"
911

1012
DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
@@ -57,3 +59,19 @@ void cpufreq_remove_update_util_hook(int cpu)
5759
rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL);
5860
}
5961
EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook);
62+
63+
/**
64+
* cpufreq_this_cpu_can_update - Check if cpufreq policy can be updated.
65+
* @policy: cpufreq policy to check.
66+
*
67+
* Return 'true' if:
68+
* - the local and remote CPUs share @policy,
69+
* - dvfs_possible_from_any_cpu is set in @policy and the local CPU is not going
70+
* offline (in which case it is not expected to run cpufreq updates any more).
71+
*/
72+
bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
73+
{
74+
return cpumask_test_cpu(smp_processor_id(), policy->cpus) ||
75+
(policy->dvfs_possible_from_any_cpu &&
76+
rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data)));
77+
}

kernel/sched/cpufreq_schedutil.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,10 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
8282
* by the hardware, as calculating the frequency is pointless if
8383
* we cannot in fact act on it.
8484
*
85-
* For the slow switching platforms, the kthread is always scheduled on
86-
* the right set of CPUs and any CPU can find the next frequency and
87-
* schedule the kthread.
85+
* This is needed on the slow switching platforms too to prevent CPUs
86+
* going offline from leaving stale IRQ work items behind.
8887
*/
89-
if (sg_policy->policy->fast_switch_enabled &&
90-
!cpufreq_this_cpu_can_update(sg_policy->policy))
88+
if (!cpufreq_this_cpu_can_update(sg_policy->policy))
9189
return false;
9290

9391
if (unlikely(sg_policy->limits_changed)) {

0 commit comments

Comments
 (0)