Skip to content

Commit

Permalink
Merge tag 'pm-5.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/rafael/linux-pm

Pull more power management updates from Rafael Wysocki:
 "These fix a recent regression causing kernels built with CONFIG_PM
  unset to crash on systems that support the Performance and Energy Bias
  Hint (EPB), clean up the cpufreq core and some users of transition
  notifiers and introduce a new power domain flag into the generic power
  domains framework (genpd).

  Specifics:

   - Fix recent regression causing kernels built with CONFIG_PM unset to
     crash on systems that support the Performance and Energy Bias Hint
     (EPB) by avoiding to compile the EPB-related code depending on
     CONFIG_PM when it is unset (Rafael Wysocki).

   - Clean up the transition notifier invocation code in the cpufreq
     core and change some users of cpufreq transition notifiers
     accordingly (Viresh Kumar).

   - Change MAINTAINERS to cover the schedutil governor as part of
     cpufreq (Viresh Kumar).

   - Simplify cpufreq_init_policy() to avoid redundant computations (Yue
     Hu).

   - Add explanatory comment to the cpufreq core (Rafael Wysocki).

   - Introduce a new flag, GENPD_FLAG_RPM_ALWAYS_ON, to the generic
     power domains (genpd) framework along with the first user of it
     (Leonard Crestez)"

* tag 'pm-5.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  soc: imx: gpc: Use GENPD_FLAG_RPM_ALWAYS_ON for ERR009619
  PM / Domains: Add GENPD_FLAG_RPM_ALWAYS_ON flag
  cpufreq: Update MAINTAINERS to include schedutil governor
  cpufreq: Don't find governor for setpolicy drivers in cpufreq_init_policy()
  cpufreq: Explain the kobject_put() in cpufreq_policy_alloc()
  cpufreq: Call transition notifier only once for each policy
  x86: intel_epb: Take CONFIG_PM into account
  • Loading branch information
torvalds committed May 15, 2019
2 parents 88f76bc + 2a8d69f commit bfbfbf7
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 105 deletions.
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4133,7 +4133,9 @@ F: Documentation/admin-guide/pm/intel_pstate.rst
F: Documentation/cpu-freq/
F: Documentation/devicetree/bindings/cpufreq/
F: drivers/cpufreq/
F: kernel/sched/cpufreq*.c
F: include/linux/cpufreq.h
F: include/linux/sched/cpufreq.h
F: tools/testing/selftests/cpufreq/

CPU FREQUENCY DRIVERS - ARM BIG LITTLE
Expand Down
24 changes: 15 additions & 9 deletions arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,15 +758,20 @@ static int cpufreq_callback(struct notifier_block *nb,
unsigned long val, void *data)
{
struct cpufreq_freqs *freq = data;
int cpu = freq->cpu;
struct cpumask *cpus = freq->policy->cpus;
int cpu, first = cpumask_first(cpus);
unsigned int lpj;

if (freq->flags & CPUFREQ_CONST_LOOPS)
return NOTIFY_OK;

if (!per_cpu(l_p_j_ref, cpu)) {
per_cpu(l_p_j_ref, cpu) =
per_cpu(cpu_data, cpu).loops_per_jiffy;
per_cpu(l_p_j_ref_freq, cpu) = freq->old;
if (!per_cpu(l_p_j_ref, first)) {
for_each_cpu(cpu, cpus) {
per_cpu(l_p_j_ref, cpu) =
per_cpu(cpu_data, cpu).loops_per_jiffy;
per_cpu(l_p_j_ref_freq, cpu) = freq->old;
}

if (!global_l_p_j_ref) {
global_l_p_j_ref = loops_per_jiffy;
global_l_p_j_ref_freq = freq->old;
Expand All @@ -778,10 +783,11 @@ static int cpufreq_callback(struct notifier_block *nb,
loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
global_l_p_j_ref_freq,
freq->new);
per_cpu(cpu_data, cpu).loops_per_jiffy =
cpufreq_scale(per_cpu(l_p_j_ref, cpu),
per_cpu(l_p_j_ref_freq, cpu),
freq->new);

lpj = cpufreq_scale(per_cpu(l_p_j_ref, first),
per_cpu(l_p_j_ref_freq, first), freq->new);
for_each_cpu(cpu, cpus)
per_cpu(cpu_data, cpu).loops_per_jiffy = lpj;
}
return NOTIFY_OK;
}
Expand Down
28 changes: 16 additions & 12 deletions arch/sparc/kernel/time_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -653,19 +653,23 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
void *data)
{
struct cpufreq_freqs *freq = data;
unsigned int cpu = freq->cpu;
struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu);
unsigned int cpu;
struct freq_table *ft;

if (!ft->ref_freq) {
ft->ref_freq = freq->old;
ft->clock_tick_ref = cpu_data(cpu).clock_tick;
}
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
cpu_data(cpu).clock_tick =
cpufreq_scale(ft->clock_tick_ref,
ft->ref_freq,
freq->new);
for_each_cpu(cpu, freq->policy->cpus) {
ft = &per_cpu(sparc64_freq_table, cpu);

if (!ft->ref_freq) {
ft->ref_freq = freq->old;
ft->clock_tick_ref = cpu_data(cpu).clock_tick;
}

if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
cpu_data(cpu).clock_tick =
cpufreq_scale(ft->clock_tick_ref, ft->ref_freq,
freq->new);
}
}

return 0;
Expand Down
22 changes: 21 additions & 1 deletion arch/x86/kernel/cpu/intel_epb.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ static void intel_epb_restore(void)
wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, (epb & ~EPB_MASK) | val);
}

#ifdef CONFIG_PM
static struct syscore_ops intel_epb_syscore_ops = {
.suspend = intel_epb_save,
.resume = intel_epb_restore,
Expand Down Expand Up @@ -193,6 +194,25 @@ static int intel_epb_offline(unsigned int cpu)
return 0;
}

static inline void register_intel_ebp_syscore_ops(void)
{
register_syscore_ops(&intel_epb_syscore_ops);
}
#else /* !CONFIG_PM */
static int intel_epb_online(unsigned int cpu)
{
intel_epb_restore();
return 0;
}

static int intel_epb_offline(unsigned int cpu)
{
return intel_epb_save();
}

static inline void register_intel_ebp_syscore_ops(void) {}
#endif

static __init int intel_epb_init(void)
{
int ret;
Expand All @@ -206,7 +226,7 @@ static __init int intel_epb_init(void)
if (ret < 0)
goto err_out_online;

register_syscore_ops(&intel_epb_syscore_ops);
register_intel_ebp_syscore_ops();
return 0;

err_out_online:
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if (!(freq->flags & CPUFREQ_CONST_LOOPS))
mark_tsc_unstable("cpufreq changes");

set_cyc2ns_scale(tsc_khz, freq->cpu, rdtsc());
set_cyc2ns_scale(tsc_khz, freq->policy->cpu, rdtsc());
}

return 0;
Expand Down
31 changes: 20 additions & 11 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -6698,10 +6698,8 @@ static void kvm_hyperv_tsc_notifier(void)
}
#endif

static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
static void __kvmclock_cpufreq_notifier(struct cpufreq_freqs *freq, int cpu)
{
struct cpufreq_freqs *freq = data;
struct kvm *kvm;
struct kvm_vcpu *vcpu;
int i, send_ipi = 0;
Expand Down Expand Up @@ -6745,17 +6743,12 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
*
*/

if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
return 0;
if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
return 0;

smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
smp_call_function_single(cpu, tsc_khz_changed, freq, 1);

spin_lock(&kvm_lock);
list_for_each_entry(kvm, &vm_list, vm_list) {
kvm_for_each_vcpu(i, vcpu, kvm) {
if (vcpu->cpu != freq->cpu)
if (vcpu->cpu != cpu)
continue;
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
if (vcpu->cpu != smp_processor_id())
Expand All @@ -6777,8 +6770,24 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
* guest context is entered kvmclock will be updated,
* so the guest will not see stale values.
*/
smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
smp_call_function_single(cpu, tsc_khz_changed, freq, 1);
}
}

static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
int cpu;

if (val == CPUFREQ_PRECHANGE && freq->old > freq->new)
return 0;
if (val == CPUFREQ_POSTCHANGE && freq->old < freq->new)
return 0;

for_each_cpu(cpu, freq->policy->cpus)
__kvmclock_cpufreq_notifier(freq, cpu);

return 0;
}

Expand Down
8 changes: 6 additions & 2 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
#define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON)
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)

static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
const struct generic_pm_domain *genpd)
Expand Down Expand Up @@ -515,7 +516,9 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
* (1) The domain is configured as always on.
* (2) When the domain has a subdomain being powered on.
*/
if (genpd_is_always_on(genpd) || atomic_read(&genpd->sd_count) > 0)
if (genpd_is_always_on(genpd) ||
genpd_is_rpm_always_on(genpd) ||
atomic_read(&genpd->sd_count) > 0)
return -EBUSY;

list_for_each_entry(pdd, &genpd->dev_list, list_node) {
Expand Down Expand Up @@ -1812,7 +1815,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
}

/* Always-on domains must be powered on at initialization. */
if (genpd_is_always_on(genpd) && !genpd_status_on(genpd))
if ((genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd)) &&
!genpd_status_on(genpd))
return -EINVAL;

if (genpd_is_cpu_domain(genpd) &&
Expand Down
Loading

0 comments on commit bfbfbf7

Please sign in to comment.