Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp3222858imm; Fri, 25 May 2018 01:47:13 -0700 (PDT) X-Google-Smtp-Source: AB8JxZpIViV5b+LkYVexb2r4Ff9EjwxRouS4NnP8x8xSpJiPQtOlUljpSFjN4h18FVqT1lWQz5Cp X-Received: by 2002:a65:590e:: with SMTP id f14-v6mr1261508pgu.282.1527238033638; Fri, 25 May 2018 01:47:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527238033; cv=none; d=google.com; s=arc-20160816; b=sl9IssJOo2S6chUqd+594QqI4iOua+tjqtNZ4hY+yfAodcldDKPSRKdM3m7OhJL7h7 rZHz/X3z5KiiAPerOLYDMggZi/ZbaktCOr3wp1LJ0Ch1A1Tsg+ZZxiXjwdswjGMSHp5x DWCF9TGlf3bgSvxW3Sh8eHWiavoKim9qzq1+Z5ybHE5lJkval7mIAT2tv/oDwY5xxvgx JMQ24WK4X6XPSVqjz0BUvH7n+X9W/lhlAHclOHZ/HBCk7Vyc+NhLHRO1XmBiXCpv9ioI P/Z5DzQXsf0JGJ9pbI2EaZ12vJ80EjxwmdYvsrqqlnroJuT/hqkupGnCOqrk2IFjZvdw JnJw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:dkim-signature :arc-authentication-results; bh=TB2OEj7kzYZsJvv0868Eb7MH67nuMHCCUeGWdlRfvxg=; b=ODDUOSp0SiAyxha0hhL+Wbb1kYTxdfD/2+tQ6TG+SHxGV15jPbU/DboakM7CdZWhBB LREFeyvEgC1XJFf+rTvge5pIqvcujiNVEcJZ7La0Dpa3FUwIDy8zE6f65Dh7BiSzzGKl qgacIoVNpMOaY2YjjfPv9D7kgPBkc5R4m/fXdt+UVA/PjSfVWS5QRSWz4I2gyKC+ZPbd dXBGVJsms68auL2FmlwAPVXOtSt/0xIjqhsBuHxjwCFqdzoehU1vXXHrpWlhntviT9vE FXlc8td2NbmUNwXjOnj4WSkd6FGPzAPaYNV5xAuzXZuqTQDtWNE+yA0gS0tqM08bf0wh 40Zg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=bQVJhGP0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k14-v6si18682645pgs.418.2018.05.25.01.46.58; Fri, 25 May 2018 01:47:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=bQVJhGP0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965145AbeEYIqM (ORCPT + 99 others); Fri, 25 May 2018 04:46:12 -0400 Received: from mail-oi0-f68.google.com ([209.85.218.68]:35689 "EHLO mail-oi0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965050AbeEYIqJ (ORCPT ); Fri, 25 May 2018 04:46:09 -0400 Received: by mail-oi0-f68.google.com with SMTP id a6-v6so3929784oia.2; Fri, 25 May 2018 01:46:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:sender:in-reply-to:references:from:date:message-id :subject:to:cc; bh=TB2OEj7kzYZsJvv0868Eb7MH67nuMHCCUeGWdlRfvxg=; b=bQVJhGP0tQV8+cVNTZq15lFV5+yDlH4cww+soCzi/Ko/A3qvCypEpaaGNPgZ8yM94g 49LKKvTeVHz1aHkQyi4ukYTA8GObWb7WFNs5/AqVsnn0NJRmxIBCcFighlGljTnJNpIt mWQx+2iXFSoeTMlf40B9FvrZwet+688QcT3gAx53+kCNpgZpyOojTRfOvmjM1yh+mfaN bFvhrq75E8h2naWl3VHL2yb4wUSM+fo3aYbz4sQB+CZjGfibWQ7H4J54PKwTrqt5nKhs Jfl68KcpsUAO5H3xBub4SnEMOI4tfnmvCeqZi/duqn9jd2Izd99rDvfp3GlcA5a2DBNl PREw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:sender:in-reply-to:references:from :date:message-id:subject:to:cc; bh=TB2OEj7kzYZsJvv0868Eb7MH67nuMHCCUeGWdlRfvxg=; b=bQ74l8p2ZixWVQ2DIstVc9d7U5CIkkdH/NBoRYs7mNjJQPcgo6DMKefOyQJfwBjwOL as+SKkRTrbPN9bGmjqOAALAce98hJ9WzwC1cG03gwUfwhZ5QdyJaMsfMzyzMcsApcDa/ gGXIMKW8+bPyH5JZyx6xx2WH31zCcyxAR4cC0oK4cYFVYS0QF3ah8azc3MfHevio4HNw /Vpma+vLjkzwGpCxsc7JiiVMF8Zx7SChQXL0OjWoltzI75q17yPNKSd5bnyODFJUfNli s7Bx9qk96LXY135snpDlBGVBGdmy4wQd/uYzMnEV3uof+GGscKkorRzJucFOBb4frxbh te0g== X-Gm-Message-State: ALKqPwes6R0OlW+1W6eBr8T4K7+/Ceo6IycVY+CH3xyJbji0AMF1FIIp wSvtyCbx/aKDY9gKfd+ufbiplgL6X0pXqHmP96o= X-Received: by 2002:aca:4c11:: with SMTP id z17-v6mr798219oia.174.1527237968357; Fri, 25 May 2018 01:46:08 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a9d:1468:0:0:0:0:0 with HTTP; Fri, 25 May 2018 01:46:08 -0700 (PDT) In-Reply-To: <5ff2bebc-fc39-dc82-d7e6-0483e38f7d9c@caviumnetworks.com> References: <1526989324-4183-1-git-send-email-george.cherian@cavium.com> <5ff2bebc-fc39-dc82-d7e6-0483e38f7d9c@caviumnetworks.com> From: "Rafael J. Wysocki" Date: Fri, 25 May 2018 10:46:08 +0200 X-Google-Sender-Auth: yFUzml4QddyYJiPDMFJypXAejkU Message-ID: Subject: Re: [PATCH] cpufreq / CPPC: Add cpuinfo_cur_freq support for CPPC To: George Cherian Cc: "Prakash, Prashanth" , George Cherian , Linux Kernel Mailing List , Linux PM , "Rafael J. Wysocki" , Viresh Kumar Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, May 25, 2018 at 8:27 AM, George Cherian wrote: > Hi Prashanth, > > > On 05/25/2018 12:55 AM, Prakash, Prashanth wrote: >> >> Hi George, >> >> On 5/22/2018 5:42 AM, George Cherian wrote: >>> >>> Per Section 8.4.7.1.3 of ACPI 6.2, The platform provides performance >>> feedback via set of performance counters. To determine the actual >>> performance level delivered over time, OSPM may read a set of >>> performance counters from the Reference Performance Counter Register >>> and the Delivered Performance Counter Register. >>> >>> OSPM calculates the delivered performance over a given time period by >>> taking a beginning and ending snapshot of both the reference and >>> delivered performance counters, and calculating: >>> >>> delivered_perf = reference_perf X (delta of delivered_perf counter / >>> delta of reference_perf counter). >>> >>> Implement the above and hook this to the cpufreq->get method. >>> >>> Signed-off-by: George Cherian >>> --- >>> drivers/cpufreq/cppc_cpufreq.c | 44 >>> ++++++++++++++++++++++++++++++++++++++++++ >>> 1 file changed, 44 insertions(+) >>> >>> diff --git a/drivers/cpufreq/cppc_cpufreq.c >>> b/drivers/cpufreq/cppc_cpufreq.c >>> index b15115a..a046915 100644 >>> --- a/drivers/cpufreq/cppc_cpufreq.c >>> +++ b/drivers/cpufreq/cppc_cpufreq.c >>> @@ -240,10 +240,54 @@ static int cppc_cpufreq_cpu_init(struct >>> cpufreq_policy *policy) >>> return ret; >>> } >>> +static int cppc_get_rate_from_fbctrs(struct cppc_perf_fb_ctrs >>> fb_ctrs_t0, >>> + struct cppc_perf_fb_ctrs fb_ctrs_t1) >>> +{ >>> + u64 delta_reference, delta_delivered; >>> + u64 reference_perf, ratio; >>> + >>> + reference_perf = fb_ctrs_t0.reference_perf; >>> + if (fb_ctrs_t1.reference > fb_ctrs_t0.reference) >>> + delta_reference = fb_ctrs_t1.reference - >>> fb_ctrs_t0.reference; >>> + else /* Counters would have wrapped-around */ >>> + delta_reference = ((u64)(~((u64)0)) - >>> fb_ctrs_t0.reference) + >>> + fb_ctrs_t1.reference; >>> + >>> + if (fb_ctrs_t1.delivered > fb_ctrs_t0.delivered) >>> + delta_delivered = fb_ctrs_t1.delivered - >>> fb_ctrs_t0.delivered; >>> + else /* Counters would have wrapped-around */ >>> + delta_delivered = ((u64)(~((u64)0)) - >>> fb_ctrs_t0.delivered) + >>> + fb_ctrs_t1.delivered; >> >> We need to check that the wraparound time is long enough to make sure that >> the counters cannot wrap around more than once. We can register a get() >> api >> only after checking that wraparound time value is reasonably high. >> >> I am not aware of any platforms where wraparound time is soo short, but >> wouldn't hurt to check once during init. > > By design the wraparound time is a 64 bit counter, for that matter even > all the feedback counters too are 64 bit counters. I don't see any > chance in which the counters can wraparound twice in back to back reads. > The only situation is in which system itself is running at a really high > frequency. Even in that case today's spec is not sufficient to support the > same. > >>> + >>> + if (delta_reference) /* Check to avoid divide-by zero */ >>> + ratio = (delta_delivered * 1000) / delta_reference; >> >> Why not just return the computed value here instead of *1000 and later >> /1000? >> return (ref_per * delta_del) / delta_ref; > > Yes. >>> >>> + else >>> + return -EINVAL; >> >> Instead of EINVAL, i think we should return current frequency. >> > Sorry, I didn't get you, How do you calculate the current frequency? > Did you mean reference performance? > >> The counters can pause if CPUs are in idle state during our sampling >> interval, so >> If the counters did not progress, it is reasonable to assume the delivered >> perf was >> equal to desired perf. > > No, that is wrong. Here the check is for reference performance delta. > This counter can never pause. In case of cpuidle only the delivered counters > could pause. Delivered counters will pause only if the particular core > enters power down mode, Otherwise we would be still clocking the core and we > should be getting a delta across 2 sampling periods. In case if the > reference counter is paused which by design is not correct then there is no > point in returning reference performance numbers. That too is wrong. In case > the low level FW is not updating the > counters properly then it should be evident till Linux, instead of returning > a bogus frequency. >> >> >> Even if platform wanted to limit, since the CPUs were asleep(idle) we >> could not have >> observed lower performance, so we will not throw off any logic that could >> be driven >> using the returned value. >>> >>> + >>> + return (reference_perf * ratio) / 1000; >> >> This should be converted to KHz as cpufreq is not aware of CPPC abstract >> scale > > In our platform all performance registers are implemented in KHz. Because of > which we never had an issue with conversion. I am not > aware whether ACPI mandates to use any particular unit. How is that > implemented in your platform? Just to avoid any extra conversion don't > you feel it is better to always report in KHz from firmware. > >>> +} >>> + >>> +static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) >>> +{ >>> + struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; >>> + int ret; >>> + >>> + ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0); >>> + if (ret) >>> + return ret; >>> + >>> + ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t1); >>> + if (ret) >>> + return ret; >>> + >>> + return cppc_get_rate_from_fbctrs(fb_ctrs_t0, fb_ctrs_t1); >>> +} >> >> We need to make sure that we get a reasonably sample so make sure the >> reported >> performance is accurate. >> The counters can capture short transient throttling/limiting, so by >> sampling a really >> short duration of time we could return quite inaccurate measure of >> performance. >> > I would say it as a momentary thing only when the frequency is being ramped > up/down. > >> We need to include some reasonable delay between the two calls. What is >> reasonable >> is debatable - so this can be few(2-10) microseconds defined as default. >> If the same value >> doesn't work for all the platforms, we might need to add a platform >> specific value. >> > cppc_get_perf_ctrs itself is a slow call, we have to format the CPC packet > and ring a doorbell and then the response to be read from the shared > registers. My initial implementation had a delay but in testing, > I found that it was unnecessary to have such a delay. Can you please > let me know whether it works without delay in your platform? > > Or else let me know whether udelay(10) is sufficient in between the > calls. > >>> + >>> static struct cpufreq_driver cppc_cpufreq_driver = { >>> .flags = CPUFREQ_CONST_LOOPS, >>> .verify = cppc_verify_policy, >>> .target = cppc_cpufreq_set_target, >>> + .get = cppc_cpufreq_get_rate, >>> .init = cppc_cpufreq_cpu_init, >>> .stop_cpu = cppc_cpufreq_stop_cpu, >>> .name = "cppc_cpufreq", >> I was about to apply the $subject patch, but now I would like you and Prashanth to agree on it, so please ask Prashanth for an ACK on the final version.