* [PATCH v7 0/4] rust: add basic serial device bus abstractions
@ 2026-04-29 18:21 Markus Probst via B4 Relay
2026-04-29 18:21 ` [PATCH v7 1/4] rust: devres: return reference in `devres::register` Markus Probst via B4 Relay
` (5 more replies)
0 siblings, 6 replies; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-29 18:21 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
This patch series adds the serdev device bus rust abstraction into the
kernel.
This abstraction will be used by a driver,
which targets the MCU devices in Synology devices.
Kari Argillander also messaged me, stating that he wants to write a
watchdog driver with this abstraction (needing initial device data).
@Rob: Are you willing to maintain these rust abstractions yourself,
as you are the expert on this subsystem, otherwise I would take care of
it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
the second case, I assume you are going to pick those patches as-is into
your tree, after they have been reviewed?
This series depends on [1].
[1]
https://lore.kernel.org/driver-core/20260427221155.2144848-1-dakr@kernel.org/
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v7:
- adapted to driver-lifetime patch series
- Link to v6: https://patch.msgid.link/20260427-rust_serdev-v6-0-173798d5e1a3@posteo.de
Changes in v6:
- rebased onto v7.1-rc1
- Link to v5: https://patch.msgid.link/20260420-rust_serdev-v5-0-57e8ba0519f3@posteo.de
Changes in v5:
- fix typo in documentation
- Link to v4: https://lore.kernel.org/r/20260411-rust_serdev-v4-0-845e960c6627@posteo.de
Changes in v4:
- fixed not selecting rust serdev abstraction in sample
- Link to v3: https://lore.kernel.org/r/20260313-rust_serdev-v3-0-c9a3af214f7f@posteo.de
Changes in v3:
- fix vertical import style
- add Kconfig entry for the rust abstraction
- fix documentation in include/linux/serdev.h
- rename private_data to rust_private_data
- fix `complete_all` <-> `wait_for_completion` typo
- move drvdata_borrow call after the completion
- Link to v2: https://lore.kernel.org/r/20260306-rust_serdev-v2-0-e9b23b42b255@posteo.de
Changes in v2:
- fix documentation in `serdev::Driver::write` and
`serdev::Driver::write_all`
- remove use of `dev_info` in probe from the sample
- remove `properties_parse` from the sample
- add optional `baudrate` property to the sample
- remove 1. patch
- remove `TryFrom<&device::Device<Ctx>> for &serdev::Device<Ctx>`
implementation
- fix import style
- add patch to return reference in `devres::register` to fix safety
issue
- add patch to add private data to serdev_device, to fix
`Device.drvdata()` from failing
- simplify abstraction by removing ability to receive the initial
transmission. It may be added later in a separate patch series if
needed.
- Link to v1: https://lore.kernel.org/r/20251220-rust_serdev-v1-0-e44645767621@posteo.de
---
Markus Probst (4):
rust: devres: return reference in `devres::register`
serdev: add rust private data to serdev_device
rust: add basic serial device bus abstractions
samples: rust: add Rust serial device bus sample device driver
drivers/tty/serdev/Kconfig | 7 +
include/linux/serdev.h | 15 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/serdev.c | 22 ++
rust/kernel/cpufreq.rs | 3 +-
rust/kernel/devres.rs | 15 +-
rust/kernel/drm/driver.rs | 3 +-
rust/kernel/lib.rs | 2 +
rust/kernel/serdev.rs | 571 +++++++++++++++++++++++++++++++++++++
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++
13 files changed, 728 insertions(+), 10 deletions(-)
---
base-commit: 5e9b7d093f3f77cb0af4409559e3d139babfb443
change-id: 20251217-rust_serdev-ee5481e9085c
prerequisite-message-id: 20260427221002.2143861-1-dakr@kernel.org
prerequisite-patch-id: 925690ac15ddd64777b2da34b343d2547bbf79e8
prerequisite-patch-id: 67318671a5eed5fb4ad23a450f1cf0e442bf8ca2
prerequisite-message-id: 20260427221155.2144848-1-dakr@kernel.org
prerequisite-patch-id: 87127047dbf7d948ae98f1ff0f4a782214a516e2
prerequisite-patch-id: 7664165039fb510368a721edfe60f5b67449b7b6
prerequisite-patch-id: 1e8c97720bab512d8646409c129edd6047164c4c
prerequisite-patch-id: f0fdd1e9912f31a3945f1c0f227dcb64cf71885d
prerequisite-patch-id: be515f7e13f7800eaadb3ed85dec6a9ddb733828
prerequisite-patch-id: 3a3c7749e017d9335f58497404d1350e96caf471
prerequisite-patch-id: 3526c9154f581497a11465b936d83ef61a875454
prerequisite-patch-id: 65d8c757b52475c2acc7d22ddc92cd3f0152b55d
prerequisite-patch-id: 4bd31f1414d5248dc080884caadf5f21684a8427
prerequisite-patch-id: 7beadbb0da3e589ed86d12f512d1c83427dd82b4
prerequisite-patch-id: f04f5427c592cb078c08ee071b965ef6fd4a9a48
prerequisite-patch-id: 64c0098c3d2420f82c89f44fccd3eed459557bfc
prerequisite-patch-id: 3294340ecd964b8e3e87e5a787ff1ffa28e0b698
prerequisite-patch-id: b2c14d06f068dc6a52814fc55d1188737dc29861
prerequisite-patch-id: c7fd96983b606bc42cc5b003022b8fa2bb1c0c34
prerequisite-patch-id: 8e9f4c2d5521fb6cdc5bed2d6661f4bbed5eb63d
prerequisite-patch-id: d868f7925ee9dfe44c5ddf50f4deb50263ff203f
prerequisite-patch-id: 5677248690560ec45e512a8cdbbf8aecfad62d77
prerequisite-patch-id: 5d9674da330ee9d0f4c91edb8acc20727ba1cd9c
prerequisite-patch-id: d5f29453bfd2e3354fb96b57d7a55521bedb2b0b
prerequisite-patch-id: 9d6f96e26fe651304e950766d6bc2006dd33e86a
prerequisite-patch-id: c7a73c58c6d4ca8556d29ce651ad78cc647f6f31
prerequisite-patch-id: c5f35030637e78ab6f5fa489172f1506493fbae1
prerequisite-patch-id: aad19e48d4fa45734050bba927a5b72d6def9673
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v7 1/4] rust: devres: return reference in `devres::register`
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
@ 2026-04-29 18:21 ` Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-29 18:21 ` [PATCH v7 2/4] serdev: add rust private data to serdev_device Markus Probst via B4 Relay
` (4 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-29 18:21 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
From: Markus Probst <markus.probst@posteo.de>
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 <viresh.kumar@linaro.org>
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
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 ac59cdfd633c..1da80dc266dd 100644
--- a/rust/kernel/cpufreq.rs
+++ b/rust/kernel/cpufreq.rs
@@ -1052,7 +1052,8 @@ pub fn new_foreign_owned(dev: &Device<Bound>) -> Result
where
T: 'static,
{
- devres::register(dev, Self::new()?, GFP_KERNEL)
+ devres::register(dev, Self::new()?, GFP_KERNEL)?;
+ Ok(())
}
}
diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
index 6f3c58355d10..d01e186be381 100644
--- a/rust/kernel/devres.rs
+++ b/rust/kernel/devres.rs
@@ -438,15 +438,26 @@ fn register_foreign<P>(dev: &Device<Bound>, data: P) -> Result
/// }
///
/// fn from_bound_context(dev: &Device<Bound>) -> Result {
-/// devres::register(dev, Registration::new(), GFP_KERNEL)
+/// devres::register(dev, Registration::new(), GFP_KERNEL)?;
+/// Ok(())
/// }
/// ```
-pub fn register<T, E>(dev: &Device<Bound>, data: impl PinInit<T, E>, flags: Flags) -> Result
+pub fn register<'a, T, E>(
+ dev: &'a Device<Bound>,
+ data: impl PinInit<T, E>,
+ flags: Flags,
+) -> Result<&'a T>
where
T: Send + 'static,
Error: From<E>,
{
let data = KBox::pin_init(data, flags)?;
+ let data_ptr = &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<Bound>`, it is guaranteed that the device is not unbound 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(
let reg = Registration::<T>::new(drm, flags)?;
- devres::register(dev, reg, GFP_KERNEL)
+ devres::register(dev, reg, GFP_KERNEL)?;
+ Ok(())
}
/// Returns a reference to the `Device` instance for this registration.
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: rust: devres: return reference in `devres::register`
2026-04-29 18:21 ` [PATCH v7 1/4] rust: devres: return reference in `devres::register` Markus Probst via B4 Relay
@ 2026-05-05 1:18 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-05-05 1:18 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**Summary:** Changes `devres::register` from returning `Result` to `Result<&'a T>`, tying the returned reference's lifetime to the `&'a Device<Bound>` parameter.
The safety argument is sound: devres-managed data is freed when the device is unbound, and holding a `&'a Device<Bound>` guarantees the device hasn't been unbound for lifetime `'a`. The pointer is captured before `register_foreign` takes ownership of the `KBox`:
```rust
+ let data_ptr = &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<Bound>`, it is guaranteed that the device is not unbound and data has not been
+ // dropped. Thus `data_ptr` is also valid for the lifetime of 'a.
+ .map(|()| unsafe { &*data_ptr })
```
The callers in `cpufreq.rs` and `drm/driver.rs` are updated to discard the new return value with `?; Ok(())`, which is correct. This patch is clean.
No issues.
---
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v7 2/4] serdev: add rust private data to serdev_device
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
2026-04-29 18:21 ` [PATCH v7 1/4] rust: devres: return reference in `devres::register` Markus Probst via B4 Relay
@ 2026-04-29 18:21 ` Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-29 18:21 ` [PATCH v7 3/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
` (3 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-29 18:21 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
From: Markus Probst <markus.probst@posteo.de>
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 <markus.probst@posteo.de>
---
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 {
/**
* 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;
};
#define to_serdev_device(d) container_of_const(d, struct serdev_device, dev)
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: serdev: add rust private data to serdev_device
2026-04-29 18:21 ` [PATCH v7 2/4] serdev: add rust private data to serdev_device Markus Probst via B4 Relay
@ 2026-05-05 1:18 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-05-05 1:18 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
**Summary:** Adds a `void *rust_private_data` field to `struct serdev_device` for use by the Rust abstraction.
```c
+ * @rust_private_data: Private data for the rust abstraction. This should
+ * not be used by the C drivers.
*/
struct serdev_device {
...
+ void *rust_private_data;
};
```
This is a C-side change touching a core kernel structure. The field is needed because the Rust abstraction stores a `PrivateData` (with a `Completion` for probe/receive synchronization) that must be accessible from the `receive_buf` callback before drvdata is fully set up. This is the same pattern used by other subsystems.
**Minor:** The doc comment says "rust" lowercase — kernel convention in documentation tends to capitalize "Rust" (e.g., `Documentation/rust/`). Consider `@rust_private_data: Private data for the Rust abstraction.`
This needs an Ack from the serdev maintainer (Rob Herring) since it modifies the core C struct.
---
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v7 3/4] rust: add basic serial device bus abstractions
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
2026-04-29 18:21 ` [PATCH v7 1/4] rust: devres: return reference in `devres::register` Markus Probst via B4 Relay
2026-04-29 18:21 ` [PATCH v7 2/4] serdev: add rust private data to serdev_device Markus Probst via B4 Relay
@ 2026-04-29 18:21 ` Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-29 18:21 ` [PATCH v7 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
` (2 subsequent siblings)
5 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-29 18:21 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
From: Markus Probst <markus.probst@posteo.de>
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 <markus.probst@posteo.de>
---
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 | 571 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 604 insertions(+)
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
Note that you typically also want to enable TTY port controller support.
+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
config SERIAL_DEV_CTRL_TTYPORT
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 446dbeaf0866..4e42635b8607 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -84,6 +84,7 @@
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
#include <linux/security.h>
+#include <linux/serdev.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/task_work.h>
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 <linux/serdev.h>
+
+__rust_helper
+void rust_helper_serdev_device_driver_unregister(struct serdev_device_driver *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..28c6cf16a3a7
--- /dev/null
+++ b/rust/kernel/serdev.rs
@@ -0,0 +1,571 @@
+// 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::{
+ ForLt,
+ 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 = bindings::serdev_parity_SERDEV_PARITY_NONE,
+ /// Even partiy.
+ Even = bindings::serdev_parity_SERDEV_PARITY_EVEN,
+ /// Odd parity.
+ Odd = bindings::serdev_parity_SERDEV_PARITY_ODD,
+}
+
+/// Timeout in Jiffies.
+pub enum Timeout {
+ /// Wait for a specific amount of [`Jiffies`].
+ Jiffies(NonZero<Jiffies>),
+ /// Wait for a specific amount of [`Msecs`].
+ Milliseconds(NonZero<Msecs>),
+ /// 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) => value.get().try_into().unwrap_or_default(),
+ Self::Milliseconds(value) => {
+ msecs_to_jiffies(value.get()).try_into().unwrap_or_default()
+ }
+ Self::Max => 0,
+ }
+ }
+}
+
+/// An adapter for the registration of serial device bus device drivers.
+///
+/// `F` is a [`ForLt`](trait@ForLt) type that maps lifetimes to the driver's device
+/// private data type, i.e. `F::Of<'a>` is the driver struct parameterized by `'a`. The macro
+/// `module_serdev_device_driver!` generates this automatically via `ForLt!()`.
+pub struct Adapter<F>(PhantomData<F>);
+
+// SAFETY:
+// - `bindings::serdev_device_driver` is a C type declared as `repr(C)`.
+// - `F::Of<'static>` is the stored 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 `struct device_driver`.
+unsafe impl<F> driver::DriverLayout for Adapter<F>
+where
+ F: ForLt + 'static,
+ for<'a> F::Of<'a>: Driver<'a>,
+{
+ type DriverType = bindings::serdev_device_driver;
+ type DriverData = F;
+ const DEVICE_DRIVER_OFFSET: usize = core::mem::offset_of!(Self::DriverType, 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<F> driver::RegistrationOps for Adapter<F>
+where
+ F: ForLt + 'static,
+ for<'a> F::Of<'a>: Driver<'a>,
+{
+ unsafe fn register(
+ sdrv: &Opaque<Self::DriverType>,
+ name: &'static CStr,
+ module: &'static ThisModule,
+ ) -> Result {
+ let of_table = match <F::Of<'static> as Driver<'static>>::OF_ID_TABLE {
+ Some(table) => table.as_ptr(),
+ None => core::ptr::null(),
+ };
+
+ let acpi_table = match <F::Of<'static> as Driver<'static>>::ACPI_ID_TABLE {
+ Some(table) => table.as_ptr(),
+ None => core::ptr::null(),
+ };
+
+ // SAFETY: It's safe to set the fields of `struct serdev_device_driver` on initialization.
+ unsafe {
+ (*sdrv.get()).driver.name = name.as_char_ptr();
+ (*sdrv.get()).probe = Some(Self::probe_callback);
+ (*sdrv.get()).remove = Some(Self::remove_callback);
+ (*sdrv.get()).driver.of_match_table = of_table;
+ (*sdrv.get()).driver.acpi_match_table = 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<Self::DriverType>) {
+ // 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<bool>,
+}
+
+impl<F> Adapter<F>
+where
+ F: ForLt + 'static,
+ for<'a> F::Of<'a>: Driver<'a>,
+{
+ const OPS: &'static bindings::serdev_device_ops = &bindings::serdev_device_ops {
+ receive_buf: if <F::Of<'static> as Driver<'static>>::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) -> kernel::ffi::c_int {
+ // SAFETY: The serial device bus only ever calls the probe callback with a valid pointer to
+ // a `struct serdev_device`.
+ //
+ // INVARIANT: `sdev` is valid for the duration of `probe_callback()`.
+ let sdev = unsafe { &*sdev.cast::<Device<device::CoreInternal>>() };
+
+ from_result(|| {
+ let private_data = 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 =
+ (&raw const *private_data).cast::<c_void>().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 callback 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 info = <Self as driver::Adapter<'_>>::id_info(sdev.as_ref());
+ let data = <F::Of<'_> as Driver<'_>>::probe(sdev, info);
+ let result = sdev.as_ref().set_drvdata::<F>(data);
+
+ // SAFETY: We have exclusive access to `private_data.error`.
+ unsafe { *private_data.error.get() = 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 callback with a valid pointer
+ // to a `struct serdev_device`.
+ //
+ // INVARIANT: `sdev` is valid for the duration of `remove_callback()`.
+ let sdev = unsafe { &*sdev.cast::<Device<device::CoreInternal>>() };
+
+ // SAFETY: `remove_callback` is only ever called after a successful call to
+ // `probe_callback`, hence it's guaranteed that drvdata has been set.
+ let data = unsafe { sdev.as_ref().drvdata_borrow::<F>() };
+
+ <F::Of<'_> as Driver<'_>>::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 callback with a valid
+ // pointer to a `struct serdev_device`.
+ //
+ // INVARIANT: `sdev` is valid for the duration of `receive_buf_callback()`.
+ let sdev = unsafe { &*sdev.cast::<Device<device::CoreInternal>>() };
+
+ // SAFETY:
+ // - The serial device bus only ever calls the receive buf callback 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_data` is a pointer
+ // to a valid `PrivateData`.
+ let private_data = unsafe { &*(*sdev.as_raw()).rust_private_data.cast::<PrivateData>() };
+
+ 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 successful call to
+ // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
+ // and stored a `Pin<KBox<T>>`.
+ let data = unsafe { sdev.as_ref().drvdata_borrow::<F>() };
+
+ // SAFETY: `buf` is guaranteed to be non-null and has the size of `length`.
+ let buf = unsafe { core::slice::from_raw_parts(buf, length) };
+
+ <F::Of<'_> as Driver<'_>>::receive(sdev, data, buf)
+ }
+}
+
+impl<'a, F> driver::Adapter<'a> for Adapter<F>
+where
+ F: ForLt + 'static,
+ for<'b> F::Of<'b>: Driver<'b>,
+{
+ type IdInfo = <F::Of<'a> as Driver<'a>>::IdInfo;
+
+ fn of_id_table() -> Option<of::IdTable<Self::IdInfo>> {
+ <F::Of<'a> as Driver<'a>>::OF_ID_TABLE
+ }
+
+ fn acpi_id_table() -> Option<acpi::IdTable<Self::IdInfo>> {
+ <F::Of<'a> as Driver<'a>>::ACPI_ID_TABLE
+ }
+}
+
+/// Declares a kernel module that exposes a single serial device bus device driver.
+///
+/// The `type` field accepts a driver type, optionally with a lifetime placeholder `'_` for
+/// lifetime-parameterized drivers. The macro wraps it in [`ForLt!`] automatically.
+///
+/// # Examples
+///
+/// ```ignore
+/// kernel::module_serdev_device_driver! {
+/// type: MyDriver,
+/// name: "Module name",
+/// authors: ["Author name"],
+/// description: "Description",
+/// license: "GPL v2",
+/// }
+/// ```
+///
+/// [`ForLt!`]: macro@ForLt
+/// [`ForLt`]: trait@ForLt
+#[macro_export]
+macro_rules! module_serdev_device_driver {
+ (type: $type:ty, $($rest:tt)*) => {
+ $crate::module_driver!(<T>, $crate::serdev::Adapter<T>, {
+ type: $crate::types::ForLt!($type),
+ $($rest)*
+ });
+ };
+}
+
+/// 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,
+/// <MyDriver as serdev::Driver<'_>>::IdInfo,
+/// [
+/// (of::DeviceId::new(c"test,device"), ())
+/// ]
+/// );
+///
+/// kernel::acpi_device_table!(
+/// ACPI_TABLE,
+/// MODULE_ACPI_TABLE,
+/// <MyDriver as serdev::Driver<'_>>::IdInfo,
+/// [
+/// (acpi::DeviceId::new(c"LNUXBEEF"), ())
+/// ]
+/// );
+///
+/// #[vtable]
+/// impl<'a> serdev::Driver<'a> for MyDriver {
+/// type IdInfo = ();
+/// const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+/// const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+///
+/// fn probe(
+/// sdev: &'a serdev::Device<Core>,
+/// _id_info: Option<&'a Self::IdInfo>,
+/// ) -> impl PinInit<Self, Error> + 'a {
+/// sdev.set_baudrate(115200);
+/// sdev.write_all(b"Hello\n", serdev::Timeout::Max)?;
+/// Ok(MyDriver)
+/// }
+/// }
+///```
+#[vtable]
+pub trait Driver<'a>: Send {
+ /// The type holding driver private data about each device id supported by the driver.
+ // TODO: Use associated_type_defaults once stabilized:
+ //
+ // ```
+ // type IdInfo: 'static = ();
+ // ```
+ type IdInfo: 'static;
+
+ /// The table of OF device ids supported by the driver.
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None;
+
+ /// The table of ACPI device ids supported by the driver.
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = 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(
+ sdev: &'a Device<device::Core>,
+ id_info: Option<&'a Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> + 'a;
+
+ /// Serial device bus device driver unbind.
+ ///
+ /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback
+ /// is optional.
+ ///
+ /// This callback serves as a place for drivers to perform teardown operations that require a
+ /// `&Device<Core>` or `&Device<Bound>` reference. For instance.
+ ///
+ /// Otherwise, release operations for driver resources should be performed in `Self::drop`.
+ fn unbind(sdev: &'a Device<device::Core>, this: Pin<&'a Self>) {
+ let _ = (sdev, this);
+ }
+
+ /// Serial device bus device data receive callback.
+ ///
+ /// Called when data got received from device.
+ ///
+ /// Returns the number of bytes accepted.
+ fn receive(sdev: &'a Device<device::Bound>, this: Pin<&'a Self>, data: &[u8]) -> usize {
+ let _ = (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 serdev_device` within Rust
+/// code that we get passed from the C side.
+///
+/// # Invariants
+///
+/// A [`Device`] instance represents a valid `struct serdev_device` created by the C portion of
+/// the kernel.
+#[repr(transparent)]
+pub struct Device<Ctx: device::DeviceContext = device::Normal>(
+ Opaque<bindings::serdev_device>,
+ PhantomData<Ctx>,
+);
+
+impl<Ctx: device::DeviceContext> Device<Ctx> {
+ fn as_raw(&self) -> *mut bindings::serdev_device {
+ self.0.get()
+ }
+}
+
+impl Device<device::Bound> {
+ /// 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 written 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 valid `serdev_device`.
+ let ret = unsafe { bindings::serdev_device_set_baudrate(self.as_raw(), speed) };
+ if ret == speed {
+ Ok(())
+ } else {
+ Err(ret)
+ }
+ }
+
+ /// Set if flow control should be enabled.
+ ///
+ /// Use [`Device::write_flush`] before calling this if you have written 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 valid `serdev_device`.
+ unsafe { bindings::serdev_device_set_flow_control(self.as_raw(), enable) };
+ }
+
+ /// Set parity to use.
+ ///
+ /// Use [`Device::write_flush`] before calling this if you have written 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 valid `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 controller. Use
+ /// [`Device::wait_until_sent`] to make sure the controller write buffer has actually been
+ /// emptied.
+ ///
+ /// Returns the number of bytes written (less than `data.len()` if interrupted).
+ /// [`kernel::error::code::ETIMEDOUT`] or [`kernel::error::code::ERESTARTSYS`] if interrupted
+ /// before any bytes were written.
+ pub fn write_all(&self, data: &[u8], timeout: Timeout) -> Result<usize> {
+ // SAFETY:
+ // - `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
+ // - `data.as_ptr()` is guaranteed to be a valid array pointer with the size of
+ // `data.len()`.
+ let ret = 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 data, use
+ /// [`Device::write_all`].
+ ///
+ /// Note that any accepted data has only been buffered by the controller. Use
+ /// [ Device::wait_until_sent`] to make sure the controller write buffer 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<u32> {
+ // SAFETY:
+ // - `self.as_raw()` is guaranteed to be a pointer to a valid `serdev_device`.
+ // - `data.as_ptr()` is guaranteed to be a valid array pointer with the size of
+ // `data.len()`.
+ let ret =
+ 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 transmitted.
+ /// 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 valid `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 valid `serdev_device`.
+ unsafe { bindings::serdev_device_wait_until_sent(self.as_raw(), timeout.into_jiffies()) };
+ }
+}
+
+// SAFETY: `serdev::Device` is a transparent wrapper of `struct serdev_device`.
+// The offset is guaranteed to point to a valid device field inside `serdev::Device`.
+unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> {
+ const OFFSET: usize = 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<Self>) {
+ // SAFETY: The safety requirements guarantee that the refcount is non-zero.
+ unsafe { bindings::serdev_device_put(obj.cast().as_ptr()) }
+ }
+}
+
+impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
+ fn as_ref(&self) -> &device::Device<Ctx> {
+ // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
+ // `struct serdev_device`.
+ let dev = 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 `Device`
+// (i.e. `Device<Normal>) are thread safe.
+unsafe impl Sync for Device {}
+
+// SAFETY: Same as `Device<Normal>` -- the underlying `struct serdev_device` is the same;
+// `Bound` is a zero-sized type-state marker that does not affect thread safety.
+unsafe impl Sync for Device<device::Bound> {}
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: rust: add basic serial device bus abstractions
2026-04-29 18:21 ` [PATCH v7 3/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
@ 2026-05-05 1:18 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-05-05 1:18 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
This is the main patch (571 lines). Several observations:
**(1) Typo in Parity doc comment:**
```rust
+ /// Even partiy.
+ Even = bindings::serdev_parity_SERDEV_PARITY_EVEN,
```
Should be `Even parity.`
**(2) `Timeout::into_jiffies` silent overflow to "wait forever":**
```rust
+ fn into_jiffies(self) -> isize {
+ match self {
+ Self::Jiffies(value) => value.get().try_into().unwrap_or_default(),
+ Self::Milliseconds(value) => {
+ msecs_to_jiffies(value.get()).try_into().unwrap_or_default()
+ }
+ Self::Max => 0,
+ }
+ }
```
The `unwrap_or_default()` on overflow returns 0, which the C `serdev_device_write` converts to `MAX_SCHEDULE_TIMEOUT` (wait forever). A caller specifying a large but finite timeout would silently get an infinite wait. This is worth noting in the doc or choosing a different fallback (e.g., `isize::MAX`).
The `Self::Max => 0` mapping relies on `serdev_device_write`'s internal `if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT;` behavior. This is correct but fragile — it couples to an implementation detail of `serdev_device_write` rather than passing `MAX_SCHEDULE_TIMEOUT` directly. If this function is ever used for other serdev calls that don't do the 0-to-MAX conversion, it would break silently.
**(3) Potential truncation in `write_all`:**
```rust
+ pub fn write_all(&self, data: &[u8], timeout: Timeout) -> Result<usize> {
+ let ret = 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())
+ }
```
`serdev_device_write` returns `ssize_t` (isize in Rust). The cast `ret as i32` is safe for negative error codes as the comment states, but on 64-bit systems, a successful return value larger than `i32::MAX` (>2GB) would be truncated to a negative i32, causing `to_result` to return a spurious error. While this is extremely unlikely for serial writes, the same pattern appears in `write()` (where `write_buf` returns `int`, so there's no issue there). A more defensive approach might be to check `ret < 0` directly instead of casting through `to_result`.
**(4) Missing bracket in doc comment for `write`:**
```rust
+ /// Note that any accepted data has only been buffered by the controller. Use
+ /// [ Device::wait_until_sent`] to make sure the controller write buffer has actually been
```
Should be `[`Device::wait_until_sent`]` (no space after `[`).
**(5) `write_all` naming may confuse Rust developers:**
In `std::io::Write`, `write_all` guarantees all bytes are written or returns an error. Here, `write_all` can return fewer bytes than `data.len()` (if interrupted). The doc is clear about this, but the name may mislead readers used to the standard library convention. The C function being wrapped is `serdev_device_write` (vs `serdev_device_write_buf`), so alternative names like `write_timeout` might be less surprising.
**(6) Probe/receive synchronization — correct:**
The `PrivateData` with `Completion` + `UnsafeCell<bool>` for synchronizing probe completion with receive_buf is correctly structured:
```rust
+ // SAFETY: We have exclusive access to `private_data.error`.
+ unsafe { *private_data.error.get() = result.is_err() };
+ private_data.probe_complete.complete_all();
```
The `complete_all()` provides the necessary memory barrier so that `wait_for_completion()` in `receive_buf_callback` sees the error flag. The ordering in `probe_callback` is also correct: `rust_private_data` is set before `set_client_ops` and `devm_serdev_device_open`, ensuring the pointer is valid when `receive_buf` can first be called.
**(7) OPS struct wires `write_wakeup` to C function directly:**
```rust
+ const OPS: &'static bindings::serdev_device_ops = &bindings::serdev_device_ops {
+ receive_buf: if <F::Of<'static> as Driver<'static>>::HAS_RECEIVE {
+ Some(Self::receive_buf_callback)
+ } else {
+ None
+ },
+ write_wakeup: Some(bindings::serdev_device_write_wakeup),
+ };
```
Using `bindings::serdev_device_write_wakeup` directly as the function pointer is fine since it has the right signature. The `receive_buf` is conditionally set based on whether the driver implements `receive`, which is a nice use of vtable detection.
**(8) `Device` Send/Sync impls:**
```rust
+unsafe impl Send for Device {}
+unsafe impl Sync for Device {}
+unsafe impl Sync for Device<device::Bound> {}
```
The `Send` impl only covers `Device` (i.e., `Device<Normal>`). Missing `Send` for `Device<device::Bound>` and other contexts. However, `Device<Bound>` is typically only used by reference within a driver callback, so it may not need `Send`. This is likely intentional but could use a comment.
---
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v7 4/4] samples: rust: add Rust serial device bus sample device driver
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
` (2 preceding siblings ...)
2026-04-29 18:21 ` [PATCH v7 3/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
@ 2026-04-29 18:21 ` Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-30 19:58 ` [PATCH v7 0/4] rust: add basic serial device bus abstractions Rob Herring
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
5 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-29 18:21 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
From: Markus Probst <markus.probst@posteo.de>
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 <markus.probst@posteo.de>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
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
If unsure, say N.
+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) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_serdev.rs
new file mode 100644
index 000000000000..956ca62831fe
--- /dev/null
+++ b/samples/rust/rust_driver_serdev.rs
@@ -0,0 +1,86 @@
+// 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<serdev::Device>,
+}
+
+kernel::of_device_table!(
+ OF_TABLE,
+ MODULE_OF_TABLE,
+ <SampleDriver as serdev::Driver<'_>>::IdInfo,
+ [(of::DeviceId::new(c"test,rust_driver_serdev"), ())]
+);
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <SampleDriver as serdev::Driver<'_>>::IdInfo,
+ [(acpi::DeviceId::new(c"LNUXBEEF"), ())]
+);
+
+#[vtable]
+impl<'a> serdev::Driver<'a> for SampleDriver {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+
+ fn probe(
+ sdev: &'a serdev::Device<Core>,
+ _info: Option<&'a Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> + 'a {
+ let dev = 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").optional())
+ .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(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = 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",
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: samples: rust: add Rust serial device bus sample device driver
2026-04-29 18:21 ` [PATCH v7 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
@ 2026-05-05 1:18 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-05-05 1:18 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
Clean, well-structured sample driver. It demonstrates:
- OF and ACPI device table registration
- Probe with optional baudrate property from firmware
- Receive callback that echoes data back
- Drop for cleanup logging
```rust
+ fn receive(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = sdev.write_all(data, serdev::Timeout::Max);
+ data.len()
+ }
```
The `let _ =` silently discards write errors during echo, which is fine for a sample. The function always returns `data.len()` claiming all bytes were consumed regardless of write success — acceptable for a demo.
**Minor:** The Kconfig entry doesn't have a `depends on SAMPLES` guard, but that's consistent with other sample drivers in the same file.
No significant issues with this patch.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v7 0/4] rust: add basic serial device bus abstractions
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
` (3 preceding siblings ...)
2026-04-29 18:21 ` [PATCH v7 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
@ 2026-04-30 19:58 ` Rob Herring
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
5 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2026-04-30 19:58 UTC (permalink / raw)
To: Markus Probst
Cc: Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda, Gary Guo,
Björn 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, linux-serial, linux-kernel, rust-for-linux,
linux-pm, driver-core, dri-devel
On Wed, Apr 29, 2026 at 08:21:30PM +0200, Markus Probst wrote:
> This patch series adds the serdev device bus rust abstraction into the
> kernel.
>
> This abstraction will be used by a driver,
> which targets the MCU devices in Synology devices.
>
> Kari Argillander also messaged me, stating that he wants to write a
> watchdog driver with this abstraction (needing initial device data).
>
> @Rob: Are you willing to maintain these rust abstractions yourself,
> as you are the expert on this subsystem, otherwise I would take care of
> it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
> the second case, I assume you are going to pick those patches as-is into
> your tree, after they have been reviewed?
Well I can ignore the Rust part as much as I ignore the C serdev part...
Honestly, I need to find someone else to maintain all of it as I don't
really have the bandwidth. I don't think we should split it though.
And I don't have a tree for serdev. Greg picks up the serdev patches. If
the Rust folks are fine with them, then I am.
Rob
^ permalink raw reply [flat|nested] 16+ messages in thread* Claude review: rust: add basic serial device bus abstractions
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
` (4 preceding siblings ...)
2026-04-30 19:58 ` [PATCH v7 0/4] rust: add basic serial device bus abstractions Rob Herring
@ 2026-05-05 1:18 ` Claude Code Review Bot
5 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-05-05 1:18 UTC (permalink / raw)
To: dri-devel-reviews
Overall Series Review
Subject: rust: add basic serial device bus abstractions
Author: Markus Probst via B4 Relay <devnull+markus.probst.posteo.de@kernel.org>
Patches: 6
Reviewed: 2026-05-05T11:18:28.881410
---
This is a well-structured 4-patch series adding Rust abstractions for the serial device bus (serdev) subsystem. The series is now at v7, showing significant iteration. The architecture follows established kernel Rust patterns: a preparatory devres API change, a C-side struct modification, the main abstraction, and a sample driver.
The code quality is generally good, with proper use of the kernel's Rust driver model (`DriverLayout`, `RegistrationOps`, `Adapter`), correct synchronization for the probe/receive race via `Completion`, and a clean sample driver. There are a few issues ranging from a potential truncation bug in `write_all` to minor doc typos.
The series depends on Danilo Krummrich's driver-lifetime patches, which is noted in the cover letter.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v6 0/4] rust: add basic serial device bus abstractions
@ 2026-04-27 18:05 Markus Probst via B4 Relay
2026-04-27 18:05 ` [PATCH v6 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-27 18:05 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
This patch series adds the serdev device bus rust abstraction into the
kernel.
This abstraction will be used by a driver,
which targets the MCU devices in Synology devices.
Kari Argillander also messaged me, stating that he wants to write a
watchdog driver with this abstraction (needing initial device data).
@Rob: Are you willing to maintain these rust abstractions yourself,
as you are the expert on this subsystem, otherwise I would take care of
it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
the second case, I assume you are going to pick those patches as-is into
your tree, after they have been reviewed?
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v6:
- rebased onto v7.1-rc1
- Link to v5: https://patch.msgid.link/20260420-rust_serdev-v5-0-57e8ba0519f3@posteo.de
Changes in v5:
- fix typo in documentation
- Link to v4: https://lore.kernel.org/r/20260411-rust_serdev-v4-0-845e960c6627@posteo.de
Changes in v4:
- fixed not selecting rust serdev abstraction in sample
- Link to v3: https://lore.kernel.org/r/20260313-rust_serdev-v3-0-c9a3af214f7f@posteo.de
Changes in v3:
- fix vertical import style
- add Kconfig entry for the rust abstraction
- fix documentation in include/linux/serdev.h
- rename private_data to rust_private_data
- fix `complete_all` <-> `wait_for_completion` typo
- move drvdata_borrow call after the completion
- Link to v2: https://lore.kernel.org/r/20260306-rust_serdev-v2-0-e9b23b42b255@posteo.de
Changes in v2:
- fix documentation in `serdev::Driver::write` and
`serdev::Driver::write_all`
- remove use of `dev_info` in probe from the sample
- remove `properties_parse` from the sample
- add optional `baudrate` property to the sample
- remove 1. patch
- remove `TryFrom<&device::Device<Ctx>> for &serdev::Device<Ctx>`
implementation
- fix import style
- add patch to return reference in `devres::register` to fix safety
issue
- add patch to add private data to serdev_device, to fix
`Device.drvdata()` from failing
- simplify abstraction by removing ability to receive the initial
transmission. It may be added later in a separate patch series if
needed.
- Link to v1: https://lore.kernel.org/r/20251220-rust_serdev-v1-0-e44645767621@posteo.de
---
Markus Probst (4):
rust: devres: return reference in `devres::register`
serdev: add rust private data to serdev_device
rust: add basic serial device bus abstractions
samples: rust: add Rust serial device bus sample device driver
drivers/tty/serdev/Kconfig | 7 +
include/linux/serdev.h | 15 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/serdev.c | 22 ++
rust/kernel/cpufreq.rs | 3 +-
rust/kernel/devres.rs | 15 +-
rust/kernel/drm/driver.rs | 3 +-
rust/kernel/lib.rs | 2 +
rust/kernel/serdev.rs | 536 +++++++++++++++++++++++++++++++++++++
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++
13 files changed, 693 insertions(+), 10 deletions(-)
---
base-commit: 5e9b7d093f3f77cb0af4409559e3d139babfb443
change-id: 20251217-rust_serdev-ee5481e9085c
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v6 4/4] samples: rust: add Rust serial device bus sample device driver
2026-04-27 18:05 [PATCH v6 0/4] " Markus Probst via B4 Relay
@ 2026-04-27 18:05 ` Markus Probst via B4 Relay
2026-04-28 4:14 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-27 18:05 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
From: Markus Probst <markus.probst@posteo.de>
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 <markus.probst@posteo.de>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
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
If unsure, say N.
+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) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_serdev.rs
new file mode 100644
index 000000000000..8cf3fb451b22
--- /dev/null
+++ b/samples/rust/rust_driver_serdev.rs
@@ -0,0 +1,86 @@
+// 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<serdev::Device>,
+}
+
+kernel::of_device_table!(
+ OF_TABLE,
+ MODULE_OF_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(of::DeviceId::new(c"test,rust_driver_serdev"), ())]
+);
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(acpi::DeviceId::new(c"LNUXBEEF"), ())]
+);
+
+#[vtable]
+impl serdev::Driver for SampleDriver {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+
+ fn probe(
+ sdev: &serdev::Device<Core>,
+ _info: Option<&Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> {
+ let dev = 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").optional())
+ .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(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = 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",
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: samples: rust: add Rust serial device bus sample device driver
2026-04-27 18:05 ` [PATCH v6 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
@ 2026-04-28 4:14 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-04-28 4:14 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
The sample is clean and demonstrates the key API surface well.
**One issue with the sample probe:**
```rust
fn probe(
sdev: &serdev::Device<Core>,
_info: Option<&Self::IdInfo>,
) -> impl PinInit<Self, Error> {
...
if sdev.set_baudrate(...).is_err() {
return Err(EINVAL);
}
```
The `set_baudrate` method is on `Device<Bound>`, but `sdev` is `&Device<Core>`. This works via the deref coercion chain, which is correct but could be surprising to readers. A brief comment in the abstraction's module-level docs explaining the device context hierarchy and auto-deref would help (though this is a broader Rust-for-Linux documentation issue, not specific to this patch).
**The receive callback echoes data back:**
```rust
fn receive(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
let _ = sdev.write_all(data, serdev::Timeout::Max);
data.len()
}
```
This is fine for a sample. The `let _ =` discards the write result, which is acceptable for demonstration purposes. Note that this always returns `data.len()` (claiming all data was consumed) regardless of whether `write_all` succeeded, which is the right behavior for a simple echo.
**The `SampleDriver` stores an `ARef<serdev::Device>` but only uses it in `Drop`** for a debug message. This is fine as a sample demonstrating how to keep a reference to the device.
No blocking issues with this patch.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v5 0/4] rust: add basic serial device bus abstractions
@ 2026-04-20 20:07 Markus Probst
2026-04-20 20:07 ` [PATCH v5 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst @ 2026-04-20 20:07 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
This patch series adds the serdev device bus rust abstraction into the
kernel.
This abstraction will be used by a driver,
which targets the MCU devices in Synology devices.
Kari Argillander also messaged me, stating that he wants to write a
watchdog driver with this abstraction (needing initial device data).
@Rob: Are you willing to maintain these rust abstractions yourself,
as you are the expert on this subsystem, otherwise I would take care of
it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
the second case, I assume you are going to pick those patches as-is into
your tree, after they have been reviewed?
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v5:
- fix typo in documentation
- Link to v4: https://lore.kernel.org/r/20260411-rust_serdev-v4-0-845e960c6627@posteo.de
Changes in v4:
- fixed not selecting rust serdev abstraction in sample
- Link to v3: https://lore.kernel.org/r/20260313-rust_serdev-v3-0-c9a3af214f7f@posteo.de
Changes in v3:
- fix vertical import style
- add Kconfig entry for the rust abstraction
- fix documentation in include/linux/serdev.h
- rename private_data to rust_private_data
- fix `complete_all` <-> `wait_for_completion` typo
- move drvdata_borrow call after the completion
- Link to v2: https://lore.kernel.org/r/20260306-rust_serdev-v2-0-e9b23b42b255@posteo.de
Changes in v2:
- fix documentation in `serdev::Driver::write` and
`serdev::Driver::write_all`
- remove use of `dev_info` in probe from the sample
- remove `properties_parse` from the sample
- add optional `baudrate` property to the sample
- remove 1. patch
- remove `TryFrom<&device::Device<Ctx>> for &serdev::Device<Ctx>`
implementation
- fix import style
- add patch to return reference in `devres::register` to fix safety
issue
- add patch to add private data to serdev_device, to fix
`Device.drvdata()` from failing
- simplify abstraction by removing ability to receive the initial
transmission. It may be added later in a separate patch series if
needed.
- Link to v1: https://lore.kernel.org/r/20251220-rust_serdev-v1-0-e44645767621@posteo.de
---
Markus Probst (4):
rust: devres: return reference in `devres::register`
serdev: add rust private data to serdev_device
rust: add basic serial device bus abstractions
samples: rust: add Rust serial device bus sample device driver
drivers/tty/serdev/Kconfig | 7 +
include/linux/serdev.h | 15 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/serdev.c | 22 ++
rust/kernel/cpufreq.rs | 3 +-
rust/kernel/devres.rs | 15 +-
rust/kernel/drm/driver.rs | 3 +-
rust/kernel/lib.rs | 2 +
rust/kernel/serdev.rs | 536 +++++++++++++++++++++++++++++++++++++
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++
13 files changed, 693 insertions(+), 10 deletions(-)
---
base-commit: 3131ff5a117498bb4b9db3a238bb311cbf8383ce
change-id: 20251217-rust_serdev-ee5481e9085c
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v5 4/4] samples: rust: add Rust serial device bus sample device driver
2026-04-20 20:07 [PATCH v5 0/4] rust: add basic serial device bus abstractions Markus Probst
@ 2026-04-20 20:07 ` Markus Probst
2026-04-22 23:21 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst @ 2026-04-20 20:07 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, 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 <markus.probst@posteo.de>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
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
If unsure, say N.
+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) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_serdev.rs
new file mode 100644
index 000000000000..8cf3fb451b22
--- /dev/null
+++ b/samples/rust/rust_driver_serdev.rs
@@ -0,0 +1,86 @@
+// 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<serdev::Device>,
+}
+
+kernel::of_device_table!(
+ OF_TABLE,
+ MODULE_OF_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(of::DeviceId::new(c"test,rust_driver_serdev"), ())]
+);
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(acpi::DeviceId::new(c"LNUXBEEF"), ())]
+);
+
+#[vtable]
+impl serdev::Driver for SampleDriver {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+
+ fn probe(
+ sdev: &serdev::Device<Core>,
+ _info: Option<&Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> {
+ let dev = 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").optional())
+ .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(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = 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",
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: samples: rust: add Rust serial device bus sample device driver
2026-04-20 20:07 ` [PATCH v5 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
@ 2026-04-22 23:21 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-04-22 23:21 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
Clean and functional sample driver. A few observations:
**Echoing data in receive callback:**
```rust
+ fn receive(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = sdev.write_all(data, serdev::Timeout::Max);
+ data.len()
+ }
```
The `write_all` with `Timeout::Max` could block indefinitely if the device can't accept data. For a sample this is acceptable, but a brief comment noting this is intentional would be helpful. Also, `let _ =` silently discards write errors, which is fine for a sample.
**Baudrate handling:**
```rust
+ if sdev
+ .set_baudrate(
+ dev.fwnode()
+ .and_then(|fwnode| fwnode.property_read(c"baudrate").optional())
+ .unwrap_or(115200),
+ )
+ .is_err()
+ {
+ return Err(EINVAL);
+ }
```
Reading a `baudrate` property from firmware and falling back to 115200 is a reasonable pattern. The `set_baudrate` error (which contains the actual baudrate set) is discarded and replaced with `EINVAL`, which is appropriate.
**Kconfig entry properly uses `select`:**
```
+ select RUST_SERIAL_DEV_BUS_ABSTRACTIONS
```
This ensures the abstraction is compiled when the sample is enabled. Correct.
The sample effectively demonstrates OF and ACPI device table setup, probe/remove lifecycle, baudrate/flow-control/parity configuration, and the receive callback -- good coverage for a sample driver.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 0/4] rust: add basic serial device bus abstractions
@ 2026-04-11 15:10 Markus Probst via B4 Relay
2026-04-11 15:10 ` [PATCH v4 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-11 15:10 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
This patch series adds the serdev device bus rust abstraction into the
kernel.
This abstraction will be used by a driver,
which targets the MCU devices in Synology devices.
Kari Argillander also messaged me, stating that he wants to write a
watchdog driver with this abstraction (needing initial device data).
@Rob: Are you willing to maintain these rust abstractions yourself,
as you are the expert on this subsystem, otherwise I would take care of
it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
the second case, I assume you are going to pick those patches as-is into
your tree, after they have been reviewed?
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v4:
- fixed not selecting rust serdev abstraction in sample
- Link to v3: https://lore.kernel.org/r/20260313-rust_serdev-v3-0-c9a3af214f7f@posteo.de
Changes in v3:
- fix vertical import style
- add Kconfig entry for the rust abstraction
- fix documentation in include/linux/serdev.h
- rename private_data to rust_private_data
- fix `complete_all` <-> `wait_for_completion` typo
- move drvdata_borrow call after the completion
- Link to v2: https://lore.kernel.org/r/20260306-rust_serdev-v2-0-e9b23b42b255@posteo.de
Changes in v2:
- fix documentation in `serdev::Driver::write` and
`serdev::Driver::write_all`
- remove use of `dev_info` in probe from the sample
- remove `properties_parse` from the sample
- add optional `baudrate` property to the sample
- remove 1. patch
- remove `TryFrom<&device::Device<Ctx>> for &serdev::Device<Ctx>`
implementation
- fix import style
- add patch to return reference in `devres::register` to fix safety
issue
- add patch to add private data to serdev_device, to fix
`Device.drvdata()` from failing
- simplify abstraction by removing ability to receive the initial
transmission. It may be added later in a separate patch series if
needed.
- Link to v1: https://lore.kernel.org/r/20251220-rust_serdev-v1-0-e44645767621@posteo.de
---
Markus Probst (4):
rust: devres: return reference in `devres::register`
serdev: add rust private data to serdev_device
rust: add basic serial device bus abstractions
samples: rust: add Rust serial device bus sample device driver
drivers/tty/serdev/Kconfig | 7 +
include/linux/serdev.h | 15 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/serdev.c | 22 ++
rust/kernel/cpufreq.rs | 3 +-
rust/kernel/devres.rs | 15 +-
rust/kernel/drm/driver.rs | 3 +-
rust/kernel/lib.rs | 2 +
rust/kernel/serdev.rs | 536 +++++++++++++++++++++++++++++++++++++
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++
13 files changed, 693 insertions(+), 10 deletions(-)
---
base-commit: c369299895a591d96745d6492d4888259b004a9e
change-id: 20251217-rust_serdev-ee5481e9085c
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v4 4/4] samples: rust: add Rust serial device bus sample device driver
2026-04-11 15:10 [PATCH v4 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
@ 2026-04-11 15:10 ` Markus Probst via B4 Relay
2026-04-11 22:55 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst via B4 Relay @ 2026-04-11 15:10 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
From: Markus Probst <markus.probst@posteo.de>
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 <markus.probst@posteo.de>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
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
If unsure, say N.
+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) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_serdev.rs
new file mode 100644
index 000000000000..8cf3fb451b22
--- /dev/null
+++ b/samples/rust/rust_driver_serdev.rs
@@ -0,0 +1,86 @@
+// 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<serdev::Device>,
+}
+
+kernel::of_device_table!(
+ OF_TABLE,
+ MODULE_OF_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(of::DeviceId::new(c"test,rust_driver_serdev"), ())]
+);
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(acpi::DeviceId::new(c"LNUXBEEF"), ())]
+);
+
+#[vtable]
+impl serdev::Driver for SampleDriver {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+
+ fn probe(
+ sdev: &serdev::Device<Core>,
+ _info: Option<&Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> {
+ let dev = 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").optional())
+ .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(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = 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",
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: samples: rust: add Rust serial device bus sample device driver
2026-04-11 15:10 ` [PATCH v4 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
@ 2026-04-11 22:55 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-04-11 22:55 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
A clean sample that demonstrates probe, receive (echo/loopback), and cleanup. A few observations:
**Error in receive is swallowed**:
```rust
+ fn receive(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = sdev.write_all(data, serdev::Timeout::Max);
+ data.len()
+ }
```
The `write_all` error is discarded with `let _ = ...`. For a sample this is acceptable, but a comment like `// Ignore write errors for simplicity` would be helpful.
**Strict baudrate matching**:
```rust
+ if sdev
+ .set_baudrate(...)
+ .is_err()
+ {
+ return Err(EINVAL);
+ }
```
This fails probe if the exact baudrate isn't matched. As noted above, many serial controllers approximate the baudrate. For a sample this is fine, but it could be confusing if someone tries to run this on real hardware.
**License string**: `"GPL v2"` is used, which is the correct form for `MODULE_LICENSE`.
**Overall the sample is clean and well-structured**, demonstrating the key abstractions (OF/ACPI ID tables, probe, receive, device reference management via `ARef`, Drop-based cleanup).
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 0/4] rust: add basic serial device bus abstractions
@ 2026-03-13 18:12 Markus Probst
2026-03-13 18:12 ` [PATCH v3 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst @ 2026-03-13 18:12 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
This patch series adds the serdev device bus rust abstraction into the
kernel.
This abstraction will be used by a driver,
which targets the MCU devices in Synology devices.
Kari Argillander also messaged me, stating that he wants to write a
watchdog driver with this abstraction (needing initial device data).
@Rob: Are you willing to maintain these rust abstractions yourself,
as you are the expert on this subsystem, otherwise I would take care of
it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
the second case, I assume you are going to pick those patches as-is into
your tree, after they have been reviewed?
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v3:
- fix vertical import style
- add Kconfig entry for the rust abstraction
- fix documentation in include/linux/serdev.h
- rename private_data to rust_private_data
- fix `complete_all` <-> `wait_for_completion` typo
- move drvdata_borrow call after the completion
- Link to v2: https://lore.kernel.org/r/20260306-rust_serdev-v2-0-e9b23b42b255@posteo.de
Changes in v2:
- fix documentation in `serdev::Driver::write` and
`serdev::Driver::write_all`
- remove use of `dev_info` in probe from the sample
- remove `properties_parse` from the sample
- add optional `baudrate` property to the sample
- remove 1. patch
- remove `TryFrom<&device::Device<Ctx>> for &serdev::Device<Ctx>`
implementation
- fix import style
- add patch to return reference in `devres::register` to fix safety
issue
- add patch to add private data to serdev_device, to fix
`Device.drvdata()` from failing
- simplify abstraction by removing ability to receive the initial
transmission. It may be added later in a separate patch series if
needed.
- Link to v1: https://lore.kernel.org/r/20251220-rust_serdev-v1-0-e44645767621@posteo.de
---
Markus Probst (4):
rust: devres: return reference in `devres::register`
serdev: add rust private data to serdev_device
rust: add basic serial device bus abstractions
samples: rust: add Rust serial device bus sample device driver
drivers/tty/serdev/Kconfig | 7 +
include/linux/serdev.h | 15 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/serdev.c | 22 ++
rust/kernel/cpufreq.rs | 3 +-
rust/kernel/devres.rs | 15 +-
rust/kernel/drm/driver.rs | 3 +-
rust/kernel/lib.rs | 2 +
rust/kernel/serdev.rs | 536 +++++++++++++++++++++++++++++++++++++
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++
13 files changed, 693 insertions(+), 10 deletions(-)
---
base-commit: 1f318b96cc84d7c2ab792fcc0bfd42a7ca890681
change-id: 20251217-rust_serdev-ee5481e9085c
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v3 4/4] samples: rust: add Rust serial device bus sample device driver
2026-03-13 18:12 [PATCH v3 0/4] rust: add basic serial device bus abstractions Markus Probst
@ 2026-03-13 18:12 ` Markus Probst
2026-03-16 2:17 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst @ 2026-03-13 18:12 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, 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 <markus.probst@posteo.de>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index c49ab9106345..a421470d2c52 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -161,6 +161,17 @@ config SAMPLE_RUST_DRIVER_AUXILIARY
If unsure, say N.
+config SAMPLE_RUST_DRIVER_SERDEV
+ tristate "Serial Device Bus Device Driver"
+ depends on SERIAL_DEV_BUS
+ 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) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_serdev.rs
new file mode 100644
index 000000000000..8cf3fb451b22
--- /dev/null
+++ b/samples/rust/rust_driver_serdev.rs
@@ -0,0 +1,86 @@
+// 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<serdev::Device>,
+}
+
+kernel::of_device_table!(
+ OF_TABLE,
+ MODULE_OF_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(of::DeviceId::new(c"test,rust_driver_serdev"), ())]
+);
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(acpi::DeviceId::new(c"LNUXBEEF"), ())]
+);
+
+#[vtable]
+impl serdev::Driver for SampleDriver {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+
+ fn probe(
+ sdev: &serdev::Device<Core>,
+ _info: Option<&Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> {
+ let dev = 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").optional())
+ .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(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = 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",
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: samples: rust: add Rust serial device bus sample device driver
2026-03-13 18:12 ` [PATCH v3 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
@ 2026-03-16 2:17 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-03-16 2:17 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
The sample is clean and demonstrates the API well.
**Missing dependency in Kconfig:**
```
+config SAMPLE_RUST_DRIVER_SERDEV
+ tristate "Serial Device Bus Device Driver"
+ depends on SERIAL_DEV_BUS
```
This should also `depends on RUST_SERIAL_DEV_BUS_ABSTRACTIONS` (or `select` it), since the sample uses `kernel::serdev` which is gated behind that config option.
**The sample stores an `ARef<serdev::Device>` but never uses it functionally:**
```rust
+struct SampleDriver {
+ sdev: ARef<serdev::Device>,
+}
```
It's only used in `Drop` for a debug message. This is fine for a sample, but the reference counting should be correct — `sdev.into()` in `probe` calls `impl_device_context_into_aref` which should increment the refcount.
**Minor: `"GPL v2"` vs `"GPL"`:**
```rust
+ license: "GPL v2",
```
Modern kernel modules typically use just `"GPL"`. `"GPL v2"` is also accepted but `"GPL"` is the recommended form.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 0/4] rust: add basic serial device bus abstractions
@ 2026-03-06 19:35 Markus Probst
2026-03-06 19:35 ` [PATCH v2 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst @ 2026-03-06 19:35 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, Markus Probst
This patch series adds the serdev device bus rust abstraction into the
kernel.
This abstraction will be used by a driver,
which targets the MCU devices in Synology devices.
Kari Argillander also messaged me, stating that he wants to write a
watchdog driver with this abstraction (needing initial device data).
@Rob: Are you willing to maintain these rust abstractions yourself,
as you are the expert on this subsystem, otherwise I would take care of
it with a "SERIAL DEVICE BUS [RUST]" section in the MAINTAINERS file. In
the second case, I assume you are going to pick those patches as-is into
your tree, after they have been reviewed?
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
Changes in v2:
- fix documentation in `serdev::Driver::write` and
`serdev::Driver::write_all`
- remove use of `dev_info` in probe from the sample
- remove `properties_parse` from the sample
- add optional `baudrate` property to the sample
- remove 1. patch
- remove `TryFrom<&device::Device<Ctx>> for &serdev::Device<Ctx>`
implementation
- fix import style
- add patch to return reference in `devres::register` to fix safety
issue
- add patch to add private data to serdev_device, to fix
`Device.drvdata()` from failing
- simplify abstraction by removing ability to receive the initial
transmission. It may be added later in a separate patch series if
needed.
- Link to v1: https://lore.kernel.org/r/20251220-rust_serdev-v1-0-e44645767621@posteo.de
---
Markus Probst (4):
rust: devres: return reference in `devres::register`
serdev: add private data to serdev_device
rust: add basic serial device bus abstractions
samples: rust: add Rust serial device bus sample device driver
include/linux/serdev.h | 14 +-
rust/bindings/bindings_helper.h | 1 +
rust/helpers/helpers.c | 1 +
rust/helpers/serdev.c | 22 ++
rust/kernel/cpufreq.rs | 3 +-
rust/kernel/devres.rs | 15 +-
rust/kernel/drm/driver.rs | 3 +-
rust/kernel/lib.rs | 2 +
rust/kernel/serdev.rs | 533 +++++++++++++++++++++++++++++++++++++
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++
12 files changed, 682 insertions(+), 10 deletions(-)
---
base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
change-id: 20251217-rust_serdev-ee5481e9085c
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v2 4/4] samples: rust: add Rust serial device bus sample device driver
2026-03-06 19:35 [PATCH v2 0/4] rust: add basic serial device bus abstractions Markus Probst
@ 2026-03-06 19:35 ` Markus Probst
2026-03-08 22:21 ` Claude review: " Claude Code Review Bot
0 siblings, 1 reply; 16+ messages in thread
From: Markus Probst @ 2026-03-06 19:35 UTC (permalink / raw)
To: Rob Herring, Greg Kroah-Hartman, Jiri Slaby, Miguel Ojeda,
Gary Guo, Björn 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, linux-kernel, rust-for-linux, linux-pm, driver-core,
dri-devel, 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 <markus.probst@posteo.de>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_driver_serdev.rs | 86 ++++++++++++++++++++++++++++++++++++++
3 files changed, 98 insertions(+)
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index c49ab9106345..a421470d2c52 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -161,6 +161,17 @@ config SAMPLE_RUST_DRIVER_AUXILIARY
If unsure, say N.
+config SAMPLE_RUST_DRIVER_SERDEV
+ tristate "Serial Device Bus Device Driver"
+ depends on SERIAL_DEV_BUS
+ 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) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) += rust_driver_usb.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) += rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_SERDEV) += rust_driver_serdev.o
obj-$(CONFIG_SAMPLE_RUST_CONFIGFS) += rust_configfs.o
obj-$(CONFIG_SAMPLE_RUST_SOC) += rust_soc.o
diff --git a/samples/rust/rust_driver_serdev.rs b/samples/rust/rust_driver_serdev.rs
new file mode 100644
index 000000000000..8cf3fb451b22
--- /dev/null
+++ b/samples/rust/rust_driver_serdev.rs
@@ -0,0 +1,86 @@
+// 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<serdev::Device>,
+}
+
+kernel::of_device_table!(
+ OF_TABLE,
+ MODULE_OF_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(of::DeviceId::new(c"test,rust_driver_serdev"), ())]
+);
+
+kernel::acpi_device_table!(
+ ACPI_TABLE,
+ MODULE_ACPI_TABLE,
+ <SampleDriver as serdev::Driver>::IdInfo,
+ [(acpi::DeviceId::new(c"LNUXBEEF"), ())]
+);
+
+#[vtable]
+impl serdev::Driver for SampleDriver {
+ type IdInfo = ();
+ const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+ const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
+
+ fn probe(
+ sdev: &serdev::Device<Core>,
+ _info: Option<&Self::IdInfo>,
+ ) -> impl PinInit<Self, Error> {
+ let dev = 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").optional())
+ .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(sdev: &serdev::Device<Bound>, _this: Pin<&Self>, data: &[u8]) -> usize {
+ let _ = 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",
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Claude review: samples: rust: add Rust serial device bus sample device driver
2026-03-06 19:35 ` [PATCH v2 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
@ 2026-03-08 22:21 ` Claude Code Review Bot
0 siblings, 0 replies; 16+ messages in thread
From: Claude Code Review Bot @ 2026-03-08 22:21 UTC (permalink / raw)
To: dri-devel-reviews
Patch Review
The sample is clean and demonstrates the abstraction well. A few notes:
**`set_baudrate` error handling is odd due to the API design:**
```rust
if sdev
.set_baudrate(
dev.fwnode()
.and_then(|fwnode| fwnode.property_read(c"baudrate").optional())
.unwrap_or(115200),
)
.is_err()
{
return Err(EINVAL);
}
```
This discards the actual baudrate returned in the error. If `set_baudrate` returned `u32` instead of `Result<(), u32>`, this would be simpler and more informative.
**Echo server with `Timeout::Max` would hang:** Due to the `Timeout::Max` bug (returning 0), `write_all` in receive would return immediately or with ETIMEDOUT rather than actually waiting. This makes the sample non-functional in practice.
**The sample stores an `ARef<serdev::Device>` but never uses it** (except in Drop for a debug message). This is fine for a sample but worth noting.
---
Generated by Claude Code Patch Reviewer
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-05-05 1:18 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-29 18:21 [PATCH v7 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
2026-04-29 18:21 ` [PATCH v7 1/4] rust: devres: return reference in `devres::register` Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-29 18:21 ` [PATCH v7 2/4] serdev: add rust private data to serdev_device Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-29 18:21 ` [PATCH v7 3/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-29 18:21 ` [PATCH v7 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
2026-04-30 19:58 ` [PATCH v7 0/4] rust: add basic serial device bus abstractions Rob Herring
2026-05-05 1:18 ` Claude review: " Claude Code Review Bot
-- strict thread matches above, loose matches on Subject: below --
2026-04-27 18:05 [PATCH v6 0/4] " Markus Probst via B4 Relay
2026-04-27 18:05 ` [PATCH v6 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
2026-04-28 4:14 ` Claude review: " Claude Code Review Bot
2026-04-20 20:07 [PATCH v5 0/4] rust: add basic serial device bus abstractions Markus Probst
2026-04-20 20:07 ` [PATCH v5 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
2026-04-22 23:21 ` Claude review: " Claude Code Review Bot
2026-04-11 15:10 [PATCH v4 0/4] rust: add basic serial device bus abstractions Markus Probst via B4 Relay
2026-04-11 15:10 ` [PATCH v4 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst via B4 Relay
2026-04-11 22:55 ` Claude review: " Claude Code Review Bot
2026-03-13 18:12 [PATCH v3 0/4] rust: add basic serial device bus abstractions Markus Probst
2026-03-13 18:12 ` [PATCH v3 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
2026-03-16 2:17 ` Claude review: " Claude Code Review Bot
2026-03-06 19:35 [PATCH v2 0/4] rust: add basic serial device bus abstractions Markus Probst
2026-03-06 19:35 ` [PATCH v2 4/4] samples: rust: add Rust serial device bus sample device driver Markus Probst
2026-03-08 22:21 ` Claude review: " Claude Code Review Bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox