Commit a095d0d1 authored by Danilo Krummrich's avatar Danilo Krummrich
Browse files

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: default avatarAlice Ryhl <aliceryhl@google.com>
Reviewed-by: default avatarBenno Lossin <benno.lossin@proton.me>
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: default avatarDanilo Krummrich <dakr@kernel.org>
parent cfec9a16
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -16,3 +16,8 @@ resource_size_t rust_helper_pci_resource_len(struct pci_dev *pdev, int bar)
{
	return pci_resource_len(pdev, bar);
}

bool rust_helper_dev_is_pci(const struct device *dev)
{
	return dev_is_pci(dev);
}
+21 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@

use crate::{
    alloc::flags::*,
    bindings, device,
    bindings, container_of, device,
    device_id::RawDeviceId,
    devres::Devres,
    driver,
@@ -455,6 +455,26 @@ fn as_ref(&self) -> &device::Device<Ctx> {
    }
}

impl<Ctx: device::DeviceContext> TryFrom<&device::Device<Ctx>> for &Device<Ctx> {
    type Error = kernel::error::Error;

    fn try_from(dev: &device::Device<Ctx>) -> Result<Self, Self::Error> {
        // 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 {}