Received: by 2002:a05:6a10:6d10:0:0:0:0 with SMTP id gq16csp818728pxb; Tue, 12 Apr 2022 14:19:00 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyAtqSjUMlDGbJXLpcOYy2XBALz6IKkzkgoIKRnk0Ixo03IZ4K0VgMRxXmtp+HeGT4mCGAi X-Received: by 2002:a17:902:e8d1:b0:156:5651:777 with SMTP id v17-20020a170902e8d100b0015656510777mr39439119plg.65.1649798340146; Tue, 12 Apr 2022 14:19:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649798340; cv=none; d=google.com; s=arc-20160816; b=JEEOfpyimn/pEa74CPR764f52QI106KyvfXQ7xwY1m6QlkOfrwcSNTQZlh6U6k0Er1 k6q7RivpmmQwpBiXum1FFkINRCnB9BO7BD7VCSW7vLH9vb/HquhwJ3q5BnxtO5CAizu7 lEioIWDgcj5mRF41fckkA5QdVmC4VfiZxjTlkJ9UnrARA//UYei88VJRJHcvpCxMC32C yx5mwFm8XCENPUl3M2QRyWGclP2G2/8Wp7GS4IgD25LU8SxJJzhVelK/w8MpRkKPxXAg Pa4gTKWfu6RI1ML9ecOFSk3GohFCZtFNp2ouJJkKApO+c21uJbPdzys+0hGcYQp74mpT VEOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=V5g3iogY/6r3EAQ5s8MMaU+CRC4ryXhLe71mng2D+E8=; b=ECvGcMf+ry4K7J5r5wlcxV+XyKgTQ/wQ9CZqVQSHR4qvtcd4mSgomlCbB3YYc3EHs4 RbWJLqlksYepc2xr4qDBsX7/FOaCfCtm19+Aryo5EiFkj2BI6SzU8OFmA7wV1itYuJCK bjeeCWXcAadymPkTa+LkrnzZ4y7QRJe8Xa25N4dPm9sAaRgeLP+vE4svTcHC2SzfjiZK K1AdGR+YyysSrb8I0wo2M3NpNIKAM8e64ROHjsVJKW2MHqarTTm8O/mwteLI8tPjLF90 FmteZ/s9tjMmaQemonMNdBn4XwnQCWYhkckiR15nTIDOCUGH1R03jHWxfiBvvkuzw2Wg k5cA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=nWIsjPGL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id 6-20020a631146000000b003816043f143si3723719pgr.824.2022.04.12.14.18.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Apr 2022 14:19:00 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=nWIsjPGL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D1740FC11E; Tue, 12 Apr 2022 13:32:31 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1358702AbiDLIcF (ORCPT + 99 others); Tue, 12 Apr 2022 04:32:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353544AbiDLHZq (ORCPT ); Tue, 12 Apr 2022 03:25:46 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 48D192656C; Tue, 12 Apr 2022 00:01:18 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id D7D3960B65; Tue, 12 Apr 2022 07:01:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DBE21C385A1; Tue, 12 Apr 2022 07:01:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1649746877; bh=0+xvbaE1I0/8b+wbY9uFiN56VFJGLSH7zHl8KdntBK8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nWIsjPGLUyjQ7TJrUnUtc2DE4mv2sHR4y1EY45cuzJTZei8JkOpPle/XWRvcPJ4SS u/CQkMq1Wy7TwaAerVTWz5kr3Aw9+oUV2z33ln1wS4tR4rtxWOOsNnG0I19RoSsya2 iv+Rm7C+K4RT6gHCvDILUc4CUGOvgE8IeuaoYPW4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Lukasz Luba , Morten Rasmussen , Pierre Gondois , Viresh Kumar , Sasha Levin Subject: [PATCH 5.16 122/285] cpufreq: CPPC: Fix performance/frequency conversion Date: Tue, 12 Apr 2022 08:29:39 +0200 Message-Id: <20220412062947.187059812@linuxfoundation.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220412062943.670770901@linuxfoundation.org> References: <20220412062943.670770901@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Pierre Gondois [ Upstream commit ec1c7ad47664f964c1101fe555b6fde0cb124b38 ] CPUfreq governors request CPU frequencies using information on current CPU usage. The CPPC driver converts them to performance requests. Frequency targets are computed as: target_freq = (util / cpu_capacity) * max_freq target_freq is then clamped between [policy->min, policy->max]. The CPPC driver converts performance values to frequencies (and vice-versa) using cppc_cpufreq_perf_to_khz() and cppc_cpufreq_khz_to_perf(). These functions both use two different factors depending on the range of the input value. For cppc_cpufreq_khz_to_perf(): - (NOMINAL_PERF / NOMINAL_FREQ) or - (LOWEST_PERF / LOWEST_FREQ) and for cppc_cpufreq_perf_to_khz(): - (NOMINAL_FREQ / NOMINAL_PERF) or - ((NOMINAL_PERF - LOWEST_FREQ) / (NOMINAL_PERF - LOWEST_PERF)) This means: 1- the functions are not inverse for some values: (perf_to_khz(khz_to_perf(x)) != x) 2- cppc_cpufreq_perf_to_khz(LOWEST_PERF) can sometimes give a different value from LOWEST_FREQ due to integer approximation 3- it is implied that performance and frequency are proportional (NOMINAL_FREQ / NOMINAL_PERF) == (LOWEST_PERF / LOWEST_FREQ) This patch changes the conversion functions to an affine function. This fixes the 3 points above. Suggested-by: Lukasz Luba Suggested-by: Morten Rasmussen Signed-off-by: Pierre Gondois Signed-off-by: Viresh Kumar Signed-off-by: Sasha Levin --- drivers/cpufreq/cppc_cpufreq.c | 43 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index db17196266e4..82d370ae6a4a 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -303,52 +303,48 @@ static u64 cppc_get_dmi_max_khz(void) /* * If CPPC lowest_freq and nominal_freq registers are exposed then we can - * use them to convert perf to freq and vice versa - * - * If the perf/freq point lies between Nominal and Lowest, we can treat - * (Low perf, Low freq) and (Nom Perf, Nom freq) as 2D co-ordinates of a line - * and extrapolate the rest - * For perf/freq > Nominal, we use the ratio perf:freq at Nominal for conversion + * use them to convert perf to freq and vice versa. The conversion is + * extrapolated as an affine function passing by the 2 points: + * - (Low perf, Low freq) + * - (Nominal perf, Nominal perf) */ static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu_data, unsigned int perf) { struct cppc_perf_caps *caps = &cpu_data->perf_caps; + s64 retval, offset = 0; static u64 max_khz; u64 mul, div; if (caps->lowest_freq && caps->nominal_freq) { - if (perf >= caps->nominal_perf) { - mul = caps->nominal_freq; - div = caps->nominal_perf; - } else { - mul = caps->nominal_freq - caps->lowest_freq; - div = caps->nominal_perf - caps->lowest_perf; - } + mul = caps->nominal_freq - caps->lowest_freq; + div = caps->nominal_perf - caps->lowest_perf; + offset = caps->nominal_freq - div64_u64(caps->nominal_perf * mul, div); } else { if (!max_khz) max_khz = cppc_get_dmi_max_khz(); mul = max_khz; div = caps->highest_perf; } - return (u64)perf * mul / div; + + retval = offset + div64_u64(perf * mul, div); + if (retval >= 0) + return retval; + return 0; } static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data, unsigned int freq) { struct cppc_perf_caps *caps = &cpu_data->perf_caps; + s64 retval, offset = 0; static u64 max_khz; u64 mul, div; if (caps->lowest_freq && caps->nominal_freq) { - if (freq >= caps->nominal_freq) { - mul = caps->nominal_perf; - div = caps->nominal_freq; - } else { - mul = caps->lowest_perf; - div = caps->lowest_freq; - } + mul = caps->nominal_perf - caps->lowest_perf; + div = caps->nominal_freq - caps->lowest_freq; + offset = caps->nominal_perf - div64_u64(caps->nominal_freq * mul, div); } else { if (!max_khz) max_khz = cppc_get_dmi_max_khz(); @@ -356,7 +352,10 @@ static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu_data, div = max_khz; } - return (u64)freq * mul / div; + retval = offset + div64_u64(freq * mul, div); + if (retval >= 0) + return retval; + return 0; } static int cppc_cpufreq_set_target(struct cpufreq_policy *policy, -- 2.35.1