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/pci.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index c97d6d470b28..8474608e7a90 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -422,19 +422,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/pci.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 8474608e7a90..7c6ec05383e0 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -425,12 +425,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 3edaefbf2b1beb9ae1cb2a842f455157b951e9f1 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Sun, 13 Apr 2025 19:37:00 +0200 Subject: rust: pci: preserve device context in AsRef Since device::Device has a generic over its context, preserve this device context in AsRef. For instance, when calling pci::Device the new AsRef implementation returns device::Device. Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20250413173758.12068-6-dakr@kernel.org Signed-off-by: Danilo Krummrich --- rust/kernel/pci.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 7c6ec05383e0..1234b0c4a403 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -360,11 +360,13 @@ impl Deref for Bar { } } -impl Device { +impl Device { fn as_raw(&self) -> *mut bindings::pci_dev { self.0.get() } +} +impl Device { /// Returns the PCI vendor ID. pub fn vendor_id(&self) -> u16 { // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. @@ -440,8 +442,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 pci_dev`. let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; -- cgit From f2a399d7b67c4a6fc0f8e59d1a9eb484efc71b5c Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Sun, 13 Apr 2025 19:37:02 +0200 Subject: rust: pci: move iomap_region() to impl Device Require the Bound device context to be able to call iomap_region() and iomap_region_sized(). Creating I/O mapping requires the device to be bound. Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20250413173758.12068-8-dakr@kernel.org Signed-off-by: Danilo Krummrich --- rust/kernel/pci.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 1234b0c4a403..3664d35b8e79 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -390,7 +390,9 @@ impl Device { // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`. Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) }) } +} +impl Device { /// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks /// can be performed on compile time for offsets (plus the requested type size) < SIZE. pub fn iomap_region_sized( -- cgit From a095d0d1e4849ee25c28d43d713a8f433d7f1f27 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Fri, 21 Mar 2025 22:47:54 +0100 Subject: rust: pci: impl TryFrom<&Device> for &pci::Device Implement TryFrom<&device::Device> for &Device. This allows us to get a &pci::Device from a generic &Device in a safe way; the conversion fails if the device' bus type does not match with the PCI bus type. Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Link: https://lore.kernel.org/r/20250321214826.140946-3-dakr@kernel.org [ Support device context types, use dev_is_pci() helper. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/pci.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 3664d35b8e79..38fc8d5ffbf9 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -6,7 +6,7 @@ use crate::{ alloc::flags::*, - bindings, device, + bindings, container_of, device, device_id::RawDeviceId, devres::Devres, driver, @@ -455,6 +455,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_pci(dev.as_raw()) } { + return Err(EINVAL); + } + + // SAFETY: We've just verified that the bus type of `dev` equals `bindings::pci_bus_type`, + // hence `dev` must be embedded in a valid `struct pci_dev` as guaranteed by the + // corresponding C code. + let pdev = unsafe { container_of!(dev.as_raw(), bindings::pci_dev, dev) }; + + // SAFETY: `pdev` is a valid pointer to a `struct pci_dev`. + 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/pci.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index c97d6d470b28..3aeb1250c27f 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -89,7 +89,7 @@ impl Adapter { extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) { // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a // `struct pci_dev`. - let ptr = unsafe { bindings::pci_get_drvdata(pdev) }; + let ptr = unsafe { bindings::pci_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 1dbaf8b1bafb8557904eb54b98bb323a3061dd2c Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 24 Mar 2025 22:03:54 +0100 Subject: rust: pci: fix docs related to missing Markdown code spans In particular: - Add missing Markdown code spans. - Improve title for `DeviceId`, adding a link to the struct in the C side, rather than referring to `bindings::`. - 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: 1bd8b6b2c5d3 ("rust: pci: add basic PCI device / driver abstractions") Reviewed-by: Benno Lossin Acked-by: Danilo Krummrich Link: https://lore.kernel.org/r/20250324210359.1199574-8-ojeda@kernel.org [ Prefixed link text with `struct`. - Miguel ] Signed-off-by: Miguel Ojeda --- rust/kernel/pci.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'rust/kernel/pci.rs') diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 3aeb1250c27f..c17a32b76d74 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -118,7 +118,9 @@ macro_rules! module_pci_driver { }; } -/// Abstraction for bindings::pci_device_id. +/// Abstraction for the PCI device ID structure ([`struct pci_device_id`]). +/// +/// [`struct pci_device_id`]: https://docs.kernel.org/PCI/pci.html#c.pci_device_id #[repr(transparent)] #[derive(Clone, Copy)] pub struct DeviceId(bindings::pci_device_id); @@ -173,7 +175,7 @@ unsafe impl RawDeviceId for DeviceId { } } -/// IdTable type for PCI +/// `IdTable` type for PCI. pub type IdTable = &'static dyn kernel::device_id::IdTable; /// Create a PCI `IdTable` with its alias for modpost. @@ -224,10 +226,11 @@ macro_rules! pci_device_table { /// `Adapter` documentation for an example. pub trait Driver: Send { /// The type holding information 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 device ids supported by the driver. -- cgit