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