Skip to content

Commit 6b872a5

Browse files
committed
Merge tag 'pm-6.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "These make the intel_pstate driver work as expected on all hybrid platforms to date (regardless of possible platform firmware issues), fix hybrid sleep on systems using suspend-to-idle by default, make the generic power domains code handle disabled idle states properly and update pm-graph. Specifics: - Make intel_pstate use what is known about the hardware instead of relying on information from the platform firmware (ACPI CPPC in particular) to establish the relationship between the HWP CPU performance levels and frequencies on all hybrid platforms available to date (Rafael Wysocki) - Allow hybrid sleep to use suspend-to-idle as a system suspend method if it is the current suspend method of choice (Mario Limonciello) - Fix handling of unavailable/disabled idle states in the generic power domains code (Sudeep Holla) - Update the pm-graph suite of utilities to version 5.10 which is fixes-mostly and does not add any new features (Todd Brandt)" * tag 'pm-6.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PM: domains: Fix handling of unavailable/disabled idle states pm-graph v5.10 cpufreq: intel_pstate: hybrid: Use known scaling factor for P-cores cpufreq: intel_pstate: Read all MSRs on the target CPU PM: hibernate: Allow hybrid sleep to work with s2idle
2 parents fd7e2a2 + 6f25793 commit 6b872a5

File tree

6 files changed

+170
-209
lines changed

6 files changed

+170
-209
lines changed

drivers/base/power/domain.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2952,6 +2952,10 @@ static int genpd_iterate_idle_states(struct device_node *dn,
29522952
np = it.node;
29532953
if (!of_match_node(idle_state_match, np))
29542954
continue;
2955+
2956+
if (!of_device_is_available(np))
2957+
continue;
2958+
29552959
if (states) {
29562960
ret = genpd_parse_state(&states[i], np);
29572961
if (ret) {

drivers/cpufreq/intel_pstate.c

Lines changed: 47 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/pm_qos.h>
2828
#include <trace/events/power.h>
2929

30+
#include <asm/cpu.h>
3031
#include <asm/div64.h>
3132
#include <asm/msr.h>
3233
#include <asm/cpu_device_id.h>
@@ -280,10 +281,10 @@ static struct cpudata **all_cpu_data;
280281
* structure is used to store those callbacks.
281282
*/
282283
struct pstate_funcs {
283-
int (*get_max)(void);
284-
int (*get_max_physical)(void);
285-
int (*get_min)(void);
286-
int (*get_turbo)(void);
284+
int (*get_max)(int cpu);
285+
int (*get_max_physical)(int cpu);
286+
int (*get_min)(int cpu);
287+
int (*get_turbo)(int cpu);
287288
int (*get_scaling)(void);
288289
int (*get_cpu_scaling)(int cpu);
289290
int (*get_aperf_mperf_shift)(void);
@@ -398,16 +399,6 @@ static int intel_pstate_get_cppc_guaranteed(int cpu)
398399

399400
return cppc_perf.nominal_perf;
400401
}
401-
402-
static u32 intel_pstate_cppc_nominal(int cpu)
403-
{
404-
u64 nominal_perf;
405-
406-
if (cppc_get_nominal_perf(cpu, &nominal_perf))
407-
return 0;
408-
409-
return nominal_perf;
410-
}
411402
#else /* CONFIG_ACPI_CPPC_LIB */
412403
static inline void intel_pstate_set_itmt_prio(int cpu)
413404
{
@@ -531,35 +522,18 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
531522
{
532523
int perf_ctl_max_phys = cpu->pstate.max_pstate_physical;
533524
int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
534-
int perf_ctl_turbo = pstate_funcs.get_turbo();
535-
int turbo_freq = perf_ctl_turbo * perf_ctl_scaling;
525+
int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu);
536526
int scaling = cpu->pstate.scaling;
537527

538528
pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys);
539-
pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max());
540529
pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo);
541530
pr_debug("CPU%d: perf_ctl_scaling = %d\n", cpu->cpu, perf_ctl_scaling);
542531
pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate);
543532
pr_debug("CPU%d: HWP_CAP highest = %d\n", cpu->cpu, cpu->pstate.turbo_pstate);
544533
pr_debug("CPU%d: HWP-to-frequency scaling factor: %d\n", cpu->cpu, scaling);
545534

546-
/*
547-
* If the product of the HWP performance scaling factor and the HWP_CAP
548-
* highest performance is greater than the maximum turbo frequency
549-
* corresponding to the pstate_funcs.get_turbo() return value, the
550-
* scaling factor is too high, so recompute it to make the HWP_CAP
551-
* highest performance correspond to the maximum turbo frequency.
552-
*/
553-
cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * scaling;
554-
if (turbo_freq < cpu->pstate.turbo_freq) {
555-
cpu->pstate.turbo_freq = turbo_freq;
556-
scaling = DIV_ROUND_UP(turbo_freq, cpu->pstate.turbo_pstate);
557-
cpu->pstate.scaling = scaling;
558-
559-
pr_debug("CPU%d: refined HWP-to-frequency scaling factor: %d\n",
560-
cpu->cpu, scaling);
561-
}
562-
535+
cpu->pstate.turbo_freq = rounddown(cpu->pstate.turbo_pstate * scaling,
536+
perf_ctl_scaling);
563537
cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling,
564538
perf_ctl_scaling);
565539

@@ -1740,23 +1714,23 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata)
17401714
intel_pstate_update_epp_defaults(cpudata);
17411715
}
17421716

1743-
static int atom_get_min_pstate(void)
1717+
static int atom_get_min_pstate(int not_used)
17441718
{
17451719
u64 value;
17461720

17471721
rdmsrl(MSR_ATOM_CORE_RATIOS, value);
17481722
return (value >> 8) & 0x7F;
17491723
}
17501724

1751-
static int atom_get_max_pstate(void)
1725+
static int atom_get_max_pstate(int not_used)
17521726
{
17531727
u64 value;
17541728

17551729
rdmsrl(MSR_ATOM_CORE_RATIOS, value);
17561730
return (value >> 16) & 0x7F;
17571731
}
17581732

1759-
static int atom_get_turbo_pstate(void)
1733+
static int atom_get_turbo_pstate(int not_used)
17601734
{
17611735
u64 value;
17621736

@@ -1834,23 +1808,23 @@ static void atom_get_vid(struct cpudata *cpudata)
18341808
cpudata->vid.turbo = value & 0x7f;
18351809
}
18361810

1837-
static int core_get_min_pstate(void)
1811+
static int core_get_min_pstate(int cpu)
18381812
{
18391813
u64 value;
18401814

1841-
rdmsrl(MSR_PLATFORM_INFO, value);
1815+
rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value);
18421816
return (value >> 40) & 0xFF;
18431817
}
18441818

1845-
static int core_get_max_pstate_physical(void)
1819+
static int core_get_max_pstate_physical(int cpu)
18461820
{
18471821
u64 value;
18481822

1849-
rdmsrl(MSR_PLATFORM_INFO, value);
1823+
rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value);
18501824
return (value >> 8) & 0xFF;
18511825
}
18521826

1853-
static int core_get_tdp_ratio(u64 plat_info)
1827+
static int core_get_tdp_ratio(int cpu, u64 plat_info)
18541828
{
18551829
/* Check how many TDP levels present */
18561830
if (plat_info & 0x600000000) {
@@ -1860,13 +1834,13 @@ static int core_get_tdp_ratio(u64 plat_info)
18601834
int err;
18611835

18621836
/* Get the TDP level (0, 1, 2) to get ratios */
1863-
err = rdmsrl_safe(MSR_CONFIG_TDP_CONTROL, &tdp_ctrl);
1837+
err = rdmsrl_safe_on_cpu(cpu, MSR_CONFIG_TDP_CONTROL, &tdp_ctrl);
18641838
if (err)
18651839
return err;
18661840

18671841
/* TDP MSR are continuous starting at 0x648 */
18681842
tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x03);
1869-
err = rdmsrl_safe(tdp_msr, &tdp_ratio);
1843+
err = rdmsrl_safe_on_cpu(cpu, tdp_msr, &tdp_ratio);
18701844
if (err)
18711845
return err;
18721846

@@ -1883,18 +1857,18 @@ static int core_get_tdp_ratio(u64 plat_info)
18831857
return -ENXIO;
18841858
}
18851859

1886-
static int core_get_max_pstate(void)
1860+
static int core_get_max_pstate(int cpu)
18871861
{
18881862
u64 tar;
18891863
u64 plat_info;
18901864
int max_pstate;
18911865
int tdp_ratio;
18921866
int err;
18931867

1894-
rdmsrl(MSR_PLATFORM_INFO, plat_info);
1868+
rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &plat_info);
18951869
max_pstate = (plat_info >> 8) & 0xFF;
18961870

1897-
tdp_ratio = core_get_tdp_ratio(plat_info);
1871+
tdp_ratio = core_get_tdp_ratio(cpu, plat_info);
18981872
if (tdp_ratio <= 0)
18991873
return max_pstate;
19001874

@@ -1903,7 +1877,7 @@ static int core_get_max_pstate(void)
19031877
return tdp_ratio;
19041878
}
19051879

1906-
err = rdmsrl_safe(MSR_TURBO_ACTIVATION_RATIO, &tar);
1880+
err = rdmsrl_safe_on_cpu(cpu, MSR_TURBO_ACTIVATION_RATIO, &tar);
19071881
if (!err) {
19081882
int tar_levels;
19091883

@@ -1918,13 +1892,13 @@ static int core_get_max_pstate(void)
19181892
return max_pstate;
19191893
}
19201894

1921-
static int core_get_turbo_pstate(void)
1895+
static int core_get_turbo_pstate(int cpu)
19221896
{
19231897
u64 value;
19241898
int nont, ret;
19251899

1926-
rdmsrl(MSR_TURBO_RATIO_LIMIT, value);
1927-
nont = core_get_max_pstate();
1900+
rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value);
1901+
nont = core_get_max_pstate(cpu);
19281902
ret = (value) & 255;
19291903
if (ret <= nont)
19301904
ret = nont;
@@ -1952,50 +1926,37 @@ static int knl_get_aperf_mperf_shift(void)
19521926
return 10;
19531927
}
19541928

1955-
static int knl_get_turbo_pstate(void)
1929+
static int knl_get_turbo_pstate(int cpu)
19561930
{
19571931
u64 value;
19581932
int nont, ret;
19591933

1960-
rdmsrl(MSR_TURBO_RATIO_LIMIT, value);
1961-
nont = core_get_max_pstate();
1934+
rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value);
1935+
nont = core_get_max_pstate(cpu);
19621936
ret = (((value) >> 8) & 0xFF);
19631937
if (ret <= nont)
19641938
ret = nont;
19651939
return ret;
19661940
}
19671941

1968-
#ifdef CONFIG_ACPI_CPPC_LIB
1969-
static u32 hybrid_ref_perf;
1970-
1971-
static int hybrid_get_cpu_scaling(int cpu)
1942+
static void hybrid_get_type(void *data)
19721943
{
1973-
return DIV_ROUND_UP(core_get_scaling() * hybrid_ref_perf,
1974-
intel_pstate_cppc_nominal(cpu));
1944+
u8 *cpu_type = data;
1945+
1946+
*cpu_type = get_this_hybrid_cpu_type();
19751947
}
19761948

1977-
static void intel_pstate_cppc_set_cpu_scaling(void)
1949+
static int hybrid_get_cpu_scaling(int cpu)
19781950
{
1979-
u32 min_nominal_perf = U32_MAX;
1980-
int cpu;
1951+
u8 cpu_type = 0;
19811952

1982-
for_each_present_cpu(cpu) {
1983-
u32 nominal_perf = intel_pstate_cppc_nominal(cpu);
1953+
smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1);
1954+
/* P-cores have a smaller perf level-to-freqency scaling factor. */
1955+
if (cpu_type == 0x40)
1956+
return 78741;
19841957

1985-
if (nominal_perf && nominal_perf < min_nominal_perf)
1986-
min_nominal_perf = nominal_perf;
1987-
}
1988-
1989-
if (min_nominal_perf < U32_MAX) {
1990-
hybrid_ref_perf = min_nominal_perf;
1991-
pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling;
1992-
}
1958+
return core_get_scaling();
19931959
}
1994-
#else
1995-
static inline void intel_pstate_cppc_set_cpu_scaling(void)
1996-
{
1997-
}
1998-
#endif /* CONFIG_ACPI_CPPC_LIB */
19991960

20001961
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
20011962
{
@@ -2025,10 +1986,10 @@ static void intel_pstate_max_within_limits(struct cpudata *cpu)
20251986

20261987
static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
20271988
{
2028-
int perf_ctl_max_phys = pstate_funcs.get_max_physical();
1989+
int perf_ctl_max_phys = pstate_funcs.get_max_physical(cpu->cpu);
20291990
int perf_ctl_scaling = pstate_funcs.get_scaling();
20301991

2031-
cpu->pstate.min_pstate = pstate_funcs.get_min();
1992+
cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
20321993
cpu->pstate.max_pstate_physical = perf_ctl_max_phys;
20331994
cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;
20341995

@@ -2044,8 +2005,8 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
20442005
}
20452006
} else {
20462007
cpu->pstate.scaling = perf_ctl_scaling;
2047-
cpu->pstate.max_pstate = pstate_funcs.get_max();
2048-
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
2008+
cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu);
2009+
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
20492010
}
20502011

20512012
if (cpu->pstate.scaling == perf_ctl_scaling) {
@@ -3221,9 +3182,9 @@ static unsigned int force_load __initdata;
32213182

32223183
static int __init intel_pstate_msrs_not_valid(void)
32233184
{
3224-
if (!pstate_funcs.get_max() ||
3225-
!pstate_funcs.get_min() ||
3226-
!pstate_funcs.get_turbo())
3185+
if (!pstate_funcs.get_max(0) ||
3186+
!pstate_funcs.get_min(0) ||
3187+
!pstate_funcs.get_turbo(0))
32273188
return -ENODEV;
32283189

32293190
return 0;
@@ -3450,7 +3411,7 @@ static int __init intel_pstate_init(void)
34503411
default_driver = &intel_pstate;
34513412

34523413
if (boot_cpu_has(X86_FEATURE_HYBRID_CPU))
3453-
intel_pstate_cppc_set_cpu_scaling();
3414+
pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling;
34543415

34553416
goto hwp_cpu_matched;
34563417
}

kernel/power/hibernate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ static void power_down(void)
645645
int error;
646646

647647
if (hibernation_mode == HIBERNATION_SUSPEND) {
648-
error = suspend_devices_and_enter(PM_SUSPEND_MEM);
648+
error = suspend_devices_and_enter(mem_sleep_current);
649649
if (error) {
650650
hibernation_mode = hibernation_ops ?
651651
HIBERNATION_PLATFORM :

tools/power/pm-graph/README

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@
66
|_| |___/ |_|
77

88
pm-graph: suspend/resume/boot timing analysis tools
9-
Version: 5.9
9+
Version: 5.10
1010
Author: Todd Brandt <[email protected]>
11-
Home Page: https://01.org/pm-graph
11+
Home Page: https://www.intel.com/content/www/us/en/developer/topic-technology/open/pm-graph/overview.html
1212

1313
Report bugs/issues at bugzilla.kernel.org Tools/pm-graph
1414
- https://bugzilla.kernel.org/buglist.cgi?component=pm-graph&product=Tools
1515

1616
Full documentation available online & in man pages
1717
- Getting Started:
18-
https://01.org/pm-graph/documentation/getting-started
18+
https://www.intel.com/content/www/us/en/developer/articles/technical/usage.html
1919

20-
- Config File Format:
21-
https://01.org/pm-graph/documentation/3-config-file-format
20+
- Feature Summary:
21+
https://www.intel.com/content/www/us/en/developer/topic-technology/open/pm-graph/features.html
2222

2323
- upstream version in git:
24-
https://github.com/intel/pm-graph/
24+
git clone https://github.com/intel/pm-graph/
2525

2626
Table of Contents
2727
- Overview

tools/power/pm-graph/sleepgraph.8

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ This helps maintain the consistency of test data for better comparison.
7878
If a wifi connection is available, check that it reconnects after resume. Include
7979
the reconnect time in the total resume time calculation and treat wifi timeouts
8080
as resume failures.
81+
.TP
82+
\fB-wifitrace\fR
83+
Trace through the wifi reconnect time and include it in the timeline.
8184

8285
.SS "advanced"
8386
.TP

0 commit comments

Comments
 (0)