From patchwork Wed Mar 31 11:00:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 412871 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp386252jai; Wed, 31 Mar 2021 04:02:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw4T613IHnFotRne0Dop2+rD9NFLT0gklEgDrVIkZ26mMb6mIP5fpBJGp2TdruXeLQSZq3t X-Received: by 2002:a17:906:1182:: with SMTP id n2mr2905195eja.234.1617188535736; Wed, 31 Mar 2021 04:02:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617188535; cv=none; d=google.com; s=arc-20160816; b=arnva8bvugbNLBm1aVJAyY3BFgk+9sYceUIaNIDOmfQzN5HuX/IWOfVC3eYaQaOsmW yglOA1KYYqxl1KRnrShzr/cjNjbKUqQe0WGFM4UUwUQnKD4tRnQAaEkI8G5r9exg6Snd FgnpjNwrjct6xWD0d7yLE74pRUUuNVV5PYc49CjysOJukFdfCBTm5i5MpMiMOcD6Hhdc HyLLsIPpHHVyxvVwaMAPD133mVyFl0TtWXP+LAuUvt8I3HmE/pJ3s2IsPSjA9+FMqA7L ZRtilxPMKnp2EKQ7Ga0kolrVgPtU8O1b4mrbE4seimHUXY4ABZwFYh6mGDS77EIkffOa TBdw== 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=5VFoz+HDWhcwV0oty4wzq4agQ6coiwbE2SClXgBAX7g=; b=033gp5KBKTTn9qI9JUTFjpXcnIpIm2iUyRq7qJZ301Nx42888hUuYjEoqQX99RiQsH dIOI/3jw42BhY7tw2m+lCTpJ7ndgXifV6SIwjX4tKO2/WjuJYL8BGKuLr4v4gH4bD2QC uH/N2DIBp23cAItmSzdYuOXDJulF4IfPMs/0yr+gmmOZIXv9AkdQ9cPvJrp4KJUNjiBT y5hMXb8zbHcR6NOa4nk3O+mOia8uUCgiWES0vyxxuNE/5jl9KRkoJsQ5Pk6q5mVKCsfM 1XyW8dDjr/mdNqnmHwOi02NjD/E1aGH/7M1aBDbMPNOvhXh+SBncOrWBH0DguDdXaGI2 zSaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=DLEOI7bs; 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 r16si1445467edw.458.2021.03.31.04.02.15; Wed, 31 Mar 2021 04:02:15 -0700 (PDT) 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=DLEOI7bs; 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 S235467AbhCaLBo (ORCPT + 7 others); Wed, 31 Mar 2021 07:01:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57348 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235508AbhCaLBG (ORCPT ); Wed, 31 Mar 2021 07:01:06 -0400 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D98AC061574 for ; Wed, 31 Mar 2021 04:01:05 -0700 (PDT) Received: by mail-wr1-x430.google.com with SMTP id v4so19188496wrp.13 for ; Wed, 31 Mar 2021 04:01:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5VFoz+HDWhcwV0oty4wzq4agQ6coiwbE2SClXgBAX7g=; b=DLEOI7bsMKH9HhiRnz4W7c14JJmrn2TLclkvtM52BFSOZt//71KNlPPgc+2hiDhmq7 wmVPExzd+7Q9ZYR5zZ+I4KUG1kCoeSkVdlFTfLXYmL8vbzkYvLR4oVOMyzKSXjMAgRuN 7V9B2p8rqOoSAlXvgLa0shKCKPpY+Yq13Hq/N3Nwga+0BvhJJzzmUYZvkHBCYZ6E2mSX TyF/3OWNhPXiaHpAnOzGPo5zKbOXILWsDr86LW4JdG+VeybAPnQYyynLKScMH0DfGCTQ icHpJHuZiFyffar9izCU0WLVI2/xMoQVsfLlFRxx3wRdLeN5cw6Oqu0AJE9CG+TjZt9C iwJA== 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=5VFoz+HDWhcwV0oty4wzq4agQ6coiwbE2SClXgBAX7g=; b=TcyBxzqCAfDaoX64ezkLBvbxf8+Lve4NxbTGDDE6W7gkz+GXfJx03fvEhnsuWF0k/t lM0mUxPMphAu9X9G9dpbnb62FTPoP4L/oj0l1z3J3hjkz2cCJdGP2zdsXYXld98QRCpr I3cwR0vk/Vo40Q8x9ETrMMM+cdksuWfEfI3oPlKqJCRKq9el9kJkhCWB6YQjUmhDw2hw ECIZ5cdOk+wnRli1cfhDoiPfm6VKv1EGdCdq91v4BeExRDm6X4A8hAPX+LwUPMkfnXOF Iqm9fF65PtGgUchFJ4VuthLCGWiOQ2vHYw+KhNx+THZ+fYExAGX0ANBA11mwqpPXNnyb cw0A== X-Gm-Message-State: AOAM531ucL4qS6DyWUbsVPoybJwcaQqarEnjyqI9eKFxIifOaVfn5btU yERswIx5gXov5jpcFeZkrn4p+Q== X-Received: by 2002:a5d:4710:: with SMTP id y16mr3042702wrq.344.1617188463815; Wed, 31 Mar 2021 04:01:03 -0700 (PDT) Received: from localhost.localdomain ([82.142.26.252]) by smtp.gmail.com with ESMTPSA id u23sm3376275wmn.26.2021.03.31.04.01.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 Mar 2021 04:01:03 -0700 (PDT) From: Daniel Lezcano To: daniel.lezcano@linaro.org Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, lukasz.luba@arm.com, rafael@kernel.org, gregkh@linuxfoundation.org Subject: [PATCH v5 2/5] powercap/drivers/dtpm: Create a registering system Date: Wed, 31 Mar 2021 13:00:45 +0200 Message-Id: <20210331110048.24956-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210331110048.24956-1-daniel.lezcano@linaro.org> References: <20210331110048.24956-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. Cc: Greg KH Signed-off-by: Daniel Lezcano Reviewed-by: Lukasz Luba --- V5: - Decrease log level from 'info' to 'debug' - Remove the refcount, it is pointless, lifetime cycle is already handled by the device refcounting. The dtpm node allocator is in charge of freeing it. - Rename the functions to 'dtpm_add, dtpm_del, dtpm_lookup' - Fix missing kfrees when deleting the node from the list V4: - Fixed typo in the commit log V2: - Fixed error code path by dropping lock --- drivers/powercap/dtpm.c | 121 ++++++++++++++++++++++++++++++++++-- drivers/powercap/dtpm_cpu.c | 8 +-- include/linux/dtpm.h | 6 ++ 3 files changed, 127 insertions(+), 8 deletions(-) -- 2.17.1 diff --git a/drivers/powercap/dtpm.c b/drivers/powercap/dtpm.c index 58433b8ef9a1..8df7adeed0cf 100644 --- a/drivers/powercap/dtpm.c +++ b/drivers/powercap/dtpm.c @@ -34,6 +34,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 +160,113 @@ 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_lookup - Lookup for a registered dtpm node given its name + * @name: the name of the dtpm device + * + * The function looks up in the list of the registered dtpm + * devices. This function must be called to create a dtpm node in the + * powercap hierarchy. + * + * Return: a pointer to a dtpm structure, NULL if not found. + */ +struct dtpm *dtpm_lookup(const char *name) +{ + struct dtpm *dtpm; + + mutex_lock(&dtpm_lock); + dtpm = __dtpm_lookup(name); + mutex_unlock(&dtpm_lock); + + return dtpm; +} + +/** + * dtpm_add - Add 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. The list contains all the devices + * which are power capable in terms of limitation and power + * consumption measurements. Even if conceptually, a power capable + * device won't register itself twice, the function will check if it + * was already registered in order to prevent a misuse of the API. + * + * Return: 0 on success, -EEXIST if the device name is already present + * in the list, -ENOMEM in case of memory allocation failure. + */ +int dtpm_add(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); + + ret = 0; +out_unlock: + mutex_unlock(&dtpm_lock); + + return ret; +} + +/** + * dtpm_del - 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_del(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); + + break; + } + + mutex_unlock(&dtpm_lock); +} + /** * dtpm_update_power - Update the power on the dtpm * @dtpm: a pointer to a dtpm structure to update @@ -208,8 +323,6 @@ int dtpm_release_zone(struct powercap_zone *pcz) if (root == dtpm) root = NULL; - kfree(dtpm); - return 0; } @@ -388,7 +501,7 @@ void dtpm_unregister(struct dtpm *dtpm) { powercap_unregister_zone(pct, &dtpm->zone); - pr_info("Unregistered dtpm node '%s'\n", dtpm->zone.name); + pr_debug("Unregistered dtpm node '%s'\n", dtpm->zone.name); } /** @@ -457,7 +570,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_debug("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..9deafd16a197 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_add(name, dtpm); if (ret) goto out_kfree_dtpm_cpu; @@ -185,12 +185,12 @@ static int cpuhp_dtpm_cpu_online(unsigned int cpu) &dtpm_cpu->qos_req, FREQ_QOS_MAX, pd->table[pd->nr_perf_states - 1].frequency); if (ret) - goto out_dtpm_unregister; + goto out_dtpm_del; return 0; -out_dtpm_unregister: - dtpm_unregister(dtpm); +out_dtpm_del: + dtpm_del(name); dtpm_cpu = NULL; dtpm = NULL; diff --git a/include/linux/dtpm.h b/include/linux/dtpm.h index acf8d3638988..577c71d4e098 100644 --- a/include/linux/dtpm.h +++ b/include/linux/dtpm.h @@ -75,4 +75,10 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent); int dtpm_register_cpu(struct dtpm *parent); +struct dtpm *dtpm_lookup(const char *name); + +int dtpm_add(const char *name, struct dtpm *dtpm); + +void dtpm_del(const char *name); + #endif