From: Markus Probst <markus.probst@posteo.de>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Miguel Ojeda <ojeda@kernel.org>,
Alex Gaynor <alex.gaynor@gmail.com>,
Danilo Krummrich <dakr@kernel.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Igor Korotin <igor.korotin.linux@gmail.com>,
Lee Jones <lee@kernel.org>, Pavel Machek <pavel@kernel.org>
Cc: Dave Ertman <david.m.ertman@intel.com>,
Ira Weiny <ira.weiny@intel.com>,
Leon Romanovsky <leon@kernel.org>,
Boqun Feng <boqun.feng@gmail.com>, Gary Guo <gary@garyguo.net>,
bjorn3_gh@protonmail.com, Benno Lossin <lossin@kernel.org>,
Andreas Hindborg <a.hindborg@kernel.org>,
Alice Ryhl <aliceryhl@google.com>,
Trevor Gross <tmgross@umich.edu>,
Daniel Almeida <daniel.almeida@collabora.com>,
Bjorn Helgaas <bhelgaas@google.com>,
kwilczynski@kernel.org, linux-kernel@vger.kernel.org,
rust-for-linux@vger.kernel.org, linux-pci@vger.kernel.org,
linux-leds@vger.kernel.org,
Markus Probst <markus.probst@posteo.de>
Subject: [PATCH v5 1/2] rust: Add trait to convert a device reference to a bus device reference
Date: Sat, 18 Oct 2025 20:59:34 +0000 [thread overview]
Message-ID: <20251018205912.1528811-2-markus.probst@posteo.de> (raw)
In-Reply-To: <20251018205912.1528811-1-markus.probst@posteo.de>
Implement the `IntoBusDevice` trait for converting a `Device` reference to a
bus device reference for all bus devices. `Device` implements this trait as a
fallback.
The `IntoBusDevice` trait allows abstractions to provide the bus device in
class device callbacks.
Signed-off-by: Markus Probst <markus.probst@posteo.de>
---
rust/kernel/auxiliary.rs | 7 +++++++
rust/kernel/device.rs | 41 ++++++++++++++++++++++++++++++++++++++++
rust/kernel/i2c.rs | 7 +++++++
rust/kernel/pci.rs | 7 +++++++
rust/kernel/usb.rs | 6 ++++++
5 files changed, 68 insertions(+)
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index e11848bbf206..dea24265f549 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -15,6 +15,7 @@
};
use core::{
marker::PhantomData,
+ mem::offset_of,
ptr::{addr_of_mut, NonNull},
};
@@ -239,6 +240,12 @@ extern "C" fn release(dev: *mut bindings::device) {
}
}
+// SAFETY: `auxilary::Device` is a transparent wrapper of `struct auxiliary_device`.
+// The offset is guaranteed to point to a valid device field inside `auxilary::Device`.
+unsafe impl<Ctx: device::DeviceContext> device::IntoBusDevice<Ctx> for Device<Ctx> {
+ const OFFSET: usize = offset_of!(bindings::auxiliary_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 });
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 1321e6f0b53c..5527854a195f 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -511,6 +511,47 @@ impl DeviceContext for Core {}
impl DeviceContext for CoreInternal {}
impl DeviceContext for Normal {}
+/// Bus devices can implement this trait to allow abstractions to provide the bus device in
+/// class device callbacks.
+///
+/// # Safety
+///
+/// `IntoBusDevice::OFFSET` must be a offset to a device field in the implemented struct.
+pub(crate) unsafe trait IntoBusDevice<Ctx: DeviceContext>:
+ AsRef<Device<Ctx>>
+{
+ /// The relative offset to the device field.
+ ///
+ /// Use `offset_of!(bindings, field)` macro to avoid breakage.
+ const OFFSET: usize;
+
+ /// Convert a reference to [`Device`] into `Self`.
+ ///
+ /// # Safety
+ ///
+ /// `dev` must be contained in `Self`.
+ unsafe fn from_device(dev: &Device<Ctx>) -> &Self
+ where
+ Self: Sized,
+ {
+ let raw = dev.as_raw();
+ // SAFETY: `raw - Self::OFFSET` is guaranteed by the safety requirements
+ // to be a valid pointer to `Self`.
+ unsafe { &*raw.byte_sub(Self::OFFSET).cast::<Self>() }
+ }
+}
+
+// SAFETY: `Device` is a transparent wrapper of `device`.
+unsafe impl<Ctx: DeviceContext> IntoBusDevice<Ctx> for Device<Ctx> {
+ const OFFSET: usize = 0;
+}
+
+impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx> {
+ fn as_ref(&self) -> &Device<Ctx> {
+ self
+ }
+}
+
/// # Safety
///
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index 7fccffebbd6c..e9a7e09b0116 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -15,6 +15,7 @@
use core::{
marker::PhantomData,
+ mem::offset_of,
ptr::{from_ref, NonNull},
};
@@ -465,6 +466,12 @@ fn as_raw(&self) -> *mut bindings::i2c_client {
}
}
+// SAFETY: `I2cClient` is a transparent wrapper of `struct i2c_client`.
+// The offset is guaranteed to point to a valid device field inside `I2cClient`.
+unsafe impl<Ctx: device::DeviceContext> device::IntoBusDevice<Ctx> for I2cClient<Ctx> {
+ const OFFSET: usize = offset_of!(bindings::i2c_client, dev);
+}
+
// SAFETY: `I2cClient` is a transparent wrapper of a type that doesn't depend on `I2cClient`'s generic
// argument.
kernel::impl_device_context_deref!(unsafe { I2cClient });
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 7fcc5f6022c1..ad00a5c1294a 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -19,6 +19,7 @@
};
use core::{
marker::PhantomData,
+ mem::offset_of,
ops::Deref,
ptr::{addr_of_mut, NonNull},
};
@@ -593,6 +594,12 @@ pub fn set_master(&self) {
}
}
+// SAFETY: `pci::Device` is a transparent wrapper of `struct pci_dev`.
+// The offset is guaranteed to point to a valid device field inside `pci::Device`.
+unsafe impl<Ctx: device::DeviceContext> device::IntoBusDevice<Ctx> for Device<Ctx> {
+ const OFFSET: usize = offset_of!(bindings::pci_dev, 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 });
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index 14ddb711bab3..8862004e54f9 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -324,6 +324,12 @@ fn as_raw(&self) -> *mut bindings::usb_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<Ctx: device::DeviceContext> device::IntoBusDevice<Ctx> for Interface<Ctx> {
+ 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 });
--
2.49.1
next prev parent reply other threads:[~2025-10-18 20:59 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-18 20:59 [PATCH v5 0/2] rust: leds: add led classdev abstractions Markus Probst
2025-10-18 20:59 ` Markus Probst [this message]
2025-10-19 14:28 ` [PATCH v5 1/2] rust: Add trait to convert a device reference to a bus device reference Danilo Krummrich
2025-10-18 20:59 ` [PATCH v5 2/2] rust: leds: add basic led classdev abstractions Markus Probst
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251018205912.1528811-2-markus.probst@posteo.de \
--to=markus.probst@posteo.de \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=bhelgaas@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=david.m.ertman@intel.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=igor.korotin.linux@gmail.com \
--cc=ira.weiny@intel.com \
--cc=kwilczynski@kernel.org \
--cc=lee@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=pavel@kernel.org \
--cc=rafael@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox