Skip to content

Commit

Permalink
Merge tag 'pm-5.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/rafael/linux-pm

Pull power management fix from Rafael Wysocki:
 "Fix a problem related to CPU offline/online and cpufreq governors that
  in some system configurations may lead to a system-wide deadlock
  during CPU online"

* tag 'pm-5.5-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: Avoid leaving stale IRQ work items during CPU offline
  • Loading branch information
torvalds committed Dec 19, 2019
2 parents 4a94c43 + 505b308 commit 5f096c0
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 16 deletions.
11 changes: 0 additions & 11 deletions include/linux/cpufreq.h
Original file line number Diff line number Diff line change
Expand Up @@ -595,17 +595,6 @@ struct governor_attr {
size_t count);
};

static inline bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
{
/*
* Allow remote callbacks if:
* - dvfs_possible_from_any_cpu flag is set
* - the local and remote CPUs share cpufreq policy
*/
return policy->dvfs_possible_from_any_cpu ||
cpumask_test_cpu(smp_processor_id(), policy->cpus);
}

/*********************************************************************
* FREQUENCY TABLE HELPERS *
*********************************************************************/
Expand Down
3 changes: 3 additions & 0 deletions include/linux/sched/cpufreq.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#define SCHED_CPUFREQ_MIGRATION (1U << 1)

#ifdef CONFIG_CPU_FREQ
struct cpufreq_policy;

struct update_util_data {
void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
};
Expand All @@ -20,6 +22,7 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
void (*func)(struct update_util_data *data, u64 time,
unsigned int flags));
void cpufreq_remove_update_util_hook(int cpu);
bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy);

static inline unsigned long map_util_freq(unsigned long util,
unsigned long freq, unsigned long cap)
Expand Down
18 changes: 18 additions & 0 deletions kernel/sched/cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Copyright (C) 2016, Intel Corporation
* Author: Rafael J. Wysocki <[email protected]>
*/
#include <linux/cpufreq.h>

#include "sched.h"

DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
Expand Down Expand Up @@ -57,3 +59,19 @@ void cpufreq_remove_update_util_hook(int cpu)
rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL);
}
EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook);

/**
* cpufreq_this_cpu_can_update - Check if cpufreq policy can be updated.
* @policy: cpufreq policy to check.
*
* Return 'true' if:
* - the local and remote CPUs share @policy,
* - dvfs_possible_from_any_cpu is set in @policy and the local CPU is not going
* offline (in which case it is not expected to run cpufreq updates any more).
*/
bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
{
return cpumask_test_cpu(smp_processor_id(), policy->cpus) ||
(policy->dvfs_possible_from_any_cpu &&
rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data)));
}
8 changes: 3 additions & 5 deletions kernel/sched/cpufreq_schedutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,10 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
* by the hardware, as calculating the frequency is pointless if
* we cannot in fact act on it.
*
* For the slow switching platforms, the kthread is always scheduled on
* the right set of CPUs and any CPU can find the next frequency and
* schedule the kthread.
* This is needed on the slow switching platforms too to prevent CPUs
* going offline from leaving stale IRQ work items behind.
*/
if (sg_policy->policy->fast_switch_enabled &&
!cpufreq_this_cpu_can_update(sg_policy->policy))
if (!cpufreq_this_cpu_can_update(sg_policy->policy))
return false;

if (unlikely(sg_policy->limits_changed)) {
Expand Down

0 comments on commit 5f096c0

Please sign in to comment.