summaryrefslogtreecommitdiff
path: root/rust/kernel/device.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel/device.rs')
-rw-r--r--rust/kernel/device.rs49
1 files changed, 38 insertions, 11 deletions
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index c4486f4b8c40..645afc49a27d 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -201,7 +201,7 @@ impl Device {
}
}
-impl Device<CoreInternal> {
+impl<'a> Device<CoreInternal<'a>> {
/// Store a pointer to the bound driver's private data.
pub fn set_drvdata<T>(&self, data: impl PinInit<T, Error>) -> Result {
let data = KBox::pin_init(data, GFP_KERNEL)?;
@@ -511,7 +511,7 @@ pub struct Normal;
/// callback it appears in. It is intended to be used for synchronization purposes. Bus device
/// implementations can implement methods for [`Device<Core>`], such that they can only be called
/// from bus callbacks.
-pub struct Core;
+pub struct Core<'a>(PhantomData<&'a ()>);
/// Semantically the same as [`Core`], but reserved for internal usage of the corresponding bus
/// abstraction.
@@ -522,7 +522,7 @@ pub struct Core;
///
/// This context mainly exists to share generic [`Device`] infrastructure that should only be called
/// from bus callbacks with bus abstractions, but without making them accessible for drivers.
-pub struct CoreInternal;
+pub struct CoreInternal<'a>(PhantomData<&'a ()>);
/// The [`Bound`] context is the [`DeviceContext`] of a bus specific device when it is guaranteed to
/// be bound to a driver.
@@ -546,14 +546,14 @@ mod private {
pub trait Sealed {}
impl Sealed for super::Bound {}
- impl Sealed for super::Core {}
- impl Sealed for super::CoreInternal {}
+ 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 Core {}
-impl DeviceContext for CoreInternal {}
+impl<'a> DeviceContext for Core<'a> {}
+impl<'a> DeviceContext for CoreInternal<'a> {}
impl DeviceContext for Normal {}
impl<Ctx: DeviceContext> AsRef<Device<Ctx>> for Device<Ctx> {
@@ -603,6 +603,22 @@ pub unsafe trait AsBusDevice<Ctx: DeviceContext>: AsRef<Device<Ctx>> {
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_device_context_deref {
+ (unsafe { $device:ident, <$lt:lifetime> $src:ty => $dst:ty }) => {
+ impl<$lt> ::core::ops::Deref for $device<$src> {
+ type Target = $device<$dst>;
+
+ fn deref(&self) -> &Self::Target {
+ let ptr: *const Self = self;
+
+ // CAST: `$device<$src>` and `$device<$dst>` transparently wrap the same type by the
+ // safety requirement of the macro.
+ let ptr = ptr.cast::<Self::Target>();
+
+ // SAFETY: `ptr` was derived from `&self`.
+ unsafe { &*ptr }
+ }
+ }
+ };
(unsafe { $device:ident, $src:ty => $dst:ty }) => {
impl ::core::ops::Deref for $device<$src> {
type Target = $device<$dst>;
@@ -635,14 +651,14 @@ macro_rules! impl_device_context_deref {
// `__impl_device_context_deref!`.
::kernel::__impl_device_context_deref!(unsafe {
$device,
- $crate::device::CoreInternal => $crate::device::Core
+ <'a> $crate::device::CoreInternal<'a> => $crate::device::Core<'a>
});
// SAFETY: This macro has the exact same safety requirement as
// `__impl_device_context_deref!`.
::kernel::__impl_device_context_deref!(unsafe {
$device,
- $crate::device::Core => $crate::device::Bound
+ <'a> $crate::device::Core<'a> => $crate::device::Bound
});
// SAFETY: This macro has the exact same safety requirement as
@@ -657,6 +673,13 @@ macro_rules! impl_device_context_deref {
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_device_context_into_aref {
+ (<$lt:lifetime> $src:ty, $device:tt) => {
+ impl<$lt> ::core::convert::From<&$device<$src>> for $crate::sync::aref::ARef<$device> {
+ fn from(dev: &$device<$src>) -> Self {
+ (&**dev).into()
+ }
+ }
+ };
($src:ty, $device:tt) => {
impl ::core::convert::From<&$device<$src>> for $crate::sync::aref::ARef<$device> {
fn from(dev: &$device<$src>) -> Self {
@@ -671,8 +694,12 @@ macro_rules! __impl_device_context_into_aref {
#[macro_export]
macro_rules! impl_device_context_into_aref {
($device:tt) => {
- ::kernel::__impl_device_context_into_aref!($crate::device::CoreInternal, $device);
- ::kernel::__impl_device_context_into_aref!($crate::device::Core, $device);
+ ::kernel::__impl_device_context_into_aref!(
+ <'a> $crate::device::CoreInternal<'a>, $device
+ );
+ ::kernel::__impl_device_context_into_aref!(
+ <'a> $crate::device::Core<'a>, $device
+ );
::kernel::__impl_device_context_into_aref!($crate::device::Bound, $device);
};
}