Skip to content

Commit fcfb679

Browse files
committed
Merge tag 'pm-5.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "Make the intel_pstate driver behave as expected when it operates in the passive mode with HWP enabled and the 'powersave' governor on top of it" * tag 'pm-5.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: cpufreq: intel_pstate: Take CPUFREQ_GOV_STRICT_TARGET into account cpufreq: Add strict_target to struct cpufreq_policy cpufreq: Introduce CPUFREQ_GOV_STRICT_TARGET cpufreq: Introduce governor flags
2 parents 3d5e28b + fcb3a1a commit fcfb679

7 files changed

Lines changed: 32 additions & 12 deletions

File tree

drivers/cpufreq/cpufreq.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2254,7 +2254,7 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy)
22542254
return -EINVAL;
22552255

22562256
/* Platform doesn't want dynamic frequency switching ? */
2257-
if (policy->governor->dynamic_switching &&
2257+
if (policy->governor->flags & CPUFREQ_GOV_DYNAMIC_SWITCHING &&
22582258
cpufreq_driver->flags & CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING) {
22592259
struct cpufreq_governor *gov = cpufreq_fallback_governor();
22602260

@@ -2280,6 +2280,8 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy)
22802280
}
22812281
}
22822282

2283+
policy->strict_target = !!(policy->governor->flags & CPUFREQ_GOV_STRICT_TARGET);
2284+
22832285
return 0;
22842286
}
22852287

drivers/cpufreq/cpufreq_governor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy);
156156
#define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \
157157
{ \
158158
.name = _name_, \
159-
.dynamic_switching = true, \
159+
.flags = CPUFREQ_GOV_DYNAMIC_SWITCHING, \
160160
.owner = THIS_MODULE, \
161161
.init = cpufreq_dbs_governor_init, \
162162
.exit = cpufreq_dbs_governor_exit, \

drivers/cpufreq/cpufreq_performance.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy)
2020
static struct cpufreq_governor cpufreq_gov_performance = {
2121
.name = "performance",
2222
.owner = THIS_MODULE,
23+
.flags = CPUFREQ_GOV_STRICT_TARGET,
2324
.limits = cpufreq_gov_performance_limits,
2425
};
2526

drivers/cpufreq/cpufreq_powersave.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static struct cpufreq_governor cpufreq_gov_powersave = {
2121
.name = "powersave",
2222
.limits = cpufreq_gov_powersave_limits,
2323
.owner = THIS_MODULE,
24+
.flags = CPUFREQ_GOV_STRICT_TARGET,
2425
};
2526

2627
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");

drivers/cpufreq/intel_pstate.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,7 +2527,7 @@ static void intel_cpufreq_trace(struct cpudata *cpu, unsigned int trace_type, in
25272527
}
25282528

25292529
static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate,
2530-
bool fast_switch)
2530+
bool strict, bool fast_switch)
25312531
{
25322532
u64 prev = READ_ONCE(cpu->hwp_req_cached), value = prev;
25332533

@@ -2539,7 +2539,7 @@ static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate,
25392539
* field in it, so opportunistically update the max too if needed.
25402540
*/
25412541
value &= ~HWP_MAX_PERF(~0L);
2542-
value |= HWP_MAX_PERF(cpu->max_perf_ratio);
2542+
value |= HWP_MAX_PERF(strict ? target_pstate : cpu->max_perf_ratio);
25432543

25442544
if (value == prev)
25452545
return;
@@ -2562,14 +2562,16 @@ static void intel_cpufreq_adjust_perf_ctl(struct cpudata *cpu,
25622562
pstate_funcs.get_val(cpu, target_pstate));
25632563
}
25642564

2565-
static int intel_cpufreq_update_pstate(struct cpudata *cpu, int target_pstate,
2566-
bool fast_switch)
2565+
static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy,
2566+
int target_pstate, bool fast_switch)
25672567
{
2568+
struct cpudata *cpu = all_cpu_data[policy->cpu];
25682569
int old_pstate = cpu->pstate.current_pstate;
25692570

25702571
target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
25712572
if (hwp_active) {
2572-
intel_cpufreq_adjust_hwp(cpu, target_pstate, fast_switch);
2573+
intel_cpufreq_adjust_hwp(cpu, target_pstate,
2574+
policy->strict_target, fast_switch);
25732575
cpu->pstate.current_pstate = target_pstate;
25742576
} else if (target_pstate != old_pstate) {
25752577
intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch);
@@ -2609,7 +2611,7 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy,
26092611
break;
26102612
}
26112613

2612-
target_pstate = intel_cpufreq_update_pstate(cpu, target_pstate, false);
2614+
target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, false);
26132615

26142616
freqs.new = target_pstate * cpu->pstate.scaling;
26152617

@@ -2628,7 +2630,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
26282630

26292631
target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling);
26302632

2631-
target_pstate = intel_cpufreq_update_pstate(cpu, target_pstate, true);
2633+
target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true);
26322634

26332635
return target_pstate * cpu->pstate.scaling;
26342636
}

include/linux/cpufreq.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ struct cpufreq_policy {
109109
bool fast_switch_possible;
110110
bool fast_switch_enabled;
111111

112+
/*
113+
* Set if the CPUFREQ_GOV_STRICT_TARGET flag is set for the current
114+
* governor.
115+
*/
116+
bool strict_target;
117+
112118
/*
113119
* Preferred average time interval between consecutive invocations of
114120
* the driver to set the frequency for this policy. To be set by the
@@ -570,12 +576,20 @@ struct cpufreq_governor {
570576
char *buf);
571577
int (*store_setspeed) (struct cpufreq_policy *policy,
572578
unsigned int freq);
573-
/* For governors which change frequency dynamically by themselves */
574-
bool dynamic_switching;
575579
struct list_head governor_list;
576580
struct module *owner;
581+
u8 flags;
577582
};
578583

584+
/* Governor flags */
585+
586+
/* For governors which change frequency dynamically by themselves */
587+
#define CPUFREQ_GOV_DYNAMIC_SWITCHING BIT(0)
588+
589+
/* For governors wanting the target frequency to be set exactly */
590+
#define CPUFREQ_GOV_STRICT_TARGET BIT(1)
591+
592+
579593
/* Pass a target to the cpufreq driver */
580594
unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
581595
unsigned int target_freq);

kernel/sched/cpufreq_schedutil.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ static void sugov_limits(struct cpufreq_policy *policy)
881881
struct cpufreq_governor schedutil_gov = {
882882
.name = "schedutil",
883883
.owner = THIS_MODULE,
884-
.dynamic_switching = true,
884+
.flags = CPUFREQ_GOV_DYNAMIC_SWITCHING,
885885
.init = sugov_init,
886886
.exit = sugov_exit,
887887
.start = sugov_start,

0 commit comments

Comments
 (0)