From patchwork Wed Apr 4 18:14:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Prakash, Prashanth" X-Patchwork-Id: 10323009 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C7EB26032A for ; Wed, 4 Apr 2018 18:15:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8B3028DD6 for ; Wed, 4 Apr 2018 18:15:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ADA2C28E5B; Wed, 4 Apr 2018 18:15:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F51B28DD6 for ; Wed, 4 Apr 2018 18:15:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751389AbeDDSPH (ORCPT ); Wed, 4 Apr 2018 14:15:07 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:43484 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751399AbeDDSPF (ORCPT ); Wed, 4 Apr 2018 14:15:05 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id A92D960F93; Wed, 4 Apr 2018 18:15:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1522865704; bh=r0BMQ1JNjczjUT1OtVD00/Sk2yAflV1Hrn5rmZN3XYU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nbcO0JpGccIp8KTr2KuyzQ5zad4aWBoNvQxVI/syp8VWiOy+2aqsaUscRV4yJJ2U8 jdEpJZfZX/HWGnG+ZBkEqa+DeSqXB+gWXOtH01MJrAB/FY1+aLUDhUXEXw8Npq5waW L1ZRBSt2kS18kP2vZGpWm0l6s7oyDTplYdy6dlUo= Received: from pprakash-lnx.qualcomm.com (unknown [129.46.14.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: pprakash@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 397BC60807; Wed, 4 Apr 2018 18:15:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1522865703; bh=r0BMQ1JNjczjUT1OtVD00/Sk2yAflV1Hrn5rmZN3XYU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZQxLMnNXZfRC8ZZROYFqUDBAGjhL1dPjYA/F7d+Q+BmV6fagnH/pdGPIPyDsQp9zO LnuqN+NUNbr3GMT9oIevcTQh480TTUHGTMgdtHVOVW5tBLrDN9aEEMtxM8tbDJYfGS nFP6nTFfPO7/OSGE1PuHMVkyLkwVAX+iJV+ak0jo= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 397BC60807 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=pprakash@codeaurora.org From: Prashanth Prakash To: linux-pm@vger.kernel.org, linux-acpi@vger.kernel.org Cc: rjw@rjwysocki.net, viresh.kumar@linaro.org, lenb@kernel.org, ahs3@redhat.com, Prashanth Prakash Subject: [PATCH 3/4] cpufreq / CPPC: Support for CPPC v3 Date: Wed, 4 Apr 2018 12:14:52 -0600 Message-Id: <1522865693-31831-4-git-send-email-pprakash@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1522865693-31831-1-git-send-email-pprakash@codeaurora.org> References: <1522865693-31831-1-git-send-email-pprakash@codeaurora.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Use CPPC v3 entries to convert the abstract processor performance to processor frequency in KHz. Signed-off-by: Prashanth Prakash Cc: Viresh Kumar Acked-by: Viresh Kumar --- drivers/cpufreq/cppc_cpufreq.c | 84 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 8300a9f..1b8ff9c 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -42,9 +42,6 @@ */ static struct cppc_cpudata **all_cpu_data; -/* Capture the max KHz from DMI */ -static u64 cppc_dmi_max_khz; - /* Callback function used to retrieve the max frequency from DMI */ static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private) { @@ -75,6 +72,64 @@ static u64 cppc_get_dmi_max_khz(void) return (1000 * mhz); } +/* + * 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 + */ +static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu, + unsigned int perf) +{ + static u64 max_khz; + struct cppc_perf_caps *caps = &cpu->perf_caps; + 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; + } + } else { + if (!max_khz) + max_khz = cppc_get_dmi_max_khz(); + mul = max_khz; + div = cpu->perf_caps.highest_perf; + } + return (u64)perf * mul / div; +} + +static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu, + unsigned int freq) +{ + static u64 max_khz; + struct cppc_perf_caps *caps = &cpu->perf_caps; + 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; + } + } else { + if (!max_khz) + max_khz = cppc_get_dmi_max_khz(); + mul = cpu->perf_caps.highest_perf; + div = max_khz; + } + + return (u64)freq * mul / div; +} + static int cppc_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) @@ -86,7 +141,7 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy, cpu = all_cpu_data[policy->cpu]; - desired_perf = (u64)target_freq * cpu->perf_caps.highest_perf / cppc_dmi_max_khz; + desired_perf = cppc_cpufreq_khz_to_perf(cpu, target_freq); /* Return if it is exactly the same perf */ if (desired_perf == cpu->perf_ctrls.desired_perf) return ret; @@ -143,24 +198,28 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) return ret; } - cppc_dmi_max_khz = cppc_get_dmi_max_khz(); + /* Convert the lowest and nominal freq from MHz to KHz */ + cpu->perf_caps.lowest_freq *= 1000; + cpu->perf_caps.nominal_freq *= 1000; /* * Set min to lowest nonlinear perf to avoid any efficiency penalty (see * Section 8.4.7.1.1.5 of ACPI 6.1 spec) */ - policy->min = cpu->perf_caps.lowest_nonlinear_perf * cppc_dmi_max_khz / - cpu->perf_caps.highest_perf; - policy->max = cppc_dmi_max_khz; + policy->min = cppc_cpufreq_perf_to_khz(cpu, + cpu->perf_caps.lowest_nonlinear_perf); + policy->max = cppc_cpufreq_perf_to_khz(cpu, + cpu->perf_caps.highest_perf); /* * Set cpuinfo.min_freq to Lowest to make the full range of performance * available if userspace wants to use any perf between lowest & lowest * nonlinear perf */ - policy->cpuinfo.min_freq = cpu->perf_caps.lowest_perf * cppc_dmi_max_khz / - cpu->perf_caps.highest_perf; - policy->cpuinfo.max_freq = cppc_dmi_max_khz; + policy->cpuinfo.min_freq = cppc_cpufreq_perf_to_khz(cpu, + cpu->perf_caps.lowest_perf); + policy->cpuinfo.max_freq = cppc_cpufreq_perf_to_khz(cpu, + cpu->perf_caps.highest_perf); policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); policy->transition_delay_us = cppc_get_transition_latency(cpu_num) / @@ -178,7 +237,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) cpu->cur_policy = policy; /* Set policy->cur to max now. The governors will adjust later. */ - policy->cur = cppc_dmi_max_khz; + policy->cur = cppc_cpufreq_perf_to_khz(cpu, + cpu->perf_caps.highest_perf); cpu->perf_ctrls.desired_perf = cpu->perf_caps.highest_perf; ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls);