From cb271c2edfd0ab7204d5ef3c9d5ae9a0710f5bf2 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Sun, 13 Apr 2025 19:36:56 +0200 Subject: 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 Signed-off-by: Benno Lossin Reviewed-by: Christian Schrefl Link: https://lore.kernel.org/r/20250413173758.12068-2-dakr@kernel.org [ Add missing `::` prefix in macros. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/platform.rs | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'rust/kernel/platform.rs') diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 4917cb34e2fe..22590bdff7bb 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -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 { - type Target = Device; - - fn deref(&self) -> &Self::Target { - let ptr: *const Self = self; - - // CAST: `Device` is a transparent wrapper of `Opaque`. - let ptr = ptr.cast::(); - - // 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> for ARef { fn from(dev: &Device) -> Self { -- cgit From fbb92b6a534081cabd75861ac9c7a8d29d8effda Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Sun, 13 Apr 2025 19:36:57 +0200 Subject: rust: device: implement impl_device_context_into_aref! Implement a macro to implement all From conversions of a certain device to ARef. This avoids unnecessary boiler plate code for every device implementation. Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20250413173758.12068-3-dakr@kernel.org [ Add missing `::` prefix in macros. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/platform.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'rust/kernel/platform.rs') diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 22590bdff7bb..9476b717c425 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -10,7 +10,7 @@ use crate::{ of, prelude::*, str::CStr, - types::{ARef, ForeignOwnable, Opaque}, + types::{ForeignOwnable, Opaque}, ThisModule, }; @@ -192,12 +192,7 @@ impl Device { // 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> for ARef { - fn from(dev: &Device) -> Self { - (&**dev).into() - } -} +kernel::impl_device_context_into_aref!(Device); // SAFETY: Instances of `Device` are always reference-counted. unsafe impl crate::types::AlwaysRefCounted for Device { -- cgit From da6c47c6cb45ffb392e016631c08098ad2a6d418 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Sun, 13 Apr 2025 19:36:59 +0200 Subject: rust: platform: preserve device context in AsRef Since device::Device has a generic over its context, preserve this device context in AsRef. For instance, when calling platform::Device the new AsRef implementation returns device::Device. Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20250413173758.12068-5-dakr@kernel.org Signed-off-by: Danilo Krummrich --- rust/kernel/platform.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'rust/kernel/platform.rs') diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 9476b717c425..b1c48cd95cd6 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -183,7 +183,7 @@ pub struct Device( PhantomData, ); -impl Device { +impl Device { fn as_raw(&self) -> *mut bindings::platform_device { self.0.get() } @@ -207,8 +207,8 @@ unsafe impl crate::types::AlwaysRefCounted for Device { } } -impl AsRef for Device { - fn as_ref(&self) -> &device::Device { +impl AsRef> for Device { + fn as_ref(&self) -> &device::Device { // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid // `struct platform_device`. let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; -- cgit From a38dfd60fe53a46a93517f02a061bb34c47946dc Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Fri, 21 Mar 2025 22:47:55 +0100 Subject: rust: platform: impl TryFrom<&Device> for &platform::Device Implement TryFrom<&device::Device> for &Device. This allows us to get a &platform::Device from a generic &Device in a safe way; the conversion fails if the device' bus type does not match with the platform bus type. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20250321214826.140946-4-dakr@kernel.org [ Support device context types, use dev_is_platform() helper. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/platform.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'rust/kernel/platform.rs') diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index b1c48cd95cd6..08849d92c074 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -5,7 +5,7 @@ //! C header: [`include/linux/platform_device.h`](srctree/include/linux/platform_device.h) use crate::{ - bindings, device, driver, + bindings, container_of, device, driver, error::{to_result, Result}, of, prelude::*, @@ -218,6 +218,26 @@ impl AsRef> for Device { } } +impl TryFrom<&device::Device> for &Device { + type Error = kernel::error::Error; + + fn try_from(dev: &device::Device) -> Result { + // SAFETY: By the type invariant of `Device`, `dev.as_raw()` is a valid pointer to a + // `struct device`. + if !unsafe { bindings::dev_is_platform(dev.as_raw()) } { + return Err(EINVAL); + } + + // SAFETY: We've just verified that the bus type of `dev` equals + // `bindings::platform_bus_type`, hence `dev` must be embedded in a valid + // `struct platform_device` as guaranteed by the corresponding C code. + let pdev = unsafe { container_of!(dev.as_raw(), bindings::platform_device, dev) }; + + // SAFETY: `pdev` is a valid pointer to a `struct platform_device`. + Ok(unsafe { &*pdev.cast() }) + } +} + // SAFETY: A `Device` is always reference-counted and can be released from any thread. unsafe impl Send for Device {} -- cgit From 1a4736c3d8394f5e64557a41b4b2b8d6dcd04622 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 23 Apr 2025 09:54:37 -0400 Subject: rust: types: add `ForeignOwnable::PointedTo` Allow implementors to specify the foreign pointer type; this exposes information about the pointed-to type such as its alignment. This requires the trait to be `unsafe` since it is now possible for implementors to break soundness by returning a misaligned pointer. Encoding the pointer type in the trait (and avoiding pointer casts) allows the compiler to check that implementors return the correct pointer type. This is preferable to directly encoding the alignment in the trait using a constant as the compiler would be unable to check it. Acked-by: Danilo Krummrich Signed-off-by: Tamir Duberstein Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20250423-rust-xarray-bindings-v19-1-83cdcf11c114@gmail.com Signed-off-by: Andreas Hindborg --- rust/kernel/platform.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rust/kernel/platform.rs') diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index 4917cb34e2fe..fd4a494f30e8 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -80,7 +80,7 @@ impl Adapter { extern "C" fn remove_callback(pdev: *mut bindings::platform_device) { // SAFETY: `pdev` is a valid pointer to a `struct platform_device`. - let ptr = unsafe { bindings::platform_get_drvdata(pdev) }; + let ptr = unsafe { bindings::platform_get_drvdata(pdev) }.cast(); // SAFETY: `remove_callback` is only ever called after a successful call to // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized -- cgit From 9f047636831a61ce0840929555245dd17695206a Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 24 Mar 2025 22:03:55 +0100 Subject: rust: platform: fix docs related to missing Markdown code spans Convert `TODO` from documentation to a normal comment, and put code in block. This was found using the Clippy `doc_markdown` lint, which we may want to enable. Fixes: 683a63befc73 ("rust: platform: add basic platform device / driver abstractions") Reviewed-by: Benno Lossin Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20250324210359.1199574-9-ojeda@kernel.org Signed-off-by: Miguel Ojeda --- rust/kernel/platform.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'rust/kernel/platform.rs') diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs index fd4a494f30e8..a02ae5b25b74 100644 --- a/rust/kernel/platform.rs +++ b/rust/kernel/platform.rs @@ -151,10 +151,11 @@ macro_rules! module_platform_driver { ///``` pub trait Driver: Send { /// The type holding driver private data about each device id supported by the driver. - /// - /// TODO: Use associated_type_defaults once stabilized: - /// - /// type IdInfo: 'static = (); + // TODO: Use associated_type_defaults once stabilized: + // + // ``` + // type IdInfo: 'static = (); + // ``` type IdInfo: 'static; /// The table of OF device ids supported by the driver. -- cgit