]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
cpufreq: Avoid redundant target() calls for unchanged limits
authorViresh Kumar <viresh.kumar@linaro.org>
Fri, 22 May 2026 04:19:09 +0000 (09:49 +0530)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 22 May 2026 16:41:24 +0000 (18:41 +0200)
Drivers setting CPUFREQ_NEED_UPDATE_LIMITS expect target() to be
invoked even if the target frequency remains unchanged, so they can
update their internal policy limits state.

Currently the core invokes target() unconditionally whenever the
requested frequency matches policy->cur for such drivers, even if
policy->min and policy->max haven't changed since the previous update.

Track pending policy limit updates explicitly and skip redundant
target() invocations when neither the target frequency nor the
effective limits changed.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Lifeng Zheng <zhenglifeng1@huawei.com>
Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
Link: https://patch.msgid.link/d0107c364b709abca21acf88072220bc05478594.1779423281.git.viresh.kumar@linaro.org
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/cpufreq/cpufreq.c
include/linux/cpufreq.h

index d41067cd1f1b25315b525957e3de3d25dcd01e63..4e78f4caab3af5961b94ce3ae252a319979777f0 100644 (file)
@@ -2368,9 +2368,13 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
         * exactly same freq is called again and so we can save on few function
         * calls.
         */
-       if (target_freq == policy->cur &&
-           !(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS))
-               return 0;
+       if (target_freq == policy->cur) {
+               if (!(cpufreq_driver->flags & CPUFREQ_NEED_UPDATE_LIMITS) ||
+                   !policy->update_limits)
+                       return 0;
+
+               policy->update_limits = false;
+       }
 
        if (cpufreq_driver->target) {
                /*
@@ -2622,6 +2626,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 {
        struct cpufreq_policy_data new_data;
        struct cpufreq_governor *old_gov;
+       unsigned int freq;
        int ret;
 
        memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
@@ -2654,12 +2659,20 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
         * compiler optimizations around them because they may be accessed
         * concurrently by cpufreq_driver_resolve_freq() during the update.
         */
-       WRITE_ONCE(policy->max, __resolve_freq(policy, new_data.max,
-                                              new_data.min, new_data.max,
-                                              CPUFREQ_RELATION_H));
-       new_data.min = __resolve_freq(policy, new_data.min, new_data.min,
-                                     new_data.max, CPUFREQ_RELATION_L);
-       WRITE_ONCE(policy->min, new_data.min > policy->max ? policy->max : new_data.min);
+       freq = __resolve_freq(policy, new_data.max, new_data.min, new_data.max,
+                             CPUFREQ_RELATION_H);
+       if (freq != policy->max) {
+               WRITE_ONCE(policy->max, freq);
+               policy->update_limits = true;
+       }
+
+       freq = __resolve_freq(policy, new_data.min, new_data.min, new_data.max,
+                             CPUFREQ_RELATION_L);
+       freq = min(freq, policy->max);
+       if (freq != policy->min) {
+               WRITE_ONCE(policy->min, freq);
+               policy->update_limits = true;
+       }
 
        trace_cpu_frequency_limits(policy);
 
index 4d4b4ed24b3037c6bd7f46ff3f1e9444d215710c..ae9d1ce4f49c4ef52193937e1a3f62f81876148f 100644 (file)
@@ -146,6 +146,9 @@ struct cpufreq_policy {
        /* Per policy boost supported flag. */
        bool                    boost_supported;
 
+       /* Pending policy->min/max update for the driver */
+       bool                    update_limits;
+
         /* Cached frequency lookup from cpufreq_driver_resolve_freq. */
        unsigned int cached_target_freq;
        unsigned int cached_resolved_idx;