Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp642204pxb; Thu, 26 Aug 2021 10:54:46 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwoDHZaLxVErT42XND90bVWtSYEcklY+6ddLh7A690cYYIbP0tIwHa/+o3HYVQ2Ig1C9Mjl X-Received: by 2002:aa7:c70c:: with SMTP id i12mr5500177edq.256.1630000485902; Thu, 26 Aug 2021 10:54:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630000485; cv=none; d=google.com; s=arc-20160816; b=paxeB9iMNnqZwe+yGQ2RP1hyFm1qe6keR2Mz2HVA4Xgi8MYmUsGoeeMnvP+JqfL/G6 5Je4bOM8L2W+o90o96q4qFhUu1rozbs5igOT1EFRHbdpVXCHFK3Ih8YHZGSBPR1Z097r SNakQsyl5AwgO3MfFXwwlRoRKnaYEm7Zs7EtTAu01jHfZo6aIhxPz4diBtLnuAGi7cD+ GEU0i646oXyQ6Rikg5ZoQDZh1t9MtDu/4g5KuUzdlYbeISCwBOSG1UDnKoKO2WPOy6R+ N6WYXEd5j2GgtP6I8oryAe6B4WpnjRWgdif5ZeJ63cfMxuY5SQ6ZIiaMTkLmEo0GCEET mF4Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=Ms1THTN9X5h1AQHqSmfMy9VX620TcyQTHWCRP9GEJs0=; b=pqYuPMXHdIXmP/G4QdHpJ+ZnLgDht96cExjFdEdX/kRF3r+yuqaKCO0XnKkHvZHQdf KYcQIJBnnws4NSEydVJn879lQbhHHiRoDIQmHsxxSllaLB61njM2+9Q4zP+vosQzHdQ0 Y/HwgEBMW3R1dbAYr9IP7i8AbrVGGI8goRY0IITR7i4PrFVqv1R+oopsqw372B46w9hh cTTGZbucUA2cBEkEAZospMdprz9gppkxrJuAMPQbXpALGsjOTLdIt/E65Yv2XPdEF2GU epaQkHsRnFY1zDbJXFpD5WRn3YJCkAIQp+QKbA6pgTtaMOCR00M0WzSS3ERaUxKtK3HX 6GIw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z23si2770673ejl.612.2021.08.26.10.54.17; Thu, 26 Aug 2021 10:54:45 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243215AbhHZRw2 (ORCPT + 99 others); Thu, 26 Aug 2021 13:52:28 -0400 Received: from foss.arm.com ([217.140.110.172]:51222 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243206AbhHZRw1 (ORCPT ); Thu, 26 Aug 2021 13:52:27 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DF38131B; Thu, 26 Aug 2021 10:51:39 -0700 (PDT) Received: from localhost (unknown [10.1.198.34]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7FD243F5A1; Thu, 26 Aug 2021 10:51:39 -0700 (PDT) Date: Thu, 26 Aug 2021 18:51:38 +0100 From: Ionela Voinescu To: "Rafael J. Wysocki" Cc: Sudeep Holla , "Rafael J . Wysocki" , Thomas Gleixner , Ingo Molnar , Giovanni Gherdovich , Catalin Marinas , Will Deacon , Valentin Schneider , Dietmar Eggemann , Sean Kelley , Linux Kernel Mailing List , ACPI Devel Maling List , Linux ARM Subject: Re: [PATCH v2 2/3] arch_topology: obtain cpu capacity using information from CPPC Message-ID: <20210826175138.GA22165@arm.com> References: <20210824105651.28660-1-ionela.voinescu@arm.com> <20210824105651.28660-3-ionela.voinescu@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.4 (2018-02-28) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Thanks for the review, Rafael! On Wednesday 25 Aug 2021 at 19:54:26 (+0200), Rafael J. Wysocki wrote: > On Tue, Aug 24, 2021 at 12:57 PM Ionela Voinescu > wrote: > > > > Define topology_init_cpu_capacity_cppc() to use highest performance > > values from _CPC objects to obtain and set maximum capacity information > > for each CPU. acpi_cppc_processor_probe() is a good point at which to > > trigger the initialization of CPU (u-arch) capacity values, as at this > > point the highest performance values can be obtained from each CPU's > > _CPC objects. Architectures can therefore use this functionality > > through arch_init_invariance_cppc(). > > > > The performance scale used by CPPC is a unified scale for all CPUs in > > the system. Therefore, by obtaining the raw highest performance values > > from the _CPC objects, and normalizing them on the [0, 1024] capacity > > scale, used by the task scheduler, we obtain the CPU capacity of each > > CPU. > > > > While an ACPI Notify(0x85) could alert about a change in the highest > > performance value, which should in turn retrigger the CPU capacity > > computations, this notification is not currently handled by the ACPI > > processor driver. When supported, a call to arch_init_invariance_cppc() > > would perform the update. > > > > Signed-off-by: Ionela Voinescu > > Tested-by: Valentin Schneider > > Cc: Sudeep Holla > > --- > > drivers/base/arch_topology.c | 37 +++++++++++++++++++++++++++++++++++ > > include/linux/arch_topology.h | 4 ++++ > > 2 files changed, 41 insertions(+) > > > > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > > index 921312a8d957..358e22cd629e 100644 > > --- a/drivers/base/arch_topology.c > > +++ b/drivers/base/arch_topology.c > > @@ -306,6 +306,43 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) > > return !ret; > > } > > > > +#ifdef CONFIG_ACPI_CPPC_LIB > > +#include > > + > > +void topology_init_cpu_capacity_cppc(void) > > +{ > > + struct cppc_perf_caps perf_caps; > > + int cpu; > > + > > + if (likely(acpi_disabled || !acpi_cpc_valid())) > > + return; > > + > > + raw_capacity = kcalloc(num_possible_cpus(), sizeof(*raw_capacity), > > + GFP_KERNEL); > > + if (!raw_capacity) > > + return; > > + > > + for_each_possible_cpu(cpu) { > > + if (!cppc_get_perf_caps(cpu, &perf_caps)) { > > + raw_capacity[cpu] = perf_caps.highest_perf; > > From experience, I would advise doing some sanity checking on the > per_caps values before using them here. > cppc_get_perf_caps() already returns -EFAULT if highest_perf is 0, and I'm not sure if I can make any other assumptions about what a sane highest_perf value would need to be here. Did you have anything else in mind for sanity checking? > Also note that highest_perf may not be sustainable, so would using > highest_perf as raw_capacity[] always work as expected? > Yes, in my opinion using it is better than the alternative, using the nominal performance value. This highest performance value helps obtain the maximum capacity of a CPU on a scale [0, 1024] when referenced to the highest performance of the biggest CPU in the system. There is no assumption in the task scheduler that this capacity is sustainable. Using lower values (nominal performance) would shorten the scale and make smaller CPUs seem bigger than they are. Also, using highest performance gives a better indication of micro-architectural differences in performance between CPUs, which plays a role in scaling utilization, even if some of the performance levels are not sustainable (which is platform dependent). Thanks, Ionela. > > + pr_debug("cpu_capacity: CPU%d cpu_capacity=%u (raw).\n", > > + cpu, raw_capacity[cpu]); > > + } else { > > + pr_err("cpu_capacity: CPU%d missing highest performance.\n", cpu); > > + pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n"); > > + goto exit; > > + } > > + } > > + > > + topology_normalize_cpu_scale(); > > + schedule_work(&update_topology_flags_work); > > + pr_debug("cpu_capacity: cpu_capacity initialization done\n"); > > + > > +exit: > > + free_raw_capacity(); > > +} > > +#endif > > + > > #ifdef CONFIG_CPU_FREQ > > static cpumask_var_t cpus_to_visit; > > static void parsing_done_workfn(struct work_struct *work); > > diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h > > index f180240dc95f..9cf1a17938f0 100644 > > --- a/include/linux/arch_topology.h > > +++ b/include/linux/arch_topology.h > > @@ -11,6 +11,10 @@ > > void topology_normalize_cpu_scale(void); > > int topology_update_cpu_topology(void); > > > > +#ifdef CONFIG_ACPI_CPPC_LIB > > +void topology_init_cpu_capacity_cppc(void); > > +#endif > > + > > struct device_node; > > bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu); > > > > -- > > 2.29.2.dirty > >