summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rust/kernel/auxiliary.rs7
-rw-r--r--rust/kernel/device.rs33
-rw-r--r--rust/kernel/i2c.rs7
-rw-r--r--rust/kernel/pci.rs7
-rw-r--r--rust/kernel/platform.rs7
-rw-r--r--rust/kernel/usb.rs15
6 files changed, 75 insertions, 1 deletions
diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs
index 618eeeec2bd0..56f3c180e8f6 100644
--- a/rust/kernel/auxiliary.rs
+++ b/rust/kernel/auxiliary.rs
@@ -16,6 +16,7 @@ use crate::{
};
use core::{
marker::PhantomData,
+ mem::offset_of,
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
// argument.
kernel::impl_device_context_deref!(unsafe { Device });
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index 1a307be953c2..660cb2b48c07 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -594,6 +594,39 @@ impl DeviceContext for Core {}
impl DeviceContext for CoreInternal {}
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
///
/// The type given as `$device` must be a transparent wrapper of a type that doesn't depend on the
diff --git a/rust/kernel/i2c.rs b/rust/kernel/i2c.rs
index aea1b44d189b..95b056cc1a71 100644
--- a/rust/kernel/i2c.rs
+++ b/rust/kernel/i2c.rs
@@ -24,6 +24,7 @@ use crate::{
use core::{
marker::PhantomData,
+ mem::offset_of,
ptr::{
from_ref,
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
// `I2cClient`'s generic argument.
kernel::impl_device_context_deref!(unsafe { I2cClient });
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 410b79d46632..82e128431f08 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -24,6 +24,7 @@ use crate::{
};
use core::{
marker::PhantomData,
+ mem::offset_of,
ptr::{
addr_of_mut,
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
// argument.
kernel::impl_device_context_deref!(unsafe { Device });
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index f4b617c570be..ed889f079cab 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -19,6 +19,7 @@ use crate::{
use core::{
marker::PhantomData,
+ mem::offset_of,
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 {
(
$(#[$meta:meta])* $fn_name:ident,
diff --git a/rust/kernel/usb.rs b/rust/kernel/usb.rs
index 534e3ded5442..d10b65e9fb6a 100644
--- a/rust/kernel/usb.rs
+++ b/rust/kernel/usb.rs
@@ -15,7 +15,14 @@ use crate::{
types::{AlwaysRefCounted, Opaque},
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.
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
// `Interface`'s generic argument.
kernel::impl_device_context_deref!(unsafe { Interface });