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 | return -EINVAL; | 2254 | return -EINVAL; |
| 2255 | 2255 | ||
| 2256 | /* Platform doesn't want dynamic frequency switching ? */ | 2256 | /* Platform doesn't want dynamic frequency switching ? */ |
| 2257 | if (policy->governor->dynamic_switching && | 2257 | if (policy->governor->flags & CPUFREQ_GOV_DYNAMIC_SWITCHING && |
| 2258 | cpufreq_driver->flags & CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING) { | 2258 | cpufreq_driver->flags & CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING) { |
| 2259 | struct cpufreq_governor *gov = cpufreq_fallback_governor(); | 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 | return 0; | 2285 | return 0; |
| 2284 | } | 2286 | } |
| 2285 | 2287 | ||
| @@ -156,7 +156,7 @@ void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy); · 155 unmodified lines | |||
| 156 | #define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \ | 156 | #define CPUFREQ_DBS_GOVERNOR_INITIALIZER(_name_) \ |
| 157 | { \ | 157 | { \ |
| 158 | .name = _name_, \ | 158 | .name = _name_, \ |
| 159 | .dynamic_switching = true, \ | 159 | .flags = CPUFREQ_GOV_DYNAMIC_SWITCHING, \ |
| 160 | .owner = THIS_MODULE, \ | 160 | .owner = THIS_MODULE, \ |
| 161 | .init = cpufreq_dbs_governor_init, \ | 161 | .init = cpufreq_dbs_governor_init, \ |
| 162 | .exit = cpufreq_dbs_governor_exit, \ | 162 | .exit = cpufreq_dbs_governor_exit, \ |
| @@ -20,6 +20,7 @@ static void cpufreq_gov_performance_limits(struct cpufreq_policy *policy) · 19 unmodified lines | |||
| 20 | static struct cpufreq_governor cpufreq_gov_performance = { | 20 | static struct cpufreq_governor cpufreq_gov_performance = { |
| 21 | .name = "performance", | 21 | .name = "performance", |
| 22 | .owner = THIS_MODULE, | 22 | .owner = THIS_MODULE, |
| 23 | .flags = CPUFREQ_GOV_STRICT_TARGET, | ||
| 23 | .limits = cpufreq_gov_performance_limits, | 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 | .name = "powersave", | 21 | .name = "powersave", |
| 22 | .limits = cpufreq_gov_powersave_limits, | 22 | .limits = cpufreq_gov_powersave_limits, |
| 23 | .owner = THIS_MODULE, | 23 | .owner = THIS_MODULE, |
| 24 | .flags = CPUFREQ_GOV_STRICT_TARGET, | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); | 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 | static void intel_cpufreq_adjust_hwp(struct cpudata *cpu, u32 target_pstate, | 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 | u64 prev = READ_ONCE(cpu->hwp_req_cached), value = prev; | 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 | * field in it, so opportunistically update the max too if needed. | 2539 | * field in it, so opportunistically update the max too if needed. |
| 2540 | */ | 2540 | */ |
| 2541 | value &= ~HWP_MAX_PERF(~0L); | 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 | if (value == prev) | 2544 | if (value == prev) |
| 2545 | return; | 2545 | return; |
| @@ -2562,14 +2562,16 @@ static void intel_cpufreq_adjust_perf_ctl(struct cpudata *cpu, · 16 unmodified lines | |||
| 2562 | pstate_funcs.get_val(cpu, target_pstate)); | 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, | 2565 | static int intel_cpufreq_update_pstate(struct cpufreq_policy *policy, |
| 2566 | bool fast_switch) | 2566 | int target_pstate, bool fast_switch) |
| 2567 | { | 2567 | { |
| 2568 | struct cpudata *cpu = all_cpu_data[policy->cpu]; | ||
| 2568 | int old_pstate = cpu->pstate.current_pstate; | 2569 | int old_pstate = cpu->pstate.current_pstate; |
| 2569 | 2570 | ||
| 2570 | target_pstate = intel_pstate_prepare_request(cpu, target_pstate); | 2571 | target_pstate = intel_pstate_prepare_request(cpu, target_pstate); |
| 2571 | if (hwp_active) { | 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 | cpu->pstate.current_pstate = target_pstate; | 2575 | cpu->pstate.current_pstate = target_pstate; |
| 2574 | } else if (target_pstate != old_pstate) { | 2576 | } else if (target_pstate != old_pstate) { |
| 2575 | intel_cpufreq_adjust_perf_ctl(cpu, target_pstate, fast_switch); | 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 | break; | 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 | freqs.new = target_pstate * cpu->pstate.scaling; | 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 | target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling); | 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 | return target_pstate * cpu->pstate.scaling; | 2635 | return target_pstate * cpu->pstate.scaling; |
| 2634 | } | 2636 | } |
| @@ -109,6 +109,12 @@ struct cpufreq_policy { · 108 unmodified lines | |||
| 109 | bool fast_switch_possible; | 109 | bool fast_switch_possible; |
| 110 | bool fast_switch_enabled; | 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 | * Preferred average time interval between consecutive invocations of | 119 | * Preferred average time interval between consecutive invocations of |
| 114 | * the driver to set the frequency for this policy. To be set by the | 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 | char *buf); | 576 | char *buf); |
| 571 | int (*store_setspeed) (struct cpufreq_policy *policy, | 577 | int (*store_setspeed) (struct cpufreq_policy *policy, |
| 572 | unsigned int freq); | 578 | unsigned int freq); |
| 573 | /* For governors which change frequency dynamically by themselves */ | ||
| 574 | bool dynamic_switching; | ||
| 575 | struct list_head governor_list; | 579 | struct list_head governor_list; |
| 576 | struct module *owner; | 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 | /* Pass a target to the cpufreq driver */ | 593 | /* Pass a target to the cpufreq driver */ |
| 580 | unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, | 594 | unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy, |
| 581 | unsigned int target_freq); | 595 | unsigned int target_freq); |
| @@ -881,7 +881,7 @@ static void sugov_limits(struct cpufreq_policy *policy) · 880 unmodified lines | |||
| 881 | struct cpufreq_governor schedutil_gov = { | 881 | struct cpufreq_governor schedutil_gov = { |
| 882 | .name = "schedutil", | 882 | .name = "schedutil", |
| 883 | .owner = THIS_MODULE, | 883 | .owner = THIS_MODULE, |
| 884 | .dynamic_switching = true, | 884 | .flags = CPUFREQ_GOV_DYNAMIC_SWITCHING, |
| 885 | .init = sugov_init, | 885 | .init = sugov_init, |
| 886 | .exit = sugov_exit, | 886 | .exit = sugov_exit, |
| 887 | .start = sugov_start, | 887 | .start = sugov_start, |