Re: [PATCH] cpufreq, intel_pstate.c, Fix rounding errors

2015-11-19 Thread Prarit Bhargava


On 11/18/2015 11:46 PM, Viresh Kumar wrote:
> On 18-11-15, 10:55, Prarit Bhargava wrote:
>> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
>> index 2e31d09..686f024 100644
>> --- a/drivers/cpufreq/intel_pstate.c
>> +++ b/drivers/cpufreq/intel_pstate.c
>> @@ -1233,6 +1233,8 @@ static int intel_pstate_set_policy(struct 
>> cpufreq_policy *policy)
>>  struct cpudata *cpu;
>>  int i;
>>  #endif
>> +int max_policy_calc;
>> +
>>  pr_debug("intel_pstate: %s max %u policy->max %u\n", __func__,
>>   policy->cpuinfo.max_freq, policy->max);
>>  if (!policy->cpuinfo.max_freq)
>> @@ -1249,7 +1251,10 @@ static int intel_pstate_set_policy(struct 
>> cpufreq_policy *policy)
>>  limits = &powersave_limits;
>>  limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
>>  limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100);
>> -limits->max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
>> +
>> +max_policy_calc = (policy->max * 1000) / policy->cpuinfo.max_freq;
>> +limits->max_policy_pct = DIV_ROUND_UP(max_policy_calc, 10);
>> +
> 
> Nice catch, but why can't we do this instead:
> 
>   limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, 
> policy->cpuinfo.max_freq);
> 

Ah, I got so deep into the code I didn't even think of simplifying the
calculation.  Thanks -- I'll do that instead.

>>  limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100);
>>  
>>  /* Normalize user input to [min_policy_pct, max_policy_pct] */
>> @@ -1269,6 +1274,7 @@ static int intel_pstate_set_policy(struct 
>> cpufreq_policy *policy)
>>int_tofp(100));
>>  limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
>>int_tofp(100));
>> +limits->max_perf = round_up(limits->max_perf, 8);
> 
> Perhaps you should fix this in a separate patch.
> 

Okay, I submit these as a 2 part patchset.

P.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] cpufreq, intel_pstate.c, Fix rounding errors

2015-11-18 Thread Viresh Kumar
On 18-11-15, 10:55, Prarit Bhargava wrote:
> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> index 2e31d09..686f024 100644
> --- a/drivers/cpufreq/intel_pstate.c
> +++ b/drivers/cpufreq/intel_pstate.c
> @@ -1233,6 +1233,8 @@ static int intel_pstate_set_policy(struct 
> cpufreq_policy *policy)
>   struct cpudata *cpu;
>   int i;
>  #endif
> + int max_policy_calc;
> +
>   pr_debug("intel_pstate: %s max %u policy->max %u\n", __func__,
>policy->cpuinfo.max_freq, policy->max);
>   if (!policy->cpuinfo.max_freq)
> @@ -1249,7 +1251,10 @@ static int intel_pstate_set_policy(struct 
> cpufreq_policy *policy)
>   limits = &powersave_limits;
>   limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
>   limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100);
> - limits->max_policy_pct = (policy->max * 100) / policy->cpuinfo.max_freq;
> +
> + max_policy_calc = (policy->max * 1000) / policy->cpuinfo.max_freq;
> + limits->max_policy_pct = DIV_ROUND_UP(max_policy_calc, 10);
> +

Nice catch, but why can't we do this instead:

limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100, 
policy->cpuinfo.max_freq);

>   limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100);
>  
>   /* Normalize user input to [min_policy_pct, max_policy_pct] */
> @@ -1269,6 +1274,7 @@ static int intel_pstate_set_policy(struct 
> cpufreq_policy *policy)
> int_tofp(100));
>   limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
> int_tofp(100));
> + limits->max_perf = round_up(limits->max_perf, 8);

Perhaps you should fix this in a separate patch.

-- 
viresh
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] cpufreq, intel_pstate.c, Fix rounding errors

2015-11-18 Thread Prarit Bhargava
I have a Intel (6,63) processor with a "marketing" frequency (from
/proc/cpuinfo) of 2100MHz, and a max turbo frequency of 2600MHz.  I
can execute

cpupower frequency-set -g powersave --min 1200MHz --max 2100MHz

and the max_freq_pct is set to 80.  When adding load to the system I noticed
that the cpu frequency only reached 2000MHZ and not 2100MHz as expected.

I wrote a little test program to set the frequencies in decrements of
100MHz and compared the targeted frequency (the frequency set through
the cpupower command) and the actual frequency (from /proc/cpuinfo), as
well as dumping out the value of the MSR_IA32_PERF_CTL.

Target Achieved Difference MSR(0x199)
 33002900  -400  0x1e00
 32002900  -300  0x1e00
 31002900  -200  0x1e00
 30002900  -100  0x1d00
 29002800  -100  0x1c00
 28002700  -100  0x1b00
 27002600  -100  0x1a00
 26002500  -100  0x1900
 25002400  -100  0x1800
 24002300  -100  0x1700
 23002200  -100  0x1600
 22002100  -100  0x1500
 21002000  -100  0x1400
 20001900  -100  0x1300
 19001800  -100  0x1200
 18001700  -100  0x1100
 17001600  -100  0x1000
 16001500  -100  0xf00
 15001400  -100  0xe00
 14001300  -100  0xd00
 13001200  -100  0xc00
 12001200 0  0xc00

As can be seen the frequencies are consistently off by 100MHz.  After
some examination I found a rounding error in intel_pstate_set_policy() for the
calculation of limits->max_policy_pct which needs to be rounded up to the
nearest percentage point.  For example, setting a frequency of 2100MHz on this
system results in limits->max_policy_pct = ((2100 * 100) / 2600) = 80.
However, ((2100 * 100) / 2600) is actually 80.7, or 81.   This is fixed
by expanding the calculation an extra decimal point and rounding to the
nearest percentage point.

A second rounding error was found in the calculation of limits->max_perf
in intel_pstate_set_policy(), which is used to calculate the max and min
pstate values in intel_pstate_get_min_max().  In this case, limits->max_perf
is truncated to 2 hex digits such that, for example, 0x169 was incorrectly
truncated to 0x16 instead of 0x17.  This resulted in the pstate being set
one level too low.

After applying these two fixes we consistently reach the targeted
frequency.

Target Achieved Difference MSR(0x199)
 33002900  -400  0x1e00
 32002900  -300  0x1e00
 31002900  -200  0x1e00
 30002900  -100  0x1d00
 29002900 0  0x1d00
 28002800 0  0x1c00
 27002700 0  0x1b00
 26002600 0  0x1a00
 25002500 0  0x1900
 24002400 0  0x1800
 23002300 0  0x1700
 22002200 0  0x1600
 21002100 0  0x1500
 20002000 0  0x1400
 19001900 0  0x1300
 18001800 0  0x1200
 17001700 0  0x1100
 16001600 0  0x1000
 15001500 0  0xf00
 14001400 0  0xe00
 13001300 0  0xd00
 12001200 0  0xc00

Additional tests were run on a (6,78) with HWP enabled and a (6,79)
system.  Testing on both systems showed that the problem was resolved.

Cc: Srinivas Pandruvada 
Cc: Len Brown 
Cc: Alexandra Yates 
Cc: Kristen Carlson Accardi 
Cc: "Rafael J. Wysocki" 
Cc: Viresh Kumar 
Cc: linux...@vger.kernel.org

Signed-off-by: Prarit Bhargava 
---
 drivers/cpufreq/intel_pstate.c |8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 2e31d09..686f024 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1233,6 +1233,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy 
*policy)
struct cpudata *cpu;
int i;
 #endif
+   int max_policy_calc;
+
pr_debug("intel_pstate: %s max %u policy->max %u\n", __func__,
 policy->cpuinfo.max_freq, policy->max);
if (!policy->cpuinfo.max_freq)
@@ -1249,7 +1251,10 @@ static int intel_pstate_set_policy(struct cpufreq_policy 
*policy)
limits = &powersave_limits;
limits->min_policy_pct = (policy->min * 100) / policy->cp