From patchwork Mon Oct 21 16:20:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: dirk.brandewie@gmail.com X-Patchwork-Id: 3078801 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 62488BF924 for ; Mon, 21 Oct 2013 16:20:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3A9552024A for ; Mon, 21 Oct 2013 16:20:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 368C020364 for ; Mon, 21 Oct 2013 16:20:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751261Ab3JUQUp (ORCPT ); Mon, 21 Oct 2013 12:20:45 -0400 Received: from mail-pa0-f44.google.com ([209.85.220.44]:42736 "EHLO mail-pa0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751085Ab3JUQUp (ORCPT ); Mon, 21 Oct 2013 12:20:45 -0400 Received: by mail-pa0-f44.google.com with SMTP id fb1so5280128pad.17 for ; Mon, 21 Oct 2013 09:20:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=cbWMBA6lUz2Si7HcXSuPKraqi1QfhDJfkY5cMLGaL3M=; b=Dvp5yRt+ufdcrSJWaFMWVMwjA/74tPrRhfE5pKVfAorPATwQqKTPb6daG8rbHxt4DA CRozXoNOpElz/HrCpqooN6bjZAKayC26wF+Q3KtkOpXmlx+7E7gKjzlIbzGKlrdbApMl jSm7Sd0nEAtNjiMfg8OvXuB6peBWH231YR39+zG+mbxZrZrplQ/VFyvQ00NSJ1Ag34v4 OcsyRNrdigjm886AVIJV2sdQ3NMrDxjor23D5Ca3YPAR/2LLFJuO6lkGsPvRT5PFQQWJ UG93Zro/XRyjC3bLAtmU2VGSCY0GaKNwrDdSeWQIQaJ2SK9zyYUSw39aPm6EziBp80sE c9CA== X-Received: by 10.66.7.68 with SMTP id h4mr19200739paa.0.1382372444813; Mon, 21 Oct 2013 09:20:44 -0700 (PDT) Received: from echolake.localdomain (static-50-43-59-152.bvtn.or.frontiernet.net. [50.43.59.152]) by mx.google.com with ESMTPSA id fy4sm21918178pbb.1.2013.10.21.09.20.43 for (version=TLSv1.2 cipher=AES128-GCM-SHA256 bits=128/128); Mon, 21 Oct 2013 09:20:43 -0700 (PDT) From: dirk.brandewie@gmail.com To: linux-pm@vger.kernel.org, rjw@rjwysocki.net Cc: Brennan Shacklett , Brennan Shacklet Subject: [PATCH 1/4] cpufreq: intel_pstate: Improve accuracy by not truncating until final result Date: Mon, 21 Oct 2013 09:20:32 -0700 Message-Id: <1382372435-29778-2-git-send-email-dirk.j.brandewie@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1382372435-29778-1-git-send-email-dirk.j.brandewie@intel.com> References: <1382372435-29778-1-git-send-email-dirk.j.brandewie@intel.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Brennan Shacklett This patch addresses Bug 60727 (https://bugzilla.kernel.org/show_bug.cgi?id=60727) which was due to the truncation of intermediate values in the calculations, which causes the code to consistently underestimate the current cpu frequency, specifically 100% cpu utilization was truncated down to the setpoint of 97%. This patch fixes the problem by keeping the results of all intermediate calculations as fixed point numbers rather scaling them back and forth between integers and fixed point. Signed-off-by: Brennan Shacklet Acked-by: Dirk Brandewie Signed-off-by: Brennan Shacklett --- drivers/cpufreq/intel_pstate.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index d576489..9f42b0a 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -48,7 +48,7 @@ static inline int32_t div_fp(int32_t x, int32_t y) } struct sample { - int core_pct_busy; + int32_t core_pct_busy; u64 aperf; u64 mperf; int freq; @@ -68,7 +68,7 @@ struct _pid { int32_t i_gain; int32_t d_gain; int deadband; - int last_err; + int32_t last_err; }; struct cpudata { @@ -153,16 +153,15 @@ static inline void pid_d_gain_set(struct _pid *pid, int percent) pid->d_gain = div_fp(int_tofp(percent), int_tofp(100)); } -static signed int pid_calc(struct _pid *pid, int busy) +static signed int pid_calc(struct _pid *pid, int32_t busy) { - signed int err, result; + signed int result; int32_t pterm, dterm, fp_error; int32_t integral_limit; - err = pid->setpoint - busy; - fp_error = int_tofp(err); + fp_error = int_tofp(pid->setpoint) - busy; - if (abs(err) <= pid->deadband) + if (abs(fp_error) <= int_tofp(pid->deadband)) return 0; pterm = mul_fp(pid->p_gain, fp_error); @@ -176,8 +175,8 @@ static signed int pid_calc(struct _pid *pid, int busy) if (pid->integral < -integral_limit) pid->integral = -integral_limit; - dterm = mul_fp(pid->d_gain, (err - pid->last_err)); - pid->last_err = err; + dterm = mul_fp(pid->d_gain, fp_error - pid->last_err); + pid->last_err = fp_error; result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm; @@ -436,8 +435,9 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, struct sample *sample) { u64 core_pct; - core_pct = div64_u64(sample->aperf * 100, sample->mperf); - sample->freq = cpu->pstate.max_pstate * core_pct * 1000; + core_pct = div64_u64(int_tofp(sample->aperf * 100), + sample->mperf); + sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000); sample->core_pct_busy = core_pct; } @@ -469,22 +469,19 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu) mod_timer_pinned(&cpu->timer, jiffies + delay); } -static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu) +static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) { - int32_t busy_scaled; int32_t core_busy, max_pstate, current_pstate; - core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy); + core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy; max_pstate = int_tofp(cpu->pstate.max_pstate); current_pstate = int_tofp(cpu->pstate.current_pstate); - busy_scaled = mul_fp(core_busy, div_fp(max_pstate, current_pstate)); - - return fp_toint(busy_scaled); + return mul_fp(core_busy, div_fp(max_pstate, current_pstate)); } static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu) { - int busy_scaled; + int32_t busy_scaled; struct _pid *pid; signed int ctl = 0; int steps;