rust: device: add drvdata accessors

Implement generic accessors for the private data of a driver bound to a
device.

Those accessors should be used by bus abstractions from their
corresponding core callbacks, such as probe(), remove(), etc.

Implementing them for device::CoreInternal guarantees that driver's can't
interfere with the logic implemented by the bus abstraction.

Acked-by: Benno Lossin <lossin@kernel.org>
Link: https://lore.kernel.org/r/20250621195118.124245-3-dakr@kernel.org
[ Improve safety comment as proposed by Benno. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Danilo Krummrich 2025-06-21 21:43:28 +02:00
parent fa7486d3f9
commit 880dec12a2
2 changed files with 58 additions and 1 deletions

View File

@ -15,3 +15,13 @@ int rust_helper_devm_add_action_or_reset(struct device *dev,
{
return devm_add_action_or_reset(dev, action, data);
}
void *rust_helper_dev_get_drvdata(const struct device *dev)
{
return dev_get_drvdata(dev);
}
void rust_helper_dev_set_drvdata(struct device *dev, void *data)
{
dev_set_drvdata(dev, data);
}

View File

@ -6,7 +6,7 @@
use crate::{
bindings,
types::{ARef, Opaque},
types::{ARef, ForeignOwnable, Opaque},
};
use core::{fmt, marker::PhantomData, ptr};
@ -62,6 +62,53 @@ impl Device {
}
}
impl Device<CoreInternal> {
/// Store a pointer to the bound driver's private data.
pub fn set_drvdata(&self, data: impl ForeignOwnable) {
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
unsafe { bindings::dev_set_drvdata(self.as_raw(), data.into_foreign().cast()) }
}
/// Take ownership of the private data stored in this [`Device`].
///
/// # Safety
///
/// - Must only be called once after a preceding call to [`Device::set_drvdata`].
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
/// [`Device::set_drvdata`].
pub unsafe fn drvdata_obtain<T: ForeignOwnable>(&self) -> T {
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
// SAFETY:
// - By the safety requirements of this function, `ptr` comes from a previous call to
// `into_foreign()`.
// - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()`
// in `into_foreign()`.
unsafe { T::from_foreign(ptr.cast()) }
}
/// Borrow the driver's private data bound to this [`Device`].
///
/// # Safety
///
/// - Must only be called after a preceding call to [`Device::set_drvdata`] and before
/// [`Device::drvdata_obtain`].
/// - The type `T` must match the type of the `ForeignOwnable` previously stored by
/// [`Device::set_drvdata`].
pub unsafe fn drvdata_borrow<T: ForeignOwnable>(&self) -> T::Borrowed<'_> {
// SAFETY: By the type invariants, `self.as_raw()` is a valid pointer to a `struct device`.
let ptr = unsafe { bindings::dev_get_drvdata(self.as_raw()) };
// SAFETY:
// - By the safety requirements of this function, `ptr` comes from a previous call to
// `into_foreign()`.
// - `dev_get_drvdata()` guarantees to return the same pointer given to `dev_set_drvdata()`
// in `into_foreign()`.
unsafe { T::borrow(ptr.cast()) }
}
}
impl<Ctx: DeviceContext> Device<Ctx> {
/// Obtain the raw `struct device *`.
pub(crate) fn as_raw(&self) -> *mut bindings::device {