* [PATCH 1/2] rust: device: add BoundInternal device context and InternalBoundContext trait
@ 2026-05-30 13:21 Danilo Krummrich
0 siblings, 0 replies; 3+ messages in thread
From: Danilo Krummrich @ 2026-05-30 13:21 UTC (permalink / raw)
To: gregkh, rafael, dakr, ojeda, boqun, gary, bjorn3_gh, lossin,
a.hindborg, aliceryhl, tmgross, beata.michalska, markus.probst
Cc: driver-core, linux-kernel, rust-for-linux
Add a new BoundInternal device context type for cases where bus
abstractions need access to internal device infrastructure, where
CoreInternal would not be justified.
Introduce the InternalBoundContext marker trait, implemented by both
CoreInternal and BoundInternal, to allow methods that require internal
bus abstraction access to a bound device to be generic over both
contexts.
The deref hierarchy now has two branches:
- CoreInternal<'a> => Core<'a> => Bound => Normal
- BoundInternal => Bound => Normal
Update impl_device_context_deref! and impl_device_context_into_aref!
macros to emit the BoundInternal => Bound deref and the corresponding
ARef conversion.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
This is needed by both the serdev bus code [1] and the runtime PM series [2].
[1] https://lore.kernel.org/driver-core/DIW1B4FUIXO7.28GSUA0CEA4EV@kernel.org/
[2] https://lore.kernel.org/driver-core/DIKIJ81CV55B.3TA7PV8N4BN0E@kernel.org/
---
rust/kernel/device.rs | 43 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 645afc49a27d..354c4045f404 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -54,7 +54,8 @@
/// reference is valid in. For instance, the [`Bound`] context guarantees that the [`Device`] is
/// bound to a driver for the entire duration of the existence of a [`Device<Bound>`] reference.
///
-/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`] and [`CoreInternal`].
+/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`], [`CoreInternal`] and
+/// [`BoundInternal`].
///
/// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`DeviceContext`], which by
/// itself has no additional requirements.
@@ -476,7 +477,8 @@ unsafe impl Sync for Device<Bound> {}
/// [`DeviceContext`] is a marker trait for types representing the context of a bus specific
/// [`Device`].
///
-/// The specific device context types are: [`CoreInternal`], [`Core`], [`Bound`] and [`Normal`].
+/// The specific device context types are: [`CoreInternal`], [`Core`], [`BoundInternal`], [`Bound`]
+/// and [`Normal`].
///
/// [`DeviceContext`] types are hierarchical, which means that there is a strict hierarchy that
/// defines which [`DeviceContext`] type can be derived from another. For instance, any
@@ -485,6 +487,11 @@ unsafe impl Sync for Device<Bound> {}
/// The following enumeration illustrates the dereference hierarchy of [`DeviceContext`] types.
///
/// - [`CoreInternal`] => [`Core`] => [`Bound`] => [`Normal`]
+/// - [`BoundInternal`] => [`Bound`] => [`Normal`]
+///
+/// Both [`CoreInternal`] and [`BoundInternal`] implement the [`InternalBoundContext`] trait,
+/// which provides access to internal bus abstraction methods on [`Device`] that are not available
+/// to drivers.
///
/// Bus devices can automatically implement the dereference hierarchy by using
/// [`impl_device_context_deref`].
@@ -524,6 +531,18 @@ pub trait DeviceContext: private::Sealed {}
/// from bus callbacks with bus abstractions, but without making them accessible for drivers.
pub struct CoreInternal<'a>(PhantomData<&'a ()>);
+/// Semantically the same as [`Bound`], but reserved for internal usage of the corresponding bus
+/// abstraction.
+///
+/// The internal bound context is intended to be used in exactly the same way as the [`Bound`]
+/// context, with the difference that this [`DeviceContext`] is internal to the corresponding bus
+/// abstraction.
+///
+/// This context exists for cases where the bus abstraction needs access to internal device
+/// infrastructure (such as [`Device::drvdata_borrow`]), where [`CoreInternal`] would not be
+/// justified.
+pub struct BoundInternal;
+
/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to
/// be bound to a driver.
///
@@ -546,16 +565,28 @@ mod private {
pub trait Sealed {}
impl Sealed for super::Bound {}
+ impl Sealed for super::BoundInternal {}
impl<'a> Sealed for super::Core<'a> {}
impl<'a> Sealed for super::CoreInternal<'a> {}
impl Sealed for super::Normal {}
}
impl DeviceContext for Bound {}
+impl DeviceContext for BoundInternal {}
impl<'a> DeviceContext for Core<'a> {}
impl<'a> DeviceContext for CoreInternal<'a> {}
impl DeviceContext for Normal {}
+/// Marker trait for [`DeviceContext`] types that have internal bound-level access.
+///
+/// This trait is implemented by [`CoreInternal`] and [`BoundInternal`], allowing methods that
+/// require internal bus abstraction access to a bound device to be generic over both contexts.
+///
+/// Methods bounded by this trait are available to bus abstractions but not to drivers.
+pub trait InternalBoundContext: DeviceContext {}
+impl<'a> InternalBoundContext for CoreInternal<'a> {}
+impl InternalBoundContext for BoundInternal {}
+
impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx> {
#[inline]
fn as_ref(&self) -> &Device<Ctx> {
@@ -661,6 +692,13 @@ macro_rules! impl_device_context_deref {
<'a> $crate::device::Core<'a> => $crate::device::Bound
});
+ // SAFETY: This macro has the exact same safety requirement as
+ // `__impl_device_context_deref!`.
+ ::kernel::__impl_device_context_deref!(unsafe {
+ $device,
+ $crate::device::BoundInternal => $crate::device::Bound
+ });
+
// SAFETY: This macro has the exact same safety requirement as
// `__impl_device_context_deref!`.
::kernel::__impl_device_context_deref!(unsafe {
@@ -700,6 +738,7 @@ macro_rules! impl_device_context_into_aref {
::kernel::__impl_device_context_into_aref!(
<'a> $crate::device::Core<'a>, $device
);
+ ::kernel::__impl_device_context_into_aref!($crate::device::BoundInternal, $device);
::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);
};
}
base-commit: 016267b521b18529c977c9eca9597a1669c3d73c
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 1/2] rust: device: add BoundInternal device context and InternalBoundContext trait
@ 2026-05-30 13:27 Danilo Krummrich
2026-05-30 13:27 ` [PATCH 2/2] rust: device: move drvdata_borrow() to InternalBoundContext Danilo Krummrich
0 siblings, 1 reply; 3+ messages in thread
From: Danilo Krummrich @ 2026-05-30 13:27 UTC (permalink / raw)
To: gregkh, rafael, dakr, ojeda, boqun, gary, bjorn3_gh, lossin,
a.hindborg, aliceryhl, tmgross, beata.michalska, markus.probst
Cc: driver-core, linux-kernel, rust-for-linux
Add a new BoundInternal device context type for cases where bus
abstractions need access to internal device infrastructure, where
CoreInternal would not be justified.
Introduce the InternalBoundContext marker trait, implemented by both
CoreInternal and BoundInternal, to allow methods that require internal
bus abstraction access to a bound device to be generic over both
contexts.
The deref hierarchy now has two branches:
- CoreInternal<'a> => Core<'a> => Bound => Normal
- BoundInternal => Bound => Normal
Update impl_device_context_deref! and impl_device_context_into_aref!
macros to emit the BoundInternal => Bound deref and the corresponding
ARef conversion.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
This is needed by both the serdev bus code [1] and the runtime PM series [2].
[1] https://lore.kernel.org/driver-core/DIW1B4FUIXO7.28GSUA0CEA4EV@kernel.org/
[2] https://lore.kernel.org/driver-core/DIKIJ81CV55B.3TA7PV8N4BN0E@kernel.org/
---
rust/kernel/device.rs | 43 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 645afc49a27d..354c4045f404 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -54,7 +54,8 @@
/// reference is valid in. For instance, the [`Bound`] context guarantees that the [`Device`] is
/// bound to a driver for the entire duration of the existence of a [`Device<Bound>`] reference.
///
-/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`] and [`CoreInternal`].
+/// Other [`DeviceContext`] types besides [`Bound`] are [`Normal`], [`Core`], [`CoreInternal`] and
+/// [`BoundInternal`].
///
/// Unless selected otherwise [`Device`] defaults to the [`Normal`] [`DeviceContext`], which by
/// itself has no additional requirements.
@@ -476,7 +477,8 @@ unsafe impl Sync for Device<Bound> {}
/// [`DeviceContext`] is a marker trait for types representing the context of a bus specific
/// [`Device`].
///
-/// The specific device context types are: [`CoreInternal`], [`Core`], [`Bound`] and [`Normal`].
+/// The specific device context types are: [`CoreInternal`], [`Core`], [`BoundInternal`], [`Bound`]
+/// and [`Normal`].
///
/// [`DeviceContext`] types are hierarchical, which means that there is a strict hierarchy that
/// defines which [`DeviceContext`] type can be derived from another. For instance, any
@@ -485,6 +487,11 @@ unsafe impl Sync for Device<Bound> {}
/// The following enumeration illustrates the dereference hierarchy of [`DeviceContext`] types.
///
/// - [`CoreInternal`] => [`Core`] => [`Bound`] => [`Normal`]
+/// - [`BoundInternal`] => [`Bound`] => [`Normal`]
+///
+/// Both [`CoreInternal`] and [`BoundInternal`] implement the [`InternalBoundContext`] trait,
+/// which provides access to internal bus abstraction methods on [`Device`] that are not available
+/// to drivers.
///
/// Bus devices can automatically implement the dereference hierarchy by using
/// [`impl_device_context_deref`].
@@ -524,6 +531,18 @@ pub trait DeviceContext: private::Sealed {}
/// from bus callbacks with bus abstractions, but without making them accessible for drivers.
pub struct CoreInternal<'a>(PhantomData<&'a ()>);
+/// Semantically the same as [`Bound`], but reserved for internal usage of the corresponding bus
+/// abstraction.
+///
+/// The internal bound context is intended to be used in exactly the same way as the [`Bound`]
+/// context, with the difference that this [`DeviceContext`] is internal to the corresponding bus
+/// abstraction.
+///
+/// This context exists for cases where the bus abstraction needs access to internal device
+/// infrastructure (such as [`Device::drvdata_borrow`]), where [`CoreInternal`] would not be
+/// justified.
+pub struct BoundInternal;
+
/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to
/// be bound to a driver.
///
@@ -546,16 +565,28 @@ mod private {
pub trait Sealed {}
impl Sealed for super::Bound {}
+ impl Sealed for super::BoundInternal {}
impl<'a> Sealed for super::Core<'a> {}
impl<'a> Sealed for super::CoreInternal<'a> {}
impl Sealed for super::Normal {}
}
impl DeviceContext for Bound {}
+impl DeviceContext for BoundInternal {}
impl<'a> DeviceContext for Core<'a> {}
impl<'a> DeviceContext for CoreInternal<'a> {}
impl DeviceContext for Normal {}
+/// Marker trait for [`DeviceContext`] types that have internal bound-level access.
+///
+/// This trait is implemented by [`CoreInternal`] and [`BoundInternal`], allowing methods that
+/// require internal bus abstraction access to a bound device to be generic over both contexts.
+///
+/// Methods bounded by this trait are available to bus abstractions but not to drivers.
+pub trait InternalBoundContext: DeviceContext {}
+impl<'a> InternalBoundContext for CoreInternal<'a> {}
+impl InternalBoundContext for BoundInternal {}
+
impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx> {
#[inline]
fn as_ref(&self) -> &Device<Ctx> {
@@ -661,6 +692,13 @@ macro_rules! impl_device_context_deref {
<'a> $crate::device::Core<'a> => $crate::device::Bound
});
+ // SAFETY: This macro has the exact same safety requirement as
+ // `__impl_device_context_deref!`.
+ ::kernel::__impl_device_context_deref!(unsafe {
+ $device,
+ $crate::device::BoundInternal => $crate::device::Bound
+ });
+
// SAFETY: This macro has the exact same safety requirement as
// `__impl_device_context_deref!`.
::kernel::__impl_device_context_deref!(unsafe {
@@ -700,6 +738,7 @@ macro_rules! impl_device_context_into_aref {
::kernel::__impl_device_context_into_aref!(
<'a> $crate::device::Core<'a>, $device
);
+ ::kernel::__impl_device_context_into_aref!($crate::device::BoundInternal, $device);
::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);
};
}
base-commit: 016267b521b18529c977c9eca9597a1669c3d73c
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] rust: device: move drvdata_borrow() to InternalBoundContext
2026-05-30 13:27 [PATCH 1/2] rust: device: add BoundInternal device context and InternalBoundContext trait Danilo Krummrich
@ 2026-05-30 13:27 ` Danilo Krummrich
0 siblings, 0 replies; 3+ messages in thread
From: Danilo Krummrich @ 2026-05-30 13:27 UTC (permalink / raw)
To: gregkh, rafael, dakr, ojeda, boqun, gary, bjorn3_gh, lossin,
a.hindborg, aliceryhl, tmgross, beata.michalska, markus.probst
Cc: driver-core, linux-kernel, rust-for-linux
Move drvdata_borrow() from impl Device<CoreInternal<'a>> to
impl<Ctx: InternalBoundContext> Device<Ctx>, making it available from
both CoreInternal and BoundInternal contexts.
Fold drvdata_unchecked() (previously on Device<Bound>) directly into
drvdata_borrow(), since it was only called from there and the generic
context cannot resolve methods through the deref chain.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
rust/kernel/device.rs | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 354c4045f404..b538c39982a6 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -236,7 +236,9 @@ pub(crate) unsafe fn drvdata_obtain<T>(&self) -> Option<Pin<KBox<T>>> {
// in `into_foreign()`.
Some(unsafe { Pin::<KBox<T>>::from_foreign(ptr.cast()) })
}
+}
+impl<Ctx: InternalBoundContext> Device<Ctx> {
/// Borrow the driver's private data bound to this [`Device`].
///
/// # Safety
@@ -246,22 +248,6 @@ pub(crate) unsafe fn drvdata_obtain<T>(&self) -> Option<Pin<KBox<T>>> {
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
/// [`Device::set_drvdata`].
pub unsafe fn drvdata_borrow<T>(&self) -> Pin<&T> {
- // SAFETY: `drvdata_unchecked()` has the exact same safety requirements as the ones
- // required by this method.
- unsafe { self.drvdata_unchecked() }
- }
-}
-
-impl Device<Bound> {
- /// Borrow the driver's private data bound to this [`Device`].
- ///
- /// # Safety
- ///
- /// - Must only be called after a preceding call to [`Device::set_drvdata`] and before
- /// the device is fully unbound.
- /// - The type `T` must match the type of the `ForeignOwnable` previously stored by
- /// [`Device::set_drvdata`].
- unsafe fn drvdata_unchecked<T>(&self) -> Pin<&T> {
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-30 13:27 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-30 13:27 [PATCH 1/2] rust: device: add BoundInternal device context and InternalBoundContext trait Danilo Krummrich
2026-05-30 13:27 ` [PATCH 2/2] rust: device: move drvdata_borrow() to InternalBoundContext Danilo Krummrich
-- strict thread matches above, loose matches on Subject: below --
2026-05-30 13:21 [PATCH 1/2] rust: device: add BoundInternal device context and InternalBoundContext trait Danilo Krummrich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox