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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.