]> git.ipfire.org Git - people/arne_f/kernel.git/commitdiff
cpufreq: Fix new policy initialization during limits updates via sysfs
authorTao Wang <kevin.wangtao@hisilicon.com>
Sat, 26 May 2018 07:16:48 +0000 (15:16 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 26 Jun 2018 00:06:32 +0000 (08:06 +0800)
commit c7d1f119c48f64bebf0fa1e326af577c6152fe30 upstream.

If the policy limits are updated via cpufreq_update_policy() and
subsequently via sysfs, the limits stored in user_policy may be
set incorrectly.

For example, if both min and max are set via sysfs to the maximum
available frequency, user_policy.min and user_policy.max will also
be the maximum.  If a policy notifier triggered by
cpufreq_update_policy() lowers both the min and the max at this
point, that change is not reflected by the user_policy limits, so
if the max is updated again via sysfs to the same lower value,
then user_policy.max will be lower than user_policy.min which
shouldn't happen.  In particular, if one of the policy CPUs is
then taken offline and back online, cpufreq_set_policy() will
fail for it due to a failing limits check.

To prevent that from happening, initialize the min and max fields
of the new_policy object to the ones stored in user_policy that
were previously set via sysfs.

Signed-off-by: Kevin Wangtao <kevin.wangtao@hisilicon.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
[ rjw: Subject & changelog ]
Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/cpufreq/cpufreq.c

index 789fc3a8289f0f03baf7474977e980bee43543a1..93754300cb579409a4c2209e98ab2cae8811b1ce 100644 (file)
@@ -693,6 +693,8 @@ static ssize_t store_##file_name                                    \
        struct cpufreq_policy new_policy;                               \
                                                                        \
        memcpy(&new_policy, policy, sizeof(*policy));                   \
+       new_policy.min = policy->user_policy.min;                       \
+       new_policy.max = policy->user_policy.max;                       \
                                                                        \
        ret = sscanf(buf, "%u", &new_policy.object);                    \
        if (ret != 1)                                                   \