mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
rust: device: implement impl_device_context_deref!
The Deref hierarchy for device context generics is the same for every (bus specific) device. Implement those with a generic macro to avoid duplicated boiler plate code and ensure the correct Deref hierarchy for every device implementation. Co-developed-by: Benno Lossin <benno.lossin@proton.me> Signed-off-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Christian Schrefl <chrisi.schrefl@gmail.com> Link: https://lore.kernel.org/r/20250413173758.12068-2-dakr@kernel.org [ Add missing `::` prefix in macros. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
@@ -235,6 +235,50 @@ mod private {
|
||||
impl DeviceContext for Core {}
|
||||
impl DeviceContext for Normal {}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
|
||||
/// generic argument of `$device`.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __impl_device_context_deref {
|
||||
(unsafe { $device:ident, $src:ty => $dst:ty }) => {
|
||||
impl ::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 }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Implement [`core::ops::Deref`] traits for allowed [`DeviceContext`] conversions of a (bus
|
||||
/// specific) device.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
|
||||
/// generic argument of `$device`.
|
||||
#[macro_export]
|
||||
macro_rules! impl_device_context_deref {
|
||||
(unsafe { $device:ident }) => {
|
||||
// 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::Normal
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! dev_printk {
|
||||
|
||||
@@ -422,19 +422,9 @@ impl Device<device::Core> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Device<device::Core> {
|
||||
type Target = Device;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
let ptr: *const Self = self;
|
||||
|
||||
// CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::pci_dev>`.
|
||||
let ptr = ptr.cast::<Device>();
|
||||
|
||||
// SAFETY: `ptr` was derived from `&self`.
|
||||
unsafe { &*ptr }
|
||||
}
|
||||
}
|
||||
// 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 });
|
||||
|
||||
impl From<&Device<device::Core>> for ARef<Device> {
|
||||
fn from(dev: &Device<device::Core>) -> Self {
|
||||
|
||||
@@ -16,7 +16,6 @@ use crate::{
|
||||
|
||||
use core::{
|
||||
marker::PhantomData,
|
||||
ops::Deref,
|
||||
ptr::{addr_of_mut, NonNull},
|
||||
};
|
||||
|
||||
@@ -190,19 +189,9 @@ impl Device {
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Device<device::Core> {
|
||||
type Target = Device;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
let ptr: *const Self = self;
|
||||
|
||||
// CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::platform_device>`.
|
||||
let ptr = ptr.cast::<Device>();
|
||||
|
||||
// SAFETY: `ptr` was derived from `&self`.
|
||||
unsafe { &*ptr }
|
||||
}
|
||||
}
|
||||
// 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 });
|
||||
|
||||
impl From<&Device<device::Core>> for ARef<Device> {
|
||||
fn from(dev: &Device<device::Core>) -> Self {
|
||||
|
||||
Reference in New Issue
Block a user