From patchwork Mon Jan 13 11:22:56 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937181 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8476D22F175 for ; Mon, 13 Jan 2025 11:23:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767419; cv=none; b=M62VwBA8I8gNbjeUznalDvUJSQqgn0haP24jXK7FFJDcseia3LF1ZN+B7Ll/3aAtkdH2CFhjTfjCINaRCm2KTGSf7X2InP4KFhr0YISFubN4eQ9QInxQj2Cnah7nfagfmnYdNArbuTqGukognEAHxEjTU0UdLosHajAq/+5wlic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767419; c=relaxed/simple; bh=t2NVGvjKSZ8jGPHeqUP8byps2cHUv/LlWtK1ugt6aZ4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WvcyZ4NoivXmIoVouTe555PWPnT8L38CHh7z3lBTtYT9bHkth8Do6pBMwyo2TAHhi1R7Wza/KTJul0VLBaKHWQNDqvXcpfmOp2QnoWRBHT3nCGXc6vLZSAHykCqi6AVKaDGmJx12bhAzlpabuoUHgy0A2+ftmgZQtKPZv/P0L0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=qAZOIls4; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="qAZOIls4" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2163b0c09afso72696565ad.0 for ; Mon, 13 Jan 2025 03:23:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767417; x=1737372217; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IkWjr0H8S/ljloJuoBCwCDqimDzQkeaXdlPta4A4wUg=; b=qAZOIls4V5W4SGXSvGGSzTWCW01R/F5//n8XhLzEJHp5pl3QruA6InJ50MzRrpkqe4 hHVFk4nBLYFBExWQi5EW1Zl55depgJDw+UdT3MPfatamxzC8wA1E1/03Na80nFupocYG uuBFKDKj17lpSxU28XSOVh2+HBX5LbV7pZMmPz8SEw/BTNXFq0E8H1JAbj8qnbtMIlFU aISjzuOyB5AmagXhv5lYG50psmI3eFwl6aUkuCZo9DhTEyqy4nwQ+fT5W4lREyySEUeK wScldyIdpZEYwX7cgaYVJ687nb/mcDk5oBm3wuehCbpwp5+d9LcGvc8nibECkdE+AvCG 850A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767417; x=1737372217; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IkWjr0H8S/ljloJuoBCwCDqimDzQkeaXdlPta4A4wUg=; b=rdEQ752gu1Q+HkXyQIx0mxng1/E7oJj+NLw8YyK7YRP58wo1Yao9sUWCdrWlrDwBEc UXexuYtj1K9Q4msbw6NaXhaLkgIOG/wskRtt0rt37MRH2HkkhhhECBWEM9y0SpMV6nPb L2I0pMXByna7CL6jKc/5USGyCfG5fVP38U8e89Iq2sP4H1VG9RzlkHjYDVdru2p3gywH Zeiqu8FdSJgsQFG45XoYdw6sbqHFcw4GP9i7iEdUwuSEaEIQavvsdo/Src3fedQHqfKV hH/N6Uhdh3ptrF20+oTN13XHjhlhd6ew90p921FiKc3i8ihisWwrt0ULhfDVOVrb7vtM z7+g== X-Gm-Message-State: AOJu0YzgxrnBEKuX0LJuLk/93EXAgKeSq4fuc7Yg5AmF7/tBihxGlGaC O+M2QnrpyykcBUM8L+cIVcUWJaI05SpD9RnMEIlT1jKdZpAGPbvEKZzFVwvjHqw= X-Gm-Gg: ASbGnctjqe2GQ5HOUTCqAgUnPBvxmgH3JQ05/Cc5svi6qLGHIALgDl4XnNCnvPKCk5v Zwk/CYGM7nSy+ah6J3V37crJnP7anwq0Cd3ewCFtSq/HE6X98pZV0nY8rRnLLkZCd5O2Qfn3x3o NhjreFAo4QpvhalS1TzV9HxpuNBY/XTMDE1NLwUIvUo+bqb74GIJDmqGD1vfNI1iC6Nz7LiZuM4 b1PE5tKlCjp4K7ui6xDphp6Vsxf749G0P2bk/1M7iFZlFXjgmI5EKWO5L8= X-Google-Smtp-Source: AGHT+IER2IavZa5iXzD4g2K372L5f9GipR0r5PB88XAPUzM7jWJLtQOWBOiD/bbJYuu6z8pO19v2iw== X-Received: by 2002:a05:6a00:846:b0:725:df1a:285 with SMTP id d2e1a72fcca58-72d21f476b9mr26557791b3a.12.1736767416693; Mon, 13 Jan 2025 03:23:36 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d406587a1sm5844149b3a.105.2025.01.13.03.23.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:36 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 01/16] cpufreq: Use enum for cpufreq flags that use BIT() Date: Mon, 13 Jan 2025 16:52:56 +0530 Message-Id: <2916658cf432f924661121a91c3269354dc41853.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The BIT() macro is too complex for Rust's bindgen to interpret as integer constants. This results in many of the cpufreq macros being undefined in Rust auto-generated bindings. By replacing the "#define" macros with an "enum", we ensure that bindgen can properly evaluate these values, enabling their seamless use in Rust code. No intentional functional impact. Suggested-by: Alice Ryhl Signed-off-by: Viresh Kumar --- include/linux/cpufreq.h | 96 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 7fe0981a7e46..bd67728081ad 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -292,11 +292,12 @@ static inline void cpufreq_stats_record_transition(struct cpufreq_policy *policy * CPUFREQ DRIVER INTERFACE * *********************************************************************/ -#define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */ -#define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ -#define CPUFREQ_RELATION_C 2 /* closest frequency to target */ -/* relation flags */ -#define CPUFREQ_RELATION_E BIT(2) /* Get if possible an efficient frequency */ +enum { + CPUFREQ_RELATION_L = 0, /* lowest frequency at or above target */ + CPUFREQ_RELATION_H = BIT(0), /* highest frequency below or at target */ + CPUFREQ_RELATION_C = BIT(1), /* closest frequency to target */ + CPUFREQ_RELATION_E = BIT(2), /* Get if possible an efficient frequency */ +}; #define CPUFREQ_RELATION_LE (CPUFREQ_RELATION_L | CPUFREQ_RELATION_E) #define CPUFREQ_RELATION_HE (CPUFREQ_RELATION_H | CPUFREQ_RELATION_E) @@ -418,52 +419,57 @@ struct cpufreq_driver { /* flags */ -/* - * Set by drivers that need to update internal upper and lower boundaries along - * with the target frequency and so the core and governors should also invoke - * the diver if the target frequency does not change, but the policy min or max - * may have changed. - */ -#define CPUFREQ_NEED_UPDATE_LIMITS BIT(0) +enum { + /* + * Set by drivers that need to update internal upper and lower + * boundaries along with the target frequency and so the core and + * governors should also invoke the diver if the target frequency does + * not change, but the policy min or max may have changed. + */ + CPUFREQ_NEED_UPDATE_LIMITS = BIT(0), -/* loops_per_jiffy or other kernel "constants" aren't affected by frequency transitions */ -#define CPUFREQ_CONST_LOOPS BIT(1) + /* + * loops_per_jiffy or other kernel "constants" aren't affected by + * frequency transitions. + */ + CPUFREQ_CONST_LOOPS = BIT(1), -/* - * Set by drivers that want the core to automatically register the cpufreq - * driver as a thermal cooling device. - */ -#define CPUFREQ_IS_COOLING_DEV BIT(2) + /* + * Set by drivers that want the core to automatically register the + * cpufreq driver as a thermal cooling device. + */ + CPUFREQ_IS_COOLING_DEV = BIT(2), -/* - * This should be set by platforms having multiple clock-domains, i.e. - * supporting multiple policies. With this sysfs directories of governor would - * be created in cpu/cpu/cpufreq/ directory and so they can use the same - * governor with different tunables for different clusters. - */ -#define CPUFREQ_HAVE_GOVERNOR_PER_POLICY BIT(3) + /* + * This should be set by platforms having multiple clock-domains, i.e. + * supporting multiple policies. With this sysfs directories of governor + * would be created in cpu/cpu/cpufreq/ directory and so they can + * use the same governor with different tunables for different clusters. + */ + CPUFREQ_HAVE_GOVERNOR_PER_POLICY = BIT(3), -/* - * Driver will do POSTCHANGE notifications from outside of their ->target() - * routine and so must set cpufreq_driver->flags with this flag, so that core - * can handle them specially. - */ -#define CPUFREQ_ASYNC_NOTIFICATION BIT(4) + /* + * Driver will do POSTCHANGE notifications from outside of their + * ->target() routine and so must set cpufreq_driver->flags with this + * flag, so that core can handle them specially. + */ + CPUFREQ_ASYNC_NOTIFICATION = BIT(4), -/* - * Set by drivers which want cpufreq core to check if CPU is running at a - * frequency present in freq-table exposed by the driver. For these drivers if - * CPU is found running at an out of table freq, we will try to set it to a freq - * from the table. And if that fails, we will stop further boot process by - * issuing a BUG_ON(). - */ -#define CPUFREQ_NEED_INITIAL_FREQ_CHECK BIT(5) + /* + * Set by drivers which want cpufreq core to check if CPU is running at + * a frequency present in freq-table exposed by the driver. For these + * drivers if CPU is found running at an out of table freq, we will try + * to set it to a freq from the table. And if that fails, we will stop + * further boot process by issuing a BUG_ON(). + */ + CPUFREQ_NEED_INITIAL_FREQ_CHECK = BIT(5), -/* - * Set by drivers to disallow use of governors with "dynamic_switching" flag - * set. - */ -#define CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING BIT(6) + /* + * Set by drivers to disallow use of governors with "dynamic_switching" + * flag set. + */ + CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING = BIT(6), +}; int cpufreq_register_driver(struct cpufreq_driver *driver_data); void cpufreq_unregister_driver(struct cpufreq_driver *driver_data); From patchwork Mon Jan 13 11:22:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937182 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D033522F158 for ; Mon, 13 Jan 2025 11:23:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767422; cv=none; b=DocZG9qnmB0NQFrJcbXPmHmDajDevlkvYd6obD1q4m0nXtSTpITxdUkkdRO2/2nUnrrKf4Ihd6iHOrBSRLOvgSXhvrQxBSHPFYMWtFsGXZ+aMYCPbrhcLU91a+ElOjmiVwAlIunXYINb3uj59a7JRl3IKNy4m1SyGNYPJW8FvZg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767422; c=relaxed/simple; bh=56mpvPQsiCQvJ/qI37RI+kZkMobzbPxSKcp097e99C8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lD7MmgtyTSQm9aU+bS7HqfFBXCTpvA/yiJGFLYA6q+y0xl5ZnKWJ4fDfJ3O3yxz9X3eO2SS+I52+i4zN9gukbYW2aB3+DZtrUaBzsHU0CtanJkXDUgVWUXEv5yD0dVYlfpnr+ebYFJtyL1pFbdwaJHmZclvL9A5J5JJJ4bC90uw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=zoeaKhat; arc=none smtp.client-ip=209.85.214.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="zoeaKhat" Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-2166f1e589cso85537965ad.3 for ; Mon, 13 Jan 2025 03:23:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767420; x=1737372220; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=pmCuXoJnBUxtp5/I8iV1DHcowuAM2GwBiNr+w7VeFWg=; b=zoeaKhatTn+ifIZiMkiG2j3DLP9fbpPpk/U28EA1lb7I2Au78wzJLNSS3m5WKglEd2 9dMU481X27b/tKaZ1JLrX1aw/4YILbogxGzTyXmUkpRFkdiGk/kWhjOBIb5z0cFdtN6o Hiy2mlXsB+f+dIQiq+ZxAie3NmU53tG6uwdi7EhvmZ6yKdqoF3M0x0SG6giN6D3wmHxN i89EHQ2YVicFju0SFWT8mA3piMSCQ+FKuXVXlE5up2ZVkU7wh5Wba3kmk3C1rmkdidyv ejUZMYUK32/rU/ybsMgmHl0KP9s9GZubI2cpdV6+X9QsLVuS+8IM2N2x33cnUfi2zLb/ Elkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767420; x=1737372220; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pmCuXoJnBUxtp5/I8iV1DHcowuAM2GwBiNr+w7VeFWg=; b=rmNRhoQ7G5Y0oQSMzXV4ih5H4RiXKoNTdYliZsnoAjSMdKnj0l1mbykcdvnnIbw/Hh vckL4Yi3nSvJtf3lBKlW8PwA5XWNAvbmGBPqGTRpqJ59xpMu4/BBWCoeoCQ0qjB9J9Y4 OPtwum0hlS5zjsxKgPiap9rbWfdibnto77keLsGe/YJCasb4GFe9AW3bk0c+pF7O1l6k 6mO3D9PiO8AZK9Yzy3JbGaKYx49vgd/O2PV5Q45Nd/BAcOeZCr6eMAXZaw7+YUpGVOSa mcBNDQTSOUJl/UnVFwbDIJMKxa0NRnFXAbboOdsZqXRcWHPsQZVRUJStDoJtz+8RzQzX DkTw== X-Forwarded-Encrypted: i=1; AJvYcCWFz63utlj0W4dMtaRRGj2GQWsbtb9RwJyOssdKuUZIuA7v4MKjBh+t62+0n8KjuNWK9vwRaZ5tWw==@vger.kernel.org X-Gm-Message-State: AOJu0YyUDEb39xl8QDw/7uozPaLOnEKoIYY25FG/25Uj+LPbZUVEM0xA mzzO/zms5TAdkq44ircEMZwwReyK4iX75mbwVT562KVg32C+dIauNYCz6D17+yw= X-Gm-Gg: ASbGncusMGrmOui1pAmVUSWF86vainhxxQtJLC/m8de47fPqlq0Uv25ZC3EQ7JZ6PqK 90uoL/pywMB73ZBixXF9ZnZOlGhGozVe5mm422MA2i3UkxpjHn9mKF91j0zZ5RE+c90kY/JYF2R bL4AFpArB4BLMBt++zQWRng45MqZlX122D7BDSKR0eE0TpOm2o2ZiPWP8Otx2pa9Z8/1LjV81UH vnOUCJPY6oqO3XuSGMgYlnw1f7MXWn7OXdIe7hr844VsIo/wkqNZnf+gXk= X-Google-Smtp-Source: AGHT+IEBqAU9m/Dz1cRS0HnmcowXNpNvmSNlZypDvYg39Eu5fhkkroa7r15wE1tObjFtw/U6RyJuJQ== X-Received: by 2002:a17:902:f70f:b0:216:32ea:c84b with SMTP id d9443c01a7336-21a83fc3652mr310297025ad.37.1736767420205; Mon, 13 Jan 2025 03:23:40 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f10f860sm51777815ad.46.2025.01.13.03.23.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:39 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 02/16] PM / OPP: Add reference counting helpers for Rust implementation Date: Mon, 13 Jan 2025 16:52:57 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To ensure that resources such as OPP tables or OPP nodes are not freed while in use by the Rust implementation, it is necessary to increment their reference count from Rust code. This commit introduces a new helper function, dev_pm_opp_get_opp_table_ref(), to increment the reference count of an OPP table and declares the existing helper dev_pm_opp_get() in pm_opp.h. Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 17 ++++++++++++----- drivers/opp/opp.h | 1 - include/linux/pm_opp.h | 6 ++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index be3291b53719..73e9a3b2f29b 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1528,11 +1528,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) return ERR_PTR(ret); } -void _get_opp_table_kref(struct opp_table *opp_table) -{ - kref_get(&opp_table->kref); -} - static struct opp_table *_update_opp_table_clk(struct device *dev, struct opp_table *opp_table, bool getclk) @@ -1693,6 +1688,17 @@ static void _opp_table_kref_release(struct kref *kref) kfree(opp_table); } +void _get_opp_table_kref(struct opp_table *opp_table) +{ + kref_get(&opp_table->kref); +} + +void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) +{ + _get_opp_table_kref(opp_table); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table_ref); + void dev_pm_opp_put_opp_table(struct opp_table *opp_table) { kref_put_mutex(&opp_table->kref, _opp_table_kref_release, @@ -1727,6 +1733,7 @@ void dev_pm_opp_get(struct dev_pm_opp *opp) { kref_get(&opp->kref); } +EXPORT_SYMBOL_GPL(dev_pm_opp_get); void dev_pm_opp_put(struct dev_pm_opp *opp) { diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index 430651e7424a..5c7c81190e41 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -250,7 +250,6 @@ struct opp_table { }; /* Routines internal to opp core */ -void dev_pm_opp_get(struct dev_pm_opp *opp); bool _opp_remove_all_static(struct opp_table *opp_table); void _get_opp_table_kref(struct opp_table *opp_table); int _get_opp_count(struct opp_table *opp_table); diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 414146abfe81..c247317aae38 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -100,6 +100,7 @@ struct dev_pm_opp_data { #if defined(CONFIG_PM_OPP) struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); +void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table); void dev_pm_opp_put_opp_table(struct opp_table *opp_table); unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index); @@ -160,6 +161,7 @@ struct dev_pm_opp *dev_pm_opp_find_bw_ceil(struct device *dev, struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, unsigned int *bw, int index); +void dev_pm_opp_get(struct dev_pm_opp *opp); void dev_pm_opp_put(struct dev_pm_opp *opp); int dev_pm_opp_add_dynamic(struct device *dev, struct dev_pm_opp_data *opp); @@ -205,6 +207,8 @@ static inline struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device * return ERR_PTR(-EOPNOTSUPP); } +static inline void dev_pm_opp_get_opp_table_ref(struct opp_table *opp_table) {} + static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {} static inline unsigned long dev_pm_opp_get_bw(struct dev_pm_opp *opp, bool peak, int index) @@ -341,6 +345,8 @@ static inline struct dev_pm_opp *dev_pm_opp_find_bw_floor(struct device *dev, return ERR_PTR(-EOPNOTSUPP); } +static inline void dev_pm_opp_get(struct dev_pm_opp *opp) {} + static inline void dev_pm_opp_put(struct dev_pm_opp *opp) {} static inline int From patchwork Mon Jan 13 11:22:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937183 Received: from mail-pl1-f178.google.com (mail-pl1-f178.google.com [209.85.214.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF161239799 for ; Mon, 13 Jan 2025 11:23:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767426; cv=none; b=b4LIbjgWhdvo/8hBEepGORuEgX6sqlB8Rx53g7Hio+SLk3tA/1/R4zbuvCjTsq1Wu3Mhg/7FohaDAGM0y6wNwBA1D7EtK5TpwBYU12ebfClZnJOol8DnhJT2+7UVkLv8kpR35uZdmmsTKA1TF0LEcRMp+24O2/gG1dyFJQ85BZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767426; c=relaxed/simple; bh=Log7cXXjzMiJkcv5gL5n5WiPvymmPQBug9ZqKR86Yek=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=MExGiOOHEkZq8qKd+2onu5fdgAoQrl6N9l3DgBkow919EsKChuwQyOC5vyAXu8dO+CvJRFMwkwkIn3CC+CsnUSZFkoKvFM4mX++vx5oZ6PyLtBW8X/A4qkW5uNIbnNWlywVEQxYUEUKpjZs0KHQTYNTblpeUNJvGfnKmWk0PmX0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=mNDWtdYm; arc=none smtp.client-ip=209.85.214.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="mNDWtdYm" Received: by mail-pl1-f178.google.com with SMTP id d9443c01a7336-2162c0f6a39so90526515ad.0 for ; Mon, 13 Jan 2025 03:23:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767424; x=1737372224; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tdn4m6dKlofswR8ctFShfrfS5TKeZlPBTra3kXQON/0=; b=mNDWtdYmQwesy81qm8USSreo7D38hLW3H26UTPJDW0KT9V4Xc2yow55rOKD8HrGwKK EA89HIE4gczQjdiWGS5a9AsRpkfk6j0xbI+aYf6jqAsuLfNEcazhlfzwSdE06+WJ96jh UOJdd7UGyVAKCY8h/cHkx6nyFlQOmDH8zV0nCkoL3eMUNVbCWGrO5IOKLEjtMKh2Hqge 1EbsTpNptfIbgBBoWfBocZ78KE/fNrq1JuygiMlnDwefnvKOv8k0/iPgsNQB9Y9TGum8 mIzHEIpT4Dt1F/PCVFV9nQfeMusgo3KKdQR9AU/kLpQkL4oS0WkRL7dkq+EfaXYNKCBV faBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767424; x=1737372224; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tdn4m6dKlofswR8ctFShfrfS5TKeZlPBTra3kXQON/0=; b=gbUPNvWm3FMeKIkFlGS2HYE5opLVVWuz/VoxTMLBMNpJOX/GE9Dbeyr29UWQYWLN5i /ZtsJDdmxICy5t+r99gR6lMbe0JhTg9wu73vdK/PUVkECR8q5zMFA5D3wd5CBeE0kpn0 TRres9r1geFCGE85uAYoGyQSKKVBO2oXJC5qrtzPXAcxUelsJa3yHZZge8OgApEWTEvE XgFdBmQawhY6JcnmPULZNkR3Uj1RIIZMkXCVdyqbzYHmeAIEyYGcFcrbYxEC/JShgrvN PYIffSmAbRry85kpD+fOTVMoTZ742IDKF5zNuokjxBml8zgv46IhDI843x1VE8oS4XFZ N1FQ== X-Forwarded-Encrypted: i=1; AJvYcCVAhuGneNV5Wyu6XngKvNTKZqST+ZG7lV+boUz25to2J1n+zdGQihdVBbn6fd6oODWBAQCnLzNk1A==@vger.kernel.org X-Gm-Message-State: AOJu0YwkbIVqHjMj7oc8JtR3xu6leil0ZPufxlTVGmFUITOyOyUAGoYi 3Ln361n7gtOgitLDkUUyxandf87Bc7f7tdTTo6z8/qI2HiIQDsCknEgRa5G965s= X-Gm-Gg: ASbGnctyMt0yN8rAt9Z+P6RkLWL1v0TKRRseocHOoxHRDX45Xgm0IVhhkEIKH+wj/k6 KYA6t5ZL6LN821eTKOKUok0P8Du8gNfX8Nfb5wH7js+sRvF1MXk/c8RmMIe4SaxNeOl33ejBkx0 jaa4z/9TJ29q9N1mlKHy8InKigxWbF1idl2zJ6cepkix371D/fiuEg/Ss7RjPuOV7NsQ/9XLF4X +GhHTtpKGP5zbPSp05wHSHIG0U+Zs5X71D3XGh8bCqrx7I+504uyDcKw+w= X-Google-Smtp-Source: AGHT+IF0Y5yG1c5M9n48ix5v1C+TyVEgXKMj6yF6bVdvpXIdxxQSPZGVPl+AyedZLky2FVhj80qa6A== X-Received: by 2002:a05:6a00:3bc9:b0:727:39a4:30cc with SMTP id d2e1a72fcca58-72d30301d86mr19474714b3a.1.1736767424079; Mon, 13 Jan 2025 03:23:44 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d4067e591sm5677575b3a.126.2025.01.13.03.23.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:43 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 03/16] rust: cpu: Add from_cpu() Date: Mon, 13 Jan 2025 16:52:58 +0530 Message-Id: <854f7b8c9cbcc7f38fe5ed548290f41224478b40.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This implements cpu::from_cpu(), which returns a reference to Device for a CPU. The C struct is created at initialization time for CPUs and is never freed and so ARef isn't returned from this function. The new helper will be used by Rust based cpufreq drivers. Signed-off-by: Viresh Kumar --- rust/bindings/bindings_helper.h | 1 + rust/kernel/cpu.rs | 26 ++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 3 files changed, 28 insertions(+) create mode 100644 rust/kernel/cpu.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index e9fdceb568b8..d63e7f6d10ea 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/cpu.rs b/rust/kernel/cpu.rs new file mode 100644 index 000000000000..422e874627d2 --- /dev/null +++ b/rust/kernel/cpu.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Generic CPU definitions. +//! +//! C header: [`include/linux/cpu.h`](srctree/include/linux/cpu.h) + +use crate::{ + bindings, + device::Device, + error::Result, + prelude::ENODEV, +}; + +/// Creates a new instance of CPU's device. +pub fn from_cpu(cpu: u32) -> Result<&'static Device> { + // SAFETY: The pointer returned by `get_cpu_device()`, if not `NULL`, is a valid pointer to + // a `struct device` and is never freed by the C code. + let ptr = unsafe { bindings::get_cpu_device(cpu) }; + if ptr.is_null() { + return Err(ENODEV); + } + + // SAFETY: The pointer returned by `get_cpu_device()`, if not `NULL`, is a valid pointer to + // a `struct device` and is never freed by the C code. + Ok(unsafe { Device::as_ref(ptr) }) +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 2d5c3d7d2e21..e9106b29c359 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -39,6 +39,7 @@ pub mod block; #[doc(hidden)] pub mod build_assert; +pub mod cpu; pub mod cred; pub mod device; pub mod device_id; From patchwork Mon Jan 13 11:22:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937184 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0D03B23A570 for ; Mon, 13 Jan 2025 11:23:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767430; cv=none; b=IoGa1nFpL62bHZSSc6BoTgBn5oRVKjo4QFUA5yk4wd0FczsA7t4X4QBm4rpxuPjRd5WSddO3udOsQAIzoBjracZq6uQCHDwhl8M6epAkY5VDa4t7q3Xpw18ruNwb06gLktKM7t7Hk0H1LrFkRkyzPM3bsOIB0ifxlB/T/BHN3cw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767430; c=relaxed/simple; bh=qFjzLah+7k0bGLsf807G16R7Nl932aHbCVEztV18Qug=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Bf+ICI/5akCYNSQ3FHXCGivkoYrfLOMn7D+ceRtFgXm4pWFQlnHTouDIpcBwNNklG+fSJdIQk9xmyeYqe6pNXnng18CnaFnstiscpN4t6LXq3/gqQBmCW7MdSI0nQJKVXw1uJx504OzLwpYyeLv1z0xgOao5rxIyjakspRZyEB0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=whRU9Cfj; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="whRU9Cfj" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-2166651f752so90387725ad.3 for ; Mon, 13 Jan 2025 03:23:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767427; x=1737372227; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Erl89OKGaS5TERvIe2o6tMzhWrw69h3Z1JOwTaxOJAQ=; b=whRU9CfjTnHWSyizQVtwhP59wdi9PnmXTxU0lGYVZ2iGN3hA10ZihH+eLtxU9PG1XH IH5HRO/Fi4Txp9Kv061J8jDSGnWBFnTnupIRUaxNaOIrUe3hDVa3pHCoKSoWlpOD+BYK 5taBS0fy3OpCTJ1BuhRd2GhQQDuX6X23Yaqa3XetPkLqrFIhCq3VVb0KCh6MrRJN65wx Q9J+IQY4lMrR8fD+lF/i2k7G8oeoiNhe3DxFfDQQwmWZoIgKGcdjEzrudnUfKB6qq2pN NbPg32wBec267vXW7RKS2id8FCkzgr9rSML4d55Fzs3T+dGCieQ5wN+OsuCtisjzkxrY 1/tQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767427; x=1737372227; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Erl89OKGaS5TERvIe2o6tMzhWrw69h3Z1JOwTaxOJAQ=; b=Ok9bTXdZp3zqUDBWZxsnTKX06pCYz2dcJj2uJzz6KACm57RQw5NVEZUJiZ6Vhwdrqv UEl524wG1e11LDJuDwc5hjHuEsZtqZETK5dqN8kGinYOzF4fJDPHk9O+Dg8S7Fl6Y2z5 0yHONiMpbmH6R9iyFf3OUtlnialR2z76uIM+puy4hU1rhGZGq1pw1UK5AmDqt1VgWbVC bFCgnHfLaDroW1OxWKNLjIKrUit+2iXwqDXEXjZPSUcJvdBYetOqUKzwprCxxs6FXdMJ g+XvHMRSuVH4D4WhH68CGSXMi5RD7G6/QQ1O3kwn/1hAArzPLVuNQHCXHSqXbrewDHPp J59g== X-Forwarded-Encrypted: i=1; AJvYcCV5YYrFA8tntPOu/LAaU0DJDum/X+c0Gl4HKKbyQjRW1nasq8C+Mgsdyxe0ribFt15vVDsSerAL8w==@vger.kernel.org X-Gm-Message-State: AOJu0YxneP+9iHB9ZIr4epqtFhm8e0nHbg6UCHDrSyZgHjCPsraLmeRy S/NDsaoMjq+GjcBbNyKU2G+KSYVqwt4TnSEW6ruMSu1dy+LmPfZtCI3fcmBRpPU= X-Gm-Gg: ASbGncuFy9N0Mu4VRiK7SwsPSOKUffE0CzmpDszLLgvk5mKFV/voDjW8zMoiYB7P23n fhTtqs1QJx3dDiO4EjtmNGfaD0bD7s688PBvfwqjSO8eBIKe3vEmuBG4x9KyYxxVKu4Zmwlt8ea EG+Zh0hpC9k8T5KKMZz4EiZ7ExdRSo14cVX9hDa3zTJhahjDHZkAq1AfVdvfQD+7eH1mkAjO8QY S4fXUEi0EHiFty5s/IVXdRRQYuo60amphGYnFqFYXIiRzn7GHSfbOEBtVQ= X-Google-Smtp-Source: AGHT+IFwnNOadRELhgUS4RHnfHmljCOFqvDn5NHiGTae6Lam/bomtLxFMSA+qHltYXwddKyNK29zYg== X-Received: by 2002:a17:902:d2d0:b0:216:45b9:439b with SMTP id d9443c01a7336-21a8400a357mr316419915ad.50.1736767427451; Mon, 13 Jan 2025 03:23:47 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f10dddfsm52432345ad.23.2025.01.13.03.23.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:47 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Greg Kroah-Hartman , Danilo Krummrich Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V7 04/16] rust: device: Add property_present() Date: Mon, 13 Jan 2025 16:52:59 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This implements Device::property_present(), which calls C APIs device_property_present() helper. The new helper will be used by Rust based cpufreq drivers. Signed-off-by: Viresh Kumar Acked-by: Greg Kroah-Hartman --- rust/bindings/bindings_helper.h | 1 + rust/kernel/device.rs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index d63e7f6d10ea..fda1e0d8f376 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs index d5e6a19ff6b7..e8c4cda5aacc 100644 --- a/rust/kernel/device.rs +++ b/rust/kernel/device.rs @@ -6,6 +6,7 @@ use crate::{ bindings, + str::CString, types::{ARef, Opaque}, }; use core::{fmt, ptr}; @@ -180,6 +181,12 @@ unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) { ) }; } + + /// Checks if property is present or not. + pub fn property_present(&self, name: &CString) -> bool { + // SAFETY: By the invariant of `CString`, `name` is null-terminated. + unsafe { bindings::device_property_present(self.as_raw().cast_const(), name.as_ptr() as *const _) } + } } // SAFETY: Instances of `Device` are always reference-counted. From patchwork Mon Jan 13 11:23:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937185 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E179823A59C for ; Mon, 13 Jan 2025 11:23:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767433; cv=none; b=CBmF2ZQSFx1GxtaxqpKyCI7kNZZftXyUaXCyJ8lsRgiodabd/tzd1Q7g8U9sjtARVwPqivZpAXNX4WSmA9SjZgeVQOeVyU0fGlr5MCm28iFjl1iOmUCoafPl3MBBGHjFuAr3pNzXVH6OYTEaM+7Gm2tfHHFY/CYYTvjqKWF1nDw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767433; c=relaxed/simple; bh=zpYDXqsOf66H5oUlZfzc8U4T3Ym6DA5SpJV3ddgDOqM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WMYjev1zbuQ5QHshyPV+Vw8tcoZtwOwez9ux0dvPa6/TplsJrldeQj2OBml5RnJYGpYRRaoyDLq2QSQkqqmvx/xnDSFMqxuIeS9VqoWZxyCD0/m9oEBWEV/LKFjuyVQM73M/Epn0T5lBY5jKrSzEaa68SQKEP00fgt5z7GRKBbk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=bfRBwU6z; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="bfRBwU6z" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-21644aca3a0so89656325ad.3 for ; Mon, 13 Jan 2025 03:23:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767431; x=1737372231; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6pq5lDpyHLAZUwHZL3qfvRqj8bZ5lnU8jFdny8YX3GE=; b=bfRBwU6z8Kn6jFtS42kbw6bXFOLddaA5LWH0bKWeb5vLVwycl94DItaHPlemQ18CKh zrBAKVKpPyNEhvl3wpiHZnbDZN9TOd6cYLwIfcHbyGJVA0NPrr9DPV2YsD3nt+DhS6Cn a3AxVjNvRyneCani2PgMDtFZU44XzJrL+llO7qBYV0kvSwwrkhenDQrKzfrQJaHkGwnW TQoPqGL5PBWxFumNaKMkujGhMMtkWZ9J69+p20VvMqMaicmcFKgosfJcxBmBoWKMjhnC 95xhRvAMxwHeFa0qReX/zJi6LRRhFrJ7n53TArofUsBfJWuWhsW9AoRFgbw/WgxS/T+t 4wIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767431; x=1737372231; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6pq5lDpyHLAZUwHZL3qfvRqj8bZ5lnU8jFdny8YX3GE=; b=cQS+NxwGeogT1em81ROFD8ngjJ1rCN3qY6G7K5wQAfVFLnVai1eKXyHULZWCAPVIWz UvxXL/Y1c27vIWxVP9qTDIXO/AZqmJbgODbthQNOqciqyBV7QKouquRQcnKHpnW12bvo NggNTqWeeL2n4YGvLTD+r/sbfBV+/6YMX3ajSwaAzHgKIRlnZ1H8O3ukTRby9dCBc7MC LIJxIuOylES6gbuIjuCNCOc99zs4HC9o9Its+iOucU/SpKgszQc1+S84K+AldJHc6VWy dcNe7K9QiFpI4jJ8jWiuNSy7+EyJEb/ipv+vxfOy0ETsL00e0E9diRgnjLhJC7OuOYHd KeTA== X-Forwarded-Encrypted: i=1; AJvYcCUyBhDNX5UOlVAXjyqEkniPDh24NiQIjqdY32gQ2+pwINvYoaj8snBaV4lCbR3yNK8i7USZnHzKhg==@vger.kernel.org X-Gm-Message-State: AOJu0YyhDzg9ArTP7vK4IVL7keveLRBZMRcF4ImZdcURP2h0/KZrIbrO twDPNKD9ar1T4sqg9AxjTrs6V8gZRTieUDPcJxN3RPZ/sIXS825wpbeUgx7tAsg= X-Gm-Gg: ASbGncvQXV/HrXNcz3/dPVXGZGG7fq1GwbnKQD8A6vsSsz+CIzxfn9S0nvgGmOmWgHH 6cXMpYjYVD7roXQaX4ZCMun0WG9i9dKtdsRB7Sl3E5v0yQGD3WxYl4akxFUtYr38GAAuX3oplV4 N3CIeXsa/rVLcW7hzY8mdal613vvrKy0VFV+qrdLabQi+GseIBk5b7Guv7vK1TqMj6lOhYt9kMD qJY2q2dkEoZvcxDbz5mPhkOZhQm9vq8rNAGHcatMAlMIsVfQ+RkrvuvNkE= X-Google-Smtp-Source: AGHT+IEOjxJGVr7HBQVa0jzU1CKfFnjVBIzuSJp/j9DkYQxsSgo0CuPg7K6fdft0Ynvn0NGP+sGtsQ== X-Received: by 2002:a05:6a00:10d2:b0:725:9d70:6ace with SMTP id d2e1a72fcca58-72d21f5c141mr27897173b3a.6.1736767431251; Mon, 13 Jan 2025 03:23:51 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d40681b3dsm5683664b3a.153.2025.01.13.03.23.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:50 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 05/16] rust: Add cpumask helpers Date: Mon, 13 Jan 2025 16:53:00 +0530 Message-Id: <5260b6f0308b67ca5cff002e95108504f04cf923.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to prepare for adding Rust abstractions for cpumask, this patch adds cpumask helpers. Signed-off-by: Viresh Kumar --- rust/bindings/bindings_helper.h | 1 + rust/helpers/cpumask.c | 35 +++++++++++++++++++++++++++++++++ rust/helpers/helpers.c | 1 + 3 files changed, 37 insertions(+) create mode 100644 rust/helpers/cpumask.c diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index fda1e0d8f376..59b4bc49d039 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/cpumask.c b/rust/helpers/cpumask.c new file mode 100644 index 000000000000..0b371826a13c --- /dev/null +++ b/rust/helpers/cpumask.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +void rust_helper_cpumask_set_cpu(unsigned int cpu, struct cpumask *dstp) +{ + cpumask_set_cpu(cpu, dstp); +} + +void rust_helper_cpumask_clear_cpu(int cpu, struct cpumask *dstp) +{ + cpumask_clear_cpu(cpu, dstp); +} + +void rust_helper_cpumask_setall(struct cpumask *dstp) +{ + cpumask_setall(dstp); +} + +void rust_helper_cpumask_copy(struct cpumask *dstp, const struct cpumask *srcp) +{ + cpumask_copy(dstp, srcp); +} + +bool rust_helper_zalloc_cpumask_var(cpumask_var_t *mask, gfp_t flags) +{ + return zalloc_cpumask_var(mask, flags); +} + +#ifndef CONFIG_CPUMASK_OFFSTACK +void rust_helper_free_cpumask_var(cpumask_var_t mask) +{ + free_cpumask_var(mask); +} +#endif diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 0640b7e115be..de2341cfd917 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -11,6 +11,7 @@ #include "bug.c" #include "build_assert.c" #include "build_bug.c" +#include "cpumask.c" #include "cred.c" #include "device.c" #include "err.c" From patchwork Mon Jan 13 11:23:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937186 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C8D4C23DEA4 for ; Mon, 13 Jan 2025 11:23:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767437; cv=none; b=g9420Yf7aPk6ooT5DlwNQr24KdSQMxtNTb+vsMOeAvlTP0+gX2IZBJx2IBioE/v505407Id6WXYqqE1B5ihBtPp+zWnDBecpn+Kupf1mT12c0LR5YBALU7lWzs3BB80pGFaCkvFqYMcPYEuBBqI2FJgPnj+c0qXw5JycXqLjiXM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767437; c=relaxed/simple; bh=fhjAe+tZdJoItHGU3pbD+/oYCE2BaIDZH25E8DWX9nw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=f0wUVWbHU/6Icnx6LUQ4XOmheO26lwnJqyBTsm72jPFK5EniYidquT06PJgVKDguregL07dIEMhhkZ4nxcBdP6YmehMCYj76mycuXVvN+FQk0ScTs3MJkIC0iXKIVX9KE1HB9HXK2bGs7p5Tq8ADODnaKrcJy3HZoI/yPwYFaMQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=QeGxawUt; arc=none smtp.client-ip=209.85.214.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="QeGxawUt" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-216401de828so66447585ad.3 for ; Mon, 13 Jan 2025 03:23:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767435; x=1737372235; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=czbTFxrFTC6BGzHp/oKzcB8oNYeLUKg2TzQ6UGtz5yk=; b=QeGxawUtpUaYPyl8MXwU04iGVaWdgKk9OXtLGWlKFqfNxFgWYcdPpzXrAc4+RrTwzA vY2DoMxneziblh8fGvMg7+rTjXOSI+tcw+iOWE+rKzJkYSJ1Nbv63F909FCLN7h8VNJE IU3nm3Vct7dsE9QqL5ub5CTYRhJU1usDc8G2S19a9kslaSwJ/j8H63vW69yAbzHUI9Uq uBcZqIvFoeCthzObNhs/sCFoTy/fFppGiW8S9hKNne/Qry91FxVorXxBuI9DfwIEmnD2 vTTtyW1+zGeU2uQixeHWQmPLdn5Dqx2m5E/A8/8GkeSNOHQ7gFpj0e71g7jZqrlc5js1 5OHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767435; x=1737372235; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=czbTFxrFTC6BGzHp/oKzcB8oNYeLUKg2TzQ6UGtz5yk=; b=eHSF5Y98v2vUoQ5AbL0Ksm00ie325dcDElnxf7OCHA7e2QNJBMC4pAeAKDkqYj0386 QePvtccyzXHOO7OCYJCuV+t70d5aGkQ7Ai/8t1oUByeRBlvuMkrgkwTfwWrDxN/9sDk/ inWbEKuWkzT/SE9+R4B6v2ov7mFWT3T5cd7jk86O1vyNEUDPPhwuyafYybSirbxs+MMt AfSxP886Qm9EmsxMu4eQ5qiuUcAJmF5xlifFKFRqpxUoqMHZZRqlj85upn3d3yfYBcIP oA7vbCgsvCk4oUk2AJIJwxeUJalKql3qkUCUcXctxRjB7yQBrvawdMEp335Ebx7vCwGP jWiw== X-Forwarded-Encrypted: i=1; AJvYcCWgZnmyo7shpGnqX86sw7iphZPRxohCLOEHJipXz5SFggzwXLG+PAQ1lQJzZCiU6FPhfZV9NlEkFQ==@vger.kernel.org X-Gm-Message-State: AOJu0YxjCOZmMC19npmxJBERSzmGgQcqdIwBQlsA1k4vJNOYgugKsNN9 frBUna4XBnTaGQkkZ5R8Fe4wQ/afiZ65WZVsR6D1K98RHems0yDMDxyJQIzWPfk= X-Gm-Gg: ASbGncs180vW5Es8GxZjur9GqVYRh1osAUg4G2qpDZyXnu1aiKx6JzzYlQm6bsmCyzm vlyzsuiHiKE/XloLHcNcz4xcSj7BjesuQNd2MBLnhYv4bI58M0jbkhFvi0i8W7Eu8NRLcKGrSl/ wgQDScpJHHB8b4j1Ls7c5h/XUyaHEsQc608o2vrscuhug3sc/g42zBs4FORZxwCle8+MFsaqtSx 6/f9Fog+tF5qG/HwloK0ZJWfOfWVEapCSJbim/AOGPVln8M2fPcSH5Cc2Y= X-Google-Smtp-Source: AGHT+IGieekbwx3qrgjAyDs5pUfdvjfV28c0KO0g2MvkIOQBBkbaEI8L2WbSDSmjUT3+UgBrDwIJ1Q== X-Received: by 2002:a05:6a21:32a0:b0:1e1:abd6:ca66 with SMTP id adf61e73a8af0-1e88cfdc6f0mr35358105637.24.1736767434793; Mon, 13 Jan 2025 03:23:54 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d4065a544sm5938475b3a.96.2025.01.13.03.23.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:54 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 06/16] rust: Add bindings for cpumask Date: Mon, 13 Jan 2025 16:53:01 +0530 Message-Id: <4f233d3f6d593ba2e1cdde68af44200cae74f6f2.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This patch adds basic Rust bindings for struct cpumask. These will be used by Rust based cpufreq / OPP core. Signed-off-by: Viresh Kumar --- rust/kernel/cpumask.rs | 85 ++++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 2 files changed, 86 insertions(+) create mode 100644 rust/kernel/cpumask.rs diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs new file mode 100644 index 000000000000..e3b15bc12798 --- /dev/null +++ b/rust/kernel/cpumask.rs @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! CPU mask abstractions. +//! +//! C header: [`include/linux/cpumask.h`](srctree/include/linux/cpumask.h) + +use crate::{bindings, error::Result, prelude::ENOMEM}; +use core::ptr; + +/// A simple implementation of `struct cpumask` from the C code. +pub struct Cpumask { + ptr: *mut bindings::cpumask, + owned: bool, +} + +impl Cpumask { + /// Creates empty cpumask. + pub fn new() -> Result { + let mut ptr: *mut bindings::cpumask = ptr::null_mut(); + + // SAFETY: Depending on the value of `gfp_flags`, this call may sleep. Other than that, it + // is always safe to call this method. + if !unsafe { bindings::zalloc_cpumask_var(&mut ptr, bindings::GFP_KERNEL) } { + return Err(ENOMEM); + } + + Ok(Self { ptr, owned: true }) + } + + /// Creates a new abstraction instance of an existing `struct cpumask` pointer. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid, and non-null. + pub unsafe fn get_cpumask(ptr: *mut bindings::cpumask) -> Self { + Self { ptr, owned: false } + } + + /// Obtain the raw `struct cpumask *`. + pub fn as_raw(&mut self) -> *mut bindings::cpumask { + self.ptr + } + + /// Sets CPU in the cpumask. + /// + /// Update the cpumask with a single CPU. + pub fn set(&mut self, cpu: u32) { + // SAFETY: `ptr` is guaranteed to be valid for the lifetime of `self`. And it is safe to + // call `cpumask_set_cpus()` for any CPU. + unsafe { bindings::cpumask_set_cpu(cpu, self.ptr) }; + } + + /// Clears CPU in the cpumask. + /// + /// Update the cpumask with a single CPU. + pub fn clear(&mut self, cpu: i32) { + // SAFETY: `ptr` is guaranteed to be valid for the lifetime of `self`. And it is safe to + // call `cpumask_clear_cpu()` for any CPU. + unsafe { bindings::cpumask_clear_cpu(cpu, self.ptr) }; + } + + /// Sets all CPUs in the cpumask. + pub fn set_all(&mut self) { + // SAFETY: `ptr` is guaranteed to be valid for the lifetime of `self`. And it is safe to + // call `cpumask_setall()`. + unsafe { bindings::cpumask_setall(self.ptr) }; + } + + /// Copies cpumask. + pub fn copy(&self, dstp: &mut Self) { + // SAFETY: `ptr` is guaranteed to be valid for the lifetime of `self`. And it is safe to + // call `cpumask_copy()`. + unsafe { bindings::cpumask_copy(dstp.as_raw(), self.ptr) }; + } +} + +impl Drop for Cpumask { + fn drop(&mut self) { + if self.owned { + // SAFETY: `ptr` is guaranteed to be valid for the lifetime of `self`. And it is safe + // to call `free_cpumask_var()`. + unsafe { bindings::free_cpumask_var(self.ptr) } + } + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index e9106b29c359..2f72e1d8a6b7 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -40,6 +40,7 @@ #[doc(hidden)] pub mod build_assert; pub mod cpu; +pub mod cpumask; pub mod cred; pub mod device; pub mod device_id; From patchwork Mon Jan 13 11:23:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937187 Received: from mail-pj1-f43.google.com (mail-pj1-f43.google.com [209.85.216.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5AE3423ED4E for ; Mon, 13 Jan 2025 11:24:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767442; cv=none; b=cMPHdQm9LSEa9DBmN0nQH0yC5DD9suiqJVjHF0kQrHHwbtsguBWEoB5nvGPB6/ZAYPcKj5QB7ESKzpC96Gz/hhoXWMuDlBhIS1N0PTJnFgLVb3/Ryj/XL5HgFlpUughX5qitLvppzAPrXg//Gh9wvaGdMvfAHWrYicUsUsJU6Dc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767442; c=relaxed/simple; bh=XP0PNO8G/853ZISR4NFJL60BlTm8G/dA7ahDgJPTbK0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=SescKbGK7b0N4gQNeegZKJPuhn1T6NNfn8xgHV5y2KPVQKIl+tuYGBFw3Aiy7M8K8Rnct0/nOcioJS2NLWi9XksiheYA81ab6HqbMH0tkPBA18wtuXW6ZLz8JL0E6khIBJJJbaXHhI4l9+aacBJ1Y1X6gdmcXJ2HhRKLrkkhYjo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=pvJ/aNJN; arc=none smtp.client-ip=209.85.216.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="pvJ/aNJN" Received: by mail-pj1-f43.google.com with SMTP id 98e67ed59e1d1-2ee9a780de4so5199042a91.3 for ; Mon, 13 Jan 2025 03:24:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767440; x=1737372240; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=217qCdop/bVuj9XoV8EFEQ4K3BvCuSwvnN0rQfYprBA=; b=pvJ/aNJNM6hWazWxuQNk18EMYgd+DQl6rWe8maE2K6y694RoJQJS3Fw2E48J+Vh/8r 7FfGwN/ihgaV1QDaWWfp+kMOUB29dLZX0DnhwbE79I/jZUIWGyErGh5FXeoGApDnPdZK O8cWXyg838GYNaC2dHu0U0Z5FfOBlS/tWOHnmZJ2ldP+p+/+++J+rreaFfg6ttqEG/OD WTvlVw9BlK0UbpDXoY8vj7qWhMZwwzHLiU2c566Q+NBo2oVBwYH8+6r7E7HpjOMl6ezJ PfcL+tbmtlleGL3K//Qd/jhBIgzUfAKjLGz/3ILSD15hihymIWt57dWFCPmww6Br0S5U Vo4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767440; x=1737372240; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=217qCdop/bVuj9XoV8EFEQ4K3BvCuSwvnN0rQfYprBA=; b=SdnsCdFHQrnJbTGJk8wY76c9bhkSztg4Ivw8qZKicDMg/30ieaYaeRx1tJFZWBpX+K afFNAQ5O06B5a925OcWYd9IsTPZ5ZFNh8FD1tecGsGmMS9iC+MMev/TRD3WIjJMrOUVB TVZgjQp+Ej6SnVZ0B9f/Y2kdbv44NyRDUAxWvut/VH7//B3XWF7qfeFyZS1OfmACC5gG 7HTX2wtHpjP5FI17pWa4gGyWeBxq4KFTZ8g1ED7PfkuKyEgOtw634pndwNnKfJkouNOd DN9s56qduIPzWSH2tRbzI53oFLpM1AoBILJkjXow4MNcthupoAlQ7+jVQw2q+WEAtK7J 3EFg== X-Forwarded-Encrypted: i=1; AJvYcCUGoRSMaCcpr9g9EDi2LOj0Rh2DkGMugwCXDVAmn9ZW5csW6nbtiiG2tS+qGcL3TqgkloEpfEBfGQ==@vger.kernel.org X-Gm-Message-State: AOJu0YxA+LM3Ngkul2BR6Zq+ME/fpj/FfJ32+RI+hsRo4jT9NuTj4d5S lj0XjSUiUU+9oCzJHg4VE70uphBK5J1XjTLOXEhHKFV+Ufb/PojhdDNeYBvVpks= X-Gm-Gg: ASbGnculzBSVaWxG7tLcIxt4QYOv3JHTxF3U76ilp8TJwPKI3lOZVAYH5bWIL2oAUvI PA1eP3aiwf4D7YQ50TltEq03yq3fwhmd9npFzow0DewbKsrsdnXIQYpWhf/ArHWsHrgvd/JPvIT a3A5ybvNeQq7MwhJeFjXw/CZkcDXCv+8AcyzZbM1H8rZEpdR9STimS0H/TpQpUiuoinPvkrPTUI KQXkoHn540pYWzmwoUHl9HZHP+aLz3mAh6zAVcst7IFdzxUr4VbW1r266E= X-Google-Smtp-Source: AGHT+IHWlPorx8XJmvX79gE5sNkxZSUXnp+Pd6+S6Fek2hXtY7a65fTM8Lo2nmZmWQWd7i9agrQzmg== X-Received: by 2002:a17:90b:51c2:b0:2ee:ab29:1a63 with SMTP id 98e67ed59e1d1-2f548ea6331mr27577987a91.3.1736767439700; Mon, 13 Jan 2025 03:23:59 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2f53e1da400sm2352192a91.0.2025.01.13.03.23.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:23:59 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 07/16] rust: Add bare minimal bindings for clk framework Date: Mon, 13 Jan 2025 16:53:02 +0530 Message-Id: <8dd38c6dce256340a5a623503023736f8e9278d8.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This adds very basic bindings for the clk framework, implements only clk_get() and clk_put(). These are the bare minimum bindings required for many users and are simple enough to add in the first attempt. These will be used by Rust based cpufreq / OPP core to begin with. Signed-off-by: Viresh Kumar --- rust/bindings/bindings_helper.h | 1 + rust/kernel/clk.rs | 48 +++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + 3 files changed, 50 insertions(+) create mode 100644 rust/kernel/clk.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 59b4bc49d039..4eadcf645df0 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs new file mode 100644 index 000000000000..123cdb43b115 --- /dev/null +++ b/rust/kernel/clk.rs @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Clock abstractions. +//! +//! C header: [`include/linux/clk.h`](srctree/include/linux/clk.h) + +use crate::{ + bindings, + device::Device, + error::{from_err_ptr, Result}, + prelude::*, +}; + +use core::ptr; + +/// A simple implementation of `struct clk` from the C code. +#[repr(transparent)] +pub struct Clk(*mut bindings::clk); + +impl Clk { + /// Creates `Clk` instance for a device and a connection id. + pub fn new(dev: &Device, name: Option<&CStr>) -> Result { + let con_id = if let Some(name) = name { + name.as_ptr() as *const _ + } else { + ptr::null() + }; + + // SAFETY: It is safe to call `clk_get()`, on a device pointer earlier received from the C + // code. + Ok(Self(from_err_ptr(unsafe { + bindings::clk_get(dev.as_raw(), con_id) + })?)) + } + + /// Obtain the raw `struct clk *`. + pub fn as_raw(&self) -> *mut bindings::clk { + self.0 + } +} + +impl Drop for Clk { + fn drop(&mut self) { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // relinquish it now. + unsafe { bindings::clk_put(self.0) }; + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 2f72e1d8a6b7..5d43dc5ec9eb 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -39,6 +39,7 @@ pub mod block; #[doc(hidden)] pub mod build_assert; +pub mod clk; pub mod cpu; pub mod cpumask; pub mod cred; From patchwork Mon Jan 13 11:23:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937188 Received: from mail-pj1-f50.google.com (mail-pj1-f50.google.com [209.85.216.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7ED53233D8D for ; Mon, 13 Jan 2025 11:24:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767446; cv=none; b=f7bUPauILfKH2PQ2N/jcA6JXiWwR+nPfw1wkRFLxzh5xosdQn+qBMmvovs7j4gzK0VaaSYN8BV4epPnLa68ekqeFbUzVZZRWfrcahlbes4xQBqfrU7K0Ji5Cc40+79JIKvDMMfI4uNIB2modUrC3XvTAatuYsHk0TLqtjjRUhMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767446; c=relaxed/simple; bh=/uvDKCjlgOnsUH8C0V/hZTcfvjq6TTMwI45slAFmITI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EGLbGSiB5eTxCszBX/R/HIq/jfrOd43EfvDKqCDo9h5jRez7I+oP3EWP5SC/uFiOhRZjchlDtU8KmF5DU4eVhMsGHVYNrvRhuNpXLWNMBQKzvDk62qaA2cqanth7O0b1VkH3Hd2xWc+kk0/QLfZfWpfsnNEw4Y44NQupRYLa33E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=QF1z3oAj; arc=none smtp.client-ip=209.85.216.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="QF1z3oAj" Received: by mail-pj1-f50.google.com with SMTP id 98e67ed59e1d1-2ee786b3277so5211232a91.1 for ; Mon, 13 Jan 2025 03:24:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767444; x=1737372244; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8DT/35uJ0SGSGPotN/aFFV/d+f5sRADYEA7sMqJpaVQ=; b=QF1z3oAj0XoyqVhwpcx088JnPrtdqTQs/WMZLO/Ivn61R0/XhcxhBH5l8RnXMl6+Xj f6wn684JaHY/WDmL0mpyM/jFyaSP3qZt+f7GhHrfdX6gC5/EhDRGBqRMIN9XS44086DA 0LjgD7e4OzB1b71uk90dwyDKYilmJjGHebmOcPZPkhz+sUJZB860uhxN9pSn++oWWsnH Ys65Ur+usMzq5Pl6QZDrEMX0jsreQfnBaVVtG5NijLNfb/okqvu8jaFwZddqSS9gXAG0 483UF4Yq3KdDuBJgOfGj5WkU07kWqYsw475ISKqk7m3N5IyYGR6B54btGs8a6bpJRoX+ aHSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767444; x=1737372244; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8DT/35uJ0SGSGPotN/aFFV/d+f5sRADYEA7sMqJpaVQ=; b=gB+rYd3RPgSfbkYGHnY5sP2FlEEOtoIpvooK+2m5GbuzcgOe6pll4saSeuMltCTd16 ZhxAMH7wV06J21nw3JkxUpuJtBQTkLwq9esXQ6X5ww/KmyMj5IS9D29sjr6TB0rXVeqU O3eyYXdQL0VKB8T9WKgJIGKdVTPVxKHLZzOHB3qyLUkiiEvIVcnWzV3XKLdrRaXW4+Se p7stOFFcs6XNne7Uf0qOlBqyvwlUFrAZyQrUExEhMY4UYzdE5I+ne/2M5EmPOz9YJkNN CPsLU+g0yzMTC1R80JUI9Xz+NXdLIx+TdZaWtsLmKcn5JRDVEWLi+vQHc8+o/HvmNjW7 5rbw== X-Forwarded-Encrypted: i=1; AJvYcCVjIJrXWlFPFi1WisbFGMtVOE3l/lWVK2aTuQew2Iguqq99FAM+8eLp2dRptgdYPEsI3ZO3l03CQA==@vger.kernel.org X-Gm-Message-State: AOJu0YzgoUNQrcl+kvby0Upq+J+akZ2JVAnd4dfZrQlDFOzddygkHElF fPm1AXB1E0F0ifCFnuNZM/i0oMtQMsLBUEzpiZaMR5qCKgQZSwua+B/GmXUU5zQ= X-Gm-Gg: ASbGncs71SawkELJu/JvQQ0wuepF3IhWGDW2N6zh+SMuJexgi9cehAK4LWFS6M5xlvZ qQJjlFT6pGo1y1Tkovk8Qsye2gwSj7hCW6S43ob+8K5LD1RYlxLE4f/6jTnsTVszzIe6YjJjpwY tYhfyMtx0QpUsPUG+LTePWoPvn0M4Ia1fdHHeiJ4RtdqQJErLpoJschK4rgz45c1gU+hYN+ogur 2OcT5L8/XNELqgvLbiDGxP2ZlE83sq+Hlvvt2E95d//5btUp0+eqkBjkOM= X-Google-Smtp-Source: AGHT+IGzJcomzKu3um0t7HxdPCLFlwOxE0siZO+gePGZ/L+Xri4khqzqUGXcTjLI5lYyDPnM+gaq7w== X-Received: by 2002:a17:90b:50c4:b0:2ee:d7d3:3019 with SMTP id 98e67ed59e1d1-2f548ebf4fbmr35219371a91.12.1736767443736; Mon, 13 Jan 2025 03:24:03 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f219f0dsm51767265ad.139.2025.01.13.03.24.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:03 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Viresh Kumar , Nishanth Menon , Stephen Boyd Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Manos Pitsidianakis , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 08/16] rust: Add initial bindings for OPP framework Date: Mon, 13 Jan 2025 16:53:03 +0530 Message-Id: <5f3c7ac94e22c8bda51910360b399439c37babe2.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit adds initial Rust bindings for the Operating performance points (OPP) core. This adds bindings for struct dev_pm_opp and struct dev_pm_opp_data to begin with. Reviewed-by: Manos Pitsidianakis Signed-off-by: Viresh Kumar --- MAINTAINERS | 1 + rust/bindings/bindings_helper.h | 1 + rust/kernel/lib.rs | 2 + rust/kernel/opp.rs | 189 ++++++++++++++++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 rust/kernel/opp.rs diff --git a/MAINTAINERS b/MAINTAINERS index 8ee1c013cd6e..3f9ebca78732 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17707,6 +17707,7 @@ F: Documentation/devicetree/bindings/opp/ F: Documentation/power/opp.rst F: drivers/opp/ F: include/linux/pm_opp.h +F: rust/kernel/opp.rs OPL4 DRIVER M: Clemens Ladisch diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 4eadcf645df0..7f851d5907af 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 5d43dc5ec9eb..d1c0f136952e 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -62,6 +62,8 @@ #[cfg(CONFIG_NET)] pub mod net; pub mod of; +#[cfg(CONFIG_PM_OPP)] +pub mod opp; pub mod page; #[cfg(CONFIG_PCI)] pub mod pci; diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs new file mode 100644 index 000000000000..becb33880c92 --- /dev/null +++ b/rust/kernel/opp.rs @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Operating performance points. +//! +//! This module provides bindings for interacting with the OPP subsystem. +//! +//! C header: [`include/linux/pm_opp.h`](srctree/include/linux/pm_opp.h) + +use crate::{ + bindings, + device::Device, + error::{code::*, to_result, Result}, + types::{ARef, AlwaysRefCounted, Opaque}, +}; + +use core::ptr; + +/// Dynamically created Operating performance point (OPP). +pub struct Token { + dev: ARef, + freq: usize, +} + +impl Token { + /// Adds an OPP dynamically. + pub fn new(dev: &ARef, mut data: Data) -> Result { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { bindings::dev_pm_opp_add_dynamic(dev.as_raw(), &mut data.0) })?; + Ok(Self { + dev: dev.clone(), + freq: data.freq(), + }) + } +} + +impl Drop for Token { + fn drop(&mut self) { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + unsafe { bindings::dev_pm_opp_remove(self.dev.as_raw(), self.freq) }; + } +} + +/// Equivalent to `struct dev_pm_opp_data` in the C Code. +#[repr(transparent)] +pub struct Data(bindings::dev_pm_opp_data); + +impl Data { + /// Creates new instance of [`Data`]. + pub fn new(freq: usize, u_volt: usize, level: u32, turbo: bool) -> Self { + Self(bindings::dev_pm_opp_data { + turbo, + freq, + u_volt, + level, + }) + } + + /// Adds an OPP dynamically. The OPP is freed once the [`Token`] gets freed. + pub fn add_opp(self, dev: &ARef) -> Result { + Token::new(dev, self) + } + + fn freq(&self) -> usize { + self.0.freq + } +} + +/// Operating performance point (OPP). +/// +/// Wraps the kernel's `struct dev_pm_opp`. +/// +/// The pointer to `struct dev_pm_opp` is non-null and valid for the lifetime of the `OPP` +/// instance. +/// +/// # Invariants +/// +/// Instances of this type are reference-counted. The reference count is incremented by the +/// `dev_pm_opp_get()` function and decremented by `dev_pm_opp_put`. The Rust type `ARef` +/// represents a pointer that owns a reference count on the OPP. +/// +/// A reference to the `OPP`, `&OPP` isn't refcounted by the Rust code. + +#[repr(transparent)] +pub struct OPP(Opaque); + +// SAFETY: It's OK to send the ownership of `OPP` across thread boundaries. +unsafe impl Send for OPP {} + +// SAFETY: It's OK to access `OPP` through shared references from other threads because we're +// either accessing properties that don't change or that are properly synchronised by C code. +unsafe impl Sync for OPP {} + +// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted. +unsafe impl AlwaysRefCounted for OPP { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::dev_pm_opp_get(self.0.get()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. + unsafe { bindings::dev_pm_opp_put(obj.cast().as_ptr()) } + } +} + +impl OPP { + /// Creates an owned reference to a [`OPP`] from a valid pointer. + /// + /// The refcount is incremented by the C code and will be decremented by `dec_ref()` when the + /// ARef object is dropped. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` is valid and the OPP's refcount is incremented. The + /// caller must also ensure that it doesn't explicitly drop the refcount of the OPP, as the + /// returned ARef object takes over the refcount increment on the underlying object and the + /// same will be dropped along with it. + pub unsafe fn from_raw_opp_owned(ptr: *mut bindings::dev_pm_opp) -> Result> { + let ptr = ptr::NonNull::new(ptr).ok_or(ENODEV)?; + + // SAFETY: The safety requirements guarantee the validity of the pointer. + Ok(unsafe { ARef::from_raw(ptr.cast()) }) + } + + /// Creates a reference to a [`OPP`] from a valid pointer. + /// + /// The refcount is not updated by the Rust API unless the returned reference is converted to + /// an ARef object. + /// + /// # Safety + /// + /// The caller must ensure that `ptr` is valid and remains valid for the duration of 'a. + pub unsafe fn from_raw_opp<'a>(ptr: *mut bindings::dev_pm_opp) -> Result<&'a Self> { + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the + // duration of 'a. The cast is okay because `OPP` is `repr(transparent)`. + Ok(unsafe { &*ptr.cast() }) + } + + #[inline] + fn as_raw(&self) -> *mut bindings::dev_pm_opp { + self.0.get() + } + + /// Returns the frequency of an OPP. + pub fn freq(&self, index: Option) -> usize { + let index = index.unwrap_or(0); + + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it. + unsafe { bindings::dev_pm_opp_get_freq_indexed(self.as_raw(), index) } + } + + /// Returns the voltage of an OPP. + pub fn voltage(&self) -> usize { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it. + unsafe { bindings::dev_pm_opp_get_voltage(self.as_raw()) } + } + + /// Returns the level of an OPP. + pub fn level(&self) -> u32 { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it. + unsafe { bindings::dev_pm_opp_get_level(self.as_raw()) } + } + + /// Returns the power of an OPP. + pub fn power(&self) -> usize { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it. + unsafe { bindings::dev_pm_opp_get_power(self.as_raw()) } + } + + /// Returns the required pstate of an OPP. + pub fn required_pstate(&self, index: u32) -> u32 { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it. + unsafe { bindings::dev_pm_opp_get_required_pstate(self.as_raw(), index) } + } + + /// Returns true if the OPP is turbo. + pub fn is_turbo(&self) -> bool { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it. + unsafe { bindings::dev_pm_opp_is_turbo(self.as_raw()) } + } +} From patchwork Mon Jan 13 11:23:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937189 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 10A482343B1 for ; Mon, 13 Jan 2025 11:24:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767450; cv=none; b=uBPBojV+2WUdoxD2JRfvdbazDkvIehWMQRVi7lHDhO7nTnrakWLdDjErRJ0DQQ30nIgwGaBr33uOFfT7/T16Rey5QZtE2YkCWPWezhnojVz++ObbB96WhuEINu6TvqtynIxkkh5Ex4OKlTH69XgkX9NCyPDis9QQHnrZUW6xp3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767450; c=relaxed/simple; bh=vsHZhCkGhVZ0mCcuXZBy4kwTUYm334wXEh9JY7v2xKM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TGJV5k/EljTaauX4LboiLkQOwGY3Jnn72G0SGfzwaNULoL4N2k2CyPcXHdFFKbYxStsWT3xP1Bv30Ge4poAAvvCATdOEwYRVkgRkcTanOaG8LMeBqPDboSIRXjtVEhVTFFa/GA9QrYsa5M+N8J1az2NnzoiVw1kRw3/RCwXa44o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=aK7H+I3X; arc=none smtp.client-ip=209.85.214.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="aK7H+I3X" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2163dc5155fso73997505ad.0 for ; Mon, 13 Jan 2025 03:24:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767447; x=1737372247; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ftCsOZitCmeRyVqQ2YCyIstFqWVeJbqxa6tUfw80DGc=; b=aK7H+I3XSJIYjWTOhYlYUF14mytD/0g6c6C83Z1I21/HwWolexuSGPO8P2Cl0xK4kb 12/JCKtsoMvlHK/q79HYJMIpwfj9OLKr3N4CzjKmFyvNb7YBhiUvgpTzK0pZbQqVI83L DSt7e++8qrLwDlPiIEW1KicX+zbXiD+7qEMaFO8tQwCYkVrxZZjmapNlsnQ3zTpd+t3G Hq2VNGzYAugMjNsqS4aDr7zMfsmdk9gNBtN2M6Cfz5XrGZVryDyAYuYwAbNzlSgxf3Il l2z17ymr5bNds2M2y3AbAMfX6Mc3GLL9Gw8H5F9tPEHmxsdkOFyl8js8MrSnvUuVWAI3 ir0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767447; x=1737372247; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ftCsOZitCmeRyVqQ2YCyIstFqWVeJbqxa6tUfw80DGc=; b=GxiWKfmazWmZR3EJFfDhrjd9SW1Uyunpp1zqGb3Ph3ltjM2MS5zehwC71tdLd8vr6N D6NpnCMhYuqky0ZL2X8gYMh+eZFSPi3lQcTqy4xJgAiLeXUtFVIOVSuoiykMYqcqRc/6 3IU/X4hEVnfs9IE7mSN+rT4ovLaHHXAxIEDCP8oHTiNL8LQBRqyREL+NIhIac9rKdz/n mkb0tgT8Y1U165n77MrvAy1uYvDYhiF4/MIk3PN7k9lNf2OdOitiDebOV+u+41CsO5sN oKSYXaKj3hHXk4tiKDBHbkYXQRb7sPJHI4gdKreVaEaMjgLQXL3PQMR3G7wkuEQRi5E+ BX2g== X-Forwarded-Encrypted: i=1; AJvYcCVjSlPejkfrRoQ0Ysk42L0isG6yM0MX0sh9M9Jck92cDHfFtOEmDYk9DGEmsAqjTNWQfnmc5WICLg==@vger.kernel.org X-Gm-Message-State: AOJu0Ywtt3Uy9BZfRHO8C0lzjFYEyXs7npq2wqLHw+8w2T0xFZ2bDL0O uBmxNWCM2mPEHdZqQFFg9mpwynFgIjksEC5osBagI94whdrXvUep+rEbOWet+4s= X-Gm-Gg: ASbGncu7EOYhdZqMgYWXOPiTlNCThgM+0LU4kU2y8bDOauY4yDAxsZbNOLp2mRylRX/ 8l4+pnbvk8w3tsM35McTaLfM4JsqRKpAj5tKl1z6JTyeeTTyIIMF7aCuREF/UDqRraD9Y1UKd3i x5Vy2ZjiRpeTPDcfYEIfEdPb+fQa1EDIZUEDekY7/wQ1oYVVbbQ8TQf0zW5MDWrT2OEFddVmmjg PE7/65S/9qPEl4+OQmg6sCOEeIRj5J8PDIMUjbWmSI8muOuP44c9FnWRRA= X-Google-Smtp-Source: AGHT+IHmleW8WQsIyr/tT0LTvcZCq3ZUva4QmBy1v6QT3fROfylP0efo3dalrM+odvmOPxjpmdrwUA== X-Received: by 2002:a05:6a00:22c7:b0:725:c8ea:b320 with SMTP id d2e1a72fcca58-72d21feb16fmr26578518b3a.14.1736767447288; Mon, 13 Jan 2025 03:24:07 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d40658b64sm5760219b3a.109.2025.01.13.03.24.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:06 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V7 09/16] rust: Extend OPP bindings for the OPP table Date: Mon, 13 Jan 2025 16:53:04 +0530 Message-Id: <6ee4476b61fba69b879b98f69668dfe0b993821a.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This extends OPP bindings with the bindings for the struct opp_table. Signed-off-by: Viresh Kumar --- rust/kernel/opp.rs | 383 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 382 insertions(+), 1 deletion(-) diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs index becb33880c92..d3b98d9a554e 100644 --- a/rust/kernel/opp.rs +++ b/rust/kernel/opp.rs @@ -8,8 +8,9 @@ use crate::{ bindings, + cpumask::Cpumask, device::Device, - error::{code::*, to_result, Result}, + error::{code::*, from_err_ptr, to_result, Error, Result}, types::{ARef, AlwaysRefCounted, Opaque}, }; @@ -67,6 +68,386 @@ fn freq(&self) -> usize { } } +/// OPP search types. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum SearchType { + /// Search for exact value. + Exact, + /// Search for highest value less than equal to value. + Floor, + /// Search for lowest value greater than equal to value. + Ceil, +} + +/// Operating performance point (OPP) table. +/// +/// Wraps the kernel's `struct opp_table`. +/// +/// The pointer stored in `Self` is non-null and valid for the lifetime of the `Table`. +pub struct Table { + ptr: *mut bindings::opp_table, + dev: ARef, + em: bool, + of: bool, + cpumask: Option, +} + +// SAFETY: It is okay to send ownership of `Table` across thread boundaries. +unsafe impl Send for Table {} + +// SAFETY: It's OK to access `Table` through shared references from other threads because we're +// either accessing properties that don't change or that are properly synchronised by C code. +unsafe impl Sync for Table {} + +impl Table { + /// Creates a new OPP table instance from raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid and non-null. + unsafe fn from_raw_table(ptr: *mut bindings::opp_table, dev: &ARef) -> Self { + // SAFETY: By the safety requirements, ptr is valid and its refcount will be incremented. + unsafe { bindings::dev_pm_opp_get_opp_table_ref(ptr) }; + + Self { + ptr, + dev: dev.clone(), + em: false, + of: false, + cpumask: None, + } + } + + /// Find OPP table from device. + pub fn from_dev(dev: &Device) -> Result { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. Refcount of the OPP table is incremented by the C code. + let ptr = from_err_ptr(unsafe { bindings::dev_pm_opp_get_opp_table(dev.as_raw()) })?; + + Ok(Self { + ptr, + dev: dev.into(), + em: false, + of: false, + cpumask: None, + }) + } + + /// Add device tree based OPP table for the device. + #[cfg(CONFIG_OF)] + pub fn from_of(dev: &ARef, index: i32) -> Result { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. Refcount of the OPP table is incremented by the C code. + to_result(unsafe { bindings::dev_pm_opp_of_add_table_indexed(dev.as_raw(), index) })?; + + // Fetch the newly created table. + let mut table = Self::from_dev(dev)?; + table.of = true; + + Ok(table) + } + + // Remove device tree based OPP table for the device. + #[cfg(CONFIG_OF)] + fn remove_of(&self) { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. We took the reference earlier from `from_of` earlier, it is safe to drop + // the same now. + unsafe { bindings::dev_pm_opp_of_remove_table(self.dev.as_raw()) }; + } + + /// Add device tree based OPP table for CPU devices. + #[cfg(CONFIG_OF)] + pub fn from_of_cpumask(dev: &Device, cpumask: &mut Cpumask) -> Result { + // SAFETY: The cpumask is valid and the returned ptr will be owned by the [`Table`] instance. + to_result(unsafe { bindings::dev_pm_opp_of_cpumask_add_table(cpumask.as_raw()) })?; + + // Fetch the newly created table. + let mut table = Self::from_dev(dev)?; + + let mut mask = Cpumask::new()?; + cpumask.copy(&mut mask); + table.cpumask = Some(mask); + + Ok(table) + } + + // Remove device tree based OPP table for CPU devices. + #[cfg(CONFIG_OF)] + fn remove_of_cpumask(&self, mut cpumask: Cpumask) { + // SAFETY: The cpumask is valid and we took the reference from `from_of_cpumask` earlier, + // it is safe to drop the same now. + unsafe { bindings::dev_pm_opp_of_cpumask_remove_table(cpumask.as_raw()) }; + } + + /// Returns the number of OPPs in the table. + pub fn opp_count(&self) -> Result { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + let ret = unsafe { bindings::dev_pm_opp_get_opp_count(self.dev.as_raw()) }; + if ret < 0 { + Err(Error::from_errno(ret)) + } else { + Ok(ret as u32) + } + } + + /// Returns max clock latency of the OPPs in the table. + pub fn max_clock_latency(&self) -> usize { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + unsafe { bindings::dev_pm_opp_get_max_clock_latency(self.dev.as_raw()) } + } + + /// Returns max volt latency of the OPPs in the table. + pub fn max_volt_latency(&self) -> usize { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + unsafe { bindings::dev_pm_opp_get_max_volt_latency(self.dev.as_raw()) } + } + + /// Returns max transition latency of the OPPs in the table. + pub fn max_transition_latency(&self) -> usize { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + unsafe { bindings::dev_pm_opp_get_max_transition_latency(self.dev.as_raw()) } + } + + /// Returns the suspend OPP. + pub fn suspend_freq(&self) -> usize { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + unsafe { bindings::dev_pm_opp_get_suspend_opp_freq(self.dev.as_raw()) } + } + + /// Synchronizes regulators used by the OPP table. + pub fn sync_regulators(&self) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { bindings::dev_pm_opp_sync_regulators(self.dev.as_raw()) }) + } + + /// Gets sharing CPUs. + pub fn sharing_cpus(dev: &Device, cpumask: &mut Cpumask) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { + bindings::dev_pm_opp_get_sharing_cpus(dev.as_raw(), cpumask.as_raw()) + }) + } + + /// Sets sharing CPUs. + pub fn set_sharing_cpus(&mut self, cpumask: &mut Cpumask) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { + bindings::dev_pm_opp_set_sharing_cpus(self.dev.as_raw(), cpumask.as_raw()) + })?; + + if let Some(mask) = self.cpumask.as_mut() { + // Update the cpumask as this will be used while removing the table. + cpumask.copy(mask); + } + + Ok(()) + } + + /// Gets sharing CPUs from Device tree. + #[cfg(CONFIG_OF)] + pub fn of_sharing_cpus(dev: &Device, cpumask: &mut Cpumask) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { + bindings::dev_pm_opp_of_get_sharing_cpus(dev.as_raw(), cpumask.as_raw()) + }) + } + + /// Updates the voltage value for an OPP. + pub fn adjust_voltage( + &self, + freq: usize, + u_volt: usize, + u_volt_min: usize, + u_volt_max: usize, + ) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { + bindings::dev_pm_opp_adjust_voltage( + self.dev.as_raw(), + freq, + u_volt, + u_volt_min, + u_volt_max, + ) + }) + } + + /// Sets a matching OPP based on frequency. + pub fn set_rate(&self, freq: usize) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { bindings::dev_pm_opp_set_rate(self.dev.as_raw(), freq) }) + } + + /// Sets exact OPP. + pub fn set_opp(&self, opp: &OPP) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { bindings::dev_pm_opp_set_opp(self.dev.as_raw(), opp.as_raw()) }) + } + + /// Finds OPP based on frequency. + pub fn opp_from_freq( + &self, + mut freq: usize, + available: Option, + index: Option, + stype: SearchType, + ) -> Result> { + let rdev = self.dev.as_raw(); + let index = index.unwrap_or(0); + + let ptr = from_err_ptr(match stype { + SearchType::Exact => { + if let Some(available) = available { + // SAFETY: The requirements are satisfied by the existence of `Device` and + // its safety requirements. The returned ptr will be owned by the new [`OPP`] + // instance. + unsafe { + bindings::dev_pm_opp_find_freq_exact_indexed(rdev, freq, index, available) + } + } else { + return Err(EINVAL); + } + } + + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Ceil => unsafe { + bindings::dev_pm_opp_find_freq_ceil_indexed(rdev, &mut freq as *mut usize, index) + }, + + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Floor => unsafe { + bindings::dev_pm_opp_find_freq_floor_indexed(rdev, &mut freq as *mut usize, index) + }, + })?; + + // SAFETY: The `ptr` is guaranteed by the C code to be valid. + unsafe { OPP::from_raw_opp_owned(ptr) } + } + + /// Finds OPP based on level. + pub fn opp_from_level(&self, mut level: u32, stype: SearchType) -> Result> { + let rdev = self.dev.as_raw(); + + let ptr = from_err_ptr(match stype { + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Exact => unsafe { bindings::dev_pm_opp_find_level_exact(rdev, level) }, + + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Ceil => unsafe { + bindings::dev_pm_opp_find_level_ceil(rdev, &mut level as *mut u32) + }, + + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Floor => unsafe { + bindings::dev_pm_opp_find_level_floor(rdev, &mut level as *mut u32) + }, + })?; + + // SAFETY: The `ptr` is guaranteed by the C code to be valid. + unsafe { OPP::from_raw_opp_owned(ptr) } + } + + /// Finds OPP based on bandwidth. + pub fn opp_from_bw(&self, mut bw: u32, index: i32, stype: SearchType) -> Result> { + let rdev = self.dev.as_raw(); + + let ptr = from_err_ptr(match stype { + // The OPP core doesn't support this yet. + SearchType::Exact => return Err(EINVAL), + + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Ceil => unsafe { + bindings::dev_pm_opp_find_bw_ceil(rdev, &mut bw as *mut u32, index) + }, + + // SAFETY: The requirements are satisfied by the existence of `Device` and its + // safety requirements. The returned ptr will be owned by the new [`OPP`] instance. + SearchType::Floor => unsafe { + bindings::dev_pm_opp_find_bw_floor(rdev, &mut bw as *mut u32, index) + }, + })?; + + // SAFETY: The `ptr` is guaranteed by the C code to be valid. + unsafe { OPP::from_raw_opp_owned(ptr) } + } + + /// Enable the OPP. + pub fn enable_opp(&self, freq: usize) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { bindings::dev_pm_opp_enable(self.dev.as_raw(), freq) }) + } + + /// Disable the OPP. + pub fn disable_opp(&self, freq: usize) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { bindings::dev_pm_opp_disable(self.dev.as_raw(), freq) }) + } + + /// Registers with Energy model. + #[cfg(CONFIG_OF)] + pub fn of_register_em(&mut self, cpumask: &mut Cpumask) -> Result<()> { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { + bindings::dev_pm_opp_of_register_em(self.dev.as_raw(), cpumask.as_raw()) + })?; + + self.em = true; + Ok(()) + } + + // Unregisters with Energy model. + #[cfg(all(CONFIG_OF, CONFIG_ENERGY_MODEL))] + fn of_unregister_em(&self) { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. We registered with the EM framework earlier, it is safe to unregister now. + unsafe { bindings::em_dev_unregister_perf_domain(self.dev.as_raw()) }; + } +} + +impl Drop for Table { + fn drop(&mut self) { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe + // to relinquish it now. + unsafe { bindings::dev_pm_opp_put_opp_table(self.ptr) }; + + #[cfg(CONFIG_OF)] + { + #[cfg(CONFIG_ENERGY_MODEL)] + if self.em { + self.of_unregister_em(); + } + + if self.of { + self.remove_of(); + } else if let Some(cpumask) = self.cpumask.take() { + self.remove_of_cpumask(cpumask); + } + } + } +} + /// Operating performance point (OPP). /// /// Wraps the kernel's `struct dev_pm_opp`. From patchwork Mon Jan 13 11:23:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937190 Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7261D3DABE0 for ; Mon, 13 Jan 2025 11:24:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767453; cv=none; b=Hk7B+0gw0yQsf1BaiDk/9cTVfHEmX63V0TNg1OHqsNQvLFPwFFoPaSpALFQfr/egh8m8Va7OSo6619intzhqDpN44kyRHFntvdo5YV7QI9UWBTOQYbT8LeXLixpB7OHv1Kd2n3XCILTZm0gH3qQ1a+7wXNqDoLj/7PuWPY5kgns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767453; c=relaxed/simple; bh=HvTNnupc2EFRJvcBV6gbrEBwWsZdiLH3T39OSFYdg68=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=owCpQws1J+E32gAFc2vg9zNSRwcrWA+L3Fp40C1eaEVfwOwBC3mvdzoA1X2yZx9+TdYjoGCffuK8vbFDKcjg43z/aMen3JBugd8LS03pnf5w0v4id1yqC32mF/ev2OzjJF8iyJ7Sv+nktCfXLrAgmy2Eg1FV+UCX7HYkg4240a8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=NHbLdA3c; arc=none smtp.client-ip=209.85.214.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="NHbLdA3c" Received: by mail-pl1-f173.google.com with SMTP id d9443c01a7336-216395e151bso49340445ad.0 for ; Mon, 13 Jan 2025 03:24:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767451; x=1737372251; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IWWPIaDzJ6TtRNiPxhkMnMASI1Go/QPlOZW3kN1s+RM=; b=NHbLdA3cgyTxTgaphjxzRMtfE5z3gmd9sPuaGPLF4X7qS0gvbKC33NZTzPGNoC8PeH Rmncp3evwKAcO1y5WhDpUzBAIKu3+lKy+sTDz5lbhisFY5XookJA/n0MOb4MXRGklGrc bG4dip1U4vguIN+0n+X0m5RBlGrHxDCR3yFFXrQhjkC10sSv+MOQyZ+erxmoD10Lv/X8 4FpPhhHgnrvU/lVFUV5npWW36Sj4c9U4Rt7dAS5r/WyBsF0tAOCvLvCUqeB+bEo7jwoD VqTVmuk9uTaRbAFZbzvJaMPOnA8cBfo3m3Nc/ihe+dlJt3ji1viic7bdc/KQ6LBkvBEH nczw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767451; x=1737372251; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IWWPIaDzJ6TtRNiPxhkMnMASI1Go/QPlOZW3kN1s+RM=; b=gEo6HQ36rL8OXp04MkDfR+XjvHI1NIlq4iFCK0eYNMnM0smk2Kx3fmTzdh7E2yxlep ytClvoU3r9XJd0iAHt/kKC7mC0InuO6g6xB9Iu6SAxfg+LQBGhozwhsX4KAJOs8xf4V/ maQQ1IQIKrNa8by9Bb0cm+tH5MgtRQfzAmNFHv0PwCoWQEZB0j9SsobFqkOg4RzjZT6/ DVHYStrgk4gTbLQZnpriLmVoPzQ0fLE78hRBMxgESo9nhqnGwDnDC/YxRW70+8jyBpBx n8Gs0mMRyU/2wQMdcmdquRpOhUU8Oezr9MSvRt+DTwR7cYLHgXaMV6KZ7HieaHdbYXoW Rwvw== X-Forwarded-Encrypted: i=1; AJvYcCVCNlnry8iWw3c+l6RAa6/PAL0gTkQzcxeNZIARd45j3Q9MsX+oN7vkExh6EeMzDIWiuJE5LWEXbQ==@vger.kernel.org X-Gm-Message-State: AOJu0Yzj0EOBWhjk3ozxSLspeOWO6MSAn8JYRLYtClWjKaANa6GJeBBS djl9PitGdaAJ0rXINHIJ6IGAnQRBYVF5ECjzQZ2plP/4ETT8cHLtOCc8bjz4KIs= X-Gm-Gg: ASbGnct7F3yppQny5O3ZqC44T0wwrO7yW9C4MKELN4Joyf4efDHW47DbQAhaIzB9YMK mz7bmkfkObeqQz5DUAxGSuTZgqK2Vh45oVjCfCNlrVIwtvhZ8bSue41VC2RoQS0rrqFmObPbBfa 56P9Yj4P2UD2Bm5rcccxdm6UaOYF1d0v1cbwAiu9NtagYiQFpKb+5Ht3nSe+9Tg+D1huEHZixla LLyLrAdqqF6eUsCmnXTJx0hqSTPFhy96AZ/qLAUv3aJR3m05S8Abg3rMQE= X-Google-Smtp-Source: AGHT+IGiyKcuVgM1Ys0i/tuRnV6jvK7jW7PsJedRIoMQWDTCXNoVpynGn0EranSE4BEcCImlbEEWdg== X-Received: by 2002:a17:903:4084:b0:215:8fd3:d1b6 with SMTP id d9443c01a7336-21ae88b9d14mr109464815ad.23.1736767450746; Mon, 13 Jan 2025 03:24:10 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f138854sm52030505ad.96.2025.01.13.03.24.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:10 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Manos Pitsidianakis , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V7 10/16] rust: Extend OPP bindings for the configuration options Date: Mon, 13 Jan 2025 16:53:05 +0530 Message-Id: <6a493402c7f856d2e0a9d7d1d296669e4b6a7010.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This extends OPP bindings with the bindings for the OPP core configuration options. Reviewed-by: Manos Pitsidianakis Signed-off-by: Viresh Kumar --- rust/kernel/opp.rs | 262 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 260 insertions(+), 2 deletions(-) diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs index d3b98d9a554e..22c4d543f456 100644 --- a/rust/kernel/opp.rs +++ b/rust/kernel/opp.rs @@ -10,11 +10,28 @@ bindings, cpumask::Cpumask, device::Device, - error::{code::*, from_err_ptr, to_result, Error, Result}, + error::{code::*, from_err_ptr, from_result, to_result, Error, Result, VTABLE_DEFAULT_ERROR}, + prelude::*, + str::CString, types::{ARef, AlwaysRefCounted, Opaque}, }; -use core::ptr; +use core::{marker::PhantomData, ptr}; + +use macros::vtable; + +// Creates a null-terminated slice of pointers to Cstrings. +fn to_c_str_array(names: &[CString]) -> Result> { + // Allocated a null-terminated vector of pointers. + let mut list = KVec::with_capacity(names.len() + 1, GFP_KERNEL)?; + + for name in names.iter() { + list.push(name.as_ptr() as _, GFP_KERNEL)?; + } + + list.push(ptr::null(), GFP_KERNEL)?; + Ok(list) +} /// Dynamically created Operating performance point (OPP). pub struct Token { @@ -79,6 +96,247 @@ pub enum SearchType { Ceil, } +/// Implement this trait to provide OPP Configuration callbacks. +#[vtable] +pub trait ConfigOps { + /// Called by the OPP core to configure OPP clks. + fn config_clks(_dev: &Device, _table: &Table, _opp: &OPP, _scaling_down: bool) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Called by the OPP core to configure OPP regulators. + fn config_regulators( + _dev: &Device, + _opp_old: &OPP, + _opp_new: &OPP, + _data: *mut *mut bindings::regulator, + _count: u32, + ) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } +} + +/// Config token returned by the C code. +pub struct ConfigToken(i32); + +impl Drop for ConfigToken { + fn drop(&mut self) { + // SAFETY: Its safe to return the configuration token number previously received from the C + // code. + unsafe { bindings::dev_pm_opp_clear_config(self.0) }; + } +} + +/// Equivalent to `struct dev_pm_opp_config` in the C Code. +#[derive(Default)] +pub struct Config { + clk_names: Option>, + prop_name: Option, + regulator_names: Option>, + supported_hw: Option>, + required_dev: Option>, + required_dev_index: Option, + _data: PhantomData, +} + +impl Config { + /// Creates a new instance of [`Config`]. + pub fn new() -> Self { + Self { + clk_names: None, + prop_name: None, + regulator_names: None, + supported_hw: None, + required_dev: None, + required_dev_index: None, + _data: PhantomData, + } + } + + /// Initializes clock names. + pub fn set_clk_names(mut self, names: KVec) -> Result { + // Already configured. + if self.clk_names.is_some() { + return Err(EBUSY); + } + + if names.is_empty() { + return Err(EINVAL); + } + + self.clk_names = Some(names); + Ok(self) + } + + /// Initializes property name. + pub fn set_prop_name(mut self, name: CString) -> Result { + // Already configured. + if self.prop_name.is_some() { + return Err(EBUSY); + } + + self.prop_name = Some(name); + Ok(self) + } + + /// Initializes regulator names. + pub fn set_regulator_names(mut self, names: KVec) -> Result { + // Already configured. + if self.regulator_names.is_some() { + return Err(EBUSY); + } + + if names.is_empty() { + return Err(EINVAL); + } + + self.regulator_names = Some(names); + + Ok(self) + } + + /// Initializes required devices. + pub fn set_required_dev(mut self, dev: ARef, index: u32) -> Result { + // Already configured. + if self.required_dev.is_some() { + return Err(EBUSY); + } + + self.required_dev = Some(dev); + self.required_dev_index = Some(index); + Ok(self) + } + + /// Initializes supported hardware. + pub fn set_supported_hw(mut self, hw: KVec) -> Result { + // Already configured. + if self.supported_hw.is_some() { + return Err(EBUSY); + } + + if hw.is_empty() { + return Err(EINVAL); + } + + self.supported_hw = Some(hw); + Ok(self) + } + + /// Sets the configuration with the OPP core. + pub fn set(self, dev: &Device) -> Result { + let (_clk_list, clk_names) = match &self.clk_names { + Some(x) => { + let list = to_c_str_array(x)?; + let ptr = list.as_ptr(); + (Some(list), ptr) + } + None => (None, ptr::null()), + }; + + let (_regulator_list, regulator_names) = match &self.regulator_names { + Some(x) => { + let list = to_c_str_array(x)?; + let ptr = list.as_ptr(); + (Some(list), ptr) + } + None => (None, ptr::null()), + }; + + let prop_name = match &self.prop_name { + Some(x) => x.as_char_ptr(), + None => ptr::null(), + }; + + let (supported_hw, supported_hw_count) = match &self.supported_hw { + Some(x) => (x.as_ptr(), x.len() as u32), + None => (ptr::null(), 0), + }; + + let (required_dev, required_dev_index) = match &self.required_dev { + Some(x) => (x.as_raw(), self.required_dev_index.unwrap()), + None => (ptr::null_mut(), 0), + }; + + let mut config = bindings::dev_pm_opp_config { + clk_names, + config_clks: if T::HAS_CONFIG_CLKS { + Some(Self::config_clks) + } else { + None + }, + prop_name, + regulator_names, + config_regulators: if T::HAS_CONFIG_REGULATORS { + Some(Self::config_regulators) + } else { + None + }, + supported_hw, + supported_hw_count, + + required_dev, + required_dev_index, + }; + + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. The OPP core guarantees to not use fields of `config`, after this call has + // returned and so we don't need to save a copy of them for future use + let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) }; + if ret < 0 { + Err(Error::from_errno(ret)) + } else { + Ok(ConfigToken(ret)) + } + } + + // Config's config_clks callback. + extern "C" fn config_clks( + dev: *mut bindings::device, + opp_table: *mut bindings::opp_table, + opp: *mut bindings::dev_pm_opp, + _data: *mut core::ffi::c_void, + scaling_down: bool, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: 'dev' is guaranteed by the C code to be valid. + let dev = unsafe { Device::get_device(dev) }; + T::config_clks( + &dev, + // SAFETY: 'opp_table' is guaranteed by the C code to be valid. + &unsafe { Table::from_raw_table(opp_table, &dev) }, + // SAFETY: 'opp' is guaranteed by the C code to be valid. + unsafe { OPP::from_raw_opp(opp)? }, + scaling_down, + ) + .map(|()| 0) + }) + } + + // Config's config_regulators callback. + extern "C" fn config_regulators( + dev: *mut bindings::device, + old_opp: *mut bindings::dev_pm_opp, + new_opp: *mut bindings::dev_pm_opp, + regulators: *mut *mut bindings::regulator, + count: core::ffi::c_uint, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: 'dev' is guaranteed by the C code to be valid. + let dev = unsafe { Device::get_device(dev) }; + T::config_regulators( + &dev, + // SAFETY: 'old_opp' is guaranteed by the C code to be valid. + unsafe { OPP::from_raw_opp(old_opp)? }, + // SAFETY: 'new_opp' is guaranteed by the C code to be valid. + unsafe { OPP::from_raw_opp(new_opp)? }, + regulators, + count, + ) + .map(|()| 0) + }) + } +} + /// Operating performance point (OPP) table. /// /// Wraps the kernel's `struct opp_table`. From patchwork Mon Jan 13 11:23:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937191 Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EAAB92343A5 for ; Mon, 13 Jan 2025 11:24:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767459; cv=none; b=GB5gRWe7W0pFhipi/wcye+vm2Y03Ennu9r3CWU/oBy6Yy+wpoyQZnYPi5yYBKumhJihpJr9ZDW/FAF+dcsUTfCFXLGRQQ6GWlNzBcmGRiU2X4XHmsPVqQu66UuGNI5JLhoR4Uw3xZkMAbDO0yksTTIQPb7/BmAOdkQ76YwBc+hw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767459; c=relaxed/simple; bh=2JkhyINaywtfILSPDjQ4c4dGWRyIRBju4YSZ0W0gffU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bAff17MPyVJ0z8z1nL5hlYPc9/jrGFZ4A9rA5zKjPAFOLqzOiy+DfRMa/Btol95+Bt8MKyfGpaOfblhamDG/qEv9uwke2iyDGo/YKi5DXv9rT7BPV8xt5XeJmIoS000yQl6Q5+0hZuEVDoa58vWLn6sw9/Hjbb6RX0jk3Eb3nj4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=po6Qqddr; arc=none smtp.client-ip=209.85.216.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="po6Qqddr" Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-2efd81c7ca4so5481413a91.2 for ; Mon, 13 Jan 2025 03:24:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767456; x=1737372256; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WwzrLAB8Dxug2z6b+uwUwN8Azj70Ar3EfIfvsIBOHtw=; b=po6Qqddr7BEQ67aYfi8OPjevKVpkOAO/k60U7UdGykICPo+8cyiJZo9tqyEoLKqtv1 3wIHbdP6GLQRKr9FXaqsi6kHxWgZ97bH25/vAUGq8rg3hq/qqD1kx/3mqXPhIXoMgpLx ePcjBHU99kSBQxvfjW3uxb3C3eTMSzbH4d0MvOyuSa5xJDimGpCsjsCJf+/O/D00xp/n GmjGa0fpSCBXBdNJLkzd/G03hkOirGU7P5rOaUkbl4z4FFvaNv5i8VIn222uy0j/j2VQ uRcns0W86aVS03RLF44atOJ67v7y2QUMtHSMPFhgYlQm0nLyoKjEHSEBX5T8kZ1klF0h cGcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767456; x=1737372256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WwzrLAB8Dxug2z6b+uwUwN8Azj70Ar3EfIfvsIBOHtw=; b=Z73jbP23RYzNb+Lw0gRkSj/70SVpm4IrkMrtG1yC4zACw0P86qinu/DZjDRYQLnQa/ u7aCxLly//2Wv+KClsgmJMpuWlPAEmS1h+XEVEZyxUOTm1GyyArpFe/St9Y1TZTRfcYF vmQAeI9lXPRV+uB1swgIPFwM05QR5RvxGTrAWthFcusRLKrfW+FUEONDBZaxPPw6jN4A GZnk2pMnTowUgMqfZU2FNVUMuwaYAv/8jDN5xFkQPdy+IoiU0GlrcsIN5N+fikqVt/bO uxbNHr9Qok3hB/LuGnUdgi8M/Ei12+7F0yCD9sk105wVNT1Q7JA0ie5KMvvfLNQU6R3D XWOw== X-Gm-Message-State: AOJu0YwJfu8LtJTHJuaocDz1gkwbrrFsxeT6igxGR2VcyjDfub/ypiZ8 Dahg6VTcpSjpY59oJnJ/j7UkAECdBhwJi2kslWmsgRuDE8Julcc95cXJsB0OpMU= X-Gm-Gg: ASbGncuKIc67zgatILYlUs+msXY/bSZt8BJAhabek/ouukHVThi10RySyGeVcQpy/UU Fe502hiXdGh7FTW/S06Gwc92/WqWyQvEwaFkIBmGwcxri4Bxy81Hoqmwye/LKCZ+Ag6WTwWPVmx nR4ig10upA0c/Z8ySsBxgjXFW2f3lzEUUm7ec5C8Xc3OelacFlFPmmi/IboNSrEBlIelzuGywMS imD9alemQbdYS7e9V4xtns5saWBtlKEeJ2qcXMplGHtBn0CILaQY4yeBrE= X-Google-Smtp-Source: AGHT+IGSrjWAXG/i1/fxPFQSZ8SgGH6S3WwvH2xeaVLAPlcZxWEtSTFord1i+91CODMVAveRLw497A== X-Received: by 2002:a17:90b:5208:b0:2ef:33a4:ae6e with SMTP id 98e67ed59e1d1-2f548eba9c4mr35243647a91.12.1736767456231; Mon, 13 Jan 2025 03:24:16 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2f53e1d3bd0sm7704068a91.0.2025.01.13.03.24.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:15 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Viresh Kumar Cc: linux-pm@vger.kernel.org, Vincent Guittot , Manos Pitsidianakis , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 11/16] rust: Add initial bindings for cpufreq framework Date: Mon, 13 Jan 2025 16:53:06 +0530 Message-Id: <535b9af357a3e6735bd5543d4cb56e632ba80697.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit adds initial Rust bindings for the cpufreq core. This adds basic bindings for cpufreq flags, relations and cpufreq table. Reviewed-by: Manos Pitsidianakis Signed-off-by: Viresh Kumar --- MAINTAINERS | 1 + rust/bindings/bindings_helper.h | 1 + rust/helpers/cpufreq.c | 10 ++ rust/helpers/helpers.c | 1 + rust/kernel/cpufreq.rs | 231 ++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 2 + 6 files changed, 246 insertions(+) create mode 100644 rust/helpers/cpufreq.c create mode 100644 rust/kernel/cpufreq.rs diff --git a/MAINTAINERS b/MAINTAINERS index 3f9ebca78732..fb92356efbba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6017,6 +6017,7 @@ F: drivers/cpufreq/ F: include/linux/cpufreq.h F: include/linux/sched/cpufreq.h F: kernel/sched/cpufreq*.c +F: rust/kernel/cpufreq.rs F: tools/testing/selftests/cpufreq/ CPU HOTPLUG diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 7f851d5907af..68bf1bc5bae8 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/cpufreq.c b/rust/helpers/cpufreq.c new file mode 100644 index 000000000000..7c1343c4d65e --- /dev/null +++ b/rust/helpers/cpufreq.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#ifdef CONFIG_CPU_FREQ +void rust_helper_cpufreq_register_em_with_opp(struct cpufreq_policy *policy) +{ + cpufreq_register_em_with_opp(policy); +} +#endif diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index de2341cfd917..32d0462219e5 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -11,6 +11,7 @@ #include "bug.c" #include "build_assert.c" #include "build_bug.c" +#include "cpufreq.c" #include "cpumask.c" #include "cred.c" #include "device.c" diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs new file mode 100644 index 000000000000..3dfdf5ccb9b8 --- /dev/null +++ b/rust/kernel/cpufreq.rs @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! CPU frequency scaling. +//! +//! This module provides bindings for interacting with the cpufreq subsystem. +//! +//! C header: [`include/linux/cpufreq.h`](srctree/include/linux/cpufreq.h) + +use crate::{ + bindings, + error::{code::*, to_result, Result}, + prelude::*, +}; + +use core::{ + pin::Pin, +}; + +/// Default transition latency value. +pub const ETERNAL_LATENCY: u32 = bindings::CPUFREQ_ETERNAL as u32; + +/// Container for cpufreq driver flags. +pub mod flags { + use crate::bindings; + + /// Set by drivers that need to update internal upper and lower boundaries along with the + /// target frequency and so the core and governors should also invoke the driver if the target + /// frequency does not change, but the policy min or max may have changed. + pub const NEED_UPDATE_LIMITS: u16 = bindings::CPUFREQ_NEED_UPDATE_LIMITS as _; + + /// Set by drivers for platforms where loops_per_jiffy or other kernel "constants" aren't + /// affected by frequency transitions. + pub const CONST_LOOPS: u16 = bindings::CPUFREQ_CONST_LOOPS as _; + + /// Set by drivers that want the core to automatically register the cpufreq driver as a thermal + /// cooling device. + pub const IS_COOLING_DEV: u16 = bindings::CPUFREQ_IS_COOLING_DEV as _; + + /// Set by drivers for platforms that have multiple clock-domains, i.e. supporting multiple + /// policies. With this sysfs directories of governor would be created in cpu/cpuN/cpufreq/ + /// directory and so they can use the same governor with different tunables for different + /// clusters. + pub const HAVE_GOVERNOR_PER_POLICY: u16 = bindings::CPUFREQ_HAVE_GOVERNOR_PER_POLICY as _; + + /// Set by drivers which do POSTCHANGE notifications from outside of their ->target() routine. + pub const ASYNC_NOTIFICATION: u16 = bindings::CPUFREQ_ASYNC_NOTIFICATION as _; + + /// Set by drivers that want cpufreq core to check if CPU is running at a frequency present in + /// freq-table exposed by the driver. For these drivers if CPU is found running at an out of + /// table freq, the cpufreq core will try to change the frequency to a value from the table. + /// And if that fails, it will stop further boot process by issuing a BUG_ON(). + pub const NEED_INITIAL_FREQ_CHECK: u16 = bindings::CPUFREQ_NEED_INITIAL_FREQ_CHECK as _; + + /// Set by drivers to disallow use of governors with "dynamic_switching" flag set. + pub const NO_AUTO_DYNAMIC_SWITCHING: u16 = bindings::CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING as _; +} + +/// CPU frequency selection relations. Each value contains a `bool` argument which corresponds to +/// the Relation being efficient. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum Relation { + /// Select the lowest frequency at or above target. + Low(bool), + /// Select the highest frequency below or at target. + High(bool), + /// Select the closest frequency to the target. + Close(bool), +} + +impl Relation { + // Converts from a value compatible with the C code. + fn new(val: u32) -> Result { + let efficient = val & bindings::CPUFREQ_RELATION_E != 0; + + Ok(match val & !bindings::CPUFREQ_RELATION_E { + bindings::CPUFREQ_RELATION_L => Self::Low(efficient), + bindings::CPUFREQ_RELATION_H => Self::High(efficient), + bindings::CPUFREQ_RELATION_C => Self::Close(efficient), + _ => return Err(EINVAL), + }) + } + + /// Converts to a value compatible with the C code. + pub fn val(&self) -> u32 { + let (mut val, e) = match self { + Self::Low(e) => (bindings::CPUFREQ_RELATION_L, e), + Self::High(e) => (bindings::CPUFREQ_RELATION_H, e), + Self::Close(e) => (bindings::CPUFREQ_RELATION_C, e), + }; + + if *e { + val |= bindings::CPUFREQ_RELATION_E; + } + + val + } +} + +/// Equivalent to `struct cpufreq_policy_data` in the C code. +#[repr(transparent)] +pub struct PolicyData(*mut bindings::cpufreq_policy_data); + +impl PolicyData { + /// Creates new instance of [`PolicyData`]. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid and non-null. + pub unsafe fn from_raw_policy_data(ptr: *mut bindings::cpufreq_policy_data) -> Self { + Self(ptr) + } + + /// Returns the raw pointer to the C structure. + #[inline] + pub fn as_raw(&self) -> *mut bindings::cpufreq_policy_data { + self.0 + } + + /// Provides a wrapper to the generic verify routine. + pub fn generic_verify(&self) -> Result<()> { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it now. + to_result(unsafe { bindings::cpufreq_generic_frequency_table_verify(self.as_raw()) }) + } +} + +/// Builder for the `struct cpufreq_frequency_table` in the C code. +#[repr(transparent)] +#[derive(Default)] +pub struct TableBuilder { + entries: KVec, +} + +impl TableBuilder { + /// Creates new instance of [`TableBuilder`]. + pub fn new() -> Self { + Self { + entries: KVec::new(), + } + } + + /// Adds a new entry to the table. + pub fn add(&mut self, frequency: u32, flags: u32, driver_data: u32) -> Result<()> { + // Adds new entry to the end of the vector. + Ok(self.entries.push( + bindings::cpufreq_frequency_table { + flags, + driver_data, + frequency, + }, + GFP_KERNEL, + )?) + } + + /// Creates [`Table`] from [`TableBuilder`]. + pub fn into_table(mut self) -> Result { + // Add last entry to the table. + self.add(bindings::CPUFREQ_TABLE_END as u32, 0, 0)?; + Table::from_builder(self.entries) + } +} + +/// A simple implementation of the cpufreq table, equivalent to the `struct +/// cpufreq_frequency_table` in the C code. +pub struct Table { + #[allow(dead_code)] + // Dynamically created table. + entries: Option>>, + + // Pointer to the statically or dynamically created table. + ptr: *mut bindings::cpufreq_frequency_table, +} + +impl Table { + /// Creates new instance of [`Table`] from [`TableBuilder`]. + fn from_builder(entries: KVec) -> Result { + if entries.is_empty() { + return Err(EINVAL); + } + + // Pin the entries to memory, since we are passing its pointer to the C code. + let mut entries = Pin::new(entries); + + // The pointer is valid until the table gets dropped. + let ptr = entries.as_mut_ptr(); + + Ok(Self { + entries: Some(entries), + ptr, + }) + } + + /// Creates new instance of [`Table`] from raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid and non-null for the lifetime of the [`Table`]. + pub unsafe fn from_raw(ptr: *mut bindings::cpufreq_frequency_table) -> Self { + Self { + entries: None, + ptr, + } + } + + /// Returns raw pointer to the `struct cpufreq_frequency_table` compatible with the C code. + #[inline] + pub fn as_raw(&self) -> *mut bindings::cpufreq_frequency_table { + self.ptr + } + + /// Returns `frequency` at index in the [`Table`]. + pub fn freq(&self, index: usize) -> Result { + // SAFETY: The pointer is guaranteed to be valid for the lifetime of `self` and `index` is + // guaranteed to be within limits of the frequency table by the C API. + Ok(unsafe { (*self.ptr.add(index)).frequency }) + } + + /// Returns `flags` at index in the [`Table`]. + pub fn flags(&self, index: usize) -> Result { + // SAFETY: The pointer is guaranteed to be valid for the lifetime of `self` and `index` is + // guaranteed to be within limits of the frequency table by the C API. + Ok(unsafe { (*self.ptr.add(index)).flags }) + } + + /// Returns `data` at index in the [`Table`]. + pub fn data(&self, index: usize) -> Result { + // SAFETY: The pointer is guaranteed to be valid for the lifetime of `self` and `index` is + // guaranteed to be within limits of the frequency table by the C API. + Ok(unsafe { (*self.ptr.add(index)).driver_data }) + } +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index d1c0f136952e..2dd134a46285 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -41,6 +41,8 @@ pub mod build_assert; pub mod clk; pub mod cpu; +#[cfg(CONFIG_CPU_FREQ)] +pub mod cpufreq; pub mod cpumask; pub mod cred; pub mod device; From patchwork Mon Jan 13 11:23:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937192 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A07641CAA76 for ; Mon, 13 Jan 2025 11:24:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767462; cv=none; b=izUIk7As1EYGX8yaVtdcTy53SzUAVh68PsJWFDuDe1lF9PoGhTSyyVFMFOeL2xVBU3JBrWFZKULY1ehf5DEVqO04FO4xtCphx2LJ5AIc9gshLkdNHY6myzgoz7tvvQ19s9qSKDHGgQQGL7gRPg8pMUQL2n4Kqh1/WH/FbFKynxg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767462; c=relaxed/simple; bh=6eUufuO+qr8rw3xAmaRGavy2ljguk2nZVG/nqhHwfEE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PCDywAHaZPhA/TxhjefhVDrympHLaXnR1yNqw+MpCp90LDnJKAg73pZU1D9PzwwD0HqLr14Q7w8hGDAfcIuXpfkLyGGpV3GFhUWTXWtZO/29L0VKxZo7BpiFetQqoH/dJcMMcM6Hozexl9qpnhbvdTy1BlGB2HJ9pPtaHWcnrxA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=pCNjr59k; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="pCNjr59k" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2162c0f6a39so90534615ad.0 for ; Mon, 13 Jan 2025 03:24:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767460; x=1737372260; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zwXoOBJkAjU4c4qfx40sQTPK06Msu4Zsat+nENe15cc=; b=pCNjr59ktGo2fiYlADUyd99VP569LacaopQXOHQdVd8wmEnjjVJ9MzYznCwgLTrvyY L4v8vgV8nr1Ufl8VtfF0Wt9kug+KFUwCP4BF5vt//whOnRy4M1fcBhmrgj9MGZZVvlR0 M9l8SylecZk5OrAtEx+65BdUT2RgB1ib8N7czCXftCQKmAQEmAoj6DvDQ7wgbGEZWLl1 HMn6B/ooea2tYPYl7X0QpxWCyQnz6VR5aN8G2w7M3trMcZN6sxZSxI8qnRMAiMqsSCHi P9cjCVcDT27c5ACwUu4mzsdaaXTk6WXypGwe7VVwOAjEM1cd2m+S/BYziGvaK/zgqZdU GONw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767460; x=1737372260; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zwXoOBJkAjU4c4qfx40sQTPK06Msu4Zsat+nENe15cc=; b=UEK5XkysThyDcTfnFTj9XP/miVk7ofTWOExvKthVeN00LCNyC7IXNq/BWxEhnBCMaA X/2Gnw6CuX+CetIaayo3DnpkQb/i43SpdjI4i5jAjdsZpk/IiUGvuwFpIx8IC/9eEf8l nXVG1dw8pArQchza2979KyUvX2kZqchVbRiQrngSF7D8Z/KSw1eWmHWQCxbuO+xxPp5a 2oXcuchnBVTJ2Ze+rxGZi/lo4+7KSsOSJ0yKJdUXUcMD0meiJYDF6+kRM2bHMpl5sT5+ FEL+TI9lmJepE9fPrrCJpRtVVOM4shp8q2XwDf48BPl/UmXRZYIHA1HrR5ftS21pXCHP dORQ== X-Gm-Message-State: AOJu0YwoGlfZCzQM4DGhIhzeXX1JmnyQ7fSSdzLfrF1KdmX9JFJdGWFV QaWmeeIjjd2h+4wsxnSolR2Tn2yv2F5lDXwmo33XOw7tjWLBTdQ+p9cy/t6lKy4= X-Gm-Gg: ASbGnctAQ+hRwykOjWlCbKKWzz0McbNSJhbj5DYGLQe51AEadz7GxrvKpOPDMdQSava N71ZDGYMdw9Q/E9vlJrJ5PhLdwzUpA+BBnnl9Yrmyo2GoMLvkbNBGqovtW5cBmM3FGms9wAkyNV deiwV4T4aYE4vGv1EAjmG9O507rNf2tdflYAMyF04m9Td5K8Iycxfig+aD+pFVPyNxpOs4pnIar IgcwJAkQBeg5zyNPA0dll0a3FhmtuWs30ImBmkQzBhV3TL+/KWetw65vxY= X-Google-Smtp-Source: AGHT+IF1jBDNlhS9BCy1e75qQA8jc0azS1BNJz+YKP3r8+t+nCxIjTXNNHlirZyqycQgyWPxMknT9g== X-Received: by 2002:a05:6a20:2d14:b0:1e1:a789:1b4d with SMTP id adf61e73a8af0-1e8b1623c35mr18366709637.15.1736767460050; Mon, 13 Jan 2025 03:24:20 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d4065c3b4sm5688313b3a.112.2025.01.13.03.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:19 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: linux-pm@vger.kernel.org, Vincent Guittot , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V7 12/16] rust: Extend cpufreq bindings for policy and driver ops Date: Mon, 13 Jan 2025 16:53:07 +0530 Message-Id: <20f7ea798034674e5be08bd6d92c7d686d93df06.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This extends the cpufreq bindings with bindings for cpufreq policy and driver operations. Signed-off-by: Viresh Kumar --- rust/kernel/cpufreq.rs | 357 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 355 insertions(+), 2 deletions(-) diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index 3dfdf5ccb9b8..8468e12ef1f5 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -7,15 +7,20 @@ //! C header: [`include/linux/cpufreq.h`](srctree/include/linux/cpufreq.h) use crate::{ - bindings, - error::{code::*, to_result, Result}, + bindings, clk, cpumask, + device::Device, + error::{code::*, from_err_ptr, to_result, Result, VTABLE_DEFAULT_ERROR}, prelude::*, + types::ForeignOwnable, }; use core::{ pin::Pin, + ptr::self, }; +use macros::vtable; + /// Default transition latency value. pub const ETERNAL_LATENCY: u32 = bindings::CPUFREQ_ETERNAL as u32; @@ -229,3 +234,351 @@ pub fn data(&self, index: usize) -> Result { Ok(unsafe { (*self.ptr.add(index)).driver_data }) } } + +/// Equivalent to `struct cpufreq_policy` in the C code. +pub struct Policy { + ptr: *mut bindings::cpufreq_policy, + put_cpu: bool, + cpumask: cpumask::Cpumask, +} + +impl Policy { + /// Creates a new instance of [`Policy`]. + /// + /// # Safety + /// + /// Callers must ensure that `ptr` is valid and non-null. + pub unsafe fn from_raw_policy(ptr: *mut bindings::cpufreq_policy) -> Self { + Self { + ptr, + put_cpu: false, + // SAFETY: The pointer is guaranteed to be valid for the lifetime of `Self`. The `cpus` + // pointer is guaranteed to be valid by the C code. + cpumask: unsafe { cpumask::Cpumask::get_cpumask((*ptr).cpus) }, + } + } + + fn from_cpu(cpu: u32) -> Result { + // SAFETY: It is safe to call `cpufreq_cpu_get()` for any CPU. + let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?; + + // SAFETY: The pointer is guaranteed to be valid by the C code. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + policy.put_cpu = true; + Ok(policy) + } + + /// Raw pointer to the underlying cpufreq policy. + #[inline] + pub fn as_raw(&self) -> *mut bindings::cpufreq_policy { + self.ptr + } + + fn as_ref(&self) -> &bindings::cpufreq_policy { + // SAFETY: By the type invariants, we know that `self` owns a reference to the pointer. + unsafe { &(*self.ptr) } + } + fn as_mut_ref(&mut self) -> &mut bindings::cpufreq_policy { + // SAFETY: By the type invariants, we know that `self` owns a reference to the pointer. + unsafe { &mut (*self.ptr) } + } + + /// Returns the primary CPU for a cpufreq policy. + pub fn cpu(&self) -> u32 { + self.as_ref().cpu + } + + /// Returns the minimum frequency for a cpufreq policy. + pub fn min(&self) -> u32 { + self.as_ref().min + } + + /// Set the minimum frequency for a cpufreq policy. + pub fn set_min(&mut self, min: u32) -> &mut Self { + self.as_mut_ref().min = min; + self + } + + /// Returns the maximum frequency for a cpufreq policy. + pub fn max(&self) -> u32 { + self.as_ref().max + } + + /// Set the maximum frequency for a cpufreq policy. + pub fn set_max(&mut self, max: u32) -> &mut Self { + self.as_mut_ref().max = max; + self + } + + /// Returns the current frequency for a cpufreq policy. + pub fn cur(&self) -> u32 { + self.as_ref().cur + } + + /// Sets the suspend frequency for a cpufreq policy. + pub fn set_suspend_freq(&mut self, freq: u32) -> &mut Self { + self.as_mut_ref().suspend_freq = freq; + self + } + + /// Returns the suspend frequency for a cpufreq policy. + pub fn suspend_freq(&self) -> u32 { + self.as_ref().suspend_freq + } + + /// Provides a wrapper to the generic suspend routine. + pub fn generic_suspend(&self) -> Result<()> { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it now. + to_result(unsafe { bindings::cpufreq_generic_suspend(self.as_raw()) }) + } + + /// Provides a wrapper to the generic get routine. + pub fn generic_get(&self) -> Result { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it now. + Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) + } + + /// Provides a wrapper to the register em with OPP routine. + pub fn register_em_opp(&self) { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // use it now. + unsafe { bindings::cpufreq_register_em_with_opp(self.as_raw()) }; + } + + /// Gets raw pointer to cpufreq policy's CPUs mask. + pub fn cpus(&mut self) -> &mut cpumask::Cpumask { + &mut self.cpumask + } + + /// Sets clock for a cpufreq policy. + pub fn set_clk(&mut self, dev: &Device, name: Option<&CStr>) -> Result { + let clk = clk::Clk::new(dev, name)?; + self.as_mut_ref().clk = clk.as_raw(); + Ok(clk) + } + + /// Allows frequency switching code to run on any CPU. + pub fn set_dvfs_possible_from_any_cpu(&mut self) -> &mut Self { + self.as_mut_ref().dvfs_possible_from_any_cpu = true; + self + } + + /// Get fast_switch_possible value. + pub fn fast_switch_possible(&self) -> bool { + self.as_ref().fast_switch_possible + } + + /// Enable/disable fast frequency switching. + pub fn set_fast_switch_possible(&mut self, val: bool) -> &mut Self { + self.as_mut_ref().fast_switch_possible = val; + self + } + + /// Sets transition latency for a cpufreq policy. + pub fn set_transition_latency(&mut self, latency: u32) -> &mut Self { + self.as_mut_ref().cpuinfo.transition_latency = latency; + self + } + + /// Set cpuinfo.min_freq. + pub fn set_cpuinfo_min_freq(&mut self, min_freq: u32) -> &mut Self { + self.as_mut_ref().cpuinfo.min_freq = min_freq; + self + } + + /// Set cpuinfo.max_freq. + pub fn set_cpuinfo_max_freq(&mut self, max_freq: u32) -> &mut Self { + self.as_mut_ref().cpuinfo.max_freq = max_freq; + self + } + + /// Set transition_delay_us, i.e. time between successive freq. change requests. + pub fn set_transition_delay_us(&mut self, transition_delay_us: u32) -> &mut Self { + self.as_mut_ref().transition_delay_us = transition_delay_us; + self + } + + /// Returns the cpufreq table for a cpufreq policy. The cpufreq table is recreated in a + /// light-weight manner from the raw pointer. The table in C code is not freed once this table + /// is dropped. + pub fn freq_table(&self) -> Result
{ + if self.as_ref().freq_table.is_null() { + return Err(EINVAL); + } + + // SAFETY: The `freq_table` is guaranteed to be valid. + Ok(unsafe { Table::from_raw(self.as_ref().freq_table) }) + } + + /// Sets the cpufreq table for a cpufreq policy. + /// + /// The cpufreq driver must guarantee that the frequency table does not get freed while it is + /// still being used by the C code. + pub fn set_freq_table(&mut self, table: &Table) -> &mut Self { + self.as_mut_ref().freq_table = table.as_raw(); + self + } + + /// Returns the data for a cpufreq policy. + pub fn data(&mut self) -> Option<::Borrowed<'_>> { + if self.as_ref().driver_data.is_null() { + None + } else { + // SAFETY: The data is earlier set by us from [`set_data()`]. + Some(unsafe { T::borrow(self.as_ref().driver_data) }) + } + } + + // Sets the data for a cpufreq policy. + fn set_data(&mut self, data: T) -> Result<()> { + if self.as_ref().driver_data.is_null() { + // Pass the ownership of the data to the foreign interface. + self.as_mut_ref().driver_data = ::into_foreign(data) as _; + Ok(()) + } else { + Err(EBUSY) + } + } + + // Returns the data for a cpufreq policy. + fn clear_data(&mut self) -> Option { + if self.as_ref().driver_data.is_null() { + None + } else { + let data = Some( + // SAFETY: The data is earlier set by us from [`set_data()`]. It is safe to take + // back the ownership of the data from the foreign interface. + unsafe { ::from_foreign(self.as_ref().driver_data) } + ); + self.as_mut_ref().driver_data = ptr::null_mut(); + data + } + } +} + +impl Drop for Policy { + fn drop(&mut self) { + if self.put_cpu { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // relinquish it now. + unsafe { bindings::cpufreq_cpu_put(self.as_raw()) }; + } + } +} + +/// Operations to be implemented by a cpufreq driver. +#[vtable] +pub trait Driver { + /// Driver specific data. + /// + /// Corresponds to the data retrieved via the kernel's + /// `cpufreq_get_driver_data()` function. + /// + /// Require that `Data` implements `ForeignOwnable`. We guarantee to + /// never move the underlying wrapped data structure. + type Data: ForeignOwnable; + + /// Policy specific data. + /// + /// Require that `PData` implements `ForeignOwnable`. We guarantee to + /// never move the underlying wrapped data structure. + type PData: ForeignOwnable; + + /// Policy's init callback. + fn init(policy: &mut Policy) -> Result; + + /// Policy's exit callback. + fn exit(_policy: &mut Policy, _data: Option) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's online callback. + fn online(_policy: &mut Policy) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's offline callback. + fn offline(_policy: &mut Policy) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's suspend callback. + fn suspend(_policy: &mut Policy) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's resume callback. + fn resume(_policy: &mut Policy) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's ready callback. + fn ready(_policy: &mut Policy) { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's verify callback. + fn verify(data: &mut PolicyData) -> Result<()>; + + /// Policy's setpolicy callback. + fn setpolicy(_policy: &mut Policy) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's target callback. + fn target(_policy: &mut Policy, _target_freq: u32, _relation: Relation) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's target_index callback. + fn target_index(_policy: &mut Policy, _index: u32) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's fast_switch callback. + fn fast_switch(_policy: &mut Policy, _target_freq: u32) -> u32 { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's adjust_perf callback. + fn adjust_perf(_policy: &mut Policy, _min_perf: usize, _target_perf: usize, _capacity: usize) { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's get_intermediate callback. + fn get_intermediate(_policy: &mut Policy, _index: u32) -> u32 { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's target_intermediate callback. + fn target_intermediate(_policy: &mut Policy, _index: u32) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's get callback. + fn get(_policy: &mut Policy) -> Result { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's update_limits callback. + fn update_limits(_policy: &mut Policy) { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's bios_limit callback. + fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's set_boost callback. + fn set_boost(_policy: &mut Policy, _state: i32) -> Result<()> { + build_error!(VTABLE_DEFAULT_ERROR) + } + + /// Policy's register_em callback. + fn register_em(_policy: &mut Policy) { + build_error!(VTABLE_DEFAULT_ERROR) + } +} From patchwork Mon Jan 13 11:23:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937193 Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com [209.85.214.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4A5D238736 for ; Mon, 13 Jan 2025 11:24:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767466; cv=none; b=bBf4G+0AG79eaqzStJf9Ba1GPugrddYyB4YhR1RO84CB8sZGam18q08udO7+N1k1Be++nHSz3Jc1rN3dyur/jjSZdJauNgXpX0WgBxNBCHfTBOxSiR/dabimSP36xGH3xtlkwhrF+4AahIgD3E8cs8MGxrQ5F+D+rqlPzCC6BPw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767466; c=relaxed/simple; bh=fmsO+gUs+PaCOyzUqE6A+eHGWzdyvpsE6BHVemBn01I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hTLTpbDnrAg3O8d0OsWQb/w6HmDU5WrKBA+Auu3jDyI3ZTnxlYiZNo66z2qCPml3oZEbbiuL8isV8tT7/rjNOn/X8BUCkbmCSXCKI3/Der95lyCl1OC7D3kP0HjwNaWBKKrSbQZxTHuRWTPaIYJdgqHELyBeTJPoJkC0PqIZPok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=zvoURDSV; arc=none smtp.client-ip=209.85.214.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="zvoURDSV" Received: by mail-pl1-f179.google.com with SMTP id d9443c01a7336-21a7ed0155cso68974585ad.3 for ; Mon, 13 Jan 2025 03:24:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767464; x=1737372264; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Jqj01KGpNi0J5xBTE+Wd2fJArhO2X9pHhv/GKSBCr2Q=; b=zvoURDSVV23i7sIvzmen8y5RTKWoZ3cMG3gfLzzfid3LUgu+Wk5BLHjNA499RTKT47 x4QzxIYyG8JpQAV98jwuYim9wsPzwMzWFdYfg/7MWhrGdtgX2TyTzsMKDhpVrK6CiNDO 0yNeJgfHWWjH2tnzB6NCRfJSJn8vVoT/2UtkxYfxtowloFsFy1TQ4sJ/x56l55SCfGZr dxqLuCtCC9ooSeFcZPcOBY4bsAnlT1S7ex1GOhIUOdk84yDGUo0xK/cdAqbp/IKQmh4t O0zc79aDGyvqY1sjMgiIqz80ea0hYocfy7Mgr6MID+koBzVGzhQdt/A2c5GhP8ex9hq5 gAug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767464; x=1737372264; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Jqj01KGpNi0J5xBTE+Wd2fJArhO2X9pHhv/GKSBCr2Q=; b=bpbQOJ7eY1YqZC6xEANfqGmIaELOQVsLx6+r2wZAuvo3vCwrzXGiZ29M3UBjDIYIh9 PmLrKXY5mDkQx2ZiuhOZxNUgxadcvMQOEB0bCxN77NgRVSatF5T4wiAMjq7le6FWcK4O icZYgYFpcBrpacX/8VNumFKEbQm+mr/WSuCXbkeCFB17F2/qPhizaGDTWqDw0d9UdZEq 6lkiRuoKYIiRuomEZ+5kOtSgIpWn7u8+/s8JoUDcYPUHL9y/sWsYVjHV371Sa5YFbx2K gy6qHKh2uSkJYCRtw+yVU7zQV+fWDmN69B3/G4uLoEwI2CRRz1Ds8mzhaPYrYBkN+JKI ObIA== X-Gm-Message-State: AOJu0YxpaR1QMBnHl59vAcvQ4OoU+ANj0kX0P+mQgerT3U+IpuShYvA/ qtJDysNtDkwNW0TMuHbBh/7vvmsTjTD0tNC5dkUTZLW1Lk5I1rZ3az4Sf4giSPk= X-Gm-Gg: ASbGncvvH2LZQYCL2poJ+khbsy6L3yjsemAcnk5cTMn5JvejdaPip5Q6MgWpzFCkst1 iBQ99MRFPKzVy3+Wg+ROXx4gIBLVkbClMgMn/zL71Jst0rPQ1KAvqPOIRQ7lnjn73KiXJKRvZqQ I2w+2mkYdvao+Z6Y5OKK4f8z45saCP6VZlSpLy0x6Yino+Ely3NyMTCUgEALIQnY0PB6O4bdsvw 2kCazgIdNQ9LTSqdXV/b/wTGCXlSCf6EochdNGaO8mkGYZizPxoUg16978= X-Google-Smtp-Source: AGHT+IF3VnF2HOh2G1jERTpOh24EBzVNaNpYbXGC2liPXlYsq5SBTdEYYq0R/pVu5nzMpPDVkfebpQ== X-Received: by 2002:a05:6a00:32cb:b0:725:df1a:288 with SMTP id d2e1a72fcca58-72d2201c96dmr33506209b3a.24.1736767463835; Mon, 13 Jan 2025 03:24:23 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-72d4065a544sm5939301b3a.96.2025.01.13.03.24.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:23 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: linux-pm@vger.kernel.org, Vincent Guittot , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V7 13/16] rust: Extend cpufreq bindings for driver registration Date: Mon, 13 Jan 2025 16:53:08 +0530 Message-Id: X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This extends the cpufreq bindings with bindings for registering a driver. Signed-off-by: Viresh Kumar --- rust/kernel/cpufreq.rs | 476 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 474 insertions(+), 2 deletions(-) diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index 8468e12ef1f5..899f5b50eb7c 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -9,14 +9,17 @@ use crate::{ bindings, clk, cpumask, device::Device, - error::{code::*, from_err_ptr, to_result, Result, VTABLE_DEFAULT_ERROR}, + devres::Devres, + error::{code::*, from_err_ptr, from_result, to_result, Result, VTABLE_DEFAULT_ERROR}, prelude::*, types::ForeignOwnable, }; use core::{ + cell::UnsafeCell, + marker::PhantomData, pin::Pin, - ptr::self, + ptr::{self, addr_of_mut}, }; use macros::vtable; @@ -582,3 +585,472 @@ fn register_em(_policy: &mut Policy) { build_error!(VTABLE_DEFAULT_ERROR) } } + +/// Registration of a cpufreq driver. +pub struct Registration { + drv: KBox>, + _p: PhantomData, +} + +// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads +// or CPUs, so it is safe to share it. +unsafe impl Sync for Registration {} + +#[allow(clippy::non_send_fields_in_send_ty)] +// SAFETY: Registration with and unregistration from the cpufreq subsystem can happen from any thread. +// Additionally, `T::Data` (which is dropped during unregistration) is `Send`, so it is okay to move +// `Registration` to different threads. +unsafe impl Send for Registration {} + +impl Registration { + /// Registers a cpufreq driver with the rest of the kernel. + pub fn new(name: &'static CStr, data: T::Data, flags: u16, boost: bool) -> Result { + let mut drv = KBox::new( + UnsafeCell::new(bindings::cpufreq_driver::default()), + GFP_KERNEL, + )?; + let drv_ref = drv.get_mut(); + + // Account for the trailing null character. + let len = name.len() + 1; + if len > drv_ref.name.len() { + return Err(EINVAL); + }; + + // SAFETY: `name` is a valid Cstr, and we are copying it to an array of equal or larger + // size. + let name = unsafe { &*(name.as_bytes_with_nul() as *const [u8]) }; + drv_ref.name[..len].copy_from_slice(name); + + drv_ref.boost_enabled = boost; + drv_ref.flags = flags; + + // Allocate an array of 3 pointers to be passed to the C code. + let mut attr = KBox::new([ptr::null_mut(); 3], GFP_KERNEL)?; + let mut next = 0; + + // SAFETY: The C code returns a valid pointer here, which is again passed to the C code in + // an array. + attr[next] = unsafe { + addr_of_mut!(bindings::cpufreq_freq_attr_scaling_available_freqs) as *mut _ + }; + next += 1; + + if boost { + // SAFETY: The C code returns a valid pointer here, which is again passed to the C code + // in an array. + attr[next] = unsafe { + addr_of_mut!(bindings::cpufreq_freq_attr_scaling_boost_freqs) as *mut _ + }; + next += 1; + } + attr[next] = ptr::null_mut(); + + // Pass the ownership of the memory block to the C code. This will be freed when + // the [`Registration`] object goes out of scope. + drv_ref.attr = KBox::leak(attr) as *mut _; + + // Initialize mandatory callbacks. + drv_ref.init = Some(Self::init_callback); + drv_ref.verify = Some(Self::verify_callback); + + // Initialize optional callbacks. + drv_ref.setpolicy = if T::HAS_SETPOLICY { + Some(Self::setpolicy_callback) + } else { + None + }; + drv_ref.target = if T::HAS_TARGET { + Some(Self::target_callback) + } else { + None + }; + drv_ref.target_index = if T::HAS_TARGET_INDEX { + Some(Self::target_index_callback) + } else { + None + }; + drv_ref.fast_switch = if T::HAS_FAST_SWITCH { + Some(Self::fast_switch_callback) + } else { + None + }; + drv_ref.adjust_perf = if T::HAS_ADJUST_PERF { + Some(Self::adjust_perf_callback) + } else { + None + }; + drv_ref.get_intermediate = if T::HAS_GET_INTERMEDIATE { + Some(Self::get_intermediate_callback) + } else { + None + }; + drv_ref.target_intermediate = if T::HAS_TARGET_INTERMEDIATE { + Some(Self::target_intermediate_callback) + } else { + None + }; + drv_ref.get = if T::HAS_GET { + Some(Self::get_callback) + } else { + None + }; + drv_ref.update_limits = if T::HAS_UPDATE_LIMITS { + Some(Self::update_limits_callback) + } else { + None + }; + drv_ref.bios_limit = if T::HAS_BIOS_LIMIT { + Some(Self::bios_limit_callback) + } else { + None + }; + drv_ref.online = if T::HAS_ONLINE { + Some(Self::online_callback) + } else { + None + }; + drv_ref.offline = if T::HAS_OFFLINE { + Some(Self::offline_callback) + } else { + None + }; + drv_ref.exit = if T::HAS_EXIT { + Some(Self::exit_callback) + } else { + None + }; + drv_ref.suspend = if T::HAS_SUSPEND { + Some(Self::suspend_callback) + } else { + None + }; + drv_ref.resume = if T::HAS_RESUME { + Some(Self::resume_callback) + } else { + None + }; + drv_ref.ready = if T::HAS_READY { + Some(Self::ready_callback) + } else { + None + }; + drv_ref.set_boost = if T::HAS_SET_BOOST { + Some(Self::set_boost_callback) + } else { + None + }; + drv_ref.register_em = if T::HAS_REGISTER_EM { + Some(Self::register_em_callback) + } else { + None + }; + + // Set driver data before registering the driver, as the cpufreq core may call few + // callbacks before `cpufreq_register_driver()` returns. + Self::set_data(drv_ref, data)?; + + // SAFETY: It is safe to register the driver with the cpufreq core in the C code. + to_result(unsafe { bindings::cpufreq_register_driver(drv_ref) })?; + + Ok(Self { + drv, + _p: PhantomData, + }) + } + + /// Same as [Registration::new`], but does not return a `Registration` instance. + /// Instead the `Registration` is owned by devres and will be revoked / dropped, once the + /// device is detached. + pub fn new_foreign_owned( + dev: &Device, + name: &'static CStr, + data: T::Data, + flags: u16, + boost: bool, + ) -> Result<()> { + let reg = Self::new(name, data, flags, boost)?; + Devres::new_foreign_owned(dev, reg, GFP_KERNEL)?; + Ok(()) + } + + // Sets the data for a cpufreq driver. + fn set_data(drv: &mut bindings::cpufreq_driver, data: T::Data) -> Result<()> { + if drv.driver_data.is_null() { + // Pass the ownership of the data to the foreign interface. + drv.driver_data = ::into_foreign(data) as _; + Ok(()) + } else { + Err(EBUSY) + } + } + + /// Returns the previous set data for a cpufreq driver. + pub fn data(&mut self) -> Option<::Borrowed<'static>> { + let drv = self.drv.get_mut(); + + if drv.driver_data.is_null() { + None + } else { + // SAFETY: The data is earlier set by us from [`set_data()`]. + Some(unsafe { ::borrow(drv.driver_data) }) + } + } + + // Clears and returns the data for a cpufreq driver. + fn clear_data(&mut self) -> Option { + let drv = self.drv.get_mut(); + + if drv.driver_data.is_null() { + None + } else { + // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to + // relinquish it now. + let data = Some(unsafe { ::from_foreign(drv.driver_data) }); + drv.driver_data = ptr::null_mut(); + data + } + } +} + +// cpufreq driver callbacks. +impl Registration { + // Policy's init callback. + extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + + let data = T::init(&mut policy)?; + policy.set_data(data)?; + Ok(0) + }) + } + + // Policy's exit callback. + extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + + let data = policy.clear_data(); + let _ = T::exit(&mut policy, data); + } + + // Policy's online callback. + extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::online(&mut policy).map(|()| 0) + }) + } + + // Policy's offline callback. + extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::offline(&mut policy).map(|()| 0) + }) + } + + // Policy's suspend callback. + extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::suspend(&mut policy).map(|()| 0) + }) + } + + // Policy's resume callback. + extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::resume(&mut policy).map(|()| 0) + }) + } + + // Policy's ready callback. + extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::ready(&mut policy); + } + + // Policy's verify callback. + extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut data = unsafe { PolicyData::from_raw_policy_data(ptr) }; + T::verify(&mut data).map(|()| 0) + }) + } + + // Policy's setpolicy callback. + extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::setpolicy(&mut policy).map(|()| 0) + }) + } + + // Policy's target callback. + extern "C" fn target_callback( + ptr: *mut bindings::cpufreq_policy, + target_freq: u32, + relation: u32, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::target(&mut policy, target_freq, Relation::new(relation)?).map(|()| 0) + }) + } + + // Policy's target_index callback. + extern "C" fn target_index_callback( + ptr: *mut bindings::cpufreq_policy, + index: u32, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::target_index(&mut policy, index).map(|()| 0) + }) + } + + // Policy's fast_switch callback. + extern "C" fn fast_switch_callback( + ptr: *mut bindings::cpufreq_policy, + target_freq: u32, + ) -> core::ffi::c_uint { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::fast_switch(&mut policy, target_freq) + } + + // Policy's adjust_perf callback. + extern "C" fn adjust_perf_callback(cpu: u32, min_perf: usize, target_perf: usize, capacity: usize) { + if let Ok(mut policy) = Policy::from_cpu(cpu) { + T::adjust_perf(&mut policy, min_perf, target_perf, capacity); + } + } + + // Policy's get_intermediate callback. + extern "C" fn get_intermediate_callback( + ptr: *mut bindings::cpufreq_policy, + index: u32, + ) -> core::ffi::c_uint { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::get_intermediate(&mut policy, index) + } + + // Policy's target_intermediate callback. + extern "C" fn target_intermediate_callback( + ptr: *mut bindings::cpufreq_policy, + index: u32, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::target_intermediate(&mut policy, index).map(|()| 0) + }) + } + + // Policy's get callback. + extern "C" fn get_callback(cpu: u32) -> core::ffi::c_uint { + Policy::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) + } + + // Policy's update_limit callback. + extern "C" fn update_limits_callback(cpu: u32) { + if let Ok(mut policy) = Policy::from_cpu(cpu) { + T::update_limits(&mut policy); + } + } + + // Policy's bios_limit callback. + extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> core::ffi::c_int { + from_result(|| { + let mut policy = Policy::from_cpu(cpu as u32)?; + + // SAFETY: The pointer is guaranteed by the C code to be valid. + T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0) + }) + } + + // Policy's set_boost callback. + extern "C" fn set_boost_callback( + ptr: *mut bindings::cpufreq_policy, + state: i32, + ) -> core::ffi::c_int { + from_result(|| { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::set_boost(&mut policy, state).map(|()| 0) + }) + } + + // Policy's register_em callback. + extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { + // SAFETY: `ptr` is valid by the contract with the C code. `policy` is alive only for the + // duration of this call, so it is guaranteed to remain alive for the lifetime of + // `ptr`. + let mut policy = unsafe { Policy::from_raw_policy(ptr) }; + T::register_em(&mut policy); + } +} + +impl Drop for Registration { + // Removes the registration from the kernel if it has completed successfully before. + fn drop(&mut self) { + pr_info!("Registration dropped\n"); + let drv = self.drv.get_mut(); + + // SAFETY: The driver was earlier registered from `new()`. + unsafe { bindings::cpufreq_unregister_driver(drv) }; + + // Free the previously leaked memory to the C code. + if !drv.attr.is_null() { + // SAFETY: The pointer was earlier initialized from the result of `KBox::leak`. + unsafe { drop(KBox::from_raw(drv.attr)) }; + } + + // Free data + drop(self.clear_data()); + } +} From patchwork Mon Jan 13 11:23:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937194 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5282222A4DC for ; Mon, 13 Jan 2025 11:24:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767469; cv=none; b=H7O6rF0GeqN2CO7fLrDioRxIHt9fZXnLrkFywczV5T+eSfEf6R9EvLpM2t+pnfCgqHnWK9kFCja23YNqlB8BrKcKiCd6GPn0a9brvzIL5AMJdzainZOJNaRKs6rcvVkfMJmvXpJxT46kHDvrnpjxDCjF9uE9kTfXlTrUdohrO9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767469; c=relaxed/simple; bh=gXRpq9a3zNo2mqoc+c+AY5iNG67itiGvRui0TBLI65I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=R6nHI7T1lTksZNwmHVIaONJKt5oFiQ6kwpSHDOuzQwXDrzQNSo1WoAfO1FySWH0iS5DmCEfgsTdbZmhx0u/Zdu9bXfqmTPTyvUnx6lEf15dCIktJYJB5b2b1xj9M8JIHGq57dRW1wKp0P8up4xvxExgLwwPfMGOLYu0ycvI931U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=j2nawjd7; arc=none smtp.client-ip=209.85.214.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="j2nawjd7" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2166f1e589cso85551715ad.3 for ; Mon, 13 Jan 2025 03:24:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767467; x=1737372267; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yF4U0fmdhazacnu5TfK3YZgG7bQEU+5HFAz9S6EWr/w=; b=j2nawjd7iYwPuhavM6cRF68mMSrXua7hAHPhY0ZH0QluSLNftg9a6nWmVW4tnkmv+5 1nty+xjQWa+6n37DCzdJ9xtRrwemFAcQJtC8J7li7SiiSDRQTRTX2ReOJTgsvHWKfCTy J2/H0l82kzdjG5ekZ79oKClMibvn2qbaVXB5lA3MVpAxe5C//CdPJJSfd+zJvrhSFMlj raCXTtcKOxFm47LBd0VY6pxXajeRPdDqHzaplPyMMFN0+7eBfS69jjwnhxGGIslEQtSB FPRIHz5fw9P4XmYj+23BEY3xou5IleKKk/tiNBmowwrBzPyanANKEbVP1II6Q3KfxRP5 qg8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767467; x=1737372267; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yF4U0fmdhazacnu5TfK3YZgG7bQEU+5HFAz9S6EWr/w=; b=Sz67VcgCIfOptsN5/8ZItfZ4vtbhGt17LEsAugncmGKEUx4+tVb2FdYbqjO5B1TcCJ XGXEoaZuUkJ9JYOv1ctv7KLPAjbvBqV4aFfFJIZ7pgru/NiJp38116AyuCAP2qShSKOj eoGxlpn4mC5uPgWRt/sQR9a8hqurq/WIyiRJoqMteLMmKlKBCsZKqc2D4hGhxixcb9BU 0ghBDT9vSrAiNEevZtfaMZH64MbheQ6CtjpW+F7IbrA3IrGicrIVyiiPVuimPEfEs7GD HNGnllOprg9RiJdtCN7xdKIkq+Jp21jWMQcwAK/4FYnSGy+dVl8DxTtg27nbfIO82V3s e5ZQ== X-Forwarded-Encrypted: i=1; AJvYcCUh0wolEQlsvTiGnzZeG4qFSBQ+6pSJhBTmKAlAbnltj7x6mPsPnKfh1UP8jHhBY7YaoRqOeInJwQ==@vger.kernel.org X-Gm-Message-State: AOJu0Yzd10iiJEdRdFKbvN3hzEITRof/tJL7PeCPyVC203XpvWY4AGgA oSuNp4o3f+1UM8OFvt2pYJKmJk3it2IranCRFv2V7E1EXyzyIsdbj/bmC9AfcoI= X-Gm-Gg: ASbGncvbPti261LlpaOV4ha0Say2N4x1iE4gXHrSVLIGsXKyxNjDudOiO2iU8vcgHua lULUH/aRBLQMRA/lSXw5exBVXmzLiH6hAckUBpCvvUNyAJ/ItQjHFUwYk4LzoxWAzef/AOk9FCf G85snIaneaYivpFUG0Sp8wvxc3BvMaJXJAHTCsrTDABMOHsJlb9d1JtlYvpskmz0djyJMYX5297 TE+mcZp1CNPIl1EXcBTa/50tcZsALWzaHRaR8g8qvMHmjqWl9tHKwI7ABw= X-Google-Smtp-Source: AGHT+IEutGiSjaMCxKF1iSM7TvMVcvoFtHqUScWeDq6/12v9Cb/p3VlYB9GXoMrO10PoJYLEx+gU2A== X-Received: by 2002:a17:903:41c3:b0:216:3732:ade3 with SMTP id d9443c01a7336-21a83fc3c07mr308109125ad.35.1736767467225; Mon, 13 Jan 2025 03:24:27 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f233851sm51636465ad.191.2025.01.13.03.24.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:26 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Nishanth Menon , Stephen Boyd , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH V7 14/16] rust: Extend OPP bindings with CPU frequency table Date: Mon, 13 Jan 2025 16:53:09 +0530 Message-Id: <47cfb24fd3c7429dc68a023a6b504e37bb13c141.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit adds bindings for CPUFreq core related API. Signed-off-by: Viresh Kumar --- rust/kernel/opp.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs index 22c4d543f456..147178410c60 100644 --- a/rust/kernel/opp.rs +++ b/rust/kernel/opp.rs @@ -16,6 +16,12 @@ types::{ARef, AlwaysRefCounted, Opaque}, }; +#[cfg(CONFIG_CPU_FREQ)] +use crate::cpufreq; + +#[cfg(CONFIG_CPU_FREQ)] +use core::ops::Deref; + use core::{marker::PhantomData, ptr}; use macros::vtable; @@ -337,6 +343,56 @@ extern "C" fn config_regulators( } } +/// CPU Frequency table created from OPP entries. +#[cfg(CONFIG_CPU_FREQ)] +pub struct FreqTable { + dev: ARef, + table: cpufreq::Table, +} + +#[cfg(CONFIG_CPU_FREQ)] +impl FreqTable { + /// Creates new instance of [`FreqTable`] from raw pointer. + fn new(table: &Table) -> Result { + let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut(); + + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + to_result(unsafe { + bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr) + })?; + Ok(Self { + dev: table.dev.clone(), + // SAFETY: The `ptr` is guaranteed by the C code to be valid. + table: unsafe { cpufreq::Table::from_raw(ptr) }, + }) + } + + /// Returns reference to the underlying [`cpufreq::Table`]. + pub fn table(&self) -> &cpufreq::Table { + &self.table + } +} + +#[cfg(CONFIG_CPU_FREQ)] +impl Deref for FreqTable { + type Target = cpufreq::Table; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.table + } +} + +#[cfg(CONFIG_CPU_FREQ)] +impl Drop for FreqTable { + fn drop(&mut self) { + // SAFETY: The requirements are satisfied by the existence of `Device` and its safety + // requirements. + unsafe { bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw()) }; + } +} + /// Operating performance point (OPP) table. /// /// Wraps the kernel's `struct opp_table`. @@ -541,6 +597,12 @@ pub fn adjust_voltage( }) } + /// Create cpufreq table from OPP table. + #[cfg(CONFIG_CPU_FREQ)] + pub fn to_cpufreq_table(&mut self) -> Result { + FreqTable::new(self) + } + /// Sets a matching OPP based on frequency. pub fn set_rate(&self, freq: usize) -> Result<()> { // SAFETY: The requirements are satisfied by the existence of `Device` and its safety From patchwork Mon Jan 13 11:23:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937195 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAC2F1CAA79 for ; Mon, 13 Jan 2025 11:24:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767473; cv=none; b=KA2eOnUyFJP433e5qUu3QUUTLEsOy1Gnl4YUIj1ZNAvWmElCU0oTek+1shorV6CNbjtG55ucxIkHA25ohCEieKcG3eyNm8t+O8MQM9msrx64eeOs3iXqgUbOpnY9liVrqICzwX3nkluGgVEkR0MIEXNYk5MSfgPYGcEgUHBmbVw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767473; c=relaxed/simple; bh=4fg2ZGQhlYA8r3JLieZC4cnAZfBC3Xm4Z/gakVH89vk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NBpqMraiDuIgMYeEEOg6foCmsSgjJsD63/kjYawvMyJmP3qGt3039Wov6WmJAlBCV8GLd1UaGr5KLwTOty35E/fjXxoZ+hJ1DKY8VIU+SEMX7ppdrl9+69Ta0IQgbwViKw9lIBG/swizeNOgTurSYYTg2SnTd2RCPBJ2zD+RArk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=CE3lnLRq; arc=none smtp.client-ip=209.85.214.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="CE3lnLRq" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-216634dd574so45794795ad.2 for ; Mon, 13 Jan 2025 03:24:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767471; x=1737372271; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ze1PBk/48GQ6DBzWf8nXWZfuqwWl+q48VfNbS3eSzOI=; b=CE3lnLRqHs9Eb9X7xJp74egoqoGopK8sPcTTd7rFl2wDNZ4L3In1wNsVcFmCq0mg+c /SBbpkRbcwJe6mvdIFU5CbmcSRlCO+gXM0WqQTh3dvMR9Ac7YTfG5xkUhv+A7h/YAGpX 3imJ3IdQq02ByE0CRScv6Y2+WisaGXQ1zWnHaVVQi6dSmu2VZhll3a8MNxN0SpRtQ0jc 4UC0yab+n9sFdK9zFAAx2ZnceFsDtun+Xcbb7lwmV8oGvcyITYjqKfmcjk6Z2XaMILYN Q5otramEYCNTpELIfiI+RlnS5iWCuZ/pVVnxH2bS8VvYHE5i2juE9HLZrJG4bbx/BFnO N9WA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767471; x=1737372271; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ze1PBk/48GQ6DBzWf8nXWZfuqwWl+q48VfNbS3eSzOI=; b=JzGDVbaUWQPI3m8FP/0D6kQ8SD0GFnfrARYV9B/pjNwVja29jkVCnyi1vyMF/gas8c hbWb216vt8q0CWLhQeg7ndKO/Bn+AttN9P57c39h/iwF0t23bQp6FPOdeo1dWNW3/g0s azMGo5x3Xb9lYDfDlNxlDxWKT1heBMHgE2I0I5yusWdp1nkOpsOZHUJ10ycqiyOsRw4C jV7MAGoXQDNkNezZnllCtaYTWmsX8g4LHYqndFV6A7zLzg+1C5gZTrbwzuiwU38kiowx 1EoTyQqmPiYPW8xAWfROIhkZ5VAYQGsRjbjmZvtQn8z9K8peemswt71tbK8ffCN8B1r6 l6Dw== X-Gm-Message-State: AOJu0YyatBNYAYby9SLhG7mU3HuqtQf9CkStTikjGyoUXLStTTqiJ8Ee OcoflcuWkW79K6hcaAfol0HEKUzXCrc3P25TI4s5pclp+F+3c+/6Gt5IsDi3cow= X-Gm-Gg: ASbGncsF23tB4K1LxVtqtqjsqyQFOhNu1pSU2Btu6f1GEoteuk+HNtiMhdEewxxcc6S yU87WW1xO1ms1Hg6QPLKqd3bq1TP2FAAVrYPFngqm42nPvsQxVNEqafgmiTUTclHZkYk8kOdtMk dMuNEr3eO1ikSRa++IFdkvvFnQL6dn6raHehLjG+MHOjcZJHBhMUTXGqGGvcQ1x6WUbTpfme0UW UTXk5/1HgbTdx4qFBTPFHwNv0d4EENlKToJg0ic3GcmhNr2XIJ6VSkeug0= X-Google-Smtp-Source: AGHT+IGGqOnEWmNDriR/HLmBnXwApY2rUgwBNSNC9XvMqqfb9u5C7/4ouaI8c61RrPI+L3Fo3BBqXQ== X-Received: by 2002:a17:902:cf0b:b0:215:431f:268a with SMTP id d9443c01a7336-21a83f647e1mr336644375ad.31.1736767471041; Mon, 13 Jan 2025 03:24:31 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f155e00sm51657985ad.103.2025.01.13.03.24.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:30 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 15/16] cpufreq: Add Rust based cpufreq-dt driver Date: Mon, 13 Jan 2025 16:53:10 +0530 Message-Id: <556e67bb5c5954d7f513716fb1bae32d55918742.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This commit adds a Rust based cpufreq-dt driver, which covers most of the functionality of the existing C based driver. Only a handful of things are left, like fetching platform data from cpufreq-dt-platdev.c. This is tested with the help of QEMU for now and switching of frequencies work as expected. Signed-off-by: Viresh Kumar --- drivers/cpufreq/Kconfig | 12 ++ drivers/cpufreq/Makefile | 1 + drivers/cpufreq/rcpufreq_dt.rs | 230 +++++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 drivers/cpufreq/rcpufreq_dt.rs diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d64b07ec48e5..78702a08364f 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -217,6 +217,18 @@ config CPUFREQ_DT If in doubt, say N. +config CPUFREQ_DT_RUST + tristate "Rust based Generic DT based cpufreq driver" + depends on HAVE_CLK && OF && RUST + select CPUFREQ_DT_PLATDEV + select PM_OPP + help + This adds a Rust based generic DT based cpufreq driver for frequency + management. It supports both uniprocessor (UP) and symmetric + multiprocessor (SMP) systems. + + If in doubt, say N. + config CPUFREQ_VIRT tristate "Virtual cpufreq driver" depends on GENERIC_ARCH_TOPOLOGY diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index d35a28dd9463..db38d1d5562d 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET) += cpufreq_governor_attr_set.o obj-$(CONFIG_CPUFREQ_DT) += cpufreq-dt.o +obj-$(CONFIG_CPUFREQ_DT_RUST) += rcpufreq_dt.o obj-$(CONFIG_CPUFREQ_DT_PLATDEV) += cpufreq-dt-platdev.o obj-$(CONFIG_CPUFREQ_VIRT) += virtual-cpufreq.o diff --git a/drivers/cpufreq/rcpufreq_dt.rs b/drivers/cpufreq/rcpufreq_dt.rs new file mode 100644 index 000000000000..9f761082fa14 --- /dev/null +++ b/drivers/cpufreq/rcpufreq_dt.rs @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust based implementation of the cpufreq-dt driver. + +use core::format_args; + +use kernel::{ + c_str, clk, cpu, cpufreq, cpumask::Cpumask, device::Device, + error::code::*, fmt, macros::vtable, module_platform_driver, of, opp, platform, prelude::*, + str::CString, sync::Arc, +}; + +// Finds exact supply name from the OF node. +fn find_supply_name_exact(dev: &Device, name: &str) -> Option { + let name_cstr = CString::try_from_fmt(fmt!("{}-supply", name)).ok()?; + + if dev.property_present(&name_cstr) { + CString::try_from_fmt(fmt!("{}", name)).ok() + } else { + None + } +} + +// Finds supply name for the CPU from DT. +fn find_supply_names(dev: &Device, cpu: u32) -> Option> { + // Try "cpu0" for older DTs. + let name = match cpu { + 0 => find_supply_name_exact(dev, "cpu0"), + _ => None, + } + .or(find_supply_name_exact(dev, "cpu"))?; + + let mut list = KVec::with_capacity(1, GFP_KERNEL).ok()?; + list.push(name, GFP_KERNEL).ok()?; + + Some(list) +} + +// Represents the cpufreq dt device. +struct CPUFreqDTDevice { + opp_table: opp::Table, + freq_table: opp::FreqTable, + #[allow(dead_code)] + mask: Cpumask, + #[allow(dead_code)] + token: Option, + #[allow(dead_code)] + clk: clk::Clk, +} + +struct CPUFreqDTDriver { + _pdev: platform::Device, +} + +#[vtable] +impl opp::ConfigOps for CPUFreqDTDriver {} + +#[vtable] +impl cpufreq::Driver for CPUFreqDTDriver { + type Data = (); + type PData = Arc; + + fn init(policy: &mut cpufreq::Policy) -> Result { + let cpu = policy.cpu(); + let dev = cpu::from_cpu(cpu)?; + let mut mask = Cpumask::new()?; + + mask.set(cpu); + + let token = match find_supply_names(dev, cpu) { + Some(names) => Some( + opp::Config::::new() + .set_regulator_names(names)? + .set(dev)?, + ), + _ => None, + }; + + // Get OPP-sharing information from "operating-points-v2" bindings. + let fallback = match opp::Table::of_sharing_cpus(dev, &mut mask) { + Ok(()) => false, + Err(e) => { + if e != ENOENT { + return Err(e); + } + + // "operating-points-v2" not supported. If the platform hasn't + // set sharing CPUs, fallback to all CPUs share the `Policy` + // for backward compatibility. + opp::Table::sharing_cpus(dev, &mut mask).is_err() + } + }; + + // Initialize OPP tables for all policy cpus. + // + // For platforms not using "operating-points-v2" bindings, we do this + // before updating policy cpus. Otherwise, we will end up creating + // duplicate OPPs for the CPUs. + // + // OPPs might be populated at runtime, don't fail for error here unless + // it is -EPROBE_DEFER. + let mut opp_table = match opp::Table::from_of_cpumask(dev, &mut mask) { + Ok(table) => table, + Err(e) => { + if e == EPROBE_DEFER { + return Err(e); + } + + // The table is added dynamically ? + opp::Table::from_dev(dev)? + } + }; + + // The OPP table must be initialized, statically or dynamically, by this point. + opp_table.opp_count()?; + + // Set sharing cpus for fallback scenario. + if fallback { + mask.set_all(); + opp_table.set_sharing_cpus(&mut mask)?; + } + + let mut transition_latency = opp_table.max_transition_latency() as u32; + if transition_latency == 0 { + transition_latency = cpufreq::ETERNAL_LATENCY; + } + + let freq_table = opp_table.to_cpufreq_table()?; + let clk = policy + .set_freq_table(freq_table.table()) + .set_dvfs_possible_from_any_cpu() + .set_suspend_freq((opp_table.suspend_freq() / 1000) as u32) + .set_transition_latency(transition_latency) + .set_clk(dev, None)?; + + mask.copy(policy.cpus()); + + Ok(Arc::new( + CPUFreqDTDevice { + opp_table, + freq_table, + mask, + token, + clk, + }, + GFP_KERNEL, + )?) + } + + fn exit(_policy: &mut cpufreq::Policy, _data: Option) -> Result<()> { + Ok(()) + } + + fn online(_policy: &mut cpufreq::Policy) -> Result<()> { + // We did light-weight tear down earlier, nothing to do here. + Ok(()) + } + + fn offline(_policy: &mut cpufreq::Policy) -> Result<()> { + // Preserve policy->data and don't free resources on light-weight + // tear down. + Ok(()) + } + + fn suspend(policy: &mut cpufreq::Policy) -> Result<()> { + policy.generic_suspend() + } + + fn verify(data: &mut cpufreq::PolicyData) -> Result<()> { + data.generic_verify() + } + + fn target_index(policy: &mut cpufreq::Policy, index: u32) -> Result<()> { + let data = match policy.data::() { + Some(data) => data, + None => return Err(ENOENT), + }; + + let freq = data.freq_table.freq(index.try_into().unwrap())? as usize; + data.opp_table.set_rate(freq * 1000) + } + + fn get(policy: &mut cpufreq::Policy) -> Result { + policy.generic_get() + } + + fn set_boost(_policy: &mut cpufreq::Policy, _state: i32) -> Result<()> { + Ok(()) + } + + fn register_em(policy: &mut cpufreq::Policy) { + policy.register_em_opp() + } +} + +kernel::of_device_table!( + OF_TABLE, + MODULE_OF_TABLE, + ::IdInfo, + [ + (of::DeviceId::new(c_str!("operating-points-v2")), ()) + ] +); + +impl platform::Driver for CPUFreqDTDriver { + type IdInfo = (); + const OF_ID_TABLE: Option> = Some(&OF_TABLE); + + fn probe(pdev: &mut platform::Device, _id_info: Option<&Self::IdInfo>) -> Result>> { + cpufreq::Registration::::new_foreign_owned( + pdev.as_ref(), + c_str!("cpufreq-dt"), + (), + cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV, + true, + )?; + + let drvdata = KBox::new(Self { _pdev: pdev.clone() }, GFP_KERNEL)?; + + Ok(drvdata.into()) + } +} + +module_platform_driver! { + type: CPUFreqDTDriver, + name: "cpufreq_dt", + author: "Viresh Kumar ", + description: "Generic CPUFreq DT driver", + license: "GPL v2", +} From patchwork Mon Jan 13 11:23:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 13937196 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D094F22CF16 for ; Mon, 13 Jan 2025 11:24:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767476; cv=none; b=cRjH+mcneT9Qt84W0B2Eufv8t9gyK/E8ZD+Ba/0LBbaoU5PBrw9nAKQL/p2u017IIAGJq173Tg/wUM/iB3ZvGD6XKmnt6ySGGSFT5YNHcdwZONYDxkOcfF52lpB63+hufw9AxPPgBpzw+w+ZIt6oNhcuav6BDfxGS1VhoSXPvzY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736767476; c=relaxed/simple; bh=zAgcTK1vxHH9JbWsGAZBhQO4BNGHJbmi22K+j/HI9GM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kJPNBl43T9n0BkeSRRqZwFN9TyZcECzGson5fhoGWx4jOkBVqXmWqawJJN4l5sgaC2aeZOnkU773vmPYvZJFzhd5mq5AFFC9OyIkXy5q1ZOKkKDR5cvpk3fwFmchb5pPYU3xGtKqzx4s9GQmWJdqxGSSY3Jlo1RTnsrU27r6+6U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=Dydf1gl3; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Dydf1gl3" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-216426b0865so70469905ad.0 for ; Mon, 13 Jan 2025 03:24:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1736767474; x=1737372274; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=X/YD84rEPrBCk3G930SjRh7BJIiSlM7R2s5ncfP28y8=; b=Dydf1gl30EAg5pPV0nDgp+E71jVeAWKNseEBW6GRrLAhPiYcn3hjPfZSaSKsbzXb3i aFEm7cKioJI/XMZ3ZaHioDk28PHbSkRjfXteDIcNOnCUVdj9LG0sAuaRkI1HyJdBjtGD 3jDDbC46Vfotceo38G3OCMbgV8Cf3iWEjxwfUB18KxKF7TlotmP3/SMf5NHR8ymjkZM6 A5mivlqepVFUney8IZ99tptEjV9Yv35DK02vrRmMvezDRN76Lfis+q8Dii7MGt4omnze i21DGgmGJ/HqTWeFPUf0f1l8fVaMrZnv/LvK0htqJBbNRbmepOxrMUjedKtQ/Nmw0U2R PEsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736767474; x=1737372274; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=X/YD84rEPrBCk3G930SjRh7BJIiSlM7R2s5ncfP28y8=; b=Y9/4xU3zk1jSiY/lZATUr8y4OKuGkiXuTafXvbRflSZcF6Ttn8gxtoDfcOlxddAxk9 jnA1HCmkudCAONWs5eU1nnBUCX7efsUdYpaJyE6lmDcz51/QbGhqGjPhgoXar9/5EIRd zhK4cRAnGXO/bn58vxJ+bwVbPla4UaQfPe6lXJQO4Bs1ZqdGgF1qSZTIGhVSKCy2+wPs pEmH4hsLwbaaMBGMqnObtyBSkS4P6ge6M/qBJruxwHH7ykJ8MwAUFS2VmFetiBBPzwjE nRBD2P0z0uoQUxrut9fwtQYdb0DoRK1Y5A9sM2gILsYYjFV5bhS6QhD2EhbnNBd1yrw/ CVMA== X-Gm-Message-State: AOJu0YwMGTgISiv57bFZc13jgOKsGHAvU3sCSToiP7YB8iZ+1qNo3j4D qyutNvnLED+1LXy2+WV9g8eYTm1Djn21pMXzrVBftFb85Frlr6mjXmxv8gQb7xkAimEGXGWnl7D z X-Gm-Gg: ASbGnctDr20NeVjQGSwIsTHnf6+MRepQbIHjMqpLirUE/Po4uTI0sfe6IcmOR9XGhVY TSDXjScJRU+c07y2HvI4OzN1y2kg3gS7EmGVi3zfIhG23ItxhQVxLDCJw8RcDFSGLh8+ik2W9mp iokFwuCHQ/xGnT4EQZJsEe1dzlxoYYn65sylBKZywGx2+YmFTJVDn+uFywIU2ogzDqwbwgAfDoU J+aHzx9tn7/CyRHyamL0JDy1HdEpUDCFUKJLFfJ/C9Fgn9Dj3fHb7BFEao= X-Google-Smtp-Source: AGHT+IELMOT0PbMKi+46Q87eT/Vfc0JWjP7to1bvIXbajUzFmNLB3hpaOQyToHivf7D0wpdCnj8xQg== X-Received: by 2002:a17:902:f693:b0:215:a179:14d2 with SMTP id d9443c01a7336-21a84009d06mr276039425ad.50.1736767474223; Mon, 13 Jan 2025 03:24:34 -0800 (PST) Received: from localhost ([122.172.84.139]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-21a9f155e00sm51658825ad.103.2025.01.13.03.24.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2025 03:24:33 -0800 (PST) From: Viresh Kumar To: "Rafael J. Wysocki" , Viresh Kumar , Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross Cc: linux-pm@vger.kernel.org, Vincent Guittot , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org Subject: [PATCH V7 16/16] DO-NOT_MERGE: cpufreq: Rename cpufreq-dt platdev Date: Mon, 13 Jan 2025 16:53:11 +0530 Message-Id: <5c93f6aaff0bcbc907d14d3a74ee5073fa135a07.1736766672.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.31.1.272.g89b43f80a514 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-pm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The module! implementation in the Rust code expects a module name without a '-' symbol, else it fails to compile with following errors: error: expected one of `:`, `;`, or `=`, found `-` --> drivers/cpufreq/rcpufreq_dt.rs:247:1 | 247 | / module_platform_driver! { 248 | | type: CPUFreqDTDriver, 249 | | name: "cpufreq-dt", 250 | | author: "Viresh Kumar ", 251 | | description: "Generic CPUFreq DT driver", 252 | | license: "GPL v2", 253 | | } | |_^ expected one of `:`, `;`, or `=` | = note: this error originates in the macro `$crate::prelude::module` which comes from the expansion of the macro `module_platform_driver` (in Nightly builds, run with -Z macro-backtrace for more info) This must be fixed properly in the Rust code instead. Not to be merged. Not-Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq-dt-platdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 9c198bd4f7e9..263e1e97538d 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -230,7 +230,7 @@ static int __init cpufreq_dt_platdev_init(void) return -ENODEV; create_pdev: - return PTR_ERR_OR_ZERO(platform_device_register_data(NULL, "cpufreq-dt", + return PTR_ERR_OR_ZERO(platform_device_register_data(NULL, "cpufreq_dt", -1, data, sizeof(struct cpufreq_dt_platform_data))); }