From patchwork Wed Mar 10 11:02:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 396684 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp275622jai; Wed, 10 Mar 2021 03:03:22 -0800 (PST) X-Google-Smtp-Source: ABdhPJxZ0S7q1/TGKBOPzsNBrgGa8Bp6gZyuEZu0kezJQNuf24k5pcPwZoTlst6SFt0f5gMsTZN8 X-Received: by 2002:aa7:d987:: with SMTP id u7mr2558688eds.326.1615374202511; Wed, 10 Mar 2021 03:03:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615374202; cv=none; d=google.com; s=arc-20160816; b=HRwdowIHsfcaRAbfTO49wG8npeL4oqWkMOix6crg/zWBPEoE3VWupEf+mjiCY87Rjx FjBdN8QQaK6LYkSuFbG/eZ3x2WZYf51eguKabN1eiSjmlskLPCD6dfoE++6rG9szzw4o i8gRS4RJ3qcJC/i2zc48E3LEeZVay8ywd5TeddNA8dzinqSZiKspYHwq9mTPU7Hq4CSU s2IyKsYr97NtOG8UpWpqfif35SnylSZr1eL0wuDIWUmu0F8X+cMa/gW6RItA3QLFE7Fk oBk/CKFNWDZ+guydArtSZh+fnGgXmrFVjagMZkMVFHMB7U53n7p7VTP0vvgZP//WYwVU icWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from :dkim-signature; bh=GoTOdV/s4l3cqoypT5zUMlfkcoLLVwoOXrCw3mPvlog=; b=hHlQkKDBWCu5EWX86ikg+XvmJnqp27VQIIs07NNCBOjMV+DLHLLUcnrVfBNunuaTOw x8APpmDGKYfEqxPhBYqmaBF/FFuKu542fLfx6tVRozCAimUmcWkauGsBC4Vs1rE2HZnF JM9TffcXiPiORXjXw5BYL7Mm8g3OToNkGt7KCo9j1GWRE12p1BxkXEuA0Q5bj2Ebmg3n x1/L3ET9LPq0bIPl0mi9XHjlJUlkavLhJ5C3uSJm7Wu10rcGAXCVuIiQ+5t5ss/Rjk8v oVQlHY0yQQxEl1vXU1stoxbyzif0af3OnN/0zT9yJ/9Mmw4fKkBwppuo5h+R256WMOIH 7PdQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="uOU9Sa/m"; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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. [23.128.96.18]) by mx.google.com with ESMTP id a19si11675468ejt.403.2021.03.10.03.03.22; Wed, 10 Mar 2021 03:03:22 -0800 (PST) Received-SPF: pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="uOU9Sa/m"; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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 S232130AbhCJLCr (ORCPT + 7 others); Wed, 10 Mar 2021 06:02:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229948AbhCJLCR (ORCPT ); Wed, 10 Mar 2021 06:02:17 -0500 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 74215C06174A for ; Wed, 10 Mar 2021 03:02:17 -0800 (PST) Received: by mail-wm1-x331.google.com with SMTP id j4-20020a05600c4104b029010c62bc1e20so10443001wmi.3 for ; Wed, 10 Mar 2021 03:02:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=GoTOdV/s4l3cqoypT5zUMlfkcoLLVwoOXrCw3mPvlog=; b=uOU9Sa/mjY/3sXsnoYbiqGp9UIKMUW0BUC06cPp7cLe8Kr46RE3DYMtrZXGJ4zyIrm 3oc9Od8g2jWBzaWwhJ9ZYAWVp7kFeO4BVykV3vksRJMbCggewFbTvTrdFZEy+LsiL2PK SnLu+OPSVXHNblBmFBaWTu4WgY4sCzN7/Ln/BvPBkFE1nkPE+VLXl2QwDITcZeUKkzXA 0S0wcHGGDowY87XpMSnZAbLQhmmOyN43lWWn55WcNNwNJQnskuJEqAWbmv/056ykB8V+ 827KPrcQkUsYOtYlaOvKB26koeBEuAMt96Wc9H5xxuzRGtFefyVC1W2lJSIOHTxnZirJ +h0A== 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=GoTOdV/s4l3cqoypT5zUMlfkcoLLVwoOXrCw3mPvlog=; b=YxbxGt89P1UHNucEjDNsE4z6x7ytkmr/X6NoAMCN6Fhxf3r18D0KiJ3Nw9w38ZjWJi QFl+YuKMmcHONQ8bURTxsyv3113oCGIPMA1l515XxWsw4ADa3IKxd7Xz7aVWCKQmw9Ax ITAQSzcjpzKt39Hk8okQuJeR1ErHHQnjtxKYn/lRpZ9lRuW9d2FmORnOTb819ewDlhsH RYFhFlFEw+dR3k8ZP/TfjM6Jk9uQXNLLcaBphpK5lnj5qTyytfqUJOyrEKoe6dqoioHU OM9TislwiOadahxopl8J5jjosSHagZZeXv7ewXwBoQ321kV6rAja7No1WLYXbJ/OAiUB aIPQ== X-Gm-Message-State: AOAM533aLkz/S5l580VIV+J8P1u363gTBGNNfyXozyyxTvuWZ+p9r2y1 CZqNZVTLo5/a4zgTgXs2HPgpDQ== X-Received: by 2002:a7b:c087:: with SMTP id r7mr2778455wmh.110.1615374136103; Wed, 10 Mar 2021 03:02:16 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id k4sm36193902wrd.9.2021.03.10.03.02.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Mar 2021 03:02:15 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com Subject: [PATCH v3 1/5] powercap/drivers/dtpm: Encapsulate even more the code Date: Wed, 10 Mar 2021 12:02:08 +0100 Message-Id: <20210310110212.26512-1-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org In order to increase the self-encapsulation of the dtpm generic code, the following changes are adding a power update ops to the dtpm ops. That allows the generic code to call directly the dtpm backend function to update the power values. The power update function does compute the power characteristics when the function is invoked. In the case of the CPUs, the power consumption depends on the number of online CPUs. The online CPUs mask is not up to date at CPUHP_AP_ONLINE_DYN state in the tear down callback. That is the reason why the online / offline are at separate state. As there is already an existing state for DTPM, this one is only moved to the DEAD state, so there is no addition of new state with these changes. The dtpm node is not removed when the cpu is unplugged. That simplifies the code for the next changes and results in a more self-encapsulated code. Signed-off-by: Daniel Lezcano --- V2: - Updated the changelog with the CPU node not being removed - Commented the cpu hotplug callbacks to explain why there are two callbacks - Changed 'upt_power_uw' to 'update_power_uw' - Removed unused cpumask variable --- drivers/powercap/dtpm.c | 54 ++++++------- drivers/powercap/dtpm_cpu.c | 148 ++++++++++++++++-------------------- include/linux/cpuhotplug.h | 2 +- include/linux/dtpm.h | 3 +- 4 files changed, 97 insertions(+), 110 deletions(-) -- 2.17.1 Reviewed-by: Lukasz Luba diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index c2185ec5f887..58433b8ef9a1 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -116,8 +116,6 @@ static void __dtpm_sub_power(struct dtpm *dtpm) parent->power_limit -= dtpm->power_limit; parent = parent->parent; } - - __dtpm_rebalance_weight(root); } static void __dtpm_add_power(struct dtpm *dtpm) @@ -130,45 +128,45 @@ static void __dtpm_add_power(struct dtpm *dtpm) parent->power_limit += dtpm->power_limit; parent = parent->parent; } +} + +static int __dtpm_update_power(struct dtpm *dtpm) +{ + int ret; + + __dtpm_sub_power(dtpm); - __dtpm_rebalance_weight(root); + ret = dtpm->ops->update_power_uw(dtpm); + if (ret) + pr_err("Failed to update power for '%s': %d\n", + dtpm->zone.name, ret); + + if (!test_bit(DTPM_POWER_LIMIT_FLAG, &dtpm->flags)) + dtpm->power_limit = dtpm->power_max; + + __dtpm_add_power(dtpm); + + if (root) + __dtpm_rebalance_weight(root); + + return ret; } /** * dtpm_update_power - Update the power on the dtpm * @dtpm: a pointer to a dtpm structure to update - * @power_min: a u64 representing the new power_min value - * @power_max: a u64 representing the new power_max value * * Function to update the power values of the dtpm node specified in * parameter. These new values will be propagated to the tree. * * Return: zero on success, -EINVAL if the values are inconsistent */ -int dtpm_update_power(struct dtpm *dtpm, u64 power_min, u64 power_max) +int dtpm_update_power(struct dtpm *dtpm) { - int ret = 0; + int ret; mutex_lock(&dtpm_lock); - - if (power_min == dtpm->power_min && power_max == dtpm->power_max) - goto unlock; - - if (power_max < power_min) { - ret = -EINVAL; - goto unlock; - } - - __dtpm_sub_power(dtpm); - - dtpm->power_min = power_min; - dtpm->power_max = power_max; - if (!test_bit(DTPM_POWER_LIMIT_FLAG, &dtpm->flags)) - dtpm->power_limit = power_max; - - __dtpm_add_power(dtpm); - -unlock: + ret = __dtpm_update_power(dtpm); mutex_unlock(&dtpm_lock); return ret; @@ -436,6 +434,7 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) if (dtpm->ops && !(dtpm->ops->set_power_uw && dtpm->ops->get_power_uw && + dtpm->ops->update_power_uw && dtpm->ops->release)) return -EINVAL; @@ -455,7 +454,8 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) root = dtpm; } - __dtpm_add_power(dtpm); + if (dtpm->ops && !dtpm->ops->update_power_uw(dtpm)) + __dtpm_add_power(dtpm); pr_info("Registered dtpm node '%s' / %llu-%llu uW, \n", dtpm->zone.name, dtpm->power_min, dtpm->power_max); diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 51c366938acd..cfb120280887 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -14,6 +14,8 @@ * The CPU hotplug is supported and the power numbers will be updated * if a CPU is hot plugged / unplugged. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -23,8 +25,6 @@ #include #include -static struct dtpm *__parent; - static DEFINE_PER_CPU(struct dtpm *, dtpm_per_cpu); struct dtpm_cpu { @@ -32,57 +32,16 @@ struct dtpm_cpu { int cpu; }; -/* - * When a new CPU is inserted at hotplug or boot time, add the power - * contribution and update the dtpm tree. - */ -static int power_add(struct dtpm *dtpm, struct em_perf_domain *em) -{ - u64 power_min, power_max; - - power_min = em->table[0].power; - power_min *= MICROWATT_PER_MILLIWATT; - power_min += dtpm->power_min; - - power_max = em->table[em->nr_perf_states - 1].power; - power_max *= MICROWATT_PER_MILLIWATT; - power_max += dtpm->power_max; - - return dtpm_update_power(dtpm, power_min, power_max); -} - -/* - * When a CPU is unplugged, remove its power contribution from the - * dtpm tree. - */ -static int power_sub(struct dtpm *dtpm, struct em_perf_domain *em) -{ - u64 power_min, power_max; - - power_min = em->table[0].power; - power_min *= MICROWATT_PER_MILLIWATT; - power_min = dtpm->power_min - power_min; - - power_max = em->table[em->nr_perf_states - 1].power; - power_max *= MICROWATT_PER_MILLIWATT; - power_max = dtpm->power_max - power_max; - - return dtpm_update_power(dtpm, power_min, power_max); -} - static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) { struct dtpm_cpu *dtpm_cpu = dtpm->private; - struct em_perf_domain *pd; + struct em_perf_domain *pd = em_cpu_get(dtpm_cpu->cpu); struct cpumask cpus; unsigned long freq; u64 power; int i, nr_cpus; - pd = em_cpu_get(dtpm_cpu->cpu); - cpumask_and(&cpus, cpu_online_mask, to_cpumask(pd->cpus)); - nr_cpus = cpumask_weight(&cpus); for (i = 0; i < pd->nr_perf_states; i++) { @@ -113,6 +72,7 @@ static u64 get_pd_power_uw(struct dtpm *dtpm) pd = em_cpu_get(dtpm_cpu->cpu); freq = cpufreq_quick_get(dtpm_cpu->cpu); + cpumask_and(&cpus, cpu_online_mask, to_cpumask(pd->cpus)); nr_cpus = cpumask_weight(&cpus); @@ -128,6 +88,27 @@ static u64 get_pd_power_uw(struct dtpm *dtpm) return 0; } +static int update_pd_power_uw(struct dtpm *dtpm) +{ + struct dtpm_cpu *dtpm_cpu = dtpm->private; + struct em_perf_domain *em = em_cpu_get(dtpm_cpu->cpu); + struct cpumask cpus; + int nr_cpus; + + cpumask_and(&cpus, cpu_online_mask, to_cpumask(em->cpus)); + nr_cpus = cpumask_weight(&cpus); + + dtpm->power_min = em->table[0].power; + dtpm->power_min *= MICROWATT_PER_MILLIWATT; + dtpm->power_min *= nr_cpus; + + dtpm->power_max = em->table[em->nr_perf_states - 1].power; + dtpm->power_max *= MICROWATT_PER_MILLIWATT; + dtpm->power_max *= nr_cpus; + + return 0; +} + static void pd_release(struct dtpm *dtpm) { struct dtpm_cpu *dtpm_cpu = dtpm->private; @@ -139,39 +120,24 @@ static void pd_release(struct dtpm *dtpm) } static struct dtpm_ops dtpm_ops = { - .set_power_uw = set_pd_power_limit, - .get_power_uw = get_pd_power_uw, - .release = pd_release, + .set_power_uw = set_pd_power_limit, + .get_power_uw = get_pd_power_uw, + .update_power_uw = update_pd_power_uw, + .release = pd_release, }; static int cpuhp_dtpm_cpu_offline(unsigned int cpu) { - struct cpufreq_policy *policy; struct em_perf_domain *pd; struct dtpm *dtpm; - policy = cpufreq_cpu_get(cpu); - - if (!policy) - return 0; - pd = em_cpu_get(cpu); if (!pd) return -EINVAL; dtpm = per_cpu(dtpm_per_cpu, cpu); - power_sub(dtpm, pd); - - if (cpumask_weight(policy->cpus) != 1) - return 0; - - for_each_cpu(cpu, policy->related_cpus) - per_cpu(dtpm_per_cpu, cpu) = NULL; - - dtpm_unregister(dtpm); - - return 0; + return dtpm_update_power(dtpm); } static int cpuhp_dtpm_cpu_online(unsigned int cpu) @@ -184,7 +150,6 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) int ret = -ENOMEM; policy = cpufreq_cpu_get(cpu); - if (!policy) return 0; @@ -194,7 +159,7 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) dtpm = per_cpu(dtpm_per_cpu, cpu); if (dtpm) - return power_add(dtpm, pd); + return dtpm_update_power(dtpm); dtpm = dtpm_alloc(&dtpm_ops); if (!dtpm) @@ -210,27 +175,20 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) for_each_cpu(cpu, policy->related_cpus) per_cpu(dtpm_per_cpu, cpu) = dtpm; - sprintf(name, "cpu%d", dtpm_cpu->cpu); + sprintf(name, "cpu%d-cpufreq", dtpm_cpu->cpu); - ret = dtpm_register(name, dtpm, __parent); + ret = dtpm_register(name, dtpm, NULL); if (ret) goto out_kfree_dtpm_cpu; - ret = power_add(dtpm, pd); - if (ret) - goto out_dtpm_unregister; - ret = freq_qos_add_request(&policy->constraints, &dtpm_cpu->qos_req, FREQ_QOS_MAX, pd->table[pd->nr_perf_states - 1].frequency); if (ret) - goto out_power_sub; + goto out_dtpm_unregister; return 0; -out_power_sub: - power_sub(dtpm, pd); - out_dtpm_unregister: dtpm_unregister(dtpm); dtpm_cpu = NULL; @@ -248,10 +206,38 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) int dtpm_register_cpu(struct dtpm *parent) { - __parent = parent; + int ret; + + /* + * The callbacks at CPU hotplug time are calling + * dtpm_update_power() which in turns calls update_pd_power(). + * + * The function update_pd_power() uses the online mask to + * figure out the power consumption limits. + * + * At CPUHP_AP_ONLINE_DYN, the CPU is present in the CPU + * online mask when the cpuhp_dtpm_cpu_online function is + * called, but the CPU is still in the online mask for the + * tear down callback. So the power can not be updated when + * the CPU is unplugged. + * + * At CPUHP_AP_DTPM_CPU_DEAD, the situation is the opposite as + * above. The CPU online mask is not up to date when the CPU + * is plugged in. + * + * For this reason, we need to call the online and offline + * callbacks at different moments when the CPU online mask is + * consistent with the power numbers we want to update. + */ + ret = cpuhp_setup_state(CPUHP_AP_DTPM_CPU_DEAD, "dtpm_cpu:offline", + NULL, cpuhp_dtpm_cpu_offline); + if (ret < 0) + return ret; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "dtpm_cpu:online", + cpuhp_dtpm_cpu_online, NULL); + if (ret < 0) + return ret; - return cpuhp_setup_state(CPUHP_AP_DTPM_CPU_ONLINE, - "dtpm_cpu:online", - cpuhp_dtpm_cpu_online, - cpuhp_dtpm_cpu_offline); + return 0; } diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index ee09a39627d6..fcb2967fb5ba 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -61,6 +61,7 @@ enum cpuhp_state { CPUHP_LUSTRE_CFS_DEAD, CPUHP_AP_ARM_CACHE_B15_RAC_DEAD, CPUHP_PADATA_DEAD, + CPUHP_AP_DTPM_CPU_DEAD, CPUHP_WORKQUEUE_PREP, CPUHP_POWER_NUMA_PREPARE, CPUHP_HRTIMERS_PREPARE, @@ -193,7 +194,6 @@ enum cpuhp_state { CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30, CPUHP_AP_X86_HPET_ONLINE, CPUHP_AP_X86_KVM_CLK_ONLINE, - CPUHP_AP_DTPM_CPU_ONLINE, CPUHP_AP_ACTIVE, CPUHP_ONLINE, }; diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index e80a332e3d8a..acf8d3638988 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -29,6 +29,7 @@ struct dtpm { struct dtpm_ops { u64 (*set_power_uw)(struct dtpm *, u64); u64 (*get_power_uw)(struct dtpm *); + int (*update_power_uw)(struct dtpm *); void (*release)(struct dtpm *); }; @@ -62,7 +63,7 @@ static inline struct dtpm *to_dtpm(struct powercap_zone *zone) return container_of(zone, struct dtpm, zone); } -int dtpm_update_power(struct dtpm *dtpm, u64 power_min, u64 power_max); +int dtpm_update_power(struct dtpm *dtpm); int dtpm_release_zone(struct powercap_zone *pcz); From patchwork Wed Mar 10 11:02:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 396688 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp275690jai; Wed, 10 Mar 2021 03:03:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJxACpAEiSEvfCEGSvGKhCyLV/88U2kRyl6oZcfJIXz6xr+fN/VcNF99Ee65tktORNgR6d4I X-Received: by 2002:aa7:d4d2:: with SMTP id t18mr2576501edr.342.1615374207422; Wed, 10 Mar 2021 03:03:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615374207; cv=none; d=google.com; s=arc-20160816; b=D+bLwyL5KdnNAFVdVwOYJs1B45jUU/6WAKgzIj6HVQRwODapBXAMY7z9bFTWYb9XvG O62lP0LXjOpoDL/PH6VBIUJvqu4FbSJwPlriWTDsMhK83fQCBHLpMjZgxB0R9kNPelx7 m2g04s04UbuD+ttiel6rPZM5A0CERH3wvYk3MEqdgcGgOSpJ4ctxeBr+LPIr8avAFkfR Of4b4r4u4sZzLqQB16+ItxXBLnSvxbimOh+2Grp0Du6W8K1Ta0a4r0eP5m1VtM44UMet GaqQ4lBbGUN3fRxshn2qkoCZwLOzriLrBAz9Z5A9K8jpbmsChHkztcyx8Y+6XFZYCxgi CvGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=84rQ3NvsOhm26IexTySRGDCIz117SxZ//6BzkM58sV8=; b=zo6JcDmhNoJY4St/UIGSOJmO0lexFuf+58y9IVYSLe5tAMStI/UELiUyhDSvATRF1I mpBQA+aoo3xQTW5CMEh/YTdA5nNGTta/A+NUPwmPal6s98wKLlKQwK2EpLBnIBOs2JZy KlRDfcNf7k6RBcxya0YTqPtnORskCsWsrcUWwxncdr2fcBRZN7lsCs0FbDekUViBN4t2 xs0ZRs9qQI45yN6AqF8E7lzxXtghXSniQUvweO/Qvodu6Gp4bboLaki7+ycI2sLIdPwp ijEgPcFic/PZktj0TRVH2NFppLzqwa/o/g9yQ15Bbx6xxNGs6f1hGcmBsTpOx2IGO1wp mEkQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=TlYjWVQ7; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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. [23.128.96.18]) by mx.google.com with ESMTP id a19si11675468ejt.403.2021.03.10.03.03.27; Wed, 10 Mar 2021 03:03:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=TlYjWVQ7; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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 S232425AbhCJLCs (ORCPT + 7 others); Wed, 10 Mar 2021 06:02:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231788AbhCJLCT (ORCPT ); Wed, 10 Mar 2021 06:02:19 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2166C061760 for ; Wed, 10 Mar 2021 03:02:18 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id i9so6834918wml.0 for ; Wed, 10 Mar 2021 03:02:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=84rQ3NvsOhm26IexTySRGDCIz117SxZ//6BzkM58sV8=; b=TlYjWVQ7uqFoVMul5rvcscdQXpDF2ylRezJ9hGGMzODMajbAiD9WDyPhgPRGee5C7L Oei/498Kl/13Y5TtA65sW5klDGRIJnHnxkmW0VIekYZMNiAwVJvNENFAlEe3lTyeqFIc ftFLatgmW/F8WzGOAoepse8r48vuolSdO7t/ClahnGD4+ZWUKEtesF+wpc7/jnpFb1FX Uq3jOBUw2JOpZDdTXskFLSC0R8xHAzn+mqr1spbvZR4qPHdxLxTKbQfU8YekuNn+VGZG DxrWxVVmAKog1nbwIPy0NTrU/8txi1ml+MXh8cvp5n9ZXddig2cn0rYw89pqS5RMQ+M0 ID+g== 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:in-reply-to :references; bh=84rQ3NvsOhm26IexTySRGDCIz117SxZ//6BzkM58sV8=; b=E81CtpPqOaVW/zrrTfipPXR5ZApZNa9Jio/U/fb7vZK3KyrTV8JFmD6uBq3VtjCAN5 ZJn+mYXs1Y/W9zWf0yeVUbX0LhRBZLEY33oEAY1tHPYWRnWbqjEPSdQhTiZGbOcaLknl 1HbpeH/3YW+heWlyoJ+yTGXw895ue/NlFrZX+Ar2WcGG3Xy4IqIXmtCa59W40z4G8mtM ujQK0q+dBsR31dLkYANzKQM2q+2sYOXOCMnbnmHfjgb9AFc++iUfN8lRzBSb03zNXR3K liHaSxNTtopZ5GPodiCLlDqYaOZFwFiJLvdngmyRH+BukZyCoa5aU4eAlKcU+Nbpx4c4 WTkA== X-Gm-Message-State: AOAM532+fZ68FZ6Pqh2eFF0qwxeXM+aa1oluNIXAnE1hPACctAEI7yCk 8/FBEoC1CDa6pKVIxQ4jaFX+lQ== X-Received: by 2002:a05:600c:4f55:: with SMTP id m21mr2763784wmq.11.1615374137170; Wed, 10 Mar 2021 03:02:17 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id k4sm36193902wrd.9.2021.03.10.03.02.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Mar 2021 03:02:16 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com Subject: [PATCH v3 2/5] powercap/drivers/dtpm: Create a registering system Date: Wed, 10 Mar 2021 12:02:09 +0100 Message-Id: <20210310110212.26512-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210310110212.26512-1-daniel.lezcano@linaro.org> References: <20210310110212.26512-1-daniel.lezcano@linaro.org> Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org A SoC can be differently structured depending on the platform and the kernel can not be aware of all the combinations, as well as the specific tweaks for a particular board. The creation of the hierarchy must be delegated to userspace. These changes provide a registering mechanism where the different subsystems will initialize their dtpm backends and register with a name the dtpm node in a list. The next changes will provide an userspace interface to create hierachically the different nodes. Those will be created by name and found via the list filled by the different subsystem. If a specified name is not found in the list, it is assumed to be a virtual node which will have children and the default is to allocate such node. When the node register in the list, the function will be dtpm_register where the previous semantic was to create the node. Thus, the functions are renamed to reflect their purpose. Signed-off-by: Daniel Lezcano --- V2: - Fixed error code path by dropping lock --- drivers/powercap/dtpm.c | 161 ++++++++++++++++++++++++++++++++++-- drivers/powercap/dtpm_cpu.c | 4 +- include/linux/dtpm.h | 12 ++- 3 files changed, 164 insertions(+), 13 deletions(-) -- 2.17.1 Reviewed-by: Lukasz Luba diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index 58433b8ef9a1..d00f55f0ee30 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,14 @@ static DEFINE_MUTEX(dtpm_lock); static struct powercap_control_type *pct; static struct dtpm *root; +struct dtpm_node { + const char *name; + struct dtpm *dtpm; + struct list_head node; +}; + +static LIST_HEAD(dtpm_list); + static int get_time_window_us(struct powercap_zone *pcz, int cid, u64 *window) { return -ENOSYS; @@ -152,6 +161,138 @@ static int __dtpm_update_power(struct dtpm *dtpm) return ret; } +static struct dtpm *__dtpm_lookup(const char *name) +{ + struct dtpm_node *node; + + list_for_each_entry(node, &dtpm_list, node) { + if (!strcmp(name, node->name)) + return node->dtpm; + } + + return NULL; +} + +/** + * dtpm_get - Get a reference to a dtpm structure + * @name: the name of the dtpm device + * + * The function looks up in the list of the registered dtpm + * devices. If the dtpm device is not found, a virtual one is + * allocated. This function must be called to create a dtpm node in + * the powercap hierarchy. + * + * Return: a pointer to a dtpm structure, NULL if there is not enough + * memory + */ +struct dtpm *dtpm_get(const char *name) +{ + struct dtpm *dtpm; + + mutex_lock(&dtpm_lock); + dtpm = __dtpm_lookup(name); + if (!dtpm) + dtpm = dtpm_alloc(NULL); + else + kref_get(&dtpm->kref); + mutex_unlock(&dtpm_lock); + + return dtpm; +} + +static void dtpm_release(struct kref *kref) +{ + struct dtpm *dtpm = container_of(kref, struct dtpm, kref); + + kfree(dtpm); +} + +/** + * dtpm_put - Release a reference on a dtpm device + * @dtpm: a pointer to a dtpm structure + * + * Release the reference on the specified dtpm device. The last + * reference leads to a memory release. + */ +void dtpm_put(struct dtpm *dtpm) +{ + kref_put(&dtpm->kref, dtpm_release); +} + +/** + * dtpm_register - Register the dtpm in the dtpm list + * @name: a name used as an identifier + * @dtpm: the dtpm node to be registered + * + * Stores the dtpm device in a list. + * + * Return: 0 on success, -EEXIST if the device name is already present + * in the list, -ENOMEM in case of memory allocation failure. + */ +int dtpm_register(const char *name, struct dtpm *dtpm) +{ + struct dtpm_node *node; + int ret; + + mutex_lock(&dtpm_lock); + + ret = -EEXIST; + if (__dtpm_lookup(name)) + goto out_unlock; + + ret = -ENOMEM; + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + goto out_unlock; + + node->name = kstrdup(name, GFP_KERNEL); + if (!node->name) { + kfree(node); + goto out_unlock; + } + + node->dtpm = dtpm; + + list_add(&node->node, &dtpm_list); + + pr_info("Registered %s\n", name); + + ret = 0; +out_unlock: + mutex_unlock(&dtpm_lock); + + return ret; +} + +/** + * dtpm_unregister - Remove the dtpm device from the list + * @name: the dtpm device name to be removed + * + * Remove the dtpm device from the list of the registered devices. + */ +void dtpm_unregister(const char *name) +{ + struct dtpm_node *node; + + mutex_lock(&dtpm_lock); + + list_for_each_entry(node, &dtpm_list, node) { + + if (strcmp(name, node->name)) + continue; + + list_del(&node->node); + kfree(node->name); + kfree(node); + + pr_info("Unregistered %s\n", name); + + break; + } + + mutex_unlock(&dtpm_lock); +} + /** * dtpm_update_power - Update the power on the dtpm * @dtpm: a pointer to a dtpm structure to update @@ -208,7 +349,7 @@ int dtpm_release_zone(struct powercap_zone *pcz) if (root == dtpm) root = NULL; - kfree(dtpm); + dtpm_put(dtpm); return 0; } @@ -370,6 +511,7 @@ struct dtpm *dtpm_alloc(struct dtpm_ops *ops) if (dtpm) { INIT_LIST_HEAD(&dtpm->children); INIT_LIST_HEAD(&dtpm->sibling); + kref_init(&dtpm->kref); dtpm->weight = 1024; dtpm->ops = ops; } @@ -378,28 +520,29 @@ struct dtpm *dtpm_alloc(struct dtpm_ops *ops) } /** - * dtpm_unregister - Unregister a dtpm node from the hierarchy tree - * @dtpm: a pointer to a dtpm structure corresponding to the node to be removed + * dtpm_destroy - Destroy a dtpm node from the hierarchy tree + * @dtpm: a pointer to a dtpm structure corresponding to the node to be + * removed and destroyed * * Call the underlying powercap unregister function. That will call * the release callback of the powercap zone. */ -void dtpm_unregister(struct dtpm *dtpm) +void dtpm_destroy(struct dtpm *dtpm) { powercap_unregister_zone(pct, &dtpm->zone); - pr_info("Unregistered dtpm node '%s'\n", dtpm->zone.name); + pr_info("Destroyed dtpm node '%s'\n", dtpm->zone.name); } /** - * dtpm_register - Register a dtpm node in the hierarchy tree + * dtpm_create - Create a dtpm node in the hierarchy tree * @name: a string specifying the name of the node * @dtpm: a pointer to a dtpm structure corresponding to the new node * @parent: a pointer to a dtpm structure corresponding to the parent node * * Create a dtpm node in the tree. If no parent is specified, the node * is the root node of the hierarchy. If the root node already exists, - * then the registration will fail. The powercap controller must be + * then the creation will fail. The powercap controller must be * initialized before calling this function. * * The dtpm structure must be initialized with the power numbers @@ -413,7 +556,7 @@ void dtpm_unregister(struct dtpm *dtpm) * * parent have ops which are reserved for leaves * Other negative values are reported back from the powercap framework */ -int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) +int dtpm_create(const char *name, struct dtpm *dtpm, struct dtpm *parent) { struct powercap_zone *pcz; @@ -457,7 +600,7 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) if (dtpm->ops && !dtpm->ops->update_power_uw(dtpm)) __dtpm_add_power(dtpm); - pr_info("Registered dtpm node '%s' / %llu-%llu uW, \n", + pr_info("Created dtpm node '%s' / %llu-%llu uW, \n", dtpm->zone.name, dtpm->power_min, dtpm->power_max); mutex_unlock(&dtpm_lock); diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index cfb120280887..628d4d6d83a6 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -177,7 +177,7 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) sprintf(name, "cpu%d-cpufreq", dtpm_cpu->cpu); - ret = dtpm_register(name, dtpm, NULL); + ret = dtpm_register(name, dtpm); if (ret) goto out_kfree_dtpm_cpu; @@ -190,7 +190,7 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) return 0; out_dtpm_unregister: - dtpm_unregister(dtpm); + dtpm_unregister(name); dtpm_cpu = NULL; dtpm = NULL; diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index acf8d3638988..d724c5a7b2f4 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -14,6 +14,7 @@ struct dtpm { struct powercap_zone zone; + struct kref kref; struct dtpm *parent; struct list_head sibling; struct list_head children; @@ -69,10 +70,17 @@ int dtpm_release_zone(struct powercap_zone *pcz); struct dtpm *dtpm_alloc(struct dtpm_ops *ops); -void dtpm_unregister(struct dtpm *dtpm); +void dtpm_destroy(struct dtpm *dtpm); -int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent); +int dtpm_create(const char *name, struct dtpm *dtpm, struct dtpm *parent); int dtpm_register_cpu(struct dtpm *parent); +int dtpm_register(const char *name, struct dtpm *dtpm); + +void dtpm_unregister(const char *name); + +struct dtpm *dtpm_get(const char *name); + +void dtpm_put(struct dtpm *dtpm); #endif From patchwork Wed Mar 10 11:02:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 396687 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp275693jai; Wed, 10 Mar 2021 03:03:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJwI4eM1myiuEQqXijaIpgQEwcPTYX/hEp8UIsS1X46t41WfiWmiohnatw+8rTxFBjA/adD8 X-Received: by 2002:a17:907:94c3:: with SMTP id dn3mr2027922ejc.280.1615374207794; Wed, 10 Mar 2021 03:03:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615374207; cv=none; d=google.com; s=arc-20160816; b=PuE77QxtQwU6z9CptdG9P8IIGMlgkSgoqVozhfB2ihZpla7p7cGK0hDIFJciwvQ9cQ qCRAsVxK0U+BeVdIH5NnApgW7kI7ylIVezc27r7suVNM1UHd5f9P3ZCiP/GXW1E5mOnT VZPZLFnZj03es6JjaQ+qRqGgKeh2po0+SG7wN/njCbHq8KNjMCkJ+IWP/EKbojx/TKf8 dVJoXjqct7mf+Nur6Z6GKO4YZ9SeImMcM3aNSYxrtuZvocC7QV+HBLzTXhjOSAQGTLpC XAyOm1MCE96EHkzhymg2jjFiVWIAJ/zzvCfXntmvnm7UR+r5Dx6WVxSB5pOLeu/ygl02 3dSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=MUZ+0f1MMpnUEJ4a2J6EdFMV+wQUIe9TSPtGUldR/hk=; b=H6TDwDiAOmhgWjoaVjRXNbKoxFuejWIOF0dpo6Zk6TIMjfpYRX97qm/j/ZWIOOnb6i B04dwkvnjArqQbKcO7glhWKH9T6wFv7KKDR6cLmoX2NbTHPOu2Ns24UW/dmx2mXHZTcx hiSTHvQTEf1bYL1ooipAn4nGBHFEBrhGrA96QS6HHQnXQlvwivaQjBaZoVdrXKsaR6jk YxR34lst3p9NPWq+uoQ7KlxfA5i7CRajnxYBUvLKhoh2Avgn/nZcUabMUIarwF9zxT94 qRFOn98G/lfVas41vEjBO174Cua43rs2O6OVo41ZR9t5wBOgBMie6U8COiwew4ZD6Hsz WiTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=y0iHqhxG; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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. [23.128.96.18]) by mx.google.com with ESMTP id a19si11675468ejt.403.2021.03.10.03.03.27; Wed, 10 Mar 2021 03:03:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=y0iHqhxG; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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 S232318AbhCJLCr (ORCPT + 7 others); Wed, 10 Mar 2021 06:02:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231790AbhCJLCT (ORCPT ); Wed, 10 Mar 2021 06:02:19 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 689B1C061760 for ; Wed, 10 Mar 2021 03:02:19 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id e10so22790882wro.12 for ; Wed, 10 Mar 2021 03:02:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MUZ+0f1MMpnUEJ4a2J6EdFMV+wQUIe9TSPtGUldR/hk=; b=y0iHqhxGqdzHFL8wfLSo6jm347ZGXsAdHL8hB108DF0MgZmBNmJGhNXA3nURpmzP9R abp//oR3F9XH2AkwvGm73nfbIgpQ5etzjh0Iy1EDw44xa0meeCekCOBUUeGxOvHImon3 GGq2U58SzGoLG5oHyFNAfj6LUVigNi1tpWiQrq90ss6/AWkiBI9JbuohUa2uqpyNUXx5 bC2C5/FGogFcHndxS9gNeIpEVzFKLDix5JOaEa9yWuujb8OCyzSAFox7qres52K3tzhV QYmli1GxoGWk0moXdVCxiKThjzqL8+2sVES9lC0bGGfnRzycsD9c+U6WQBGAJaPw5NLE DmxQ== 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:in-reply-to :references; bh=MUZ+0f1MMpnUEJ4a2J6EdFMV+wQUIe9TSPtGUldR/hk=; b=TrxEOYv2qvJkDINRY6J3hKcBexEKXhjnjqo5QEkqpGwh4vCZ0wALKbtybkLiEdKv6E mn1NIk9HWnwelyz1xGXNCfbJivNRyt+zwIEgpN0q8scWyl8JyyrXBFS6GDqSdGSoMDXk wrDx9CfiEwbAs0UR4PtOiUEzmqdFaWFaFj3Gu8eyGIMKAdbmShp/FlxDy4jadQs89wdM tsD+iQR32XejeGXm8dioGb1FLFRXyL++X8ztr1l+jjXKYPv/0o2S9zNjmn0P0k7/Myqs SJ2F+IzfYCfFeRYXj8sdPU134kwtk7fylRK3BHWTY0ShWmsT+2VMXxoEG6NkFC0uqOH/ TtmQ== X-Gm-Message-State: AOAM533ywumGu1Vc5i960GDP5s8IEzJ3slxhVJ+r8VYa8f3WSd9Y9FuU zi149eBfwq8DwvXO8rYMNgABxw== X-Received: by 2002:adf:ed46:: with SMTP id u6mr2885348wro.350.1615374138108; Wed, 10 Mar 2021 03:02:18 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id k4sm36193902wrd.9.2021.03.10.03.02.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Mar 2021 03:02:17 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com Subject: [PATCH v3 3/5] powercap/drivers/dtpm: Simplify the dtpm table Date: Wed, 10 Mar 2021 12:02:10 +0100 Message-Id: <20210310110212.26512-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210310110212.26512-1-daniel.lezcano@linaro.org> References: <20210310110212.26512-1-daniel.lezcano@linaro.org> Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The dtpm table is an array of pointers, that forces the user of the table to define initdata along with the declaration of the table entry. It is more efficient to create an array of dtpm structure, so the declaration of the table entry can be done by initializing the different fields. Signed-off-by: Daniel Lezcano Reviewed-by: Lukasz Luba --- drivers/powercap/dtpm.c | 4 ++-- drivers/powercap/dtpm_cpu.c | 4 +++- include/linux/dtpm.h | 22 +++++++++------------- 3 files changed, 14 insertions(+), 16 deletions(-) -- 2.17.1 diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index d00f55f0ee30..74d9603bd42a 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -610,7 +610,7 @@ int dtpm_create(const char *name, struct dtpm *dtpm, struct dtpm *parent) static int __init dtpm_init(void) { - struct dtpm_descr **dtpm_descr; + struct dtpm_descr *dtpm_descr; pct = powercap_register_control_type(NULL, "dtpm", NULL); if (IS_ERR(pct)) { @@ -619,7 +619,7 @@ static int __init dtpm_init(void) } for_each_dtpm_table(dtpm_descr) - (*dtpm_descr)->init(*dtpm_descr); + dtpm_descr->init(); return 0; } diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 628d4d6d83a6..983f1ca27dc3 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -204,7 +204,7 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) return ret; } -int dtpm_register_cpu(struct dtpm *parent) +static int __init dtpm_cpu_init(void) { int ret; @@ -241,3 +241,5 @@ int dtpm_register_cpu(struct dtpm *parent) return 0; } + +DTPM_DECLARE(dtpm_cpu, dtpm_cpu_init); diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index d724c5a7b2f4..5f71ddc18ee9 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -34,25 +34,23 @@ struct dtpm_ops { void (*release)(struct dtpm *); }; -struct dtpm_descr; - -typedef int (*dtpm_init_t)(struct dtpm_descr *); +typedef int (*dtpm_init_t)(void); struct dtpm_descr { - struct dtpm *parent; - const char *name; dtpm_init_t init; }; /* Init section thermal table */ -extern struct dtpm_descr *__dtpm_table[]; -extern struct dtpm_descr *__dtpm_table_end[]; +extern struct dtpm_descr __dtpm_table[]; +extern struct dtpm_descr __dtpm_table_end[]; -#define DTPM_TABLE_ENTRY(name) \ - static typeof(name) *__dtpm_table_entry_##name \ - __used __section("__dtpm_table") = &name +#define DTPM_TABLE_ENTRY(name, __init) \ + static struct dtpm_descr __dtpm_table_entry_##name \ + __used __section("__dtpm_table") = { \ + .init = __init, \ + } -#define DTPM_DECLARE(name) DTPM_TABLE_ENTRY(name) +#define DTPM_DECLARE(name, init) DTPM_TABLE_ENTRY(name, init) #define for_each_dtpm_table(__dtpm) \ for (__dtpm = __dtpm_table; \ @@ -74,8 +72,6 @@ void dtpm_destroy(struct dtpm *dtpm); int dtpm_create(const char *name, struct dtpm *dtpm, struct dtpm *parent); -int dtpm_register_cpu(struct dtpm *parent); - int dtpm_register(const char *name, struct dtpm *dtpm); void dtpm_unregister(const char *name); From patchwork Wed Mar 10 11:02:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 396685 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp275634jai; Wed, 10 Mar 2021 03:03:23 -0800 (PST) X-Google-Smtp-Source: ABdhPJyOIIfhrL/BG8x6UTJd2QBMLzFZPOp6jTNCTznvACJgYRjvyiWTxreHN4er0q7Bl6CGnGgx X-Received: by 2002:a05:6402:32a:: with SMTP id q10mr2556847edw.15.1615374202892; Wed, 10 Mar 2021 03:03:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615374202; cv=none; d=google.com; s=arc-20160816; b=th1L3r2USsrNqEY8d0EVXRXDDX6+nAYghFOUGgGSdbWJAsNWdtB8S/hda0KJHLvyUJ Grj35xE89YoT7R7LnccWHEFnllymn5CZl6gkMrMmkZnILgqIgq9aRwZ+/Xz236jfCMIf aSl9S7QupJCBqcRZH01YSoI5kybmgIbyM0lvhddibAcqQ57QTlaVsshDTf1pmt/hcLnq 0WaTyu56IMRkyRqDdPKqgEWmYtElOj4cgUnrrPtjwux5OTFtty8h/Mjl130GtsMurqyu FUWzEI/5epkws7byyokVUIx78isq9m7W5EinLAJsuSJ0JdhaXLClddHFMxbMl8k+fOk0 iSag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=tGAdxc5Fb2RB7pZV+JmXUvhQNnyRCNFzDkDAeSmuI2Q=; b=Vn8VZ1g02nVbjfeW1OH2VzGyw7gnU7Rj5Ki+xJrcfbaJV4fXODa+pFDbzXX5/FbXZt YSAWont3eqgK8hkEq0SyyXPpNAysrEP9rwMKH2hxbKwCoPkMRWueY+jIAkQGr81/FxQA t/1KQ9969DyQIHQM9aA5o98QEzGwQrOqU6xAyV2uBKeOcupUr6gnzhWRbPFirpVXtUOE ZZ5dWVokyswVWChzLU2s4HjDgy6PbRph2UKDPG6Zb+AbRlV2tUYCggq2qcwHZ/NinWDU Y9MCjR7l2uqqP0OKvdKur5QYfHAduLrIS5roRTWMw9ad5H0fmLx8SbY3Iwcig4JcEwdO fvug== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=HRcp200V; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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. [23.128.96.18]) by mx.google.com with ESMTP id a19si11675468ejt.403.2021.03.10.03.03.22; Wed, 10 Mar 2021 03:03:22 -0800 (PST) Received-SPF: pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=HRcp200V; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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 S231228AbhCJLCs (ORCPT + 7 others); Wed, 10 Mar 2021 06:02:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43080 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231828AbhCJLCV (ORCPT ); Wed, 10 Mar 2021 06:02:21 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 94407C061761 for ; Wed, 10 Mar 2021 03:02:20 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id j2so22801046wrx.9 for ; Wed, 10 Mar 2021 03:02:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tGAdxc5Fb2RB7pZV+JmXUvhQNnyRCNFzDkDAeSmuI2Q=; b=HRcp200V8cJIq/KIQKB5usXavn2eG6oRm3TNQK1E41SRfEqvOPo3Z7WG3uKfTZjOrn ZjJYq5xQypTHV5YbppkC897cTQhzONM/+pmW5HQeVDVwg50OFm93Wab6VFfeb4aP8rGk deABqcK+FMItibPkAP61eOdbBWhdZw9k5lFPWzyFOhJ7EZpPVyyIDJOsvpWFN9TuInwL 6ZjuWt+YBnWVErrkH2FDABdDYV+RAtRbNiNQ2Zc75h5bdvHpJwF88/KSnhEVFqmc1Kvj 2BLCIRGvGRA+vjK1qHK0MRnl0PE+1H+Co+h7RTlupS0Y9VyjbHfRf5QDJtBZZJIYa7AA hKCQ== 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:in-reply-to :references; bh=tGAdxc5Fb2RB7pZV+JmXUvhQNnyRCNFzDkDAeSmuI2Q=; b=McDFS9td/NopLbr+RM57EbHaSniNvh0ISEn6nT2R/dW+h2Kzdm2JRKbwYxan3BxNWX tgcGyzCMMNi7wmDVGrzoFAtT2+7KoST0pWXfnNNt/xZJrJ+21w9EsmW/cg0bAtYKo7xM hZUCDIhdv1MG5FEkrN1+qKztSJFiJwO4WNi4H+pUZHQMydL7Pinrwnpe/1+bO54hr5Bb pcMMbg/6esM8KatjyOcsQ+5WiHwGTzgZlspyBaxcLDWwmopsBa2UUd234HixIbUZHFvJ decIcHizz6ih34hnruJdI7H5LzZa//oXrFpBi6LnuPL41npOqQud4+EOf/d0TdXVg1KB jFjQ== X-Gm-Message-State: AOAM530lwN8v9CdKV/a75iZJVOu2lzKbud0D9V6McNFvt1Bkoo4IButl Du+B5UgEZZFDtcj4tzAHayrhLE+sXva6Ig== X-Received: by 2002:a5d:52c2:: with SMTP id r2mr3024382wrv.40.1615374139204; Wed, 10 Mar 2021 03:02:19 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id k4sm36193902wrd.9.2021.03.10.03.02.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Mar 2021 03:02:18 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com Subject: [PATCH v3 4/5] powercap/drivers/dtpm: Use container_of instead of a private data field Date: Wed, 10 Mar 2021 12:02:11 +0100 Message-Id: <20210310110212.26512-4-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210310110212.26512-1-daniel.lezcano@linaro.org> References: <20210310110212.26512-1-daniel.lezcano@linaro.org> Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The dtpm framework provides an API to allocate a dtpm node. However when a backend dtpm driver needs to allocate a dtpm node it must define its own structure and store the pointer of this structure in the private field of the dtpm structure. It is more elegant to use the container_of macro and add the dtpm structure inside the dtpm backend specific structure. The code will be able to deal properly with the dtpm structure as a generic entity, making all this even more self-encapsulated. The dtpm_alloc() function does no longer make sense as the dtpm structure will be allocated when allocating the device specific dtpm structure. The dtpm_init() is provided instead. Signed-off-by: Daniel Lezcano Reviewed-by: Lukasz Luba --- drivers/powercap/dtpm.c | 27 ++++++++++------------ drivers/powercap/dtpm_cpu.c | 46 ++++++++++++++++++------------------- include/linux/dtpm.h | 3 +-- 3 files changed, 35 insertions(+), 41 deletions(-) -- 2.17.1 diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index 74d9603bd42a..a4784ac2f79b 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -191,10 +191,13 @@ struct dtpm *dtpm_get(const char *name) mutex_lock(&dtpm_lock); dtpm = __dtpm_lookup(name); - if (!dtpm) - dtpm = dtpm_alloc(NULL); - else + if (!dtpm) { + dtpm = kzalloc(sizeof(*dtpm), GFP_KERNEL); + if (dtpm) + dtpm_init(dtpm, NULL); + } else { kref_get(&dtpm->kref); + } mutex_unlock(&dtpm_lock); return dtpm; @@ -498,16 +501,12 @@ static struct powercap_zone_ops zone_ops = { }; /** - * dtpm_alloc - Allocate and initialize a dtpm struct - * @name: a string specifying the name of the node - * - * Return: a struct dtpm pointer, NULL in case of error + * dtpm_init - Allocate and initialize a dtpm struct + * @dtpm: The dtpm struct pointer to be initialized + * @ops: The dtpm device specific ops, NULL for a virtual node */ -struct dtpm *dtpm_alloc(struct dtpm_ops *ops) +void dtpm_init(struct dtpm *dtpm, struct dtpm_ops *ops) { - struct dtpm *dtpm; - - dtpm = kzalloc(sizeof(*dtpm), GFP_KERNEL); if (dtpm) { INIT_LIST_HEAD(&dtpm->children); INIT_LIST_HEAD(&dtpm->sibling); @@ -515,8 +514,6 @@ struct dtpm *dtpm_alloc(struct dtpm_ops *ops) dtpm->weight = 1024; dtpm->ops = ops; } - - return dtpm; } /** @@ -608,7 +605,7 @@ int dtpm_create(const char *name, struct dtpm *dtpm, struct dtpm *parent) return 0; } -static int __init dtpm_init(void) +static int __init init_dtpm(void) { struct dtpm_descr *dtpm_descr; @@ -623,4 +620,4 @@ static int __init dtpm_init(void) return 0; } -late_initcall(dtpm_init); +late_initcall(init_dtpm); diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 983f1ca27dc3..ac7f2e7e262f 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -25,16 +25,22 @@ #include #include -static DEFINE_PER_CPU(struct dtpm *, dtpm_per_cpu); - struct dtpm_cpu { + struct dtpm dtpm; struct freq_qos_request qos_req; int cpu; }; +static DEFINE_PER_CPU(struct dtpm_cpu *, dtpm_per_cpu); + +static struct dtpm_cpu *to_dtpm_cpu(struct dtpm *dtpm) +{ + return container_of(dtpm, struct dtpm_cpu, dtpm); +} + static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) { - struct dtpm_cpu *dtpm_cpu = dtpm->private; + struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); struct em_perf_domain *pd = em_cpu_get(dtpm_cpu->cpu); struct cpumask cpus; unsigned long freq; @@ -64,7 +70,7 @@ static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) static u64 get_pd_power_uw(struct dtpm *dtpm) { - struct dtpm_cpu *dtpm_cpu = dtpm->private; + struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); struct em_perf_domain *pd; struct cpumask cpus; unsigned long freq; @@ -90,7 +96,7 @@ static u64 get_pd_power_uw(struct dtpm *dtpm) static int update_pd_power_uw(struct dtpm *dtpm) { - struct dtpm_cpu *dtpm_cpu = dtpm->private; + struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); struct em_perf_domain *em = em_cpu_get(dtpm_cpu->cpu); struct cpumask cpus; int nr_cpus; @@ -111,7 +117,7 @@ static int update_pd_power_uw(struct dtpm *dtpm) static void pd_release(struct dtpm *dtpm) { - struct dtpm_cpu *dtpm_cpu = dtpm->private; + struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); if (freq_qos_request_active(&dtpm_cpu->qos_req)) freq_qos_remove_request(&dtpm_cpu->qos_req); @@ -129,20 +135,19 @@ static struct dtpm_ops dtpm_ops = { static int cpuhp_dtpm_cpu_offline(unsigned int cpu) { struct em_perf_domain *pd; - struct dtpm *dtpm; + struct dtpm_cpu *dtpm_cpu; pd = em_cpu_get(cpu); if (!pd) return -EINVAL; - dtpm = per_cpu(dtpm_per_cpu, cpu); + dtpm_cpu = per_cpu(dtpm_per_cpu, cpu); - return dtpm_update_power(dtpm); + return dtpm_update_power(&dtpm_cpu->dtpm); } static int cpuhp_dtpm_cpu_online(unsigned int cpu) { - struct dtpm *dtpm; struct dtpm_cpu *dtpm_cpu; struct cpufreq_policy *policy; struct em_perf_domain *pd; @@ -157,27 +162,23 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) if (!pd) return -EINVAL; - dtpm = per_cpu(dtpm_per_cpu, cpu); - if (dtpm) - return dtpm_update_power(dtpm); - - dtpm = dtpm_alloc(&dtpm_ops); - if (!dtpm) - return -EINVAL; + dtpm_cpu = per_cpu(dtpm_per_cpu, cpu); + if (dtpm_cpu) + return dtpm_update_power(&dtpm_cpu->dtpm); dtpm_cpu = kzalloc(sizeof(*dtpm_cpu), GFP_KERNEL); if (!dtpm_cpu) - goto out_kfree_dtpm; + return -ENOMEM; - dtpm->private = dtpm_cpu; + dtpm_init(&dtpm_cpu->dtpm, &dtpm_ops); dtpm_cpu->cpu = cpu; for_each_cpu(cpu, policy->related_cpus) - per_cpu(dtpm_per_cpu, cpu) = dtpm; + per_cpu(dtpm_per_cpu, cpu) = dtpm_cpu; sprintf(name, "cpu%d-cpufreq", dtpm_cpu->cpu); - ret = dtpm_register(name, dtpm); + ret = dtpm_register(name, &dtpm_cpu->dtpm); if (ret) goto out_kfree_dtpm_cpu; @@ -192,15 +193,12 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) out_dtpm_unregister: dtpm_unregister(name); dtpm_cpu = NULL; - dtpm = NULL; out_kfree_dtpm_cpu: for_each_cpu(cpu, policy->related_cpus) per_cpu(dtpm_per_cpu, cpu) = NULL; kfree(dtpm_cpu); -out_kfree_dtpm: - kfree(dtpm); return ret; } diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index 5f71ddc18ee9..4f7ad21291e6 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -24,7 +24,6 @@ struct dtpm { u64 power_max; u64 power_min; int weight; - void *private; }; struct dtpm_ops { @@ -66,7 +65,7 @@ int dtpm_update_power(struct dtpm *dtpm); int dtpm_release_zone(struct powercap_zone *pcz); -struct dtpm *dtpm_alloc(struct dtpm_ops *ops); +void dtpm_init(struct dtpm *dtpm, struct dtpm_ops *ops); void dtpm_destroy(struct dtpm *dtpm); From patchwork Wed Mar 10 11:02:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 396686 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp275640jai; Wed, 10 Mar 2021 03:03:23 -0800 (PST) X-Google-Smtp-Source: ABdhPJzt0t9K7QggUHVTPF18hA+Iis9b1108aIeBiY5LZMChTJQqnR4YEsFD2ct1tXyI3w8j7Vla X-Received: by 2002:aa7:cf14:: with SMTP id a20mr2580647edy.49.1615374203252; Wed, 10 Mar 2021 03:03:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615374203; cv=none; d=google.com; s=arc-20160816; b=fLD6jiJWrJUcltzLGHbBiw50Tm0ec9+HGBsTzCQJEsoZVRly/S2MgLUzuHe36uWCZX OUdsuHUFoibdx9NRkMCaoORe0VTIVmTB+OgeWo/j2l/D0Wt3AQd0K+5V95KSmVy1ge9l F0RXEYif4yq5DWnLHpxk3w06InbGdZn31kZlZxmrWxgdy3DKH3YF9Qjp1neiQQznSniH hGdZ2ug/VOqtuzWXxU2wz1ivLZm4hJKYccA92h4xNTCwWmD4F+FWIMWwhpV7Lg6Whlvx WJR7JcaeYqI3v5mwP2QuAFlx0M1YDEhzcwXuaNsKDyPmWhkJkRIpAfML67JnaB7S9CYN FJGg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:dkim-signature; bh=v0a0P82FBqcJYMtTstBhU6OwDjxrI0ymrdgmVRwXE98=; b=qHGQxo5XPvtWYQwBe352QhK0kRFJIaTvPKIke2PyJwxXtcWH2D0D+Q4RZ48eUejgtZ Kom68DpjCGC4TqUn8AfiNYGqzBO2mPwhBwjBlIN0JU1yJFchl9JOheI88i4VRpaKTMTH tOLyTgeRRG2K7K377bbn77rmgWnJYaa5JHV99xmw2teWbbRSeOuxtiWf2vMkR0uvGpn+ tAI3e3a8h6UcJ+It57WhznqBCDTBC0QBHZEmfTL/0t7uZrPrWHMpQJ/plsQC558DiCea Rm8s3mCQt/EfeyF4QU0prFuCG9QT0PQcgMcaVZIHSjU04BJ2zv4x8omhNYOBh/pc0W75 pAxw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=oSnESTuR; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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. [23.128.96.18]) by mx.google.com with ESMTP id a19si11675468ejt.403.2021.03.10.03.03.23; Wed, 10 Mar 2021 03:03:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=oSnESTuR; spf=pass (google.com: domain of linux-pm-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-pm-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 S232456AbhCJLCt (ORCPT + 7 others); Wed, 10 Mar 2021 06:02:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231958AbhCJLCW (ORCPT ); Wed, 10 Mar 2021 06:02:22 -0500 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9795C061761 for ; Wed, 10 Mar 2021 03:02:21 -0800 (PST) Received: by mail-wm1-x336.google.com with SMTP id r10-20020a05600c35cab029010c946c95easo10420155wmq.4 for ; Wed, 10 Mar 2021 03:02:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=v0a0P82FBqcJYMtTstBhU6OwDjxrI0ymrdgmVRwXE98=; b=oSnESTuRrlSPD8vl748DcLdzGj6QpSScfFvSqW6pyUMeI5jXG4tMVHSYvKVBkuawlj 89UFnoMMkfLlf/vEwqmA+mMYghOq0Ji1bIzA7UXBRv+0/QvToOGMHyCtN1NDriEssZeb U6RR95/XVyJ45HFSSjbAmamJU067SJx8F0YaOnWdiyyGdyUWGMYq/s8bpAkFgobt9Lri MOViG6bwNvLYa8c1WMuPVu5Ha0sWIYyBvNtFSNLNBOkB1lJOfgUDNU7Ur5hhUdLRJKFD ozrdV3mVMYFCB/pKfRnR2DTQkn2gBVIU9WOihIMwdBQ4t5bCIVpM7cbU61S7UcCtk8sI vAFw== 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:in-reply-to :references; bh=v0a0P82FBqcJYMtTstBhU6OwDjxrI0ymrdgmVRwXE98=; b=SWPgfW0rVp0OVhisZ2tJLjkhF4cTfRdCV0WzvWngmo1tda48WoS4cfH++NC3+vS0VV M8AnA0I/QDoqQqPskcmtXrje9vNlhluV4RxFbIYHNqFFoQvSjMoJUUmS7EEkQpahvtz8 heKwIhxNMIU9o0inqNZfs0FOngMd6Vge1ElC3txLB9OofHq0fvc8Pdn3iMILoQ8F7OzF 1lIUatw8FJ3AFoexRaQiIWoH84GG9RWaVVGmd55PnryU1JQmOhVlDFbO5ysNr/PPUHqW jY3WI+44UAnVqak2x1NqblAodw+YbsAUL/lJpEZ268TUyrpkbXhLzBNHQy9YXVcUPsXj YeCQ== X-Gm-Message-State: AOAM531ZNhR95oMsg1uSzwFHnSJcrmVf/jqGW6JhWHvfLYjQUhA6sbYF uBZ5oM1GDttmxqt1xUA8buFXEw== X-Received: by 2002:a05:600c:2945:: with SMTP id n5mr2801524wmd.78.1615374140239; Wed, 10 Mar 2021 03:02:20 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id k4sm36193902wrd.9.2021.03.10.03.02.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Mar 2021 03:02:19 -0800 (PST) From: Daniel Lezcano To: daniel.lezcano@linaro.org, rafael@kernel.org Cc: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, lukasz.luba@arm.com Subject: [PATCH v3 5/5] powercap/drivers/dtpm: Scale the power with the load Date: Wed, 10 Mar 2021 12:02:12 +0100 Message-Id: <20210310110212.26512-5-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210310110212.26512-1-daniel.lezcano@linaro.org> References: <20210310110212.26512-1-daniel.lezcano@linaro.org> Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Currently the power consumption is based on the current OPP power assuming the entire performance domain is fully loaded. That gives very gross power estimation and we can do much better by using the load to scale the power consumption. Use the utilization to normalize and scale the power usage over the max possible power. Tested on a rock960 with 2 big CPUS, the power consumption estimation conforms with the expected one. Before this change: ~$ ~/dhrystone -t 1 -l 10000& ~$ cat /sys/devices/virtual/powercap/dtpm/dtpm:0/dtpm:0:1/constraint_0_max_power_uw 2260000 After this change: ~$ ~/dhrystone -t 1 -l 10000& ~$ cat /sys/devices/virtual/powercap/dtpm/dtpm:0/dtpm:0:1/constraint_0_max_power_uw 1130000 ~$ ~/dhrystone -t 2 -l 10000& ~$ cat /sys/devices/virtual/powercap/dtpm/dtpm:0/dtpm:0:1/constraint_0_max_power_uw 2260000 Signed-off-by: Daniel Lezcano --- V3: - Fixed uninitialized 'cpu' in scaled_power_uw() V2: - Replaced cpumask by em_span_cpus - Changed 'util' metrics variable types - Optimized utilization scaling power computation - Renamed parameter name for scale_pd_power_uw() --- drivers/powercap/dtpm_cpu.c | 46 +++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) -- 2.17.1 Reviewed-by: Lukasz Luba diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index ac7f2e7e262f..47854923d958 100644 --- a/drivers/powercap/dtpm_cpu.c +++ b/drivers/powercap/dtpm_cpu.c @@ -68,27 +68,59 @@ static u64 set_pd_power_limit(struct dtpm *dtpm, u64 power_limit) return power_limit; } +static u64 scale_pd_power_uw(struct cpumask *pd_mask, u64 power) +{ + unsigned long max = 0, sum_util = 0; + int cpu; + + for_each_cpu_and(cpu, pd_mask, cpu_online_mask) { + + /* + * The capacity is the same for all CPUs belonging to + * the same perf domain, so a single call to + * arch_scale_cpu_capacity() is enough. However, we + * need the CPU parameter to be initialized by the + * loop, so the call ends up in this block. + * + * We can initialize 'max' with a cpumask_first() call + * before the loop but the bits computation is not + * worth given the arch_scale_cpu_capacity() just + * returns a value where the resulting assembly code + * will be optimized by the compiler. + */ + max = arch_scale_cpu_capacity(cpu); + sum_util += sched_cpu_util(cpu, max); + } + + /* + * In the improbable case where all the CPUs of the perf + * domain are offline, 'max' will be zero and will lead to an + * illegal operation with a zero division. + */ + return max ? (power * ((sum_util << 10) / max)) >> 10 : 0; +} + static u64 get_pd_power_uw(struct dtpm *dtpm) { struct dtpm_cpu *dtpm_cpu = to_dtpm_cpu(dtpm); struct em_perf_domain *pd; - struct cpumask cpus; + struct cpumask *pd_mask; unsigned long freq; - int i, nr_cpus; + int i; pd = em_cpu_get(dtpm_cpu->cpu); - freq = cpufreq_quick_get(dtpm_cpu->cpu); - cpumask_and(&cpus, cpu_online_mask, to_cpumask(pd->cpus)); - nr_cpus = cpumask_weight(&cpus); + pd_mask = em_span_cpus(pd); + + freq = cpufreq_quick_get(dtpm_cpu->cpu); for (i = 0; i < pd->nr_perf_states; i++) { if (pd->table[i].frequency < freq) continue; - return pd->table[i].power * - MICROWATT_PER_MILLIWATT * nr_cpus; + return scale_pd_power_uw(pd_mask, pd->table[i].power * + MICROWATT_PER_MILLIWATT); } return 0;