From patchwork Fri Mar 12 13:04:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 398611 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp1181594jai; Fri, 12 Mar 2021 05:10:36 -0800 (PST) X-Google-Smtp-Source: ABdhPJwPYQ4ovIW8SohGYn7KrHrZ9NuLJxOy5XNP8e9KxNH/u6mtj22Q7Gb/Vai/hEV9Nw8VPlBg X-Received: by 2002:a05:6402:14cc:: with SMTP id f12mr14524882edx.19.1615554635870; Fri, 12 Mar 2021 05:10:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615554635; cv=none; d=google.com; s=arc-20160816; b=wgHTXlpgxVEkJISiu3Rb9Kar5Va5tdSfqC4l+A969HnlABc2fg/hY0frSkD4JIN9xJ uXu+y/Bvt4YtSshREhPFNOhvbzGupVLF7YHji8fwtqragVPVKvuCHxYl/0v8PjfIDLKl 9z127G12Hm3IvkNUcjgsdkakpV/FeyLiT2MdsnIFWGtjdR09Bc1bYnTRbPxEtbwnxHFI VuTvGysh34DQXhhL+qmPClAuaFMKxuChB1ulyT325AOFfKyCw6GLZaFTGzmw3ZpwzSif b7bQpk1i9gND5Jjwp+WiQWgO+dxjOZSoFZRKIqAOpuQ1ISxVqmDAASb6+lmK1H9Vpm77 cLpA== 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=M5SGZfBWTxGnrRmJMSKycIe7vQtvGUeYvLVf8SZiSFw=; b=dEyRIRpwyA6JHqNfK4XYBhmi3UHW3NhkV73jlgzd437cBcPGgBiKQlPGWo4o1RBFm/ 72jT0gV3T3ukhObdaAFvv9h4H88YJcoAGqg7/T5RaC760C15PUYDsZAcUftFBejZMW4k 535JkMcBoE5kxiaVwn6P/G+AF5fqS16K4bBYkpj/lmlJI4pLnvT6lotSu4cHTrO3Sj57 WTDBuhxEE+aERpzam71SmhsCvvztaGKWmy2R2w7j/K4xLiPPT67Dy4XHts8Tz5iU6r8R WyhQLs4LmAh7ZxVbR2StIRc94MJ2gUOmbGD08Ha+jTBwpt6HkgkbxOiV2jYnJd+B6fkh t0qw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="rGPg/VML"; 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 jz7si4043056ejb.476.2021.03.12.05.10.35; Fri, 12 Mar 2021 05:10:35 -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="rGPg/VML"; 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 S231223AbhCLNKD (ORCPT + 7 others); Fri, 12 Mar 2021 08:10:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230491AbhCLNJq (ORCPT ); Fri, 12 Mar 2021 08:09:46 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E1950C061761 for ; Fri, 12 Mar 2021 05:09:45 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id j18so1742845wra.2 for ; Fri, 12 Mar 2021 05:09:45 -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=M5SGZfBWTxGnrRmJMSKycIe7vQtvGUeYvLVf8SZiSFw=; b=rGPg/VMLiVOtxxjANKuRkKsmjMp4vvofFM3TGJjE+WDSi5siL0qNE/m/zixrdqlLoS NvjWLyY7xghAxUTAyOWtlmAS0D9cpi/GenAD42ub9m7ehvRo+goVfCgerah+1pC1Uype fe1tQ0SitlRPDYvIiVaQtWE4r4KOMWm3mZ33Q6Ohmdn7mfsUDtLigVdQ+c8c1cAJST7N Ds6CPFAV8krF0JDMJhg/t/ADVBLz2U+ktsqCEeE1nVG6SVKV47RFRRPOOClLWZ4x0575 cD/e2qXj4wEn2AuMVPx7bgJ4kA2eEsjns70+JhF7faB5pnH3kfcpCsxYYwhMVkQyldky xRwQ== 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=M5SGZfBWTxGnrRmJMSKycIe7vQtvGUeYvLVf8SZiSFw=; b=NuZZEwkGPJmcuwWfIo4Ni/CDNx1PvWoDTiX0kkdmLf/3TFTgYHihVPnTqfTU8ZA2bs 9KsSu5iK1zyevuo9dlLYsrIKuQquIbcp8vOiZPtJJCocZrurXsvRyQ0ouwDt/gCOHamD wjmd+HRagju2aEVXUmBdcBnFoQEkU1eYvXVXoqNd7QB+04yTnsqX+Y850AAEY4vDP43Y ZeQC86Cu4uLL/GT7t0GHPHSt4yTxS2PGvz/1UQfFNRpwBrgweNhPR3Yf+ypj5PQt2+/b DMRmqRuyrj9xWMp+S3mY4r6V1ym52skSDwqDibbC7paOgC+WpZyizjLu8nMN3v8wW3ue WNXA== X-Gm-Message-State: AOAM530c+dFMkBROXDPzqr2gt7Pp+0Ri102k9HJrshDA00s3xCa90o1Y RVVTErvliuGgdRPnbx0smLrFhQ== X-Received: by 2002:a05:6000:18a:: with SMTP id p10mr14143550wrx.166.1615554584307; Fri, 12 Mar 2021 05:09:44 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id q15sm7655033wrr.58.2021.03.12.05.09.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Mar 2021 05:09:43 -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 v4 1/5] powercap/drivers/dtpm: Encapsulate even more the code Date: Fri, 12 Mar 2021 14:04:07 +0100 Message-Id: <20210312130411.29833-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 Reviewed-by: Lukasz Luba --- V4: - Replaced s/sprintf/snprintf/ for the dtpm node name 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 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..f6076de39540 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); + snprintf(name, sizeof(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 Fri Mar 12 13:04: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: 398612 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp1181617jai; Fri, 12 Mar 2021 05:10:37 -0800 (PST) X-Google-Smtp-Source: ABdhPJwY+/zZA30uGFgsd5CQ4t5lpMCHhHV59LMNSY1k23gLtBmKMA5oQCJ3NbAY2mM7QVM7Z5Hr X-Received: by 2002:a05:6402:95b:: with SMTP id h27mr14289552edz.93.1615554637130; Fri, 12 Mar 2021 05:10:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615554637; cv=none; d=google.com; s=arc-20160816; b=KpfaHQPr3+7TfKO935ldxntWjIDA005VAL5eX1kZoaKLJbOziPT5TjfN6u6Od4dFF6 UIOEE3ky1RvVP6uMlWaR6wGHxHGdvvLV8qKE2nuTFUFfPfau5ruiOystGk+LQNZE6P4X U2TvCX0uadwx3KLdhQepoguIuPpjndYEeHAybDVVEO91y6mk9OaHLSi6WZh7tfCkANiM y+Ef0z5MlM9KBs0ZS7uEJJL0dAxWYA+RPUqSINoy0L4+8ZLoLlW6Czz5SLr39xWL/Cep HRJ10CjxFJhhRTA7ol6vyazho4p/b4yQpUFiSbQZ4CPHQ9/1Np3FqqdkwLZhokYfERHO U6Tw== 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=W5HXQCi40XxOvUZzXEGLC9mNtUSNsDNwrGp6F1F7KDs=; b=bqlMwPZZEnqaZ+1FBMD75lP6u4a0kMVuiBOLDi9CTYzkAqUHBaK5tVG1C9VGs+jXPf RAU3WmRb5JLh4MG2B42GfgnKN1ZGRhypNfdhWsltnBZZznPydPj0qrHVktPjjYE8boWs vNgY0aG9FEgvdmEpiTbtVPLCPocPy46tvBpxeHhP3IE+gfb17lM1lgXJy9RO6y0dJBUQ /1JDfmKtmZncQvjENtlUe9vLCmO5VQLkQ2uJBC/mPGmhlJDyq0ShDn+LlUC8BuydIH+Q favVXzEupMA4iLA3qDULyakNeMO3ZrfPB6phX5kxXoTn9rIWodNMT5KLWuvPhJIgcc2K pi5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GgIUvoCw; 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 jz7si4043056ejb.476.2021.03.12.05.10.36; Fri, 12 Mar 2021 05:10:37 -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=GgIUvoCw; 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 S231276AbhCLNKD (ORCPT + 7 others); Fri, 12 Mar 2021 08:10:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41940 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230520AbhCLNJs (ORCPT ); Fri, 12 Mar 2021 08:09:48 -0500 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBB04C061761 for ; Fri, 12 Mar 2021 05:09:47 -0800 (PST) Received: by mail-wr1-x436.google.com with SMTP id a18so4749294wrc.13 for ; Fri, 12 Mar 2021 05:09:47 -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=W5HXQCi40XxOvUZzXEGLC9mNtUSNsDNwrGp6F1F7KDs=; b=GgIUvoCw6pn4Lc1qQuisnsf/TT9SajavPJYQ8RGchpfnZxFTwNC8yoVZlxntS4EWOT Ch3dkBxdPbmVPXZ1WNZddhAmNj4FZEpKe/6rKb4LAc3UUU2THEt15cgNSykQyAgDHKpl 82wYLDF9HseYFQ+PBvp9WR6j1s/LKT2sLAuiCV5l3zLnaBxY1Z+doyv8RFw4pwK9fSUr yAwsmTBY/StXU7zkUkKPP+LJKx6LJuYdrTF870/7Wl0pT+SK/Bs+Kdq7rvTfM+CpLV1n IyxR6R1WHLH3saEIV1PjMpK9fevr0M3YGE2CqBRNXR457gEdrdncpvRP5GegteEt12xC Zo+A== 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=W5HXQCi40XxOvUZzXEGLC9mNtUSNsDNwrGp6F1F7KDs=; b=W0/2S4LvyzU3cNuwiz7qyvk3STs4SO/22VyVbWRSKpcVHW8rGziX0Xw9NfrrN5dnXk NdrZxdxrFdElOolqbR0CRdfwJPQqiQClHcBYALzAngiIgxqezwET6HJPRfmHRS1OyCNS bvkacHb4E76CUnbSYypriqOXow5XnM7O28EW8YiLyFiyHqTDtOLTGwvwNXGvDOZVlmi5 W39fS3pltXOuClW5Cf5INOoL0rVg11rmOpZhpM+gOzvAvR5R3LasQ00R4qO31hTiOjCn 7wSMAqfBPKZ7QllFwfVctH/ssAxBRjnsSk1p/Exw7H8+qtwQCn/pC8jVJqkRCkOQN0pt m/8Q== X-Gm-Message-State: AOAM532dHdJQI0+T1ywjAzeUERdCYGipgQXwDD8IRfoSlXRJA/I/O3TY 450ubwqH3hHpqy2tx6VUAkEAXWoMmj6+RQ== X-Received: by 2002:a5d:6312:: with SMTP id i18mr14157379wru.149.1615554586277; Fri, 12 Mar 2021 05:09:46 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id q15sm7655033wrr.58.2021.03.12.05.09.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Mar 2021 05:09:45 -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 v4 2/5] powercap/drivers/dtpm: Create a registering system Date: Fri, 12 Mar 2021 14:04:08 +0100 Message-Id: <20210312130411.29833-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210312130411.29833-1-daniel.lezcano@linaro.org> References: <20210312130411.29833-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 hierarchically 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 Reviewed-by: Lukasz Luba --- V4: - Fixed typo in the commit log 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 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 f6076de39540..8592a78e47e4 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) snprintf(name, sizeof(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 Fri Mar 12 13:04: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: 398609 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp1181586jai; Fri, 12 Mar 2021 05:10:35 -0800 (PST) X-Google-Smtp-Source: ABdhPJw35CGTrWWDMddgtuUfGMWGNgLmTqq4u9U9DigH4nId5YmKEHc39H7E9g34DK2ufliVMA27 X-Received: by 2002:aa7:c345:: with SMTP id j5mr13660914edr.338.1615554635471; Fri, 12 Mar 2021 05:10:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615554635; cv=none; d=google.com; s=arc-20160816; b=AyTb/XHOC/APq/IlAb2kMD++ll2TsZ6k8MODINdCqbjWvEJ5n0a8dM4DjKKsxWyJ3h 53StagxxoFseZpK1AlTLzLt8zS3NB/c9A3J6uqsDzIF5t51n8a38iwFprQ5CuCsc+i8I ppUMZaK+xkA4smKyRipRm4fQkkEsr/Tb+KBjDWpalbfdx/NQOX5NZS7THILimDzjgKDR x9Y//MZrvC4XZf/DrVIzHSuWfpo45fPidyJXAtB0cbCUTCqI9FZx+2s2+YCIZ09uOWaP NEfQiXQ+3TAxD6TK6I/b1ej1U/MtrFwwQDBI7CqBN2CDvjDcUrQv+kvNWcqFh3T1s+mn 7upg== 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=Y+3de1AeeAJ1f3wvK6vHJ9cHErXRUBGiuppggQN/HY8=; b=syIVCIkbcShglrmiVj9mLx6y9bgX1r89oT9llGqtyxzJjJNgXg713lBvdkE1yeezoT RvUeIPjTNMGDWWE2kR+w+LtlH9u6YowQl2EIQec3ONbjv5bW2IZX2E4FvgXMXVID+kbl BcR7SEE+tPCXJ1bgbUZSWX4o7t98n1lGgVv+8Efk7BDmdJ/Qnq5mekGU7a52jbVphFiI WrMM0RPirqpjO15FdQCoK5Dyo8LWNXSUMKR5X//Ix56E+VtS/MT36napMtTJZVVf8ufD K46HW6KaSB2jErfkriXp4eBj7kFKu2e9WEKjAotMoeIA9x46Sg3eXccwWnSZJ9eSjXyF eOcg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="Pkgj/hKq"; 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 jz7si4043056ejb.476.2021.03.12.05.10.35; Fri, 12 Mar 2021 05:10:35 -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="Pkgj/hKq"; 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 S230243AbhCLNKE (ORCPT + 7 others); Fri, 12 Mar 2021 08:10:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231131AbhCLNJt (ORCPT ); Fri, 12 Mar 2021 08:09:49 -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 88DD6C061761 for ; Fri, 12 Mar 2021 05:09:49 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id e10so4764182wro.12 for ; Fri, 12 Mar 2021 05:09:49 -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=Y+3de1AeeAJ1f3wvK6vHJ9cHErXRUBGiuppggQN/HY8=; b=Pkgj/hKqaE5pZ9CRW1TFxEV3VYj479VPkYabx0stapmnfeYvEipZ62n4iTBYqKsvlG 0d9JosIdJZp26i9crzbWxJMw15hpPU/hxsJ17qd5uNj2sO+x6SQ6qteZjiPaspB4p3Qj dbQa+tw5W4FoPXr5D1ka+3DwwifS+40VImXpTU1aTJX661EwlB31jS0QFu4Ni1E3zum9 rd++tKPJbXVVk5mHdMTBOpX1/EnJDeDZXYh2y2tB6Bzue2pNvzX628DUnN1lJGyvOgzg IK11/3zPDOmaaiYXnrnZZbv0Ojl+NET2GOw8S8jiXNvn1GxTyPyScJvSCMXsYOsJ/GvP QNFA== 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=Y+3de1AeeAJ1f3wvK6vHJ9cHErXRUBGiuppggQN/HY8=; b=X2od+fYJLn+y9a5hHXqunBldfy/FWBFpza/UwyBgMILZOhi27fq60ymbxUhfotrgcO V6R5SaEDV6nOGPWKndUjjYm6MraIzBaq/y3NZHxno4KZDdWzn0JJqB/xkDrb48NOSY7X VprszKX5G2yGapvaw1shjnk40Ug3JLhxsOIZzJYpJpUrEKDkPcL3PdrB+kEU3WbM4sV1 xHd1UNYXpKMTO3Y963g2ofI8fxdc78vYXynxLHoOpETlWHUEoJC0qmwUQUb1+6dnYWCo 93py316bTKhqTynPLCO5Fk6opaiXqsOsrSGeKkrl4iHHy3FrK+K1dHANTeoGyD//yJK8 QqQA== X-Gm-Message-State: AOAM531XPoiIU9jsNe5VdLP2XSHUN3V4l+o0GQy5d5juyxS51ya2jlN3 eqVkrPtBMcNjI7xz0UQBwN0tcQ== X-Received: by 2002:a5d:4445:: with SMTP id x5mr14268622wrr.30.1615554588225; Fri, 12 Mar 2021 05:09:48 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id q15sm7655033wrr.58.2021.03.12.05.09.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Mar 2021 05:09:47 -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 v4 3/5] powercap/drivers/dtpm: Simplify the dtpm table Date: Fri, 12 Mar 2021 14:04:09 +0100 Message-Id: <20210312130411.29833-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210312130411.29833-1-daniel.lezcano@linaro.org> References: <20210312130411.29833-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 8592a78e47e4..c4fa35fabc40 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 Fri Mar 12 13:04: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: 398613 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp1181639jai; Fri, 12 Mar 2021 05:10:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJxqGnNW609EJibuFE2EsGISOu3QV0a8Q24aw6T70rDhXFlNsUiMkhGshE9x6j2TMRgWv+TH X-Received: by 2002:aa7:c3cd:: with SMTP id l13mr13872448edr.52.1615554638799; Fri, 12 Mar 2021 05:10:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615554638; cv=none; d=google.com; s=arc-20160816; b=vSbKRgJbGdCpHqrPzmJ5zI17hsic9+KknEDx6N6hE38VagkFeoBd2Pw6jcHBG/nYpF Kh7+Pczdcv7IELS/5SSbkC/palXQQ7jYGCen4KzrF2o1odux9BS+L10WdtaCxGnZ3/mA aPWF3of6MZ4E+yxG03JMAJAaS6IPqTbNe7l/G0GC5zENUN9vEqvbyYcQNiCv6m+kzzZK 4/nyBGGTdsI1lxwDjwNCvV+uYJbwPenLl9IgZtUCLuDZQs6VSHLtiUhoTlxGuysCHsgU TbLM1h4qDFZUsbRHKJopm5VJKsdme+ti95oHRtlF8sIofz6HxmZGaU0PahkOK/2o5MQD Y/Xg== 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=KpveMINi5uXwaTB3etXOif2Qu8MdIK4KNh+5Pxmbs+s=; b=LhWCdsqjRscVICOG1hV0ekozzgXuUusipbk8Jjs4aW776gEXjOB+WA76ZExi/BKfNX J39LAbwK6UsPANvIWs0qhk+zBpqxcNNZzFTMvpJQNXmIM8KqU3pqPm/kD5rIhpOY3VkB cBaszhcKrvLVbkvrCGnWcoryxFGC8sb2KbQf3pnpwgOJ/YnuHZarz+MrkA8MSw+R6EV6 u/KdzTtNkyGxB+IgXh38/VPAsMT9RjYW0ODSq5TD6BIywYCKRFHRK3xyThjZ78LlVbpk zJ3IKgSAr6oPLng74tE1vwaGy1IkF1b6YclB+XBtrNowBEYW44kvExN2e1Pvkm6X69mS erBw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=wjrfsnch; 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 jz7si4043056ejb.476.2021.03.12.05.10.38; Fri, 12 Mar 2021 05:10:38 -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=wjrfsnch; 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 S230127AbhCLNKF (ORCPT + 7 others); Fri, 12 Mar 2021 08:10:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231173AbhCLNJv (ORCPT ); Fri, 12 Mar 2021 08:09:51 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0B2AC061574 for ; Fri, 12 Mar 2021 05:09:50 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id y16so4788694wrw.3 for ; Fri, 12 Mar 2021 05:09:50 -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=KpveMINi5uXwaTB3etXOif2Qu8MdIK4KNh+5Pxmbs+s=; b=wjrfsnchgZQQL1g3RUznMrA3TT0WVuJt+4uJxxAx17O4+ywP1LkZd7IpjbEZDjoXqy ueqqlHoWWTO7GObu8lfFgPE1iFlfA7gse5C2KZH1jjM5Zno+fCfL4vC0VRlQ9Rre+tOu 5nNpsT0DXzX9UBSP6UbPxYmb5hQGETyS4BCKylDvkil91jhpytqQoToA2CxBAkKa+Z1f lq0Qe5DoAMXV+aF52ct4r6GwPY2/5PhLrPnamazKfIMp6AMX+jYD+R0xOB1MPM/a3xSi if80KSXZFVEP0owOyBGDONZ+qE9d/CXB95X9MUjOFpyyiUUWWhCxBy6WzojxU8uaUpOb 9BSg== 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=KpveMINi5uXwaTB3etXOif2Qu8MdIK4KNh+5Pxmbs+s=; b=AwImfIbxPzJPa4+cKoiZDSGERlZdO7EJ4ZEZc5F6sLKRBCL1QuRKVUi1PeWuEHgcvT qpt5tZeHCYWJZ8TvZaa5/8t5g2sfN4y7mk5i60Rg1ruIszU51Xsy4Z8I/BNWS/NCBMV7 2mWkeNrhJPHbNb7olLuDj29KphO07GBK5xoDxmxY8IARkNvmWlB/BhhxfCEzowNRo0le pl+0oaH0z+xHBZomT/1pP6106i3+qm6+KY8lj9SvBt34wrTJHplnjKer6aFL9olA+SXm HJjqfpVEh0lOQHjChk0jxc/u/6tDId1BzqP7AxUbK2nkG7X0CHj4Y2PxadosS4MxZMpw VUCw== X-Gm-Message-State: AOAM533b5u9TtFepnMjIBdRR3kOUAJSuz7LXcTBlfG8NUItGI5TYoqZI 8xn+VbbmjJBU/bZbiZ7LB7usIw== X-Received: by 2002:adf:d1ce:: with SMTP id b14mr13881031wrd.126.1615554589418; Fri, 12 Mar 2021 05:09:49 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id q15sm7655033wrr.58.2021.03.12.05.09.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Mar 2021 05:09:49 -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 v4 4/5] powercap/drivers/dtpm: Use container_of instead of a private data field Date: Fri, 12 Mar 2021 14:04:10 +0100 Message-Id: <20210312130411.29833-4-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210312130411.29833-1-daniel.lezcano@linaro.org> References: <20210312130411.29833-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 c4fa35fabc40..1c6d1e54691f 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; snprintf(name, sizeof(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 Fri Mar 12 13:04: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: 398610 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp1181602jai; Fri, 12 Mar 2021 05:10:36 -0800 (PST) X-Google-Smtp-Source: ABdhPJztHg/WHgPhWAkyWWUTWzwHTV+bGfaYxw4C32JT6U3B+4/AZefIAUAHF6JWMSg3xMNE+Cry X-Received: by 2002:a05:6402:168c:: with SMTP id a12mr14241593edv.344.1615554636303; Fri, 12 Mar 2021 05:10:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615554636; cv=none; d=google.com; s=arc-20160816; b=pd2TLVv89bTEeozr2JysNGG6F52s09DeZjk+0jisOd2XiS0g9+4k9vpcdZ3x2YbreK HDaKTpwa80QrY3130mNnms8oRoPPohgpfln8bdVlF/hXii/1FNrY9azJDLM3gqbZHupc /1ag5CZ2zniO9R2hG7AODGc2kPfRXIDShwQfnbTSVTConEjiwNQ+9pWjabPoZgKoCGDq PnmS51+xrc+ilO4gbrNzNsDT6XfVbfcVTazjG7Dl00iAq86ELn79l9Ecps0aPwG6XOYX 6AlK88g1OB2cY3hFMOkHQHKRwcP4pAUbGI8f6vx/jSY04SvIjBHrNV2X0yziuXKroOPQ vr+g== 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=ciQbVSMUlmG+EHnejb8dZoNHxiJgO/iaArkSXQInEQA=; b=gqwIpmnuUI2Ss3HoeFBBa3D9nbAN9R/doU7oEWYohrFBJi0qkSVK+e3EBraLm7iBOC 7SMj3cTjbMBGmUwtvAn2S/IJAhJwp/Plzag40JSigNGJNR+gbkIBVr94mg/5yUvwyTzX ofPIzNX9rUrlcoIlQMvurvZCgGhWjGuFmA0TsUjWUClsIqkJxvjIH/sadUk0X3xQoYwR +TZfTXbMp6v1j/W4RCV+Tlqh/CMJcU6XTY4/ZGtJiKbpCtnegvsKsGnAe2ztH7TKr/YN ofEL35gfDSpsSGghzW0OWU+vg2onBK4CRMLgyqlwhPd38uXdu+vinE8J9tEuKbQjXER7 3PaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VPZw1uaR; 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 jz7si4043056ejb.476.2021.03.12.05.10.36; Fri, 12 Mar 2021 05:10:36 -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=VPZw1uaR; 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 S231290AbhCLNKG (ORCPT + 7 others); Fri, 12 Mar 2021 08:10:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231186AbhCLNJx (ORCPT ); Fri, 12 Mar 2021 08:09:53 -0500 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3E90C061762 for ; Fri, 12 Mar 2021 05:09:52 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id d191so3759863wmd.2 for ; Fri, 12 Mar 2021 05:09:52 -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=ciQbVSMUlmG+EHnejb8dZoNHxiJgO/iaArkSXQInEQA=; b=VPZw1uaRvXSaT1vcJm+4Tnk6DwVz8AS7pSmoBzLltwLgKQw9Wcf8vpLZBqyWkPlG2Q GSTCPnBz92ZbF5VYfMEOfHgQQ3LyTRgvnZ7sMoIOSlrlFiWpB+xia3q3KXHSF2dp1OmR kaDmuSHHyekLUkOKYe9Lzs4/rXDtFWDS9F+P8b7Z1Cxut6cxFHB0smQTnVGh6H5ONLjN p4Y+BJ9YwFfsTIM1ABf2Y/oHOYQQqNWjS7uvUf2j3L2qe/bLELJH4SpgA/g+QnU4ZDnt z9j62hPLTGn521bJ70hotMTAVUOR/4vtZpQN5yyYMJrr0uyLlPyAe+BydTYPn2mWHkqt uWaQ== 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=ciQbVSMUlmG+EHnejb8dZoNHxiJgO/iaArkSXQInEQA=; b=b3+k6V7MTMTv35pO/EDg9JlEO4Rb7YGW0cThvIO4EkuAUqPLTAUUbf9nUWxk04PWlB SFaAj47Opw43eS8TRGZ2s/NCs79U5uuvdgjbDHBQgDtg1SzmGPObh37TzgZlNm4BDwXi IaQmvgT7hLObxqakN5qWcHzA5KzZLdUACYZPYRMPwbivioLqeaC0pys0E4dHkh3CUOwv V3Ag8mGmiFUT3O9455Ga+C+hB5QJb7AfOCN8vY6bHf2WJ9t9mLGTNWtYD02xQAY/Yxb5 qb+K8vb4i8Gzs2Armf+6VsqUU5S+SdKq0i8PbUhTiMEanyeO4KjsphemD8jhkEr1BCyc viTw== X-Gm-Message-State: AOAM531lQ2cOMD2+tcU3v8MAPMTeB4LNhOq7iUpyA85UioTPABV6QzLL RjN+sJLE0bbETsyApPrtzxx8OQ== X-Received: by 2002:a7b:ca50:: with SMTP id m16mr12749759wml.113.1615554591411; Fri, 12 Mar 2021 05:09:51 -0800 (PST) Received: from localhost.localdomain ([82.142.0.212]) by smtp.gmail.com with ESMTPSA id q15sm7655033wrr.58.2021.03.12.05.09.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Mar 2021 05:09:51 -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 v4 5/5] powercap/drivers/dtpm: Scale the power with the load Date: Fri, 12 Mar 2021 14:04:11 +0100 Message-Id: <20210312130411.29833-5-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210312130411.29833-1-daniel.lezcano@linaro.org> References: <20210312130411.29833-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 Reviewed-by: Lukasz Luba --- 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 diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c index 1c6d1e54691f..e120ea239d75 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;