rust: Add trait to convert a device reference to a bus device reference
Implement the `AsBusDevice` trait for converting a `Device` reference to a bus device reference for all bus devices. The `AsBusDevice` trait allows abstractions to provide the bus device in class device callbacks. It must not be used by drivers and is intended for bus and class device abstractions only. Signed-off-by: Markus Probst <markus.probst@posteo.de> Link: https://patch.msgid.link/20251027200547.1038967-2-markus.probst@posteo.de [ * Remove unused import. * Change visibility of AsBusDevice to public. * Fix build for USB. * Add impl for I2cClient. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
committed by
Danilo Krummrich
parent
13ae55e24a
commit
e4addc7cc2
@@ -16,6 +16,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
mem::offset_of,
|
||||||
ptr::{addr_of_mut, NonNull},
|
ptr::{addr_of_mut, NonNull},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -245,6 +246,12 @@ impl Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: `auxiliary::Device` is a transparent wrapper of `struct auxiliary_device`.
|
||||||
|
// The offset is guaranteed to point to a valid device field inside `auxiliary::Device`.
|
||||||
|
unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<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
|
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
|
||||||
// argument.
|
// argument.
|
||||||
kernel::impl_device_context_deref!(unsafe { Device });
|
kernel::impl_device_context_deref!(unsafe { Device });
|
||||||
|
|||||||
@@ -594,6 +594,39 @@ impl DeviceContext for Core {}
|
|||||||
impl DeviceContext for CoreInternal {}
|
impl DeviceContext for CoreInternal {}
|
||||||
impl DeviceContext for Normal {}
|
impl DeviceContext for Normal {}
|
||||||
|
|
||||||
|
/// Convert device references to bus device references.
|
||||||
|
///
|
||||||
|
/// Bus devices can implement this trait to allow abstractions to provide the bus device in
|
||||||
|
/// class device callbacks.
|
||||||
|
///
|
||||||
|
/// This must not be used by drivers and is intended for bus and class device abstractions only.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `AsBusDevice::OFFSET` must be the offset of the embedded base `struct device` field within a
|
||||||
|
/// bus device structure.
|
||||||
|
pub unsafe trait AsBusDevice<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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
|
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use crate::{
|
|||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
mem::offset_of,
|
||||||
ptr::{
|
ptr::{
|
||||||
from_ref,
|
from_ref,
|
||||||
NonNull, //
|
NonNull, //
|
||||||
@@ -476,6 +477,12 @@ impl<Ctx: device::DeviceContext> I2cClient<Ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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::AsBusDevice<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
|
// SAFETY: `I2cClient` is a transparent wrapper of a type that doesn't depend on
|
||||||
// `I2cClient`'s generic argument.
|
// `I2cClient`'s generic argument.
|
||||||
kernel::impl_device_context_deref!(unsafe { I2cClient });
|
kernel::impl_device_context_deref!(unsafe { I2cClient });
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
mem::offset_of,
|
||||||
ptr::{
|
ptr::{
|
||||||
addr_of_mut,
|
addr_of_mut,
|
||||||
NonNull, //
|
NonNull, //
|
||||||
@@ -443,6 +444,12 @@ impl Device<device::Core> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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::AsBusDevice<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
|
// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
|
||||||
// argument.
|
// argument.
|
||||||
kernel::impl_device_context_deref!(unsafe { Device });
|
kernel::impl_device_context_deref!(unsafe { Device });
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use crate::{
|
|||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
mem::offset_of,
|
||||||
ptr::{addr_of_mut, NonNull},
|
ptr::{addr_of_mut, NonNull},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -287,6 +288,12 @@ impl Device<Bound> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: `platform::Device` is a transparent wrapper of `struct platform_device`.
|
||||||
|
// The offset is guaranteed to point to a valid device field inside `platform::Device`.
|
||||||
|
unsafe impl<Ctx: device::DeviceContext> device::AsBusDevice<Ctx> for Device<Ctx> {
|
||||||
|
const OFFSET: usize = offset_of!(bindings::platform_device, dev);
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! define_irq_accessor_by_index {
|
macro_rules! define_irq_accessor_by_index {
|
||||||
(
|
(
|
||||||
$(#[$meta:meta])* $fn_name:ident,
|
$(#[$meta:meta])* $fn_name:ident,
|
||||||
|
|||||||
@@ -15,7 +15,14 @@ use crate::{
|
|||||||
types::{AlwaysRefCounted, Opaque},
|
types::{AlwaysRefCounted, Opaque},
|
||||||
ThisModule,
|
ThisModule,
|
||||||
};
|
};
|
||||||
use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull};
|
use core::{
|
||||||
|
marker::PhantomData,
|
||||||
|
mem::{
|
||||||
|
offset_of,
|
||||||
|
MaybeUninit, //
|
||||||
|
},
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
/// An adapter for the registration of USB drivers.
|
/// An adapter for the registration of USB drivers.
|
||||||
pub struct Adapter<T: Driver>(T);
|
pub struct Adapter<T: Driver>(T);
|
||||||
@@ -324,6 +331,12 @@ impl<Ctx: device::DeviceContext> Interface<Ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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::AsBusDevice<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
|
// SAFETY: `Interface` is a transparent wrapper of a type that doesn't depend on
|
||||||
// `Interface`'s generic argument.
|
// `Interface`'s generic argument.
|
||||||
kernel::impl_device_context_deref!(unsafe { Interface });
|
kernel::impl_device_context_deref!(unsafe { Interface });
|
||||||
|
|||||||
Reference in New Issue
Block a user