xref: /linux/rust/kernel/pci.rs (revision ec7714e4947909190ffb3041a03311a975350fe0)
11bd8b6b2SDanilo Krummrich // SPDX-License-Identifier: GPL-2.0
21bd8b6b2SDanilo Krummrich 
31bd8b6b2SDanilo Krummrich //! Abstractions for the PCI bus.
41bd8b6b2SDanilo Krummrich //!
51bd8b6b2SDanilo Krummrich //! C header: [`include/linux/pci.h`](srctree/include/linux/pci.h)
61bd8b6b2SDanilo Krummrich 
71bd8b6b2SDanilo Krummrich use crate::{
8bf9651f8SDanilo Krummrich     alloc::flags::*,
9a095d0d1SDanilo Krummrich     bindings, container_of, device,
101bd8b6b2SDanilo Krummrich     device_id::RawDeviceId,
11bf9651f8SDanilo Krummrich     devres::Devres,
121bd8b6b2SDanilo Krummrich     driver,
131bd8b6b2SDanilo Krummrich     error::{to_result, Result},
14bf9651f8SDanilo Krummrich     io::Io,
15bf9651f8SDanilo Krummrich     io::IoRaw,
161bd8b6b2SDanilo Krummrich     str::CStr,
171bd8b6b2SDanilo Krummrich     types::{ARef, ForeignOwnable, Opaque},
181bd8b6b2SDanilo Krummrich     ThisModule,
191bd8b6b2SDanilo Krummrich };
207b948a2aSDanilo Krummrich use core::{
217b948a2aSDanilo Krummrich     marker::PhantomData,
227b948a2aSDanilo Krummrich     ops::Deref,
237b948a2aSDanilo Krummrich     ptr::{addr_of_mut, NonNull},
247b948a2aSDanilo Krummrich };
251bd8b6b2SDanilo Krummrich use kernel::prelude::*;
261bd8b6b2SDanilo Krummrich 
271bd8b6b2SDanilo Krummrich /// An adapter for the registration of PCI drivers.
281bd8b6b2SDanilo Krummrich pub struct Adapter<T: Driver>(T);
291bd8b6b2SDanilo Krummrich 
30e1a51c2bSDanilo Krummrich // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
31e1a51c2bSDanilo Krummrich // a preceding call to `register` has been successful.
32e1a51c2bSDanilo Krummrich unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
331bd8b6b2SDanilo Krummrich     type RegType = bindings::pci_driver;
341bd8b6b2SDanilo Krummrich 
register( pdrv: &Opaque<Self::RegType>, name: &'static CStr, module: &'static ThisModule, ) -> Result35e1a51c2bSDanilo Krummrich     unsafe fn register(
361bd8b6b2SDanilo Krummrich         pdrv: &Opaque<Self::RegType>,
371bd8b6b2SDanilo Krummrich         name: &'static CStr,
381bd8b6b2SDanilo Krummrich         module: &'static ThisModule,
391bd8b6b2SDanilo Krummrich     ) -> Result {
401bd8b6b2SDanilo Krummrich         // SAFETY: It's safe to set the fields of `struct pci_driver` on initialization.
411bd8b6b2SDanilo Krummrich         unsafe {
421bd8b6b2SDanilo Krummrich             (*pdrv.get()).name = name.as_char_ptr();
431bd8b6b2SDanilo Krummrich             (*pdrv.get()).probe = Some(Self::probe_callback);
441bd8b6b2SDanilo Krummrich             (*pdrv.get()).remove = Some(Self::remove_callback);
451bd8b6b2SDanilo Krummrich             (*pdrv.get()).id_table = T::ID_TABLE.as_ptr();
461bd8b6b2SDanilo Krummrich         }
471bd8b6b2SDanilo Krummrich 
481bd8b6b2SDanilo Krummrich         // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
491bd8b6b2SDanilo Krummrich         to_result(unsafe {
501bd8b6b2SDanilo Krummrich             bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr())
511bd8b6b2SDanilo Krummrich         })
521bd8b6b2SDanilo Krummrich     }
531bd8b6b2SDanilo Krummrich 
unregister(pdrv: &Opaque<Self::RegType>)54e1a51c2bSDanilo Krummrich     unsafe fn unregister(pdrv: &Opaque<Self::RegType>) {
551bd8b6b2SDanilo Krummrich         // SAFETY: `pdrv` is guaranteed to be a valid `RegType`.
561bd8b6b2SDanilo Krummrich         unsafe { bindings::pci_unregister_driver(pdrv.get()) }
571bd8b6b2SDanilo Krummrich     }
581bd8b6b2SDanilo Krummrich }
591bd8b6b2SDanilo Krummrich 
601bd8b6b2SDanilo Krummrich impl<T: Driver + 'static> Adapter<T> {
probe_callback( pdev: *mut bindings::pci_dev, id: *const bindings::pci_device_id, ) -> kernel::ffi::c_int611bd8b6b2SDanilo Krummrich     extern "C" fn probe_callback(
621bd8b6b2SDanilo Krummrich         pdev: *mut bindings::pci_dev,
631bd8b6b2SDanilo Krummrich         id: *const bindings::pci_device_id,
641bd8b6b2SDanilo Krummrich     ) -> kernel::ffi::c_int {
651bd8b6b2SDanilo Krummrich         // SAFETY: The PCI bus only ever calls the probe callback with a valid pointer to a
661bd8b6b2SDanilo Krummrich         // `struct pci_dev`.
677b948a2aSDanilo Krummrich         //
687b948a2aSDanilo Krummrich         // INVARIANT: `pdev` is valid for the duration of `probe_callback()`.
697b948a2aSDanilo Krummrich         let pdev = unsafe { &*pdev.cast::<Device<device::Core>>() };
701bd8b6b2SDanilo Krummrich 
711bd8b6b2SDanilo Krummrich         // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct pci_device_id` and
721bd8b6b2SDanilo Krummrich         // does not add additional invariants, so it's safe to transmute.
731bd8b6b2SDanilo Krummrich         let id = unsafe { &*id.cast::<DeviceId>() };
741bd8b6b2SDanilo Krummrich         let info = T::ID_TABLE.info(id.index());
751bd8b6b2SDanilo Krummrich 
767b948a2aSDanilo Krummrich         match T::probe(pdev, info) {
771bd8b6b2SDanilo Krummrich             Ok(data) => {
781bd8b6b2SDanilo Krummrich                 // Let the `struct pci_dev` own a reference of the driver's private data.
791bd8b6b2SDanilo Krummrich                 // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a
801bd8b6b2SDanilo Krummrich                 // `struct pci_dev`.
811bd8b6b2SDanilo Krummrich                 unsafe { bindings::pci_set_drvdata(pdev.as_raw(), data.into_foreign() as _) };
821bd8b6b2SDanilo Krummrich             }
831bd8b6b2SDanilo Krummrich             Err(err) => return Error::to_errno(err),
841bd8b6b2SDanilo Krummrich         }
851bd8b6b2SDanilo Krummrich 
861bd8b6b2SDanilo Krummrich         0
871bd8b6b2SDanilo Krummrich     }
881bd8b6b2SDanilo Krummrich 
remove_callback(pdev: *mut bindings::pci_dev)891bd8b6b2SDanilo Krummrich     extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) {
901bd8b6b2SDanilo Krummrich         // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a
911bd8b6b2SDanilo Krummrich         // `struct pci_dev`.
921a4736c3STamir Duberstein         let ptr = unsafe { bindings::pci_get_drvdata(pdev) }.cast();
931bd8b6b2SDanilo Krummrich 
941bd8b6b2SDanilo Krummrich         // SAFETY: `remove_callback` is only ever called after a successful call to
951bd8b6b2SDanilo Krummrich         // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized
961bd8b6b2SDanilo Krummrich         // `KBox<T>` pointer created through `KBox::into_foreign`.
971bd8b6b2SDanilo Krummrich         let _ = unsafe { KBox::<T>::from_foreign(ptr) };
981bd8b6b2SDanilo Krummrich     }
991bd8b6b2SDanilo Krummrich }
1001bd8b6b2SDanilo Krummrich 
1011bd8b6b2SDanilo Krummrich /// Declares a kernel module that exposes a single PCI driver.
1021bd8b6b2SDanilo Krummrich ///
1031bd8b6b2SDanilo Krummrich /// # Example
1041bd8b6b2SDanilo Krummrich ///
1051bd8b6b2SDanilo Krummrich ///```ignore
1061bd8b6b2SDanilo Krummrich /// kernel::module_pci_driver! {
1071bd8b6b2SDanilo Krummrich ///     type: MyDriver,
1081bd8b6b2SDanilo Krummrich ///     name: "Module name",
10938559da6SGuilherme Giacomo Simoes ///     authors: ["Author name"],
1101bd8b6b2SDanilo Krummrich ///     description: "Description",
1111bd8b6b2SDanilo Krummrich ///     license: "GPL v2",
1121bd8b6b2SDanilo Krummrich /// }
1131bd8b6b2SDanilo Krummrich ///```
1141bd8b6b2SDanilo Krummrich #[macro_export]
1151bd8b6b2SDanilo Krummrich macro_rules! module_pci_driver {
1161bd8b6b2SDanilo Krummrich ($($f:tt)*) => {
1171bd8b6b2SDanilo Krummrich     $crate::module_driver!(<T>, $crate::pci::Adapter<T>, { $($f)* });
1181bd8b6b2SDanilo Krummrich };
1191bd8b6b2SDanilo Krummrich }
1201bd8b6b2SDanilo Krummrich 
121*1dbaf8b1SMiguel Ojeda /// Abstraction for the PCI device ID structure ([`struct pci_device_id`]).
122*1dbaf8b1SMiguel Ojeda ///
123*1dbaf8b1SMiguel Ojeda /// [`struct pci_device_id`]: https://docs.kernel.org/PCI/pci.html#c.pci_device_id
1241bd8b6b2SDanilo Krummrich #[repr(transparent)]
1251bd8b6b2SDanilo Krummrich #[derive(Clone, Copy)]
1261bd8b6b2SDanilo Krummrich pub struct DeviceId(bindings::pci_device_id);
1271bd8b6b2SDanilo Krummrich 
1281bd8b6b2SDanilo Krummrich impl DeviceId {
1291bd8b6b2SDanilo Krummrich     const PCI_ANY_ID: u32 = !0;
1301bd8b6b2SDanilo Krummrich 
1311bd8b6b2SDanilo Krummrich     /// Equivalent to C's `PCI_DEVICE` macro.
1321bd8b6b2SDanilo Krummrich     ///
1331bd8b6b2SDanilo Krummrich     /// Create a new `pci::DeviceId` from a vendor and device ID number.
from_id(vendor: u32, device: u32) -> Self1341bd8b6b2SDanilo Krummrich     pub const fn from_id(vendor: u32, device: u32) -> Self {
1351bd8b6b2SDanilo Krummrich         Self(bindings::pci_device_id {
1361bd8b6b2SDanilo Krummrich             vendor,
1371bd8b6b2SDanilo Krummrich             device,
1381bd8b6b2SDanilo Krummrich             subvendor: DeviceId::PCI_ANY_ID,
1391bd8b6b2SDanilo Krummrich             subdevice: DeviceId::PCI_ANY_ID,
1401bd8b6b2SDanilo Krummrich             class: 0,
1411bd8b6b2SDanilo Krummrich             class_mask: 0,
1421bd8b6b2SDanilo Krummrich             driver_data: 0,
1431bd8b6b2SDanilo Krummrich             override_only: 0,
1441bd8b6b2SDanilo Krummrich         })
1451bd8b6b2SDanilo Krummrich     }
1461bd8b6b2SDanilo Krummrich 
1471bd8b6b2SDanilo Krummrich     /// Equivalent to C's `PCI_DEVICE_CLASS` macro.
1481bd8b6b2SDanilo Krummrich     ///
1491bd8b6b2SDanilo Krummrich     /// Create a new `pci::DeviceId` from a class number and mask.
from_class(class: u32, class_mask: u32) -> Self1501bd8b6b2SDanilo Krummrich     pub const fn from_class(class: u32, class_mask: u32) -> Self {
1511bd8b6b2SDanilo Krummrich         Self(bindings::pci_device_id {
1521bd8b6b2SDanilo Krummrich             vendor: DeviceId::PCI_ANY_ID,
1531bd8b6b2SDanilo Krummrich             device: DeviceId::PCI_ANY_ID,
1541bd8b6b2SDanilo Krummrich             subvendor: DeviceId::PCI_ANY_ID,
1551bd8b6b2SDanilo Krummrich             subdevice: DeviceId::PCI_ANY_ID,
1561bd8b6b2SDanilo Krummrich             class,
1571bd8b6b2SDanilo Krummrich             class_mask,
1581bd8b6b2SDanilo Krummrich             driver_data: 0,
1591bd8b6b2SDanilo Krummrich             override_only: 0,
1601bd8b6b2SDanilo Krummrich         })
1611bd8b6b2SDanilo Krummrich     }
1621bd8b6b2SDanilo Krummrich }
1631bd8b6b2SDanilo Krummrich 
1641bd8b6b2SDanilo Krummrich // SAFETY:
1651bd8b6b2SDanilo Krummrich // * `DeviceId` is a `#[repr(transparent)` wrapper of `pci_device_id` and does not add
1661bd8b6b2SDanilo Krummrich //   additional invariants, so it's safe to transmute to `RawType`.
1671bd8b6b2SDanilo Krummrich // * `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.
1681bd8b6b2SDanilo Krummrich unsafe impl RawDeviceId for DeviceId {
1691bd8b6b2SDanilo Krummrich     type RawType = bindings::pci_device_id;
1701bd8b6b2SDanilo Krummrich 
1711bd8b6b2SDanilo Krummrich     const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data);
1721bd8b6b2SDanilo Krummrich 
index(&self) -> usize1731bd8b6b2SDanilo Krummrich     fn index(&self) -> usize {
1741bd8b6b2SDanilo Krummrich         self.0.driver_data as _
1751bd8b6b2SDanilo Krummrich     }
1761bd8b6b2SDanilo Krummrich }
1771bd8b6b2SDanilo Krummrich 
178*1dbaf8b1SMiguel Ojeda /// `IdTable` type for PCI.
1791bd8b6b2SDanilo Krummrich pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>;
1801bd8b6b2SDanilo Krummrich 
1811bd8b6b2SDanilo Krummrich /// Create a PCI `IdTable` with its alias for modpost.
1821bd8b6b2SDanilo Krummrich #[macro_export]
1831bd8b6b2SDanilo Krummrich macro_rules! pci_device_table {
1841bd8b6b2SDanilo Krummrich     ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
1851bd8b6b2SDanilo Krummrich         const $table_name: $crate::device_id::IdArray<
1861bd8b6b2SDanilo Krummrich             $crate::pci::DeviceId,
1871bd8b6b2SDanilo Krummrich             $id_info_type,
1881bd8b6b2SDanilo Krummrich             { $table_data.len() },
1891bd8b6b2SDanilo Krummrich         > = $crate::device_id::IdArray::new($table_data);
1901bd8b6b2SDanilo Krummrich 
1911bd8b6b2SDanilo Krummrich         $crate::module_device_table!("pci", $module_table_name, $table_name);
1921bd8b6b2SDanilo Krummrich     };
1931bd8b6b2SDanilo Krummrich }
1941bd8b6b2SDanilo Krummrich 
1951bd8b6b2SDanilo Krummrich /// The PCI driver trait.
1961bd8b6b2SDanilo Krummrich ///
1971bd8b6b2SDanilo Krummrich /// # Example
1981bd8b6b2SDanilo Krummrich ///
1991bd8b6b2SDanilo Krummrich ///```
2007b948a2aSDanilo Krummrich /// # use kernel::{bindings, device::Core, pci};
2011bd8b6b2SDanilo Krummrich ///
2021bd8b6b2SDanilo Krummrich /// struct MyDriver;
2031bd8b6b2SDanilo Krummrich ///
2041bd8b6b2SDanilo Krummrich /// kernel::pci_device_table!(
2051bd8b6b2SDanilo Krummrich ///     PCI_TABLE,
2061bd8b6b2SDanilo Krummrich ///     MODULE_PCI_TABLE,
2071bd8b6b2SDanilo Krummrich ///     <MyDriver as pci::Driver>::IdInfo,
2081bd8b6b2SDanilo Krummrich ///     [
2091bd8b6b2SDanilo Krummrich ///         (pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as _), ())
2101bd8b6b2SDanilo Krummrich ///     ]
2111bd8b6b2SDanilo Krummrich /// );
2121bd8b6b2SDanilo Krummrich ///
2131bd8b6b2SDanilo Krummrich /// impl pci::Driver for MyDriver {
2141bd8b6b2SDanilo Krummrich ///     type IdInfo = ();
2151bd8b6b2SDanilo Krummrich ///     const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
2161bd8b6b2SDanilo Krummrich ///
2171bd8b6b2SDanilo Krummrich ///     fn probe(
2187b948a2aSDanilo Krummrich ///         _pdev: &pci::Device<Core>,
2191bd8b6b2SDanilo Krummrich ///         _id_info: &Self::IdInfo,
2201bd8b6b2SDanilo Krummrich ///     ) -> Result<Pin<KBox<Self>>> {
2211bd8b6b2SDanilo Krummrich ///         Err(ENODEV)
2221bd8b6b2SDanilo Krummrich ///     }
2231bd8b6b2SDanilo Krummrich /// }
2241bd8b6b2SDanilo Krummrich ///```
2251bd8b6b2SDanilo Krummrich /// Drivers must implement this trait in order to get a PCI driver registered. Please refer to the
2261bd8b6b2SDanilo Krummrich /// `Adapter` documentation for an example.
227935e1d90SDanilo Krummrich pub trait Driver: Send {
2281bd8b6b2SDanilo Krummrich     /// The type holding information about each device id supported by the driver.
229*1dbaf8b1SMiguel Ojeda     // TODO: Use `associated_type_defaults` once stabilized:
230*1dbaf8b1SMiguel Ojeda     //
231*1dbaf8b1SMiguel Ojeda     // ```
232*1dbaf8b1SMiguel Ojeda     // type IdInfo: 'static = ();
233*1dbaf8b1SMiguel Ojeda     // ```
2341bd8b6b2SDanilo Krummrich     type IdInfo: 'static;
2351bd8b6b2SDanilo Krummrich 
2361bd8b6b2SDanilo Krummrich     /// The table of device ids supported by the driver.
2371bd8b6b2SDanilo Krummrich     const ID_TABLE: IdTable<Self::IdInfo>;
2381bd8b6b2SDanilo Krummrich 
2391bd8b6b2SDanilo Krummrich     /// PCI driver probe.
2401bd8b6b2SDanilo Krummrich     ///
2411bd8b6b2SDanilo Krummrich     /// Called when a new platform device is added or discovered.
2421bd8b6b2SDanilo Krummrich     /// Implementers should attempt to initialize the device here.
probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>2437b948a2aSDanilo Krummrich     fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>;
2441bd8b6b2SDanilo Krummrich }
2451bd8b6b2SDanilo Krummrich 
2461bd8b6b2SDanilo Krummrich /// The PCI device representation.
2471bd8b6b2SDanilo Krummrich ///
2487b948a2aSDanilo Krummrich /// This structure represents the Rust abstraction for a C `struct pci_dev`. The implementation
2497b948a2aSDanilo Krummrich /// abstracts the usage of an already existing C `struct pci_dev` within Rust code that we get
2507b948a2aSDanilo Krummrich /// passed from the C side.
251bf9651f8SDanilo Krummrich ///
252bf9651f8SDanilo Krummrich /// # Invariants
253bf9651f8SDanilo Krummrich ///
2547b948a2aSDanilo Krummrich /// A [`Device`] instance represents a valid `struct device` created by the C portion of the kernel.
2557b948a2aSDanilo Krummrich #[repr(transparent)]
2567b948a2aSDanilo Krummrich pub struct Device<Ctx: device::DeviceContext = device::Normal>(
2577b948a2aSDanilo Krummrich     Opaque<bindings::pci_dev>,
2587b948a2aSDanilo Krummrich     PhantomData<Ctx>,
2597b948a2aSDanilo Krummrich );
2601bd8b6b2SDanilo Krummrich 
261bf9651f8SDanilo Krummrich /// A PCI BAR to perform I/O-Operations on.
262bf9651f8SDanilo Krummrich ///
263bf9651f8SDanilo Krummrich /// # Invariants
264bf9651f8SDanilo Krummrich ///
265bf9651f8SDanilo Krummrich /// `Bar` always holds an `IoRaw` inststance that holds a valid pointer to the start of the I/O
266bf9651f8SDanilo Krummrich /// memory mapped PCI bar and its size.
267bf9651f8SDanilo Krummrich pub struct Bar<const SIZE: usize = 0> {
2687b948a2aSDanilo Krummrich     pdev: ARef<Device>,
269bf9651f8SDanilo Krummrich     io: IoRaw<SIZE>,
270bf9651f8SDanilo Krummrich     num: i32,
271bf9651f8SDanilo Krummrich }
272bf9651f8SDanilo Krummrich 
273bf9651f8SDanilo Krummrich impl<const SIZE: usize> Bar<SIZE> {
new(pdev: &Device, num: u32, name: &CStr) -> Result<Self>2747b948a2aSDanilo Krummrich     fn new(pdev: &Device, num: u32, name: &CStr) -> Result<Self> {
275bf9651f8SDanilo Krummrich         let len = pdev.resource_len(num)?;
276bf9651f8SDanilo Krummrich         if len == 0 {
277bf9651f8SDanilo Krummrich             return Err(ENOMEM);
278bf9651f8SDanilo Krummrich         }
279bf9651f8SDanilo Krummrich 
280bf9651f8SDanilo Krummrich         // Convert to `i32`, since that's what all the C bindings use.
281bf9651f8SDanilo Krummrich         let num = i32::try_from(num)?;
282bf9651f8SDanilo Krummrich 
283bf9651f8SDanilo Krummrich         // SAFETY:
284bf9651f8SDanilo Krummrich         // `pdev` is valid by the invariants of `Device`.
285bf9651f8SDanilo Krummrich         // `num` is checked for validity by a previous call to `Device::resource_len`.
286bf9651f8SDanilo Krummrich         // `name` is always valid.
287bf9651f8SDanilo Krummrich         let ret = unsafe { bindings::pci_request_region(pdev.as_raw(), num, name.as_char_ptr()) };
288bf9651f8SDanilo Krummrich         if ret != 0 {
289bf9651f8SDanilo Krummrich             return Err(EBUSY);
290bf9651f8SDanilo Krummrich         }
291bf9651f8SDanilo Krummrich 
292bf9651f8SDanilo Krummrich         // SAFETY:
293bf9651f8SDanilo Krummrich         // `pdev` is valid by the invariants of `Device`.
294bf9651f8SDanilo Krummrich         // `num` is checked for validity by a previous call to `Device::resource_len`.
295bf9651f8SDanilo Krummrich         // `name` is always valid.
296bf9651f8SDanilo Krummrich         let ioptr: usize = unsafe { bindings::pci_iomap(pdev.as_raw(), num, 0) } as usize;
297bf9651f8SDanilo Krummrich         if ioptr == 0 {
298bf9651f8SDanilo Krummrich             // SAFETY:
299bf9651f8SDanilo Krummrich             // `pdev` valid by the invariants of `Device`.
300bf9651f8SDanilo Krummrich             // `num` is checked for validity by a previous call to `Device::resource_len`.
301bf9651f8SDanilo Krummrich             unsafe { bindings::pci_release_region(pdev.as_raw(), num) };
302bf9651f8SDanilo Krummrich             return Err(ENOMEM);
303bf9651f8SDanilo Krummrich         }
304bf9651f8SDanilo Krummrich 
305bf9651f8SDanilo Krummrich         let io = match IoRaw::new(ioptr, len as usize) {
306bf9651f8SDanilo Krummrich             Ok(io) => io,
307bf9651f8SDanilo Krummrich             Err(err) => {
308bf9651f8SDanilo Krummrich                 // SAFETY:
309bf9651f8SDanilo Krummrich                 // `pdev` is valid by the invariants of `Device`.
310bf9651f8SDanilo Krummrich                 // `ioptr` is guaranteed to be the start of a valid I/O mapped memory region.
311bf9651f8SDanilo Krummrich                 // `num` is checked for validity by a previous call to `Device::resource_len`.
3127b948a2aSDanilo Krummrich                 unsafe { Self::do_release(pdev, ioptr, num) };
313bf9651f8SDanilo Krummrich                 return Err(err);
314bf9651f8SDanilo Krummrich             }
315bf9651f8SDanilo Krummrich         };
316bf9651f8SDanilo Krummrich 
3177b948a2aSDanilo Krummrich         Ok(Bar {
3187b948a2aSDanilo Krummrich             pdev: pdev.into(),
3197b948a2aSDanilo Krummrich             io,
3207b948a2aSDanilo Krummrich             num,
3217b948a2aSDanilo Krummrich         })
322bf9651f8SDanilo Krummrich     }
323bf9651f8SDanilo Krummrich 
324bf9651f8SDanilo Krummrich     /// # Safety
325bf9651f8SDanilo Krummrich     ///
326bf9651f8SDanilo Krummrich     /// `ioptr` must be a valid pointer to the memory mapped PCI bar number `num`.
do_release(pdev: &Device, ioptr: usize, num: i32)327bf9651f8SDanilo Krummrich     unsafe fn do_release(pdev: &Device, ioptr: usize, num: i32) {
328bf9651f8SDanilo Krummrich         // SAFETY:
329bf9651f8SDanilo Krummrich         // `pdev` is valid by the invariants of `Device`.
330bf9651f8SDanilo Krummrich         // `ioptr` is valid by the safety requirements.
331bf9651f8SDanilo Krummrich         // `num` is valid by the safety requirements.
332bf9651f8SDanilo Krummrich         unsafe {
333bf9651f8SDanilo Krummrich             bindings::pci_iounmap(pdev.as_raw(), ioptr as _);
334bf9651f8SDanilo Krummrich             bindings::pci_release_region(pdev.as_raw(), num);
335bf9651f8SDanilo Krummrich         }
336bf9651f8SDanilo Krummrich     }
337bf9651f8SDanilo Krummrich 
release(&self)338bf9651f8SDanilo Krummrich     fn release(&self) {
339bf9651f8SDanilo Krummrich         // SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`.
340bf9651f8SDanilo Krummrich         unsafe { Self::do_release(&self.pdev, self.io.addr(), self.num) };
341bf9651f8SDanilo Krummrich     }
342bf9651f8SDanilo Krummrich }
343bf9651f8SDanilo Krummrich 
344bf9651f8SDanilo Krummrich impl Bar {
index_is_valid(index: u32) -> bool345bf9651f8SDanilo Krummrich     fn index_is_valid(index: u32) -> bool {
346bf9651f8SDanilo Krummrich         // A `struct pci_dev` owns an array of resources with at most `PCI_NUM_RESOURCES` entries.
347bf9651f8SDanilo Krummrich         index < bindings::PCI_NUM_RESOURCES
348bf9651f8SDanilo Krummrich     }
349bf9651f8SDanilo Krummrich }
350bf9651f8SDanilo Krummrich 
351bf9651f8SDanilo Krummrich impl<const SIZE: usize> Drop for Bar<SIZE> {
drop(&mut self)352bf9651f8SDanilo Krummrich     fn drop(&mut self) {
353bf9651f8SDanilo Krummrich         self.release();
354bf9651f8SDanilo Krummrich     }
355bf9651f8SDanilo Krummrich }
356bf9651f8SDanilo Krummrich 
357bf9651f8SDanilo Krummrich impl<const SIZE: usize> Deref for Bar<SIZE> {
358bf9651f8SDanilo Krummrich     type Target = Io<SIZE>;
359bf9651f8SDanilo Krummrich 
deref(&self) -> &Self::Target360bf9651f8SDanilo Krummrich     fn deref(&self) -> &Self::Target {
361bf9651f8SDanilo Krummrich         // SAFETY: By the type invariant of `Self`, the MMIO range in `self.io` is properly mapped.
362bf9651f8SDanilo Krummrich         unsafe { Io::from_raw(&self.io) }
363bf9651f8SDanilo Krummrich     }
364bf9651f8SDanilo Krummrich }
365bf9651f8SDanilo Krummrich 
3663edaefbfSDanilo Krummrich impl<Ctx: device::DeviceContext> Device<Ctx> {
as_raw(&self) -> *mut bindings::pci_dev3671bd8b6b2SDanilo Krummrich     fn as_raw(&self) -> *mut bindings::pci_dev {
3687b948a2aSDanilo Krummrich         self.0.get()
3691bd8b6b2SDanilo Krummrich     }
3703edaefbfSDanilo Krummrich }
3711bd8b6b2SDanilo Krummrich 
3723edaefbfSDanilo Krummrich impl Device {
3731bd8b6b2SDanilo Krummrich     /// Returns the PCI vendor ID.
vendor_id(&self) -> u163741bd8b6b2SDanilo Krummrich     pub fn vendor_id(&self) -> u16 {
3751bd8b6b2SDanilo Krummrich         // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.
3761bd8b6b2SDanilo Krummrich         unsafe { (*self.as_raw()).vendor }
3771bd8b6b2SDanilo Krummrich     }
3781bd8b6b2SDanilo Krummrich 
3791bd8b6b2SDanilo Krummrich     /// Returns the PCI device ID.
device_id(&self) -> u163801bd8b6b2SDanilo Krummrich     pub fn device_id(&self) -> u16 {
3811bd8b6b2SDanilo Krummrich         // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.
3821bd8b6b2SDanilo Krummrich         unsafe { (*self.as_raw()).device }
3831bd8b6b2SDanilo Krummrich     }
3841bd8b6b2SDanilo Krummrich 
385bf9651f8SDanilo Krummrich     /// Returns the size of the given PCI bar resource.
resource_len(&self, bar: u32) -> Result<bindings::resource_size_t>386bf9651f8SDanilo Krummrich     pub fn resource_len(&self, bar: u32) -> Result<bindings::resource_size_t> {
387bf9651f8SDanilo Krummrich         if !Bar::index_is_valid(bar) {
388bf9651f8SDanilo Krummrich             return Err(EINVAL);
389bf9651f8SDanilo Krummrich         }
390bf9651f8SDanilo Krummrich 
391bf9651f8SDanilo Krummrich         // SAFETY:
392bf9651f8SDanilo Krummrich         // - `bar` is a valid bar number, as guaranteed by the above call to `Bar::index_is_valid`,
393bf9651f8SDanilo Krummrich         // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`.
394bf9651f8SDanilo Krummrich         Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) })
395bf9651f8SDanilo Krummrich     }
396f2a399d7SDanilo Krummrich }
397bf9651f8SDanilo Krummrich 
398f2a399d7SDanilo Krummrich impl Device<device::Bound> {
399bf9651f8SDanilo Krummrich     /// Mapps an entire PCI-BAR after performing a region-request on it. I/O operation bound checks
400bf9651f8SDanilo Krummrich     /// can be performed on compile time for offsets (plus the requested type size) < SIZE.
iomap_region_sized<const SIZE: usize>( &self, bar: u32, name: &CStr, ) -> Result<Devres<Bar<SIZE>>>401bf9651f8SDanilo Krummrich     pub fn iomap_region_sized<const SIZE: usize>(
402bf9651f8SDanilo Krummrich         &self,
403bf9651f8SDanilo Krummrich         bar: u32,
404bf9651f8SDanilo Krummrich         name: &CStr,
405bf9651f8SDanilo Krummrich     ) -> Result<Devres<Bar<SIZE>>> {
4067b948a2aSDanilo Krummrich         let bar = Bar::<SIZE>::new(self, bar, name)?;
407bf9651f8SDanilo Krummrich         let devres = Devres::new(self.as_ref(), bar, GFP_KERNEL)?;
408bf9651f8SDanilo Krummrich 
409bf9651f8SDanilo Krummrich         Ok(devres)
410bf9651f8SDanilo Krummrich     }
411bf9651f8SDanilo Krummrich 
412bf9651f8SDanilo Krummrich     /// Mapps an entire PCI-BAR after performing a region-request on it.
iomap_region(&self, bar: u32, name: &CStr) -> Result<Devres<Bar>>413bf9651f8SDanilo Krummrich     pub fn iomap_region(&self, bar: u32, name: &CStr) -> Result<Devres<Bar>> {
414bf9651f8SDanilo Krummrich         self.iomap_region_sized::<0>(bar, name)
415bf9651f8SDanilo Krummrich     }
4161bd8b6b2SDanilo Krummrich }
4171bd8b6b2SDanilo Krummrich 
4187b948a2aSDanilo Krummrich impl Device<device::Core> {
4197b948a2aSDanilo Krummrich     /// Enable memory resources for this device.
enable_device_mem(&self) -> Result4207b948a2aSDanilo Krummrich     pub fn enable_device_mem(&self) -> Result {
4217b948a2aSDanilo Krummrich         // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`.
4227b948a2aSDanilo Krummrich         to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) })
4237b948a2aSDanilo Krummrich     }
4247b948a2aSDanilo Krummrich 
4257b948a2aSDanilo Krummrich     /// Enable bus-mastering for this device.
set_master(&self)4267b948a2aSDanilo Krummrich     pub fn set_master(&self) {
4277b948a2aSDanilo Krummrich         // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`.
4287b948a2aSDanilo Krummrich         unsafe { bindings::pci_set_master(self.as_raw()) };
4297b948a2aSDanilo Krummrich     }
4307b948a2aSDanilo Krummrich }
4317b948a2aSDanilo Krummrich 
432cb271c2eSDanilo Krummrich // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
433cb271c2eSDanilo Krummrich // argument.
434cb271c2eSDanilo Krummrich kernel::impl_device_context_deref!(unsafe { Device });
435fbb92b6aSDanilo Krummrich kernel::impl_device_context_into_aref!(Device);
4367b948a2aSDanilo Krummrich 
4377b948a2aSDanilo Krummrich // SAFETY: Instances of `Device` are always reference-counted.
4387b948a2aSDanilo Krummrich unsafe impl crate::types::AlwaysRefCounted for Device {
inc_ref(&self)4397b948a2aSDanilo Krummrich     fn inc_ref(&self) {
4407b948a2aSDanilo Krummrich         // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
4417b948a2aSDanilo Krummrich         unsafe { bindings::pci_dev_get(self.as_raw()) };
4427b948a2aSDanilo Krummrich     }
4437b948a2aSDanilo Krummrich 
dec_ref(obj: NonNull<Self>)4447b948a2aSDanilo Krummrich     unsafe fn dec_ref(obj: NonNull<Self>) {
4457b948a2aSDanilo Krummrich         // SAFETY: The safety requirements guarantee that the refcount is non-zero.
4467b948a2aSDanilo Krummrich         unsafe { bindings::pci_dev_put(obj.cast().as_ptr()) }
4477b948a2aSDanilo Krummrich     }
4487b948a2aSDanilo Krummrich }
4497b948a2aSDanilo Krummrich 
4503edaefbfSDanilo Krummrich impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
as_ref(&self) -> &device::Device<Ctx>4513edaefbfSDanilo Krummrich     fn as_ref(&self) -> &device::Device<Ctx> {
4527b948a2aSDanilo Krummrich         // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
4537b948a2aSDanilo Krummrich         // `struct pci_dev`.
4547b948a2aSDanilo Krummrich         let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
4557b948a2aSDanilo Krummrich 
4567b948a2aSDanilo Krummrich         // SAFETY: `dev` points to a valid `struct device`.
4577b948a2aSDanilo Krummrich         unsafe { device::Device::as_ref(dev) }
4581bd8b6b2SDanilo Krummrich     }
4591bd8b6b2SDanilo Krummrich }
460e2942bb4SDanilo Krummrich 
461a095d0d1SDanilo Krummrich impl<Ctx: device::DeviceContext> TryFrom<&device::Device<Ctx>> for &Device<Ctx> {
462a095d0d1SDanilo Krummrich     type Error = kernel::error::Error;
463a095d0d1SDanilo Krummrich 
try_from(dev: &device::Device<Ctx>) -> Result<Self, Self::Error>464a095d0d1SDanilo Krummrich     fn try_from(dev: &device::Device<Ctx>) -> Result<Self, Self::Error> {
465a095d0d1SDanilo Krummrich         // SAFETY: By the type invariant of `Device`, `dev.as_raw()` is a valid pointer to a
466a095d0d1SDanilo Krummrich         // `struct device`.
467a095d0d1SDanilo Krummrich         if !unsafe { bindings::dev_is_pci(dev.as_raw()) } {
468a095d0d1SDanilo Krummrich             return Err(EINVAL);
469a095d0d1SDanilo Krummrich         }
470a095d0d1SDanilo Krummrich 
471a095d0d1SDanilo Krummrich         // SAFETY: We've just verified that the bus type of `dev` equals `bindings::pci_bus_type`,
472a095d0d1SDanilo Krummrich         // hence `dev` must be embedded in a valid `struct pci_dev` as guaranteed by the
473a095d0d1SDanilo Krummrich         // corresponding C code.
474a095d0d1SDanilo Krummrich         let pdev = unsafe { container_of!(dev.as_raw(), bindings::pci_dev, dev) };
475a095d0d1SDanilo Krummrich 
476a095d0d1SDanilo Krummrich         // SAFETY: `pdev` is a valid pointer to a `struct pci_dev`.
477a095d0d1SDanilo Krummrich         Ok(unsafe { &*pdev.cast() })
478a095d0d1SDanilo Krummrich     }
479a095d0d1SDanilo Krummrich }
480a095d0d1SDanilo Krummrich 
481e2942bb4SDanilo Krummrich // SAFETY: A `Device` is always reference-counted and can be released from any thread.
482e2942bb4SDanilo Krummrich unsafe impl Send for Device {}
483e2942bb4SDanilo Krummrich 
484e2942bb4SDanilo Krummrich // SAFETY: `Device` can be shared among threads because all methods of `Device`
485e2942bb4SDanilo Krummrich // (i.e. `Device<Normal>) are thread safe.
486e2942bb4SDanilo Krummrich unsafe impl Sync for Device {}
487