Skip to content

Commit cb271c2

Browse files
author
Danilo Krummrich
committed
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 <[email protected]> Signed-off-by: Benno Lossin <[email protected]> Reviewed-by: Christian Schrefl <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Add missing `::` prefix in macros. - Danilo ] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent 0af2f6b commit cb271c2

File tree

3 files changed

+50
-27
lines changed

3 files changed

+50
-27
lines changed

rust/kernel/device.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,50 @@ mod private {
235235
impl DeviceContext for Core {}
236236
impl DeviceContext for Normal {}
237237

238+
/// # Safety
239+
///
240+
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
241+
/// generic argument of `$device`.
242+
#[doc(hidden)]
243+
#[macro_export]
244+
macro_rules! __impl_device_context_deref {
245+
(unsafe { $device:ident, $src:ty => $dst:ty }) => {
246+
impl ::core::ops::Deref for $device<$src> {
247+
type Target = $device<$dst>;
248+
249+
fn deref(&self) -> &Self::Target {
250+
let ptr: *const Self = self;
251+
252+
// CAST: `$device<$src>` and `$device<$dst>` transparently wrap the same type by the
253+
// safety requirement of the macro.
254+
let ptr = ptr.cast::<Self::Target>();
255+
256+
// SAFETY: `ptr` was derived from `&self`.
257+
unsafe { &*ptr }
258+
}
259+
}
260+
};
261+
}
262+
263+
/// Implement [`core::ops::Deref`] traits for allowed [`DeviceContext`] conversions of a (bus
264+
/// specific) device.
265+
///
266+
/// # Safety
267+
///
268+
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
269+
/// generic argument of `$device`.
270+
#[macro_export]
271+
macro_rules! impl_device_context_deref {
272+
(unsafe { $device:ident }) => {
273+
// SAFETY: This macro has the exact same safety requirement as
274+
// `__impl_device_context_deref!`.
275+
::kernel::__impl_device_context_deref!(unsafe {
276+
$device,
277+
$crate::device::Core => $crate::device::Normal
278+
});
279+
};
280+
}
281+
238282
#[doc(hidden)]
239283
#[macro_export]
240284
macro_rules! dev_printk {

rust/kernel/pci.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -422,19 +422,9 @@ impl Device<device::Core> {
422422
}
423423
}
424424

425-
impl Deref for Device<device::Core> {
426-
type Target = Device;
427-
428-
fn deref(&self) -> &Self::Target {
429-
let ptr: *const Self = self;
430-
431-
// CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::pci_dev>`.
432-
let ptr = ptr.cast::<Device>();
433-
434-
// SAFETY: `ptr` was derived from `&self`.
435-
unsafe { &*ptr }
436-
}
437-
}
425+
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
426+
// argument.
427+
kernel::impl_device_context_deref!(unsafe { Device });
438428

439429
impl From<&Device<device::Core>> for ARef<Device> {
440430
fn from(dev: &Device<device::Core>) -> Self {

rust/kernel/platform.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use crate::{
1616

1717
use core::{
1818
marker::PhantomData,
19-
ops::Deref,
2019
ptr::{addr_of_mut, NonNull},
2120
};
2221

@@ -190,19 +189,9 @@ impl Device {
190189
}
191190
}
192191

193-
impl Deref for Device<device::Core> {
194-
type Target = Device;
195-
196-
fn deref(&self) -> &Self::Target {
197-
let ptr: *const Self = self;
198-
199-
// CAST: `Device<Ctx>` is a transparent wrapper of `Opaque<bindings::platform_device>`.
200-
let ptr = ptr.cast::<Device>();
201-
202-
// SAFETY: `ptr` was derived from `&self`.
203-
unsafe { &*ptr }
204-
}
205-
}
192+
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
193+
// argument.
194+
kernel::impl_device_context_deref!(unsafe { Device });
206195

207196
impl From<&Device<device::Core>> for ARef<Device> {
208197
fn from(dev: &Device<device::Core>) -> Self {

0 commit comments

Comments
 (0)