From patchwork Fri Jun 2 11:29:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 101234 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp341607qge; Fri, 2 Jun 2017 04:30:02 -0700 (PDT) X-Received: by 10.101.90.199 with SMTP id d7mr6802615pgt.227.1496403002236; Fri, 02 Jun 2017 04:30:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496403002; cv=none; d=google.com; s=arc-20160816; b=sbTEl3/qW37alDNsbz05Z+njMTQSkE9moi7bXaVAp0/Itu/jaeaTnwGVH204PmA13m 3NzTFR2ctQZuyL9dyVjtpqwASyP2GCdvZz/Cys0VUYzhB3Tpyn+zvkYg4BpWDB8z1LDV mQewXAzacu4RqXdXb7InReFkxOoTTL2M6waiCEtCBaqcBLeZPkBCnOO/PR/vCNeLM1b9 /sweYUEcDWHOFt0+IRdXhDWJgZRzoVQLl+H4s5zK1beyyYb1/JkQTL3+Lj5CEwDHPtUq 1uKHVMAZ+GxCHANrSw+xtINA578m8azj77gzHiAnVvwHSaf+/cVL3EQNahadjliUCE2K rfpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=vjLVBKtxqyC7Lu4qzl7iBGDmAN7TIim/VVSe8nJ13dk=; b=an9TsWMNPTclcHoF5iO9X0DCTA1jNfsmgCNhduGGRkWhCv2Vg3sPbUPvUsiuVoVqVn gsNoTs2F8SnO2ViFawQOYiw8dvIHBu5GdUCSLfwCXKEKIMahXRmvaCNa7BE0HRG0Jq/9 CUEQjw9Xe+Eu0NJ31qWvANrgFXxBxOCRAT83dqYP2gB7vzdsCzBvVGteTOChDyo2li4Y QR4OQzpciX9rZU/QmoUH8dt7kO4fwglctm0HsEbKH+DUD+zMHF8oDWMxZBuSI0i1kuNs bq+bojhAqXU5XkfXXzKFToYuDNl0u8kGADgmd0pES4tyNpRv/MUWOiH2qAUsROlZ0q4f HG1w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 1si49945040ply.117.2017.06.02.04.30.01; Fri, 02 Jun 2017 04:30:02 -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=pass header.i=@linaro.org; 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=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751230AbdFBL3s (ORCPT + 25 others); Fri, 2 Jun 2017 07:29:48 -0400 Received: from mail-it0-f53.google.com ([209.85.214.53]:37794 "EHLO mail-it0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751126AbdFBL3q (ORCPT ); Fri, 2 Jun 2017 07:29:46 -0400 Received: by mail-it0-f53.google.com with SMTP id m47so16154852iti.0 for ; Fri, 02 Jun 2017 04:29:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=vjLVBKtxqyC7Lu4qzl7iBGDmAN7TIim/VVSe8nJ13dk=; b=MbR6HtuOS+wqpmnFBAFP+ncpieOTN6zMtrdIl24tTjf1LzfK5gXgblrgTqW0bZjn9w i/lup1CBKn8IhNuGhVNUEEXahm1hJurfxHXWR++9+2lkjBJTsuGeXHzAifG1IrxjGTdt voY8xnD2exIDjt+hDkCWaTX/4IPlbKXfrkIDY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=vjLVBKtxqyC7Lu4qzl7iBGDmAN7TIim/VVSe8nJ13dk=; b=oE/5DyEYKQG1tDG0/4UKOXhOli/5U+k+xRPN/Gy0SCJXB0BbmJ+r2H3epIPKpV8cgL LEYUnPdLQEVQArO3LKGHKmdS9NO/QXJX+5pT9j+EVi6GEv+swhk0RQkPFE41CoRtXv6L kGlCL7mZCPeTDGDb/rZCmO8T96lHbFTt9+sdC7yLRlect8J28xXixztGAyBbUwP4KPnb mezPdqYhGVDTgm266+im0bK0LoBcgCV91FQdpruN3k5LJgcbzAR2QAijW62GqMmGWtcj qVMq7F43Lc2yBMyypIWhtExAmNAnjZpcI3f5E3T/ImND8Cota13BvbRRJrsMwa421vTA 79zw== X-Gm-Message-State: AODbwcBn89zr8OesMTB+dXcM9Cs2ArrKTkWZLrrmjiJJHAb1Wo3aJTNK AQth5rOYPzTNJt6j X-Received: by 10.101.70.129 with SMTP id h1mr6737809pgr.50.1496402985441; Fri, 02 Jun 2017 04:29:45 -0700 (PDT) Received: from localhost ([122.167.19.84]) by smtp.gmail.com with ESMTPSA id o8sm36645461pgn.52.2017.06.02.04.29.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Jun 2017 04:29:44 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , Viresh Kumar Cc: linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Guittot Subject: [PATCH] cpufreq: Find transition latency dynamically Date: Fri, 2 Jun 2017 16:59:38 +0530 Message-Id: <8041a965fcca71231576ae77a141b1e4333a81cc.1496402967.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.13.0.70.g6367777092d9 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The transition_latency_ns represents the maximum time it can take for the hardware to switch from/to any frequency for a CPU. The transition_latency_ns is used currently for two purposes: o To check if the hardware latency is over the maximum allowed for a governor (only for ondemand and conservative (why not schedutil?)) and to decide if the governor can be used or not. o To calculate the sampling_rate or rate_limit for the governors by multiplying transition_latency_ns with a constant. The platform drivers can also set this value to CPUFREQ_ETERNAL if they don't know this number and in that case we disallow use of ondemand and conservative governors as the latency would be higher than the maximum allowed for the governors. In many cases this number is forged by the driver authors to get the default sampling rate to a desired value. Anyway, the actual latency values can differ from what is received from the hardware designers. Over that, what is provided by the drivers is most likely the time it takes to change frequency of the hardware, which doesn't account the software overhead involved. In order to have guarantees about this number, this patch tries to calculate the latency dynamically at cpufreq driver registration time by first switching to min frequency, then to the max and finally back to the initial frequency. And the maximum of all three is used as the target_latency. Specifically the time it takes to go from min to max frequency (when the software runs the slowest) should be good enough, and even if there is a delta involved then it shouldn't be a lot. For now this patch limits this feature only for platforms which have set the transition latency to CPUFREQ_ETERNAL. Maybe we can convert everyone to use it in future, but lets see. This is tested over ARM64 Hikey platform which currently sets "clock-latency" as 500 us from DT, while with this patch the actualy value increased to 800 us. Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) -- 2.13.0.70.g6367777092d9 diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0e3f6496524d..478a18364b1f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -977,6 +978,66 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void) return NULL; } +static int find_dvfs_latency(struct cpufreq_policy *policy, unsigned long freq, + unsigned int *latency_ns) +{ + u64 time; + int ret; + + time = local_clock(); + ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); + *latency_ns = local_clock() - time; + + return ret; +} + +/* + * Find the transition latency dynamically by: + * - Switching to min freq first. + * - Then switching to max freq. + * - And finally switching back to the initial freq. + * + * The maximum duration of the above three freq changes should be good enough to + * find the maximum transition latency for a platform. + */ +static void cpufreq_find_target_latency(struct cpufreq_policy *policy) +{ + unsigned long initial_freq = policy->cur; + unsigned int latency_ns, latency_max_ns; + int ret; + + if (!has_target()) + return; + + /* Limit to drivers with latency set to CPUFREQ_ETERNAL for now */ + if (policy->cpuinfo.transition_latency != CPUFREQ_ETERNAL) + return; + + /* Go to min frequency first */ + ret = find_dvfs_latency(policy, policy->cpuinfo.min_freq, &latency_ns); + if (ret) + return; + + latency_max_ns = latency_ns; + + /* Go to max frequency then.. */ + ret = find_dvfs_latency(policy, policy->cpuinfo.max_freq, &latency_ns); + if (ret) + return; + + latency_max_ns = max(latency_max_ns, latency_ns); + + /* And finally switch back to where we started from */ + ret = find_dvfs_latency(policy, initial_freq, &latency_ns); + if (ret) + return; + + policy->cpuinfo.transition_latency = max(latency_max_ns, latency_ns); + + pr_info("%s: Setting transition latency to %u ns for policy of CPU%d\n", + __func__, policy->cpuinfo.transition_latency, policy->cpu); +} + static int cpufreq_init_policy(struct cpufreq_policy *policy) { struct cpufreq_governor *gov = NULL; @@ -1246,6 +1307,8 @@ static int cpufreq_online(unsigned int cpu) } if (new_policy) { + cpufreq_find_target_latency(policy); + ret = cpufreq_add_dev_interface(policy); if (ret) goto out_exit_policy;