[RFC 2/7] [!UPSTREAM] rust: pci: support configuration space access

Zhi Wang posted 7 patches 1 week, 6 days ago
[RFC 2/7] [!UPSTREAM] rust: pci: support configuration space access
Posted by Zhi Wang 1 week, 6 days ago
The work is WIP at [1].

Link: https://lore.kernel.org/all/20251119112117.116979-1-zhiw@nvidia.com/ [1]
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
 rust/kernel/pci.rs | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 9a82e83dfd30..e7fdded9d746 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -526,6 +526,40 @@ pub fn sriov_get_totalvfs(&self) -> Result<i32> {
             Err(ENODEV)
         }
     }
+
+    /// Find the extended capability
+    pub fn find_ext_capability(&self, cap: i32) -> Option<u16> {
+        // SAFETY: `self.as_raw()` is a valid pointer to a `struct pci_dev`.
+        let offset = unsafe { bindings::pci_find_ext_capability(self.as_raw(), cap) };
+        if offset != 0 {
+            Some(offset as u16)
+        } else {
+            None
+        }
+    }
+
+    /// Read configuration space by word
+    pub fn config_read_word(&self, where_: i32) -> Result<u16, Error> {
+        let mut val: u16 = 0;
+
+        // SAFETY: `self.as_raw()` is a valid pointer to `struct pci_dev`,
+        // and `&mut val` is a valid pointer to writable memory.
+        to_result(unsafe {
+            bindings::pci_read_config_word(self.as_raw(), where_, &mut val)
+        })?;
+
+        Ok(val)
+    }
+
+    /// Read configuration space by dword
+    pub fn config_read_dword(&self, where_: i32) -> Result<u32, Error> {
+        let mut val: u32 = 0;
+        // SAFETY: `self.as_raw()` is a valid pointer to `struct pci_dev`,
+        // and `&mut val` is a valid pointer to writable memory.
+        to_result(unsafe { bindings::pci_read_config_dword(self.as_raw(), where_, &mut val) })?;
+
+        Ok(val)
+    }
 }
 
 impl Device<device::Bound> {
-- 
2.51.0
Re: [RFC 2/7] [!UPSTREAM] rust: pci: support configuration space access
Posted by Ewan CHORYNSKI 1 week, 1 day ago
On Sat, Dec 06, 2025 at 12:42:03PM +0000, Zhi Wang wrote:
> +    /// Find the extended capability
> +    pub fn find_ext_capability(&self, cap: i32) -> Option<u16> {
> +        // SAFETY: `self.as_raw()` is a valid pointer to a `struct pci_dev`.
> +        let offset = unsafe { bindings::pci_find_ext_capability(self.as_raw(), cap) };
> +        if offset != 0 {
> +            Some(offset as u16)
> +        } else {
> +            None
> +        }
> +    }

This is a good candidate to use `Option<NonZeroU16>` for the return
type as you don't expect Some(0) to be valid. It will also enable niche
optimisation for the Option. The whole if statement can even be replaced
by `NonZeroU16::new(offset as 16)` which return an option directly.