From 0242623384c767b1156b61b67894b4ecf6682b8b Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Thu, 16 Oct 2025 14:55:28 +0200 Subject: rust: driver: let probe() return impl PinInit The driver model defines the lifetime of the private data stored in (and owned by) a bus device to be valid from when the driver is bound to a device (i.e. from successful probe()) until the driver is unbound from the device. This is already taken care of by the Rust implementation of the driver model. However, we still ask drivers to return a Result>> from probe(). Unlike in C, where we do not have the concept of initializers, but rather deal with uninitialized memory, drivers can just return an impl PinInit instead. This contributes to more clarity to the fact that a driver returns it's device private data in probe() and the Rust driver model owns the data, manages the lifetime and - considering the lifetime - provides (safe) accessors for the driver. Hence, let probe() functions return an impl PinInit instead of Result>>. Reviewed-by: Alice Ryhl Acked-by: Viresh Kumar Reviewed-by: Alexandre Courbot Acked-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/usb.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'rust/kernel/usb.rs') diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 14ddb711bab3..fa8367c0dbaa 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -67,10 +67,10 @@ impl Adapter { let id = unsafe { &*id.cast::() }; let info = T::ID_TABLE.info(id.index()); - let data = T::probe(intf, id, info)?; + let data = T::probe(intf, id, info); let dev: &device::Device = intf.as_ref(); - dev.set_drvdata(data); + dev.set_drvdata(data)?; Ok(0) }) } @@ -270,7 +270,7 @@ macro_rules! usb_device_table { /// _interface: &usb::Interface, /// _id: &usb::DeviceId, /// _info: &Self::IdInfo, -/// ) -> Result>> { +/// ) -> impl PinInit { /// Err(ENODEV) /// } /// @@ -292,7 +292,7 @@ pub trait Driver { interface: &Interface, id: &DeviceId, id_info: &Self::IdInfo, - ) -> Result>>; + ) -> impl PinInit; /// USB driver disconnect. /// -- cgit From 6bbaa93912bfdfd5ffdc804275cc6a444c9400af Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Tue, 21 Oct 2025 00:34:23 +0200 Subject: rust: device: narrow the generic of drvdata_obtain() Let T be the actual private driver data type without the surrounding box, as it leaves less room for potential bugs. Reviewed-by: Alice Ryhl Reviewed-by: Greg Kroah-Hartman Signed-off-by: Danilo Krummrich --- rust/kernel/usb.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'rust/kernel/usb.rs') diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index fa8367c0dbaa..92215fdc3c6a 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -87,9 +87,9 @@ impl Adapter { // SAFETY: `disconnect_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>`. - let data = unsafe { dev.drvdata_obtain::>>() }; + let data = unsafe { dev.drvdata_obtain::() }; - T::disconnect(intf, data.as_ref()); + T::disconnect(intf, data.data()); } } -- cgit From fde40a558dbd4945bba03cd7f425feab4c92e1d1 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Mon, 3 Nov 2025 12:01:03 +0100 Subject: rust: usb: fix broken call to T::disconnect() A refactoring of Device::drvdata_obtain() broke T::disconnect() in the USB abstractions. """ error[E0599]: no method named `data` found for struct `core::pin::Pin>` in the current scope --> rust/kernel/usb.rs:92:34 | 92 | T::disconnect(intf, data.data()); | ^^^^ method not found in `core::pin::Pin>` error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0599`. make[2]: *** [rust/Makefile:553: rust/kernel.o] Error 1 make[1]: *** [/builddir/build/BUILD/kernel-6.18.0-build/kernel-next-20251103/linux-6.18.0-0.0.next.20251103.436.vanilla.fc44.x86_64/Makefile:1316: prepare] Error 2 make: *** [Makefile:256: __sub-make] Error 2 """ This slipped through, since the USB abstractions are globally disabled. However, the USB tree recently enabled them, hence it showed up in linux-next. Reported-by: Thorsten Leemhuis Closes: https://lore.kernel.org/all/1c8afbc0-e888-4702-9e4e-fa8aef0f97ae@leemhuis.info/ Fixes: 6bbaa93912bf ("rust: device: narrow the generic of drvdata_obtain()") Reviewed-by: Alice Ryhl Tested-by: Thorsten Leemhuis Link: https://patch.msgid.link/20251103110115.1925072-1-dakr@kernel.org Signed-off-by: Danilo Krummrich --- rust/kernel/usb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rust/kernel/usb.rs') diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 92215fdc3c6a..534e3ded5442 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -89,7 +89,7 @@ impl Adapter { // and stored a `Pin>`. let data = unsafe { dev.drvdata_obtain::() }; - T::disconnect(intf, data.data()); + T::disconnect(intf, data.as_ref()); } } -- cgit From e4addc7cc2dfcc19f1c8c8e47f3834b22cb21559 Mon Sep 17 00:00:00 2001 From: Markus Probst Date: Mon, 27 Oct 2025 20:06:03 +0000 Subject: rust: Add trait to convert a device reference to a bus device reference Implement the `AsBusDevice` trait for converting a `Device` reference to a bus device reference for all bus devices. The `AsBusDevice` trait allows abstractions to provide the bus device in class device callbacks. It must not be used by drivers and is intended for bus and class device abstractions only. Signed-off-by: Markus Probst Link: https://patch.msgid.link/20251027200547.1038967-2-markus.probst@posteo.de [ * Remove unused import. * Change visibility of AsBusDevice to public. * Fix build for USB. * Add impl for I2cClient. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/usb.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'rust/kernel/usb.rs') diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs index 534e3ded5442..d10b65e9fb6a 100644 --- a/rust/kernel/usb.rs +++ b/rust/kernel/usb.rs @@ -15,7 +15,14 @@ use crate::{ types::{AlwaysRefCounted, Opaque}, ThisModule, }; -use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; +use core::{ + marker::PhantomData, + mem::{ + offset_of, + MaybeUninit, // + }, + ptr::NonNull, +}; /// An adapter for the registration of USB drivers. pub struct Adapter(T); @@ -324,6 +331,12 @@ impl Interface { } } +// SAFETY: `usb::Interface` is a transparent wrapper of `struct usb_interface`. +// The offset is guaranteed to point to a valid device field inside `usb::Interface`. +unsafe impl device::AsBusDevice for Interface { + const OFFSET: usize = offset_of!(bindings::usb_interface, dev); +} + // SAFETY: `Interface` is a transparent wrapper of a type that doesn't depend on // `Interface`'s generic argument. kernel::impl_device_context_deref!(unsafe { Interface }); -- cgit