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
Unified · Split
| @@ -2254,7 +2254,7 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy) · 2253 unmodified lines | ||
| 2254 | 2254 | return -EINVAL; |
| 2255 | 2255 | |
| 2256 | 2256 | /* Platform doesn't want dynamic frequency switching ? */ |
| 2257 | − if (policy->governor->dynamic_switching && | |
| 2257 | + if (policy->governor->flags & CPUFREQ_GOV_DYNAMIC_SWITCHING && | |
| 2258 | 2258 | cpufreq_driver->flags & CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING) { |
| 2259 | 2259 | struct cpufreq_governor *gov = cpufreq_fallback_governor(); |
| 2260 | 2260 | |
| @@ -2280,6 +2280,8 @@ static int cpufreq_init_governor(struct cpufreq_policy *policy) · 19 unmodified lines | ||
| 2280 | 2280 | } |
| 2281 | 2281 | } |
| 2282 | 2282 | |
| 2283 | + policy->strict_target = !!(policy->governor->flags & CPUFREQ_GOV_STRICT_TARGET); | |
| 2284 | + | |
| 2283 | 2285 | return 0; |
| 2284 | 2286 | } |
| 2285 | 2287 | |
| @@ -156,7 +156,7 @@ void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy); · 155 unmodified lines | ||
| 156 | 156 | #define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \ |
| 157 | 157 | { \ |
| 158 | 158 | .name = _name_, \ |
| 159 | − .dynamic_switching = true, \ | |
| 159 | + .flags = CPUFREQ_GOV_DYNAMIC_SWITCHING, \ | |
| 160 | 160 | .owner = THIS_MODULE, \ |
| 161 | 161 | .init = cpufreq_dbs_governor_init, \ |
| 162 | 162 | .exit = cpufreq_dbs_governor_exit, \ |
| @@ -20,6 +20,7 @@ static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy) · 19 unmodified lines | ||
| 20 | 20 | static struct cpufreq_governor cpufreq_gov_performance = { |
| 21 | 21 | .name = "performance", |
| 22 | 22 | .owner = THIS_MODULE, |
| 23 | + .flags = CPUFREQ_GOV_STRICT_TARGET, | |
| 23 | 24 | .limits = cpufreq_gov_performance_limits, |
| 24 | 25 | }; |
| 25 | 26 | |
| @@ -21,6 +21,7 @@ static struct cpufreq_governor cpufreq_gov_powersave = { · 20 unmodified lines | ||
| 21 | 21 | .name = "powersave", |
| 22 | 22 | .limits = cpufreq_gov_powersave_limits, |
| 23 | 23 | .owner = THIS_MODULE, |
| 24 | + .flags = CPUFREQ_GOV_STRICT_TARGET, | |
| 24 | 25 | }; |
| 25 | 26 | |
| 26 | 27 | MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); |
| @@ -2527,7 +2527,7 @@ static void intel_cpufreq_trace(struct cpudata *cpu, unsigned int trace_type, in · 2526 unmodified lines | ||
| 2527 | 2527 | } |
| 2528 | 2528 | |
| 2529 | 2529 | static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate, |
| 2530 | − bool fast_switch) | |
| 2530 | + bool strict, bool fast_switch) | |
| 2531 | 2531 | { |
| 2532 | 2532 | u64 prev = READ_ONCE(cpu->hwp_req_cached), value = prev; |
| 2533 | 2533 | |
| @@ -2539,7 +2539,7 @@ static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate, · 5 unmodified lines | ||
| 2539 | 2539 | * field in it, so opportunistically update the max too if needed. |
| 2540 | 2540 | */ |
| 2541 | 2541 | 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); | |
| 2543 | 2543 | |
| 2544 | 2544 | if (value == prev) |
| 2545 | 2545 | return; |
| @@ -2562,14 +2562,16 @@ static void intel_cpufreq_adjust_perf_ctl(struct cpudata *cpu, · 16 unmodified lines | ||
| 2562 | 2562 | pstate_funcs.get_val(cpu, target_pstate)); |
| 2563 | 2563 | } |
| 2564 | 2564 | |
| 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) | |
| 2567 | 2567 | { |
| 2568 | + struct cpudata *cpu = all_cpu_data[policy->cpu]; | |
| 2568 | 2569 | int old_pstate = cpu->pstate.current_pstate; |
| 2569 | 2570 | |
| 2570 | 2571 | target_pstate = intel_pstate_prepare_request(cpu, target_pstate); |
| 2571 | 2572 | 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); | |
| 2573 | 2575 | cpu->pstate.current_pstate = target_pstate; |
| 2574 | 2576 | } else if (target_pstate != old_pstate) { |
| 2575 | 2577 | intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch); |
| @@ -2609,7 +2611,7 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy, · 33 unmodified lines | ||
| 2609 | 2611 | break; |
| 2610 | 2612 | } |
| 2611 | 2613 | |
| 2612 | − target_pstate = intel_cpufreq_update_pstate(cpu, target_pstate, false); | |
| 2614 | + target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, false); | |
| 2613 | 2615 | |
| 2614 | 2616 | freqs.new = target_pstate * cpu->pstate.scaling; |
| 2615 | 2617 | |
| @@ -2628,7 +2630,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy, · 12 unmodified lines | ||
| 2628 | 2630 | |
| 2629 | 2631 | target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling); |
| 2630 | 2632 | |
| 2631 | − target_pstate = intel_cpufreq_update_pstate(cpu, target_pstate, true); | |
| 2633 | + target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true); | |
| 2632 | 2634 | |
| 2633 | 2635 | return target_pstate * cpu->pstate.scaling; |
| 2634 | 2636 | } |
| @@ -109,6 +109,12 @@ struct cpufreq_policy { · 108 unmodified lines | ||
| 109 | 109 | bool fast_switch_possible; |
| 110 | 110 | bool fast_switch_enabled; |
| 111 | 111 | |
| 112 | + /* | |
| 113 | + * Set if the CPUFREQ_GOV_STRICT_TARGET flag is set for the current | |
| 114 | + * governor. | |
| 115 | + */ | |
| 116 | + bool strict_target; | |
| 117 | + | |
| 112 | 118 | /* |
| 113 | 119 | * Preferred average time interval between consecutive invocations of |
| 114 | 120 | * the driver to set the frequency for this policy. To be set by the |
| @@ -570,12 +576,20 @@ struct cpufreq_governor { · 455 unmodified lines | ||
| 570 | 576 | char *buf); |
| 571 | 577 | int (*store_setspeed) (struct cpufreq_policy *policy, |
| 572 | 578 | unsigned int freq); |
| 573 | − /* For governors which change frequency dynamically by themselves */ | |
| 574 | − bool dynamic_switching; | |
| 575 | 579 | struct list_head governor_list; |
| 576 | 580 | struct module *owner; |
| 581 | + u8 flags; | |
| 577 | 582 | }; |
| 578 | 583 | |
| 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 | + | |
| 579 | 593 | /* Pass a target to the cpufreq driver */ |
| 580 | 594 | unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, |
| 581 | 595 | unsigned int target_freq); |
| @@ -881,7 +881,7 @@ static void sugov_limits(struct cpufreq_policy *policy) · 880 unmodified lines | ||
| 881 | 881 | struct cpufreq_governor schedutil_gov = { |
| 882 | 882 | .name = "schedutil", |
| 883 | 883 | .owner = THIS_MODULE, |
| 884 | − .dynamic_switching = true, | |
| 884 | + .flags = CPUFREQ_GOV_DYNAMIC_SWITCHING, | |
| 885 | 885 | .init = sugov_init, |
| 886 | 886 | .exit = sugov_exit, |
| 887 | 887 | .start = sugov_start, |