Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp4494422rdh; Wed, 29 Nov 2023 03:09:41 -0800 (PST) X-Google-Smtp-Source: AGHT+IFUc23VkJWjHgtgsZARhxehanxPo8891AL76Ob1lW41QC2SmoD2cxhwFD7KQuC9LcVmiuE/ X-Received: by 2002:a05:6870:4712:b0:1f5:c37c:ac37 with SMTP id b18-20020a056870471200b001f5c37cac37mr22857674oaq.30.1701256181339; Wed, 29 Nov 2023 03:09:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701256181; cv=none; d=google.com; s=arc-20160816; b=yyPWC51yss5LbCx1TiFZjMKE+lj00mjSE5x9bDYY5EopGVovfxn7i/4eM51OrF5LDe nPM4KOEH8LqzoqJXgPkGQdJX4KHzZDpN1AVngW7XjaVMJsOtLwS15SmEthkaEWywHVOQ DRvzCAqnqd06/DxV8ROiiB1TpyHVkxp7hsAB9V2UvaOEVE7qTfmAhO6ZHibfZcPVq2xj +f1IKEsmKLyHexqkQS6/abTNyyTA//MgotjRLrGwgF2TSB3fiPEQFjFi2K9vsbYW3AVU AUZCpW13SR/VUc58MphSigU5j6norB4sBJZlTepDp1QUC40yM236/vw9e2EcEf+3VWBf AKlQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=PoLfy7zu3UWgb2JA6nfONGW74VylY61vParIU9vFcwY=; fh=jF+j1UEDAwnYbShW3HmO1TshMsWh36Jt7pSLTP62NeE=; b=S1R6exFRaybzBzJgX9eFcU1rnAWRBZIAolkIoZdcorm4tFiWmev/vj1BGwj0I1UFxw Y4Dql/E0LQ0xt/vroK5TMQ2Nt5P7YmQe8ALASajWdE31OYvjDj/pOOILLSAS4mj1ARR9 SohgbFqyavUQrmtceCeG+MMZbYSu+Lb/t0WBX9baqZLgcs3BKFw8XchfK+wsX7Kx6RRT EkrCKts8STEZphDjGtSO6jq1n3xRXJgcBTy40ezmrqZ50uihz8h+QPW0E6ODKT/FZwQs eaCZKp1ZONBN8us3ZphLFfvQELxif0JNIvWimWeNKWh73m8UsForycVcrs1dg6E95LP6 IAag== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id s12-20020a63524c000000b005bd66bfc256si13958561pgl.869.2023.11.29.03.09.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Nov 2023 03:09:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 9E08080A9DE7; Wed, 29 Nov 2023 03:09:36 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231735AbjK2LJI (ORCPT + 99 others); Wed, 29 Nov 2023 06:09:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232596AbjK2LIh (ORCPT ); Wed, 29 Nov 2023 06:08:37 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 0DAD01BC5; Wed, 29 Nov 2023 03:08:29 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E51B8C15; Wed, 29 Nov 2023 03:09:15 -0800 (PST) Received: from e129166.arm.com (unknown [10.57.4.241]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 5A01B3F5A1; Wed, 29 Nov 2023 03:08:26 -0800 (PST) From: Lukasz Luba To: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, rafael@kernel.org Cc: lukasz.luba@arm.com, dietmar.eggemann@arm.com, rui.zhang@intel.com, amit.kucheria@verdurent.com, amit.kachhap@gmail.com, daniel.lezcano@linaro.org, viresh.kumar@linaro.org, len.brown@intel.com, pavel@ucw.cz, mhiramat@kernel.org, qyousef@layalina.io, wvw@google.com Subject: [PATCH v5 10/23] PM: EM: Add API for memory allocations for new tables Date: Wed, 29 Nov 2023 11:08:40 +0000 Message-Id: <20231129110853.94344-11-lukasz.luba@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231129110853.94344-1-lukasz.luba@arm.com> References: <20231129110853.94344-1-lukasz.luba@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Wed, 29 Nov 2023 03:09:36 -0800 (PST) The runtime modified EM table can be provided from drivers. Create mechanism which allows safely allocate and free the table for device drivers. The same table can be used by the EAS in task scheduler code paths, so make sure the memory is not freed when the device driver module is unloaded. Signed-off-by: Lukasz Luba --- include/linux/energy_model.h | 11 +++++++++ kernel/power/energy_model.c | 44 ++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h index 94a77a813724..e785211828fe 100644 --- a/include/linux/energy_model.h +++ b/include/linux/energy_model.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -39,10 +40,12 @@ struct em_perf_state { /** * struct em_perf_table - Performance states table * @rcu: RCU used for safe access and destruction + * @refcount: Reference count to track the owners * @state: List of performance states, in ascending order */ struct em_perf_table { struct rcu_head rcu; + struct kref refcount; struct em_perf_state state[]; }; @@ -184,6 +187,8 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, struct em_data_callback *cb, cpumask_t *span, bool microwatts); void em_dev_unregister_perf_domain(struct device *dev); +struct em_perf_table __rcu *em_allocate_table(struct em_perf_domain *pd); +void em_free_table(struct em_perf_table __rcu *table); /** * em_pd_get_efficient_state() - Get an efficient performance state from the EM @@ -368,6 +373,12 @@ static inline int em_pd_nr_perf_states(struct em_perf_domain *pd) { return 0; } +static inline +struct em_perf_table __rcu *em_allocate_table(struct em_perf_domain *pd) +{ + return NULL; +} +static inline void em_free_table(struct em_perf_table __rcu *table) {} #endif #endif diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c index 489287666705..489a358b9a00 100644 --- a/kernel/power/energy_model.c +++ b/kernel/power/energy_model.c @@ -114,12 +114,46 @@ static void em_destroy_table_rcu(struct rcu_head *rp) kfree(runtime_table); } -static void em_free_table(struct em_perf_table __rcu *table) +static void em_release_table_kref(struct kref *kref) { + struct em_perf_table __rcu *table; + + /* It was the last owner of this table so we can free */ + table = container_of(kref, struct em_perf_table, refcount); + call_rcu(&table->rcu, em_destroy_table_rcu); } -static struct em_perf_table __rcu * +static inline void em_inc_usage(struct em_perf_table __rcu *table) +{ + kref_get(&table->refcount); +} + +static void em_dec_usage(struct em_perf_table __rcu *table) +{ + kref_put(&table->refcount, em_release_table_kref); +} + +/** + * em_free_table() - Handles safe free of the EM table when needed + * @table : EM memory which is going to be freed + * + * No return values. + */ +void em_free_table(struct em_perf_table __rcu *table) +{ + em_dec_usage(table); +} + +/** + * em_allocate_table() - Handles safe allocation of the new EM table + * @table : EM memory which is going to be freed + * + * Increments the reference counter to mark that there is an owner of that + * EM table. That might be a device driver module or EAS. + * Returns allocated table or error. + */ +struct em_perf_table __rcu * em_allocate_table(struct em_perf_domain *pd) { struct em_perf_table __rcu *table; @@ -128,6 +162,12 @@ em_allocate_table(struct em_perf_domain *pd) table_size = sizeof(struct em_perf_state) * pd->nr_perf_states; table = kzalloc(sizeof(*table) + table_size, GFP_KERNEL); + if (!table) + return table; + + kref_init(&table->refcount); + em_inc_usage(table); + return table; } -- 2.25.1