From nobody Mon Jun 8 09:48:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EED062D0603; Sat, 30 May 2026 01:13:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; cv=none; b=B1WCFILS60WurQ1nGUZYbm727Q7FRkyoC7QSWshlCZHJ4/vyYIEFKmf3XgwhZ4JTKgoHP8RqWw06jZ8DgqvHlQSemza6fWW/plIyjaE8m2OfAaiz8pTP9MGuS/vvzmL/ZJQrw9db99XxS53QcV+qEhV3QyACaW/TS8qNHjHh8rU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; c=relaxed/simple; bh=RgWLROqVUmbJHm4UXu0rSXVgRGuzObKlOShCAHydctM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NZUwYuy+Gtq+1Vlz+M3P49qyIL75dynY6djwmf7hsHNLHuZRULNVhRo3C4fYH90dbi1AAvnK9DV3M2VNh5AmKI6LtCnXspiLW92LIVi40V9iY+V40N20OO0dUQUuSDxMDGmUVKW1SofR/SUabD2gEM9sWqpjQJ5TfV9ZoUieqco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QFAMHzMz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QFAMHzMz" Received: by smtp.kernel.org (Postfix) with ESMTPS id 960A1C2BCB3; Sat, 30 May 2026 01:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780103633; bh=RgWLROqVUmbJHm4UXu0rSXVgRGuzObKlOShCAHydctM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=QFAMHzMzZvMWzzzRlqnQlJLBMimsxWzPzBYet+pBWbM9NJmpU/TLX1uuk7mx3qLtb C8MP3Qv2PoZNSZ4/0gog8109IgZnfRwdjdXGI5XiEaop4BHTMrTIekhw4m5pg/7WBu zWAHfpLdMUT5CAMdBjjMaFWq+CaFY48Y3WetXZILxoJCKiSyT7NQZkXxSrc5fSywvM Cft79HmgLoAdP3C6BzxA0EQ60CwtjNQxe4PqmtGio3eyn9mTlPsVq1yCBNB1QHzcwB GD54RiFgQLm4MCgs9IHWMc3m7Cq+uHLQ1SqyvzxvJpvmujEMAgWpUaU4cN/To3BBcD Wnx7g77x+i8XA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7EAFECD6E43; Sat, 30 May 2026 01:13:53 +0000 (UTC) From: Markus Probst via B4 Relay Date: Sat, 30 May 2026 03:13:49 +0200 Subject: [PATCH v8 1/5] rust: devres: return reference in `devres::register` Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260530-rust_serdev-v8-1-2a95f1da22a7@posteo.de> References: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> In-Reply-To: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> To: Rob Herring , Greg Kroah-Hartman , Jiri Slaby , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Kari Argillander , "Rafael J. Wysocki" , Viresh Kumar , Boqun Feng , David Airlie , Simona Vetter , Boqun Feng Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-pm@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, Markus Probst X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2621; i=markus.probst@posteo.de; h=from:subject:message-id; bh=040JEx0DJs+3yI1YzAd4eTxo71xnuIqutPJWJv523rI=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqGjnPYjXoxu4XSUVvUyFrUA22UYYXUt1sBEHJy boxVAJjcqWJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaho5zxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9I2Yw//XSEvApDXiC0aI/+tyQQXaC2WtluKDYJ q4pL6a7XX4I7V/C+yXIbvDd5fiPpzcHx8uBpkpbV5/7NA/vwAFU2El46OuNEOW9vM20K+XgKkOg XTBRmGFuI4wZKjridroUTHVMOaKGh2EPcLtnN8TPPBZ+PemcFluAH5r0fj6PyZHVRYiJcbfW+U0 YTFyvzsL2oySHl43EElJUh7NdxPGhfBW+hPhDy8Gi8Car43qYTmbKTOf9t0mJhrAYuuVjNOenfP 8gsSgDfcV8VQbaU7qbElj5mgCZ7eGGpkLIlwvK5k7q/kptLtlJNq5zVWNxPTLoHM3uZcKkNOVwi XssxOIHr62UU1Y4Pf0obE36CJYCFbMEkogte6SY2YOmIJjn7OKv9+qCGY233bgxbn5Jsrwnd0mr RuNzx53K60TXoMApp8NhOiCxc7JjeA7XI0bWU3Y21u5Ys2X8KCKtiVoN73WYwnyuyGsqhKr/q6O 3DzN1n4ykSc53TzCYh/euLX7+1up/XS4UNaJ+JkNlMM1TgJ3RNYNXNbnpsmuhGLN3d1hcUzjl2a 3OCeliEpqf6n6fCViEYxTvSE6qKmYY5nM5rU8XDxwnCs3CyGKuLQ0Ps2ne09H3wmXHhatXdkWMu pVD/Mg2jgx86QoJrcwLhv8KI1iEHPuv5YNPRySqtmZEdCNR8C2Bc= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Return the reference to the initialized data in the `devres::register` function. This is needed in a following commit (rust: add basic serial device bus abstractions). Acked-by: Viresh Kumar Signed-off-by: Markus Probst Acked-by: Danilo Krummrich --- rust/kernel/cpufreq.rs | 3 ++- rust/kernel/devres.rs | 15 +++++++++++++-- rust/kernel/drm/driver.rs | 3 ++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/rust/kernel/cpufreq.rs b/rust/kernel/cpufreq.rs index d94c6cdbc45a..bbbd4f54218a 100644 --- a/rust/kernel/cpufreq.rs +++ b/rust/kernel/cpufreq.rs @@ -1053,7 +1053,8 @@ pub fn new_foreign_owned(dev: &Device) -> Resu= lt where T: 'static, { - devres::register(dev, Self::new()?, GFP_KERNEL) + devres::register(dev, Self::new()?, GFP_KERNEL)?; + Ok(()) } } =20 diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index 82cbd8b969fb..e3e954478caa 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -419,15 +419,26 @@ fn register_foreign

(dev: &Device, data: P) = -> Result /// } /// /// fn from_bound_context(dev: &Device) -> Result { -/// devres::register(dev, Registration::new(), GFP_KERNEL) +/// devres::register(dev, Registration::new(), GFP_KERNEL)?; +/// Ok(()) /// } /// ``` -pub fn register(dev: &Device, data: impl PinInit, flags= : Flags) -> Result +pub fn register<'a, T, E>( + dev: &'a Device, + data: impl PinInit, + flags: Flags, +) -> Result<&'a T> where T: Send + 'static, Error: From, { let data =3D KBox::pin_init(data, flags)?; =20 + let data_ptr =3D &raw const *data; + register_foreign(dev, data) + // SAFETY: `dev` is valid for the lifetime of 'a. As long as there= is a reference to + // `Device`, it is guaranteed that the device is not unboun= d and data has not been + // dropped. Thus `data_ptr` is also valid for the lifetime of 'a. + .map(|()| unsafe { &*data_ptr }) } diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs index 5233bdebc9fc..1edfd7bacddb 100644 --- a/rust/kernel/drm/driver.rs +++ b/rust/kernel/drm/driver.rs @@ -147,7 +147,8 @@ pub fn new_foreign_owned( =20 let reg =3D Registration::::new(drm, flags)?; =20 - devres::register(dev, reg, GFP_KERNEL) + devres::register(dev, reg, GFP_KERNEL)?; + Ok(()) } =20 /// Returns a reference to the `Device` instance for this registration. --=20 2.53.0 From nobody Mon Jun 8 09:48:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0B572E040E; Sat, 30 May 2026 01:13:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; cv=none; b=CbVaa+VnLNdzrEHGr2c53m4q5W8ViTtnmXWYPZ2c2gyVCT/NcOIjnBnfGiFQ86Ksshx5cAw/RJ6GH17kf+JoXULvV76tbOm7jGxcMM98Jr8dBoSg0LG3bPF06axvwNMNwI0T4rJbl+G0CP2ktimKkw90maJkzNNn8WXqU7aYyD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; c=relaxed/simple; bh=0ud1QnU6DSZTrgik1DuQ8GzbwSpCgKyutvxo4R3s3/Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Qm3yP40vhb9n0xE2MwFFlnoXHoAhQ4ovr8g0O7iQ26jN2h9i1gJICL6WtVdOL734lrvrD3DLyxC+bSkedn6scgDYIzhiA6R1Jh38mHbtw3fYSWabQh3UQ64/5WWKwp7Q7TK1z5ZRIibQ15r46eS71aGQiAB5hkIbHrAb0ThVyf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bev7/HEH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bev7/HEH" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9C2CAC4AF09; Sat, 30 May 2026 01:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780103633; bh=0ud1QnU6DSZTrgik1DuQ8GzbwSpCgKyutvxo4R3s3/Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=bev7/HEHgvD5ODGAAPDH4NLT8ZoG85HIiOyTU8eVjhjl8dF+GTP9SNItnayyWxCBd KPsieC5Rvq1vZ961HMAeAuXC1DRtCvIkydjPRQd+IiGAEb79gIrc5Yu9ZBYWPzNUvb ZEqhGIFIH47ngOQEquOabjIa4iYth9UXfUTwmOwgExM7ox5auNNAlmPAoRkBylqi45 Xb3gilT5GuIpo2HFfTkZAnur/oAb/ujtvr/PdU1WTy14wDv8CS49Sk33Kky/Ta8J6z 0ijBDGynlaDiaPBSIpT86cyrctic2b5Y25IA47l432g/0QY3UV1UMX/ZkXoAhFRUIl PEoN3/wwg/y6g== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8CEB9CD6E53; Sat, 30 May 2026 01:13:53 +0000 (UTC) From: Markus Probst via B4 Relay Date: Sat, 30 May 2026 03:13:50 +0200 Subject: [PATCH v8 2/5] serdev: add rust private data to serdev_device Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260530-rust_serdev-v8-2-2a95f1da22a7@posteo.de> References: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> In-Reply-To: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> To: Rob Herring , Greg Kroah-Hartman , Jiri Slaby , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Kari Argillander , "Rafael J. Wysocki" , Viresh Kumar , Boqun Feng , David Airlie , Simona Vetter , Boqun Feng Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-pm@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, Markus Probst X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=1683; i=markus.probst@posteo.de; h=from:subject:message-id; bh=Lci9sJZ/Hd89WrWg8pDQ/wKU3djKPRT47wh61HUUHxo=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqGjnPHOTEhfqnhbwmmGCBFLn1wOiKsWKQOa3Sj kHB2JgOI4WJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaho5zxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9LvBw/8DEH1sCnx1FyuswKn4avKv4ZzqA70FFn n9D2QN0m7Fm+3amdoXrUwEGTD+TARN3zMV+52cl1/OXK5qOHuxhPaZKvR7TmriwGkhNyYzkAcZ5 Rbds3vnyFKF0mT78MgmeL8HKkSYawt/s+u+HOu4IiaVmO38uv1nrzZuSH3TkHdALy8cdiXMczdj TmWYE4s2pG30yijY+GF08s68ncu3+uWIsaBJyV2MgHKuYKhEtvtSWpgILfgUe35GtCKQw/zrc7a qHdzbgpn2/vgahiufKVawAP6GavvtVT/kN5LxFjEAJ7Yxui5vlmuMM7JxqZUcyvToQpHHER4u8h 7g++96xJrtGBggPkwjAXTyuVxscke2sLpjOBwWYxvqMOUrdxMBT/DARM6rakngR3xrvbNP4UV3U CHQp2q3RrOaJs1ObUBGT6G/TJPO9TNy98sCgCjP/qQcXnH/73vg8OzfMEALQYI+HClQys0IztLO mZVmF2YQfMCX0GtklLIikareIim2XCs4v/RePtI/MOBQgAc3+DIN9nCFnuv9DneBCQTmPStZyC0 qo7mxgLjvmLhMwYtMsBsgzxzlaK7s8kavOkWnD+/EdB3qo/YPjT5TIQX5U97SH1CZSl7vcq23ra Yl4bf2qGOUs4zILBtrQzKgq6pv2x807b8NVTqCraNNSiKc3ToMJs= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Add rust private data to `struct serdev_device`, as it is required by the rust abstraction added in the following commit (rust: add basic serial device bus abstractions). Signed-off-by: Markus Probst --- include/linux/serdev.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/linux/serdev.h b/include/linux/serdev.h index b6c3d957ec15..048ef5857786 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -33,12 +33,14 @@ struct serdev_device_ops { =20 /** * struct serdev_device - Basic representation of an serdev device - * @dev: Driver model representation of the device. - * @nr: Device number on serdev bus. - * @ctrl: serdev controller managing this device. - * @ops: Device operations. - * @write_comp: Completion used by serdev_device_write() internally - * @write_lock: Lock to serialize access when writing data + * @dev: Driver model representation of the device. + * @nr: Device number on serdev bus. + * @ctrl: serdev controller managing this device. + * @ops: Device operations. + * @write_comp: Completion used by serdev_device_write() internally + * @write_lock: Lock to serialize access when writing data + * @rust_private_data: Private data for the rust abstraction. This should + * not be used by the C drivers. */ struct serdev_device { struct device dev; @@ -47,6 +49,7 @@ struct serdev_device { const struct serdev_device_ops *ops; struct completion write_comp; struct mutex write_lock; + void *rust_private_data; }; =20 #define to_serdev_device(d) container_of_const(d, struct serdev_device, de= v) --=20 2.53.0 From nobody Mon Jun 8 09:48:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 029D62E11C7; Sat, 30 May 2026 01:13:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; cv=none; b=oyHI9lBiiUFKRt/A4A3PAfDx3R7fLERUqwklLf5s+L2kz7lkT72gdIj35FE5CqPGSfdmmtMzgpQ3gq6TDbLroE4cQF9bRyj1nubCiyPNzBd9yrxeMhJNi2Omh/rw4S9/W+ETbBsvUYHKX/DGHn0ePhkoUug2NntTZETBeeYqbgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; c=relaxed/simple; bh=y9horUcInQtaWKmG+82L1PF3CO5D3BdZUY7vMMjPoLI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pN/pAb5rg0bXbE/GFWaqqs8MGksmDSnybTvZQ/i/gs8Lcxbefc7/BKy8cR40WPDJ9GRu6SYEwto2uIk9tmBzLRvflrIrEjnQf/8MdSkkKrwNGad9pb8S5RIKGmgrR2abyUQrBt8Ia4fuQwGP1x76nfChT95XVPAyd+gal2GVves= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SpbzlSDf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SpbzlSDf" Received: by smtp.kernel.org (Postfix) with ESMTPS id A8FEAC2BCFA; Sat, 30 May 2026 01:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780103633; bh=y9horUcInQtaWKmG+82L1PF3CO5D3BdZUY7vMMjPoLI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=SpbzlSDfk9VHRl54Q6qdbKct3xsJyW4GQj+5//PtE7bCoNJ6nvS4RfJU8EOzV+pkp 7LZnVq4yT1aOU0izoEsiem5a3cG3oinKanqXr1wgam7wg1AVaArBDz6/WrqnEAuKlN W+rTBs6LhZgU/7DDkjEk/MI5wyuTdUcpgPUlwfDRfqptrz9axE8EwHLzc6dRPLCIbM IiWSzdaDJl5bssx3WxUO7UabNEZj21AujAcVhZHpTUFDm+0zkm5N2BDebKN4gCOKIA KqiHfYeVKbDypVt6WSnLxpBSSCfSpjgI+MYJUCEH7xizuNtDcahA6P1XWuPci+tKki 1EG99eOWp9Y1w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D5AFCD6E52; Sat, 30 May 2026 01:13:53 +0000 (UTC) From: Markus Probst via B4 Relay Date: Sat, 30 May 2026 03:13:51 +0200 Subject: [PATCH v8 3/5] rust: add basic serial device bus abstractions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260530-rust_serdev-v8-3-2a95f1da22a7@posteo.de> References: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> In-Reply-To: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> To: Rob Herring , Greg Kroah-Hartman , Jiri Slaby , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Kari Argillander , "Rafael J. Wysocki" , Viresh Kumar , Boqun Feng , David Airlie , Simona Vetter , Boqun Feng Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-pm@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, Markus Probst X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=24563; i=markus.probst@posteo.de; h=from:subject:message-id; bh=4nhzKj6GzJdtGMCEjrIRwCiclgE0DeMOdzMd+5duWTQ=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqGjnPlLLrNi719ndb+gerpd0dyDc5TFR9u3Wek uXZ0IcnGRiJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaho5zxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9JA6g//YwZJdfZmcpQTmIL1PuReAG50gXWouzp 3n86mIACBM1JLTL/GwckhItfpMFNKTU6UelZU8ZWZMnR15xpeIjxgmP4rWQ853jrDDYq9uJ6cun 6IOSavuep62i1oZJjdusRmItRMMK5ZbAcYuOhJpPKsYaKVXshI5erc6WzU3WDqsooo5vv1NxGNp 9J/2iYtCs2WZvR1ZVIBnUqCbTpEHszXdD1p1Vqme0LTLFoUmME+mhBEQS7rqe5TPwt27eDJvfuO Fbl5oXgaP1c8EVRuEJqXm/K1/zpgvtWCaXNoMkUzabl9Qio8iUwdNAGmFiFl+0RYa1ZZAU7o1Q8 arWXYZPOtZeL/9kTxSYWRay98vc0Jk987fWiChTqGhoqQ6xsVO0sr0O969JndHDyc/oIqsbMl8b /3BEwmjoZo63vsUImTd3LBSRW3o3Kg2Jz8ozu1EmrkI7MIh08mkur2yRj6/NIRK1DcCqT2MURGo kjropevjRfTzatYCByVh3UF83g283b64qshaUl0M0USG3I8kt3xgbR4HkjLiDfkla9qRL5GXEbR vBMNsHcclWGk4QGA9ytPCs0UNsZXkKvYO2hCBVl5dMAUkSP7AiBUsb4XMyNIyG/v/crSLeqZujM IDeKwoH/WZYsbk0oEboH7GHudZsGAQwrvsFD3uD5U2amK5mO50nE= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Implement the basic serial device bus abstractions required to write a serial device bus device driver with or without the need for initial device data. This includes the following data structures: The `serdev::Driver` trait represents the interface to the driver. The `serdev::Device` abstraction represents a `struct serdev_device`. In order to provide the Serdev specific parts to a generic `driver::Registration` the `driver::RegistrationOps` trait is implemented by `serdev::Adapter`. Signed-off-by: Markus Probst Reviewed-by: Danilo Krummrich --- MAINTAINERS | 2 + drivers/tty/serdev/Kconfig | 7 + rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/serdev.c | 22 ++ rust/kernel/lib.rs | 2 + rust/kernel/serdev.rs | 548 ++++++++++++++++++++++++++++++++++++= ++++ 7 files changed, 583 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 4e118f704699..d2f608ff8ca0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -24276,6 +24276,8 @@ S: Maintained F: Documentation/devicetree/bindings/serial/serial.yaml F: drivers/tty/serdev/ F: include/linux/serdev.h +F: rust/helpers/serdev.c +F: rust/kernel/serdev.rs =20 SERIAL IR RECEIVER M: Sean Young diff --git a/drivers/tty/serdev/Kconfig b/drivers/tty/serdev/Kconfig index 46ae732bfc68..e6dfe949ad01 100644 --- a/drivers/tty/serdev/Kconfig +++ b/drivers/tty/serdev/Kconfig @@ -9,6 +9,13 @@ menuconfig SERIAL_DEV_BUS =20 Note that you typically also want to enable TTY port controller support. =20 +config RUST_SERIAL_DEV_BUS_ABSTRACTIONS + bool "Rust Serial device bus abstractions" + depends on RUST + select SERIAL_DEV_BUS + help + This enables the Rust abstraction for the serial device bus API. + if SERIAL_DEV_BUS =20 config SERIAL_DEV_CTRL_TTYPORT diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 446dbeaf0866..4e42635b8607 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -84,6 +84,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 38b34518eff1..2fb8506a748a 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -86,6 +86,7 @@ #include "regulator.c" #include "scatterlist.c" #include "security.c" +#include "serdev.c" #include "signal.c" #include "slab.c" #include "spinlock.c" diff --git a/rust/helpers/serdev.c b/rust/helpers/serdev.c new file mode 100644 index 000000000000..c52b78ca3fc7 --- /dev/null +++ b/rust/helpers/serdev.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +__rust_helper +void rust_helper_serdev_device_driver_unregister(struct serdev_device_driv= er *sdrv) +{ + serdev_device_driver_unregister(sdrv); +} + +__rust_helper +void rust_helper_serdev_device_put(struct serdev_device *serdev) +{ + serdev_device_put(serdev); +} + +__rust_helper +void rust_helper_serdev_device_set_client_ops(struct serdev_device *serdev, + const struct serdev_device_ops *ops) +{ + serdev_device_set_client_ops(serdev, ops); +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index b72b2fbe046d..83bc2c312241 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -118,6 +118,8 @@ pub mod scatterlist; pub mod security; pub mod seq_file; +#[cfg(CONFIG_RUST_SERIAL_DEV_BUS_ABSTRACTIONS)] +pub mod serdev; pub mod sizes; #[cfg(CONFIG_SOC_BUS)] pub mod soc; diff --git a/rust/kernel/serdev.rs b/rust/kernel/serdev.rs new file mode 100644 index 000000000000..e78dac480533 --- /dev/null +++ b/rust/kernel/serdev.rs @@ -0,0 +1,548 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Abstractions for the serial device bus. +//! +//! C header: [`include/linux/serdev.h`](srctree/include/linux/serdev.h) + +use crate::{ + acpi, + device, + devres, + driver, + error::{ + from_result, + to_result, + VTABLE_DEFAULT_ERROR, // + }, + of, + prelude::*, + sync::{ + aref::AlwaysRefCounted, + Completion, // + }, + time::{ + msecs_to_jiffies, + Jiffies, + Msecs, // + }, + types::Opaque, // +}; + +use core::{ + cell::UnsafeCell, + marker::PhantomData, + mem::offset_of, + num::NonZero, + ptr::NonNull, // +}; + +/// Parity bit to use with a serial device. +#[repr(u32)] +pub enum Parity { + /// No parity bit. + None =3D bindings::serdev_parity_SERDEV_PARITY_NONE, + /// Even partiy. + Even =3D bindings::serdev_parity_SERDEV_PARITY_EVEN, + /// Odd parity. + Odd =3D bindings::serdev_parity_SERDEV_PARITY_ODD, +} + +/// Timeout in Jiffies. +pub enum Timeout { + /// Wait for a specific amount of [`Jiffies`]. + Jiffies(NonZero), + /// Wait for a specific amount of [`Msecs`]. + Milliseconds(NonZero), + /// Wait as long as possible. + /// + /// This is equivalent to [`kernel::task::MAX_SCHEDULE_TIMEOUT`]. + Max, +} + +impl Timeout { + fn into_jiffies(self) -> isize { + match self { + Self::Jiffies(value) =3D> value.get().try_into().unwrap_or_def= ault(), + Self::Milliseconds(value) =3D> { + msecs_to_jiffies(value.get()).try_into().unwrap_or_default= () + } + Self::Max =3D> 0, + } + } +} + +/// An adapter for the registration of serial device bus device drivers. +pub struct Adapter(T); + +// SAFETY: +// - `bindings::serdev_device_driver` is a C type declared as `repr(C)`. +// - `T::Data` is the type of the driver's device private data. +// - `struct serdev_device_driver` embeds a `struct device_driver`. +// - `DEVICE_DRIVER_OFFSET` is the correct byte offset to the embedded `st= ruct device_driver`. +unsafe impl driver::DriverLayout for Adapter { + type DriverType =3D bindings::serdev_device_driver; + type DriverData<'bound> =3D T::Data<'bound>; + const DEVICE_DRIVER_OFFSET: usize =3D core::mem::offset_of!(Self::Driv= erType, driver); +} + +// SAFETY: A call to `unregister` for a given instance of `DriverType` is = guaranteed to be valid if +// a preceding call to `register` has been successful. +unsafe impl driver::RegistrationOps for Adapter { + unsafe fn register( + sdrv: &Opaque, + name: &'static CStr, + module: &'static ThisModule, + ) -> Result { + let of_table =3D match T::OF_ID_TABLE { + Some(table) =3D> table.as_ptr(), + None =3D> core::ptr::null(), + }; + + let acpi_table =3D match T::ACPI_ID_TABLE { + Some(table) =3D> table.as_ptr(), + None =3D> core::ptr::null(), + }; + + // SAFETY: It's safe to set the fields of `struct serdev_device_dr= iver` on initialization. + unsafe { + (*sdrv.get()).driver.name =3D name.as_char_ptr(); + (*sdrv.get()).probe =3D Some(Self::probe_callback); + (*sdrv.get()).remove =3D Some(Self::remove_callback); + (*sdrv.get()).driver.of_match_table =3D of_table; + (*sdrv.get()).driver.acpi_match_table =3D acpi_table; + } + + // SAFETY: `sdrv` is guaranteed to be a valid `DriverType`. + to_result(unsafe { bindings::__serdev_device_driver_register(sdrv.= get(), module.0) }) + } + + unsafe fn unregister(sdrv: &Opaque) { + // SAFETY: `sdrv` is guaranteed to be a valid `DriverType`. + unsafe { bindings::serdev_device_driver_unregister(sdrv.get()) }; + } +} + +#[pin_data] +struct PrivateData { + #[pin] + probe_complete: Completion, + error: UnsafeCell, +} + +impl Adapter { + const OPS: &'static bindings::serdev_device_ops =3D &bindings::serdev_= device_ops { + receive_buf: if T::HAS_RECEIVE { + Some(Self::receive_buf_callback) + } else { + None + }, + write_wakeup: Some(bindings::serdev_device_write_wakeup), + }; + + extern "C" fn probe_callback(sdev: *mut bindings::serdev_device) -> ke= rnel::ffi::c_int { + // SAFETY: The serial device bus only ever calls the probe callbac= k with a valid pointer to + // a `struct serdev_device`. + // + // INVARIANT: `sdev` is valid for the duration of `probe_callback(= )`. + let sdev =3D unsafe { &*sdev.cast::>>() }; + let info =3D ::id_info(sdev.as_ref()); + + from_result(|| { + let private_data =3D devres::register( + sdev.as_ref(), + try_pin_init!(PrivateData { + probe_complete <- Completion::new(), + error: false.into(), + }), + GFP_KERNEL, + )?; + + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer= to `serdev_device`. + unsafe { + (*sdev.as_raw()).rust_private_data =3D + (&raw const *private_data).cast::().cast_mut() + }; + + // SAFETY: `sdev.as_raw()` is guaranteed to be a valid pointer= to `serdev_device`. + unsafe { bindings::serdev_device_set_client_ops(sdev.as_raw(),= Self::OPS) }; + + // SAFETY: The serial device bus only ever calls the probe cal= lback with a valid pointer + // to a `serdev_device`. + to_result(unsafe { + bindings::devm_serdev_device_open(sdev.as_ref().as_raw(), = sdev.as_raw()) + })?; + + let data =3D T::probe(sdev, info); + let result =3D sdev.as_ref().set_drvdata(data); + + // SAFETY: We have exclusive access to `private_data.error`. + unsafe { *private_data.error.get() =3D result.is_err() }; + + private_data.probe_complete.complete_all(); + + result.map(|()| 0) + }) + } + + extern "C" fn remove_callback(sdev: *mut bindings::serdev_device) { + // SAFETY: The serial device bus only ever calls the remove callba= ck with a valid pointer + // to a `struct serdev_device`. + // + // INVARIANT: `sdev` is valid for the duration of `remove_callback= ()`. + let sdev =3D unsafe { &*sdev.cast::>>() }; + + // SAFETY: `remove_callback` is only ever called after a successfu= l call to + // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called + // and stored a `Pin>>`. + let data =3D unsafe { sdev.as_ref().drvdata_borrow::>(= ) }; + + T::unbind(sdev, data); + } + + extern "C" fn receive_buf_callback( + sdev: *mut bindings::serdev_device, + buf: *const u8, + length: usize, + ) -> usize { + // SAFETY: The serial device bus only ever calls the receive buf c= allback with a valid + // pointer to a `struct serdev_device`. + // + // INVARIANT: `sdev` is valid for the duration of `receive_buf_cal= lback()`. + let sdev =3D unsafe { &*sdev.cast::>>() }; + + // SAFETY: + // - The serial device bus only ever calls the receive buf callbac= k with a valid pointer to + // a `struct serdev_device`. + // - `receive_buf_callback` is only ever called after a successful= call to + // `probe_callback`, hence it's guaranteed that `sdev.private_da= ta` is a pointer + // to a valid `PrivateData`. + let private_data =3D unsafe { &*(*sdev.as_raw()).rust_private_data= .cast::() }; + + private_data.probe_complete.wait_for_completion(); + + // SAFETY: No one has exclusive access to `private_data.error`. + if unsafe { *private_data.error.get() } { + return length; + } + + // SAFETY: `receive_buf_callback` is only ever called after a succ= essful call to + // `probe_callback`, hence it's guaranteed that `Device::set_drvda= ta()` has been called + // and stored a `Pin>>`. + let data =3D unsafe { sdev.as_ref().drvdata_borrow::>(= ) }; + + // SAFETY: `buf` is guaranteed to be non-null and has the size of = `length`. + let buf =3D unsafe { core::slice::from_raw_parts(buf, length) }; + + T::receive(sdev, data, buf) + } +} + +impl driver::Adapter for Adapter { + type IdInfo =3D T::IdInfo; + + fn of_id_table() -> Option> { + T::OF_ID_TABLE + } + + fn acpi_id_table() -> Option> { + T::ACPI_ID_TABLE + } +} + +/// Declares a kernel module that exposes a single serial device bus devic= e driver. +/// +/// # Examples +/// +/// ```ignore +/// kernel::module_serdev_device_driver! { +/// type: MyDriver, +/// name: "Module name", +/// authors: ["Author name"], +/// description: "Description", +/// license: "GPL v2", +/// } +/// ``` +#[macro_export] +macro_rules! module_serdev_device_driver { + ($($f:tt)*) =3D> { + $crate::module_driver!(, $crate::serdev::Adapter, { $($f)* }= ); + }; +} + +/// The serial device bus device driver trait. +/// +/// Drivers must implement this trait in order to get a serial device bus = device driver registered. +/// +/// # Examples +/// +///``` +/// # use kernel::{ +/// acpi, +/// bindings, +/// device::{ +/// Bound, +/// Core, // +/// }, +/// of, +/// serdev, // +/// }; +/// +/// struct MyDriver; +/// +/// kernel::of_device_table!( +/// OF_TABLE, +/// MODULE_OF_TABLE, +/// ::IdInfo, +/// [ +/// (of::DeviceId::new(c"test,device"), ()) +/// ] +/// ); +/// +/// kernel::acpi_device_table!( +/// ACPI_TABLE, +/// MODULE_ACPI_TABLE, +/// ::IdInfo, +/// [ +/// (acpi::DeviceId::new(c"LNUXBEEF"), ()) +/// ] +/// ); +/// +/// #[vtable] +/// impl serdev::Driver for MyDriver { +/// type IdInfo =3D (); +/// type Data<'bound> =3D Self; +/// const OF_ID_TABLE: Option> =3D Some(&OF_= TABLE); +/// const ACPI_ID_TABLE: Option> =3D Some(= &ACPI_TABLE); +/// +/// fn probe<'bound>( +/// sdev: &'bound serdev::Device>, +/// _id_info: Option<&'bound Self::IdInfo>, +/// ) -> impl PinInit, Error> + 'bound { +/// sdev.set_baudrate(115200); +/// sdev.write_all(b"Hello\n", serdev::Timeout::Max)?; +/// Ok(MyDriver) +/// } +/// } +///``` +#[vtable] +pub trait Driver { + /// The type holding driver private data about each device id supporte= d by the driver. + // TODO: Use associated_type_defaults once stabilized: + // + // ``` + // type IdInfo: 'static =3D (); + // ``` + type IdInfo: 'static; + + /// The type of the driver's bus device private data. + type Data<'bound>: Send + 'bound; + + /// The table of OF device ids supported by the driver. + const OF_ID_TABLE: Option> =3D None; + + /// The table of ACPI device ids supported by the driver. + const ACPI_ID_TABLE: Option> =3D None; + + /// Serial device bus device driver probe. + /// + /// Called when a new serial device bus device is added or discovered. + /// Implementers should attempt to initialize the device here. + fn probe<'bound>( + sdev: &'bound Device>, + id_info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit, Error> + 'bound; + + /// Serial device bus device driver unbind. + /// + /// Called when a [`Device`] is unbound from its bound [`Driver`]. Imp= lementing this callback + /// is optional. + /// + /// This callback serves as a place for drivers to perform teardown op= erations that require a + /// `&Device` or `&Device` reference. For instance. + /// + /// Otherwise, release operations for driver resources should be perfo= rmed in `Drop`. + fn unbind<'bound>(sdev: &'bound Device>, this: Pin<&S= elf::Data<'bound>>) { + let _ =3D (sdev, this); + } + + /// Serial device bus device data receive callback. + /// + /// Called when data got received from device. + /// + /// Returns the number of bytes accepted. + fn receive<'bound>( + sdev: &'bound Device, + this: Pin<&Self::Data<'bound>>, + data: &[u8], + ) -> usize { + let _ =3D (sdev, this, data); + build_error!(VTABLE_DEFAULT_ERROR) + } +} + +/// The serial device bus device representation. +/// +/// This structure represents the Rust abstraction for a C `struct serdev_= device`. The +/// implementation abstracts the usage of an already existing C `struct se= rdev_device` within Rust +/// code that we get passed from the C side. +/// +/// # Invariants +/// +/// A [`Device`] instance represents a valid `struct serdev_device` create= d by the C portion of +/// the kernel. +#[repr(transparent)] +pub struct Device( + Opaque, + PhantomData, +); + +impl Device { + fn as_raw(&self) -> *mut bindings::serdev_device { + self.0.get() + } +} + +impl Device { + /// Set the baudrate in bits per second. + /// + /// Common baudrates are 115200, 9600, 19200, 57600, 4800. + /// + /// Use [`Device::write_flush`] before calling this if you have writte= n data prior to this call. + pub fn set_baudrate(&self, speed: u32) -> Result<(), u32> { + // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a vali= d `serdev_device`. + let ret =3D unsafe { bindings::serdev_device_set_baudrate(self.as_= raw(), speed) }; + if ret =3D=3D speed { + Ok(()) + } else { + Err(ret) + } + } + + /// Set if flow control should be enabled. + /// + /// Use [`Device::write_flush`] before calling this if you have writte= n data prior to this call. + pub fn set_flow_control(&self, enable: bool) { + // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a vali= d `serdev_device`. + unsafe { bindings::serdev_device_set_flow_control(self.as_raw(), e= nable) }; + } + + /// Set parity to use. + /// + /// Use [`Device::write_flush`] before calling this if you have writte= n data prior to this call. + pub fn set_parity(&self, parity: Parity) -> Result { + // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a vali= d `serdev_device`. + to_result(unsafe { bindings::serdev_device_set_parity(self.as_raw(= ), parity as u32) }) + } + + /// Write data to the serial device until the controller has accepted = all the data or has + /// been interrupted by a timeout or signal. + /// + /// Note that any accepted data has only been buffered by the controll= er. Use + /// [`Device::wait_until_sent`] to make sure the controller write buff= er has actually been + /// emptied. + /// + /// Returns the number of bytes written (less than `data.len()` if int= errupted). + /// [`kernel::error::code::ETIMEDOUT`] or [`kernel::error::code::EREST= ARTSYS`] if interrupted + /// before any bytes were written. + pub fn write_all(&self, data: &[u8], timeout: Timeout) -> Result { + // SAFETY: + // - `self.as_raw()` is guaranteed to be a pointer to a valid `ser= dev_device`. + // - `data.as_ptr()` is guaranteed to be a valid array pointer wit= h the size of + // `data.len()`. + let ret =3D unsafe { + bindings::serdev_device_write( + self.as_raw(), + data.as_ptr(), + data.len(), + timeout.into_jiffies(), + ) + }; + // CAST: negative return values are guaranteed to be between `-MAX= _ERRNO` and `-1`, + // which always fit into a `i32`. + to_result(ret as i32).map(|()| ret.unsigned_abs()) + } + + /// Write data to the serial device. + /// + /// If you want to write until the controller has accepted all the dat= a, use + /// [`Device::write_all`]. + /// + /// Note that any accepted data has only been buffered by the controll= er. Use + /// [ Device::wait_until_sent`] to make sure the controller write buff= er has actually been + /// emptied. + /// + /// Returns the number of bytes written (less than `data.len()` if not= enough room in the + /// write buffer). + pub fn write(&self, data: &[u8]) -> Result { + // SAFETY: + // - `self.as_raw()` is guaranteed to be a pointer to a valid `ser= dev_device`. + // - `data.as_ptr()` is guaranteed to be a valid array pointer wit= h the size of + // `data.len()`. + let ret =3D + unsafe { bindings::serdev_device_write_buf(self.as_raw(), data= .as_ptr(), data.len()) }; + + to_result(ret as i32).map(|()| ret.unsigned_abs()) + } + + /// Send data to the serial device immediately. + /// + /// Note that this doesn't guarantee that the data has been transmitte= d. + /// Use [`Device::wait_until_sent`] for this purpose. + pub fn write_flush(&self) { + // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a vali= d `serdev_device`. + unsafe { bindings::serdev_device_write_flush(self.as_raw()) }; + } + + /// Wait for the data to be sent. + /// + /// After this function, the write buffer of the controller should be = empty. + pub fn wait_until_sent(&self, timeout: Timeout) { + // SAFETY: `self.as_raw()` is guaranteed to be a pointer to a vali= d `serdev_device`. + unsafe { bindings::serdev_device_wait_until_sent(self.as_raw(), ti= meout.into_jiffies()) }; + } +} + +// SAFETY: `serdev::Device` is a transparent wrapper of `struct serdev_dev= ice`. +// The offset is guaranteed to point to a valid device field inside `serde= v::Device`. +unsafe impl device::AsBusDevice for Devic= e { + const OFFSET: usize =3D offset_of!(bindings::serdev_device, dev); +} + +// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend= on `Device`'s generic +// argument. +kernel::impl_device_context_deref!(unsafe { Device }); +kernel::impl_device_context_into_aref!(Device); + +// SAFETY: Instances of `Device` are always reference-counted. +unsafe impl AlwaysRefCounted for Device { + fn inc_ref(&self) { + self.as_ref().inc_ref(); + } + + unsafe fn dec_ref(obj: NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is = non-zero. + unsafe { bindings::serdev_device_put(obj.cast().as_ptr()) } + } +} + +impl AsRef> for Device { + fn as_ref(&self) -> &device::Device { + // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a p= ointer to a valid + // `struct serdev_device`. + let dev =3D unsafe { &raw mut (*self.as_raw()).dev }; + + // SAFETY: `dev` points to a valid `struct device`. + unsafe { device::Device::from_raw(dev) } + } +} + +// SAFETY: A `Device` is always reference-counted and can be released from= any thread. +unsafe impl Send for Device {} + +// SAFETY: `Device` can be shared among threads because all methods of `De= vice` +// (i.e. `Device) are thread safe. +unsafe impl Sync for Device {} + +// SAFETY: Same as `Device` -- the underlying `struct serdev_devic= e` is the same; +// `Bound` is a zero-sized type-state marker that does not affect thread s= afety. +unsafe impl Sync for Device {} --=20 2.53.0 From nobody Mon Jun 8 09:48:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 115352E6CA8; Sat, 30 May 2026 01:13:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; cv=none; b=oXIjejCj3FpsbaGDdXzi6Hgj4BfTeqtzhqGD1OIE41Zly14F9ASfOtubURFRByXgVjZ2jT2FZtJzKIV5otaIVfgX9CQdOQN/KVQHUKSOTyTlPpW3DCYKdZQTChBt1szoZHtApYkGBj3ajI+3ly1usEs6pojuhnK/ptYv6ozbjhk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; c=relaxed/simple; bh=gzwQn4QR7YvkVSmraaAW6KXwXLc7aY1SuTuzC9ytKeY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OJaMIiN+AshMArtrEy/0VcDl41lUWrsJBoDoHZrbmDt15OQGx0JngFBS2A6ykGXo22laTXO/cMI8+vTRfeGUHCdsfKumWLB/NMF51Kq4pkwnZHDtqz8wf9DxQwuYY4OY7QM3WQuHBdWA2WbVl7G+ogYXGLklV2txx/gSV0GqdR8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hEg8xX1D; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hEg8xX1D" Received: by smtp.kernel.org (Postfix) with ESMTPS id BD829C2BCFC; Sat, 30 May 2026 01:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780103633; bh=gzwQn4QR7YvkVSmraaAW6KXwXLc7aY1SuTuzC9ytKeY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hEg8xX1DlcMKvY4DHYO805qYw6KD+oO9TKaKQpO+sTctFwAgEAMB49t/SOjm6tyKP 15MbHpLYAilrGl9wyJSXBy4nJKQfTsOgZDEADBxXuXRIy7EcbjmhkO339kRVHO2cVL mwAUmEiHbsRCF4KikuFsfUVI6pEMp5vmtQB70m3x/TLoj6H9E18RxStZ1+t5qAKpiW +PV4zyAwaMnms/p7t7Iy+94m3vvDYQ5rChkMOY2I9SRIi/i3uEkXwdGBMTQZsXVMDu K/Y7XY3Xah1HmYja6z2jf7KhqUac/pNbTzJhxK5q8UYGe/74qpgOlKkocZ8/YXirNR 83dXRa1I6O5Sw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC13ECD6E55; Sat, 30 May 2026 01:13:53 +0000 (UTC) From: Markus Probst via B4 Relay Date: Sat, 30 May 2026 03:13:52 +0200 Subject: [PATCH v8 4/5] samples: rust: add Rust serial device bus sample device driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260530-rust_serdev-v8-4-2a95f1da22a7@posteo.de> References: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> In-Reply-To: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> To: Rob Herring , Greg Kroah-Hartman , Jiri Slaby , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Kari Argillander , "Rafael J. Wysocki" , Viresh Kumar , Boqun Feng , David Airlie , Simona Vetter , Boqun Feng Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-pm@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, Markus Probst X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=4748; i=markus.probst@posteo.de; h=from:subject:message-id; bh=kWHqDqopsoLEzI8G/1jRCL4n/V6ei1IvSJlqCr5mfNY=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqGjnPRNn72Td9zq8gBDeHPnEwMLuEbyhn9QoJV 7ey3OYIKxWJAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaho5zxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9ISoBAAiz6b0ORg5BQJX/iNveBI9tafUecjAyu c+U6qKgV30WGr5MewI9Iinpt7nsRbnmU+01AjgNMCdx26gWY9FjzkW7+OVWoJ/G9TdVIwAcfvHf tnGzhUKll2OWRD4uot1CLYHetld0GYNqvQ1tr4oOijbC2+u02HbIJtno/tJPd0bLB18mBBavOri Ky3DQjPm8P8NnL+igy6AF+tLXeazsOnWGL6vcKoOkP4XynqGQhiJ8ijeNrvFVSMBD3c68kaQsr8 D8KsPLCuEDSpWqu8YaY9AcrsYafKdXxXEVreakOA+xsr78dv5xSzYr52+SNVXY9nIQiex3gsnE9 q3Z866JASaUXifXzi8mGIPIV8NgRr6UW8G44jS3bI1pxyhnSFEoZcBmbfZDWR+av3A4w56vLgpw By5v7d1/dkWZDPwLezSkeA/1ZITL9WrIDlnAmGJUfcpc+a99EgBLzn9WWVuFKH6MXxWOPDCtsLI B26Y1p+gzAwDE7LtO4fFZ+siv8nRmN+RJwRJjTpv18ABRdbY1R6h4PaXIIU0njuxI4OiL3S/iYv jC06yLDXv6Y/7I8EwC+JC/0CxoVUzX3nbuaqEYpnbh8FkHLOgUOWh5sH2U2Vv71BlwBWy10z/Is otrIh140NXGcapzfqqjKzylpF1b7lO54PuzNwRwUZDTr6EDhMJhw= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Add a sample Rust serial device bus device driver illustrating the usage of the serial device bus abstractions. This drivers probes through either a match of device / driver name or a match within the OF ID table. Signed-off-by: Markus Probst --- MAINTAINERS | 1 + samples/rust/Kconfig | 11 +++++ samples/rust/Makefile | 1 + samples/rust/rust_driver_serdev.rs | 91 ++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 104 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d2f608ff8ca0..fa3f20f0cc4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -24278,6 +24278,7 @@ F: drivers/tty/serdev/ F: include/linux/serdev.h F: rust/helpers/serdev.c F: rust/kernel/serdev.rs +F: samples/rust/rust_driver_serdev.rs =20 SERIAL IR RECEIVER M: Sean Young diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index c49ab9106345..31d62533ef25 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -161,6 +161,17 @@ config SAMPLE_RUST_DRIVER_AUXILIARY =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_SERDEV + tristate "Serial Device Bus Device Driver" + select RUST_SERIAL_DEV_BUS_ABSTRACTIONS + help + This option builds the Rust serial device bus driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_serdev. + + If unsure, say N. + config SAMPLE_RUST_SOC tristate "SoC Driver" select SOC_BUS diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 6c0aaa58cccc..b986b681cde5 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_drive= r_platform.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) +=3D rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) +=3D rust_driver_auxiliary.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) +=3D rust_driver_serdev.o obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) +=3D rust_configfs.o obj-$(CONFIG_SAMPLE_RUST_SOC) +=3D rust_soc.o =20 diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_= serdev.rs new file mode 100644 index 000000000000..824affbf6593 --- /dev/null +++ b/samples/rust/rust_driver_serdev.rs @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust Serial device bus device driver sample. + +use kernel::{ + acpi, + device::{ + Bound, + Core, // + }, + of, + prelude::*, + serdev, + sync::aref::ARef, // +}; + +struct SampleDriver { + sdev: ARef, +} + +kernel::of_device_table!( + OF_TABLE, + MODULE_OF_TABLE, + ::IdInfo, + [(of::DeviceId::new(c"test,rust_driver_serdev"), ())] +); + +kernel::acpi_device_table!( + ACPI_TABLE, + MODULE_ACPI_TABLE, + ::IdInfo, + [(acpi::DeviceId::new(c"LNUXBEEF"), ())] +); + +#[vtable] +impl serdev::Driver for SampleDriver { + type IdInfo =3D (); + type Data<'bound> =3D Self; + const OF_ID_TABLE: Option> =3D Some(&OF_TABL= E); + const ACPI_ID_TABLE: Option> =3D Some(&ACP= I_TABLE); + + fn probe<'bound>( + sdev: &'bound serdev::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit + 'bound { + let dev =3D sdev.as_ref(); + + dev_dbg!(dev, "Probe Rust Serial device bus device driver sample.\= n"); + + if sdev + .set_baudrate( + dev.fwnode() + .and_then(|fwnode| fwnode.property_read(c"baudrate").o= ptional()) + .unwrap_or(115200), + ) + .is_err() + { + return Err(EINVAL); + } + sdev.set_flow_control(false); + sdev.set_parity(serdev::Parity::None)?; + + Ok(Self { sdev: sdev.into() }) + } + + fn receive<'bound>( + sdev: &'bound serdev::Device, + _this: Pin<&Self>, + data: &[u8], + ) -> usize { + let _ =3D sdev.write_all(data, serdev::Timeout::Max); + data.len() + } +} + +impl Drop for SampleDriver { + fn drop(&mut self) { + dev_dbg!( + self.sdev.as_ref(), + "Remove Rust Serial device bus device driver sample.\n" + ); + } +} + +kernel::module_serdev_device_driver! { + type: SampleDriver, + name: "rust_driver_serdev", + authors: ["Markus Probst"], + description: "Rust Serial device bus device driver", + license: "GPL v2", +} --=20 2.53.0 From nobody Mon Jun 8 09:48:23 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20F5E2EFD95; Sat, 30 May 2026 01:13:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; cv=none; b=IXjMC24r7hCIOPPf5IKO95amfQn5/A1Vui+qLX9xPCNmOSxhTIVWr7YEsAF/1LdqTy2Tg8NT2tA/gnogle4hUyrxYKvkw3o88mZa+f1zZGXc1jE+EjP6jmzaYQ5dJHYcU2Y2WQX7mNw0j6mY1kxk5EB4Z2IEBTlhyN92EQLq/pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780103634; c=relaxed/simple; bh=i6yyE0Dn4THGDheAsQuCbxaViLFW1ARK5q9G8YpPkPo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Ln5114kYLQDnuP1j44WWkSIHMrQRFN6UVh0g0dxMYE4vlcZccMMroADzHOb1JxPyexIBOZLDYXHG93MQUdj7KSNq9oISLxBJ3hUj1DoHXLS7recOIJudKeb9k9nyLxhF3rSdgkj7XETncWPMP2mFRHMFzi+kieCAoPx6UPuKpSg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RtsC3ZGz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RtsC3ZGz" Received: by smtp.kernel.org (Postfix) with ESMTPS id CC977C32782; Sat, 30 May 2026 01:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780103633; bh=i6yyE0Dn4THGDheAsQuCbxaViLFW1ARK5q9G8YpPkPo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=RtsC3ZGz9u2DK+Zyrk2jsN1VIMkR+g4cATyoF/zIiAjIYMTknDJHNjnSpNnXbM4as 0Rm6vTKsObq0n1kaRMmhzl1A2SHLnGS9IUTVIdD9x+p9qPKRUs20BXM7HYXfUuvry0 ITo7TRxXHaRobKnL3Qxl6BGf+Rc1sgp9tfezmEGZAXLA2PQyHfawkDXfjml9n+cRB5 alvrMKWL0TnsLCXAL3CGQOO0vrBFJ+kzcXobU9+eW63XPIZXJ1lptQSMbtMtZxEHf4 xGNtBmwh42++H9XI3N7YCwdkyZaf34k0AaryqBBcoSuMkH3JciM35iJgO6Qd31fWuL ZzD4bdfpFm1Ag== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9FD5CD6E54; Sat, 30 May 2026 01:13:53 +0000 (UTC) From: Markus Probst via B4 Relay Date: Sat, 30 May 2026 03:13:53 +0200 Subject: [PATCH v8 5/5] MAINTAINERS: serdev: Add self for serdev Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260530-rust_serdev-v8-5-2a95f1da22a7@posteo.de> References: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> In-Reply-To: <20260530-rust_serdev-v8-0-2a95f1da22a7@posteo.de> To: Rob Herring , Greg Kroah-Hartman , Jiri Slaby , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Kari Argillander , "Rafael J. Wysocki" , Viresh Kumar , Boqun Feng , David Airlie , Simona Vetter , Boqun Feng Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-pm@vger.kernel.org, driver-core@lists.linux.dev, dri-devel@lists.freedesktop.org, Markus Probst X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=838; i=markus.probst@posteo.de; h=from:subject:message-id; bh=P+qqzzRwhI8B2ZhOfr+PVqRWtfVtS9KesBahL8YX4uk=; b=owEBiQJ2/ZANAwAIATR2H/jnrUPSAcsmYgBqGjnPhljelHIuzdbOLC3zhJwHUwihLpJ+X/2k8 18CITrGo5+JAk8EAAEIADkWIQSCdBjE9KxY53IwxHM0dh/4561D0gUCaho5zxsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMiwyLDIACgkQNHYf+OetQ9JNdQ/+IR2iPGEy8sqtRVurCujsY1VhZ/t7tm+ 6bWZdXnedNebKNUT6bpdRAAxnB0/Kf7Iu/bWpGDcSZ/esml58O+dBLKANgmpDEn3Hb/kFG/8LmB cmAGhf2LSuYuN3IpSJax6GiRzWxb5NaDMhUHM81xmnNSWYnBnQ26L+kUw8x0A4rIkfF5SSu5FAG xfnu+x6oVlgHGj4SBPi9IrW5awYtoRMgLuGd97RaA9PSYUS54Zmih3fKnbnoqwUAolRi2iOM7SP 6lNBjb7sEhpDMsG7SiwfYC4RKp4bjI77UtZA7cFsNDNoV2FJvZAQePzkthoFFbd1i+kFgDiHdg4 G24/p9FN9pUJ2PbuwfSXpJIZmkPi3W8Hw0hqgh6J64Jd0AtU9gU6x6FX+DBPgdjrax3/YV8PW7F UNrktM48Or5Vao7WkN39D2fD7+38l5CS/eWj5kJzeQQP/hn3E/TKPv+7FSSpFUX+8UMjJSpByik xqok0SyWTgVdW0JlXHGxsG5d10++pOpV+qXV+qbGjpeFs2aZ9KLLM0BhN1AZv5uMYA6qTU4BCad 3qCvEJMtgW1uR+gpWCO/uxlJdVexI7D79yFEu6Rj5eLADedrgkRuna6hkubYrkC7fYkqK3+kpZl I4h7OJ7fIeJGnn/h65/wr4XgfwNeMWAikFFjuM89/Lbmb0aBvlo0= X-Developer-Key: i=markus.probst@posteo.de; a=openpgp; fpr=827418C4F4AC58E77230C47334761FF8E7AD43D2 X-Endpoint-Received: by B4 Relay for markus.probst@posteo.de/default with auth_id=680 X-Original-From: Markus Probst Reply-To: markus.probst@posteo.de From: Markus Probst Rob mentioned he needs to find someone else to maintain serdev. Link: https://lore.kernel.org/rust-for-linux/20260430195858.GA1650658-robh@= kernel.org/ Link: https://lore.kernel.org/rust-for-linux/da85ceb81f51079d4a8248a1ffde6a= 27d2ef24ad.camel@posteo.de/ Signed-off-by: Markus Probst --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index fa3f20f0cc4f..58db6aedf45a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -24270,7 +24270,7 @@ F: drivers/iio/chemical/sps30_i2c.c F: drivers/iio/chemical/sps30_serial.c =20 SERIAL DEVICE BUS -M: Rob Herring +M: Markus Probst L: linux-serial@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/serial/serial.yaml --=20 2.53.0