cpufreq: Correct a freq check in cpufreq_set_policy
Subsystems (2)
PATCH 1/1 cpufreq: Correct a freq check in cpufreq_set_policy
From: Pan Xinhui <[email protected]>
This check was originally added by commit 9c9a43ed2734 ("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check if new_policy->min > new_policy->max. Because at least one of max/min is copied from cpufreq_get_policy().
For example, when we echo xxx > .../scaling_min_freq, new_policy is copied from policy in cpufreq_get_policy. new_policy->max is same with policy->max. new_policy->min is set to a new value.
Let me explain it in deduction method, first statment in if ():new_policy->min > policy->maxpolicy->max == new_policy->max
==> new_policy->min > new_policy->max
second statment in if():new_policy->max < policy->minpolicy->max < policy->min
==>new_policy->min > new_policy->max (induction method)
So we have proved that we only need check if new_policy->min > new_policy->max.
After apply this patch, we can also modify ->min and ->max in same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because new_policy->min > policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check.
--- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/cpufreq.c +1 -1
@@ -2276,7 +2276,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,memcpy (&new_policy->cpuinfo, &policy->cpuinfo,sizeof (policy->cpuinfo)); -if (new_policy->min > policy->max || new_policy->max < policy->min) +if (new_policy->min > new_policy->max)return -EINVAL ;/* verify the cpu speed can be set within this limit */
Signature · 1 line
1.9.1
Viresh Kumar
maintainerQuoted 25 lines · Pan Xinhui
From: Pan Xinhui <[email protected]>
This check was originally added by commit
9c9a43ed2734("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check ifnew_policy->min>new_policy->max. Because at least one of max/min is copied fromcpufreq_get_policy().For example, when we echo xxx > .../scaling_min_freq,
new_policyis copied from policy incpufreq_get_policy.new_policy->maxis same withpolicy->max.new_policy->minis set to a new value.Let me explain it in deduction method, first statment in if ():
new_policy->min>policy->maxpolicy->max==new_policy->max
==>new_policy->min>new_policy->maxsecond statment in
if():new_policy->max<policy->minpolicy->max<policy->min
==>new_policy->min >new_policy->max(induction method)So we have proved that we only need check if
new_policy->min>new_policy->max.
Quoted 8 lines
After apply this patch, we can also modify ->min and ->max in same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because
new_policy->min>policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check.Signed-off-by Pan Xinhui <[email protected]>
Does this patch depend on the other patch you sent where you are trying to update both min/max in the same call to cpufreq_set_policy()? If so, they should have been part of the same series in proper order, as you have sent them as separate patches.
Now, if we don't consider your first patch at all, then this patch is obviously wrong. We need to take care of both the checks.
Signature · 1 line
viresh
hi, Viresh
thanks for your quick reply! :)
Quoted 33 lines · Viresh Kumar
Quoted 32 lines · Pan Xinhui
From: Pan Xinhui <[email protected]>
This check was originally added by commit
9c9a43ed2734("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check ifnew_policy->min>new_policy->max. Because at least one of max/min is copied fromcpufreq_get_policy().For example, when we echo xxx > .../scaling_min_freq,
new_policyis copied from policy incpufreq_get_policy.new_policy->maxis same withpolicy->max.new_policy->minis set to a new value.Let me explain it in deduction method, first statment in if ():
new_policy->min>policy->maxpolicy->max==new_policy->max
==>new_policy->min>new_policy->maxsecond statment in
if():new_policy->max<policy->minpolicy->max<policy->min
==>new_policy->min >new_policy->max(induction method)So we have proved that we only need check if
new_policy->min>new_policy->max.After apply this patch, we can also modify ->min and ->max in same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because
new_policy->min>policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check.
Quoted 7 lines
Quoted 1 line
Signed-off-by Pan Xinhui <[email protected]>Does this patch depend on the other patch you sent where you are trying to update both min/max in the same call to
cpufreq_set_policy()? If so, they should have been part of the same series in proper order, as you have sent them as separate patches.
Thanks for pointing out my mistakes. I will send them in a same series with proper order. Sorry for that.
Quoted 3 lines
Now, if we don't consider your first patch at all, then this patch is obviously wrong. We need to take care of both the checks.
Agree, we need take care of every checks. BUT, As We have proved, it's equal to check if (new_policy->min > new_policy->max). I don't why it's wrong. with/without this patch, echo 0 > .../scaling_min_freq has no error. min freq is just set to the limit min freq. I prefer to treat it as a feature. :) So I don't add new_policy->min < policy->cpuinfo.min_freq || new_policy->max > policy->cpuinfo.max_freq.
We have ->verify callback, no need to worry about that an out-of-limit cpufreq will harm kernel. This check is just to tell userspace that *the cpufreq you are trying to set is wrong, pls double check.*
thanks
xinhui
Quoted 42 lines · Pan Xinhui
From: Pan Xinhui <[email protected]>
This check was originally added by commit
9c9a43ed2734("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check ifnew_policy->min>new_policy->max. Because at least one of max/min is copied fromcpufreq_get_policy().For example, when we echo xxx > .../scaling_min_freq,
new_policyis copied from policy incpufreq_get_policy.new_policy->maxis same withpolicy->max.new_policy->minis set to a new value.Let me explain it in deduction method, first statment in if ():
new_policy->min>policy->maxpolicy->max==new_policy->max
==>new_policy->min>new_policy->maxsecond statment in
if():new_policy->max<policy->minpolicy->max<policy->min
==>new_policy->min >new_policy->max(induction method)So we have proved that we only need check if
new_policy->min>new_policy->max.After apply this patch, we can also modify ->min and ->max in same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because
new_policy->min>policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check.Signed-off-by Pan Xinhui <[email protected]>--- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/cpufreq/cpufreq.c +0
-0
drivers/cpufreq/cpufreq.c static int cpufreq_set_policy(struct cpufreq_policy *policy, · line 2280
Quoted 6 lines
drivers/cpufreq/cpufreq.c +1
-1@@ -2276,7 +2276,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,memcpy (&new_policy->cpuinfo, &policy->cpuinfo,sizeof (policy->cpuinfo)); -if (new_policy->min > policy->max || new_policy->max < policy->min) +if (new_policy->min > new_policy->max)return -EINVAL ;
Signature · 1 line
viresh
Quoted 42 lines · Pan Xinhui
From: Pan Xinhui <[email protected]>
This check was originally added by commit
9c9a43ed2734("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check ifnew_policy->min>new_policy->max. Because at least one of max/min is copied fromcpufreq_get_policy().For example, when we echo xxx > .../scaling_min_freq,
new_policyis copied from policy incpufreq_get_policy.new_policy->maxis same withpolicy->max.new_policy->minis set to a new value.Let me explain it in deduction method, first statment in if ():
new_policy->min>policy->maxpolicy->max==new_policy->max
==>new_policy->min>new_policy->maxsecond statment in
if():new_policy->max<policy->minpolicy->max<policy->min
==>new_policy->min >new_policy->max(induction method)So we have proved that we only need check if
new_policy->min>new_policy->max.After apply this patch, we can also modify ->min and ->max in same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because
new_policy->min>policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check.Signed-off-by Pan Xinhui <[email protected]>--- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/cpufreq/cpufreq.c +0
-0
drivers/cpufreq/cpufreq.c static int cpufreq_set_policy(struct cpufreq_policy *policy, · line 2279
Quoted 4 lines
drivers/cpufreq/cpufreq.c +0
-1@@ -2276,7 +2276,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,memcpy (&new_policy->cpuinfo, &policy->cpuinfo,sizeof (policy->cpuinfo)); -if (new_policy->min > policy->max || new_policy->max < policy->min)
Please add a comment here mentioning the fact that this *relies* on new_policy being a copy of policy with one field updated.
Quoted 5 lines
drivers/cpufreq/cpufreq.c +1
-0+if (new_policy->min > new_policy->max)return -EINVAL ;/* verify the cpu speed can be set within this limit */
Signature · 2 lines
I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center.
PATCH v2 1/1 cpufreq: Correct a freq check in cpufreq_set_policy
In reply to Pan XinhuiFrom: Pan Xinhui <[email protected]>
This check was originally added by commit 9c9a43ed2734 ("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check if new_policy->min > new_policy->max. Because at least one of max/min is copied from cpufreq_get_policy().
For example, when we echo xxx > .../scaling_min_freq, new_policy is copied from policy in cpufreq_get_policy. new_policy->max is same with policy->max. new_policy->min is set to a new value.
Let me explain it in deduction method, first statement in if ():new_policy->min > policy->maxpolicy->max == new_policy->max
==> new_policy->min > new_policy->max
second statement in if():new_policy->max < policy->minpolicy->max < policy->min
==>new_policy->min > new_policy->max (induction method)
So we have proved that we only need check if new_policy->min > new_policy->max.
After apply this patch, we can also modify ->min and ->max at same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because new_policy->min > policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check to avoid such case.
---
Change from V1:
just update comments.
--- drivers/cpufreq/cpufreq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/cpufreq/cpufreq.c +5 -1
@@ -2245,7 +2245,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,memcpy (&new_policy->cpuinfo, &policy->cpuinfo,sizeof (policy->cpuinfo)); -if (new_policy->min > policy->max || new_policy->max < policy->min) +/* +* This check works well when we store new min/max freq attributes, +* because new_policy is a copy of policy with one field updated. +*/ +if (new_policy->min > new_policy->max)return -EINVAL ;/* verify the cpu speed can be set within this limit */
Signature · 1 line
1.9.1
Rafael J. Wysocki
AppliedQuoted 33 lines · Pan Xinhui
From: Pan Xinhui <[email protected]>
This check was originally added by commit
9c9a43ed2734("[CPUFREQ] return error when failing to set minfreq").It attempt to return an error on obviously incorrect limits when we echo xxx >.../scaling_max,min_freq Actually we just need check ifnew_policy->min>new_policy->max. Because at least one of max/min is copied fromcpufreq_get_policy().For example, when we echo xxx > .../scaling_min_freq,
new_policyis copied from policy incpufreq_get_policy.new_policy->maxis same withpolicy->max.new_policy->minis set to a new value.Let me explain it in deduction method, first statement in if ():
new_policy->min>policy->maxpolicy->max==new_policy->max
==>new_policy->min>new_policy->maxsecond statement in
if():new_policy->max<policy->minpolicy->max<policy->min
==>new_policy->min >new_policy->max(induction method)So we have proved that we only need check if
new_policy->min>new_policy->max.After apply this patch, we can also modify ->min and ->max at same time if new freq range is very much different from current freq range. For example, if current freq range is 480000-960000, then we want to set this range to 1120000-2240000, we would fail in the past because
new_policy->min>policy->max. As long as the cpufreq range is valid, we has no reason to reject the user. So correct the check to avoid such case.
Quoted 1 line
Signed-off-by Pan Xinhui <[email protected]>
Queued up for 4.3, thanks!
Signature · 2 lines
I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center.