Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: pci: add basic PCI device / driver abstractions

Implement the basic PCI abstractions required to write a basic PCI
driver. This includes the following data structures:

The `pci::Driver` trait represents the interface to the driver and
provides `pci::Driver::probe` for the driver to implement.

The `pci::Device` abstraction represents a `struct pci_dev` and provides
abstractions for common functions, such as `pci::Device::set_master`.

In order to provide the PCI specific parts to a generic
`driver::Registration` the `driver::RegistrationOps` trait is implemented
by `pci::Adapter`.

`pci::DeviceId` implements PCI device IDs based on the generic
`device_id::RawDevceId` abstraction.

Co-developed-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
Link: https://lore.kernel.org/r/20241219170425.12036-10-dakr@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Danilo Krummrich and committed by
Greg Kroah-Hartman
1bd8b6b2 76c01ded

+315
+1
MAINTAINERS
··· 18105 18105 F: include/linux/of_pci.h 18106 18106 F: include/linux/pci* 18107 18107 F: include/uapi/linux/pci* 18108 + F: rust/kernel/pci.rs 18108 18109 18109 18110 PCIE BANDWIDTH CONTROLLER 18110 18111 M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+1
rust/bindings/bindings_helper.h
··· 20 20 #include <linux/jump_label.h> 21 21 #include <linux/mdio.h> 22 22 #include <linux/miscdevice.h> 23 + #include <linux/pci.h> 23 24 #include <linux/phy.h> 24 25 #include <linux/pid_namespace.h> 25 26 #include <linux/poll.h>
+1
rust/helpers/helpers.c
··· 20 20 #include "kunit.c" 21 21 #include "mutex.c" 22 22 #include "page.c" 23 + #include "pci.c" 23 24 #include "pid_namespace.c" 24 25 #include "rbtree.c" 25 26 #include "rcu.c"
+18
rust/helpers/pci.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/pci.h> 4 + 5 + void rust_helper_pci_set_drvdata(struct pci_dev *pdev, void *data) 6 + { 7 + pci_set_drvdata(pdev, data); 8 + } 9 + 10 + void *rust_helper_pci_get_drvdata(struct pci_dev *pdev) 11 + { 12 + return pci_get_drvdata(pdev); 13 + } 14 + 15 + resource_size_t rust_helper_pci_resource_len(struct pci_dev *pdev, int bar) 16 + { 17 + return pci_resource_len(pdev, bar); 18 + }
+2
rust/kernel/lib.rs
··· 82 82 pub use bindings; 83 83 pub mod io; 84 84 pub use macros; 85 + #[cfg(all(CONFIG_PCI, CONFIG_PCI_MSI))] 86 + pub mod pci; 85 87 pub use uapi; 86 88 87 89 #[doc(hidden)]
+292
rust/kernel/pci.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Abstractions for the PCI bus. 4 + //! 5 + //! C header: [`include/linux/pci.h`](srctree/include/linux/pci.h) 6 + 7 + use crate::{ 8 + bindings, container_of, device, 9 + device_id::RawDeviceId, 10 + driver, 11 + error::{to_result, Result}, 12 + str::CStr, 13 + types::{ARef, ForeignOwnable, Opaque}, 14 + ThisModule, 15 + }; 16 + use core::ptr::addr_of_mut; 17 + use kernel::prelude::*; 18 + 19 + /// An adapter for the registration of PCI drivers. 20 + pub struct Adapter<T: Driver>(T); 21 + 22 + impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 23 + type RegType = bindings::pci_driver; 24 + 25 + fn register( 26 + pdrv: &Opaque<Self::RegType>, 27 + name: &'static CStr, 28 + module: &'static ThisModule, 29 + ) -> Result { 30 + // SAFETY: It's safe to set the fields of `struct pci_driver` on initialization. 31 + unsafe { 32 + (*pdrv.get()).name = name.as_char_ptr(); 33 + (*pdrv.get()).probe = Some(Self::probe_callback); 34 + (*pdrv.get()).remove = Some(Self::remove_callback); 35 + (*pdrv.get()).id_table = T::ID_TABLE.as_ptr(); 36 + } 37 + 38 + // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 39 + to_result(unsafe { 40 + bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr()) 41 + }) 42 + } 43 + 44 + fn unregister(pdrv: &Opaque<Self::RegType>) { 45 + // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 46 + unsafe { bindings::pci_unregister_driver(pdrv.get()) } 47 + } 48 + } 49 + 50 + impl<T: Driver + 'static> Adapter<T> { 51 + extern "C" fn probe_callback( 52 + pdev: *mut bindings::pci_dev, 53 + id: *const bindings::pci_device_id, 54 + ) -> kernel::ffi::c_int { 55 + // SAFETY: The PCI bus only ever calls the probe callback with a valid pointer to a 56 + // `struct pci_dev`. 57 + let dev = unsafe { device::Device::get_device(addr_of_mut!((*pdev).dev)) }; 58 + // SAFETY: `dev` is guaranteed to be embedded in a valid `struct pci_dev` by the call 59 + // above. 60 + let mut pdev = unsafe { Device::from_dev(dev) }; 61 + 62 + // SAFETY: `DeviceId` is a `#[repr(transparent)` wrapper of `struct pci_device_id` and 63 + // does not add additional invariants, so it's safe to transmute. 64 + let id = unsafe { &*id.cast::<DeviceId>() }; 65 + let info = T::ID_TABLE.info(id.index()); 66 + 67 + match T::probe(&mut pdev, info) { 68 + Ok(data) => { 69 + // Let the `struct pci_dev` own a reference of the driver's private data. 70 + // SAFETY: By the type invariant `pdev.as_raw` returns a valid pointer to a 71 + // `struct pci_dev`. 72 + unsafe { bindings::pci_set_drvdata(pdev.as_raw(), data.into_foreign() as _) }; 73 + } 74 + Err(err) => return Error::to_errno(err), 75 + } 76 + 77 + 0 78 + } 79 + 80 + extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) { 81 + // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a 82 + // `struct pci_dev`. 83 + let ptr = unsafe { bindings::pci_get_drvdata(pdev) }; 84 + 85 + // SAFETY: `remove_callback` is only ever called after a successful call to 86 + // `probe_callback`, hence it's guaranteed that `ptr` points to a valid and initialized 87 + // `KBox<T>` pointer created through `KBox::into_foreign`. 88 + let _ = unsafe { KBox::<T>::from_foreign(ptr) }; 89 + } 90 + } 91 + 92 + /// Declares a kernel module that exposes a single PCI driver. 93 + /// 94 + /// # Example 95 + /// 96 + ///```ignore 97 + /// kernel::module_pci_driver! { 98 + /// type: MyDriver, 99 + /// name: "Module name", 100 + /// author: "Author name", 101 + /// description: "Description", 102 + /// license: "GPL v2", 103 + /// } 104 + ///``` 105 + #[macro_export] 106 + macro_rules! module_pci_driver { 107 + ($($f:tt)*) => { 108 + $crate::module_driver!(<T>, $crate::pci::Adapter<T>, { $($f)* }); 109 + }; 110 + } 111 + 112 + /// Abstraction for bindings::pci_device_id. 113 + #[repr(transparent)] 114 + #[derive(Clone, Copy)] 115 + pub struct DeviceId(bindings::pci_device_id); 116 + 117 + impl DeviceId { 118 + const PCI_ANY_ID: u32 = !0; 119 + 120 + /// Equivalent to C's `PCI_DEVICE` macro. 121 + /// 122 + /// Create a new `pci::DeviceId` from a vendor and device ID number. 123 + pub const fn from_id(vendor: u32, device: u32) -> Self { 124 + Self(bindings::pci_device_id { 125 + vendor, 126 + device, 127 + subvendor: DeviceId::PCI_ANY_ID, 128 + subdevice: DeviceId::PCI_ANY_ID, 129 + class: 0, 130 + class_mask: 0, 131 + driver_data: 0, 132 + override_only: 0, 133 + }) 134 + } 135 + 136 + /// Equivalent to C's `PCI_DEVICE_CLASS` macro. 137 + /// 138 + /// Create a new `pci::DeviceId` from a class number and mask. 139 + pub const fn from_class(class: u32, class_mask: u32) -> Self { 140 + Self(bindings::pci_device_id { 141 + vendor: DeviceId::PCI_ANY_ID, 142 + device: DeviceId::PCI_ANY_ID, 143 + subvendor: DeviceId::PCI_ANY_ID, 144 + subdevice: DeviceId::PCI_ANY_ID, 145 + class, 146 + class_mask, 147 + driver_data: 0, 148 + override_only: 0, 149 + }) 150 + } 151 + } 152 + 153 + // SAFETY: 154 + // * `DeviceId` is a `#[repr(transparent)` wrapper of `pci_device_id` and does not add 155 + // additional invariants, so it's safe to transmute to `RawType`. 156 + // * `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 157 + unsafe impl RawDeviceId for DeviceId { 158 + type RawType = bindings::pci_device_id; 159 + 160 + const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data); 161 + 162 + fn index(&self) -> usize { 163 + self.0.driver_data as _ 164 + } 165 + } 166 + 167 + /// IdTable type for PCI 168 + pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 169 + 170 + /// Create a PCI `IdTable` with its alias for modpost. 171 + #[macro_export] 172 + macro_rules! pci_device_table { 173 + ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 174 + const $table_name: $crate::device_id::IdArray< 175 + $crate::pci::DeviceId, 176 + $id_info_type, 177 + { $table_data.len() }, 178 + > = $crate::device_id::IdArray::new($table_data); 179 + 180 + $crate::module_device_table!("pci", $module_table_name, $table_name); 181 + }; 182 + } 183 + 184 + /// The PCI driver trait. 185 + /// 186 + /// # Example 187 + /// 188 + ///``` 189 + /// # use kernel::{bindings, pci}; 190 + /// 191 + /// struct MyDriver; 192 + /// 193 + /// kernel::pci_device_table!( 194 + /// PCI_TABLE, 195 + /// MODULE_PCI_TABLE, 196 + /// <MyDriver as pci::Driver>::IdInfo, 197 + /// [ 198 + /// (pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as _), ()) 199 + /// ] 200 + /// ); 201 + /// 202 + /// impl pci::Driver for MyDriver { 203 + /// type IdInfo = (); 204 + /// const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 205 + /// 206 + /// fn probe( 207 + /// _pdev: &mut pci::Device, 208 + /// _id_info: &Self::IdInfo, 209 + /// ) -> Result<Pin<KBox<Self>>> { 210 + /// Err(ENODEV) 211 + /// } 212 + /// } 213 + ///``` 214 + /// Drivers must implement this trait in order to get a PCI driver registered. Please refer to the 215 + /// `Adapter` documentation for an example. 216 + pub trait Driver { 217 + /// The type holding information about each device id supported by the driver. 218 + /// 219 + /// TODO: Use associated_type_defaults once stabilized: 220 + /// 221 + /// type IdInfo: 'static = (); 222 + type IdInfo: 'static; 223 + 224 + /// The table of device ids supported by the driver. 225 + const ID_TABLE: IdTable<Self::IdInfo>; 226 + 227 + /// PCI driver probe. 228 + /// 229 + /// Called when a new platform device is added or discovered. 230 + /// Implementers should attempt to initialize the device here. 231 + fn probe(dev: &mut Device, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 232 + } 233 + 234 + /// The PCI device representation. 235 + /// 236 + /// A PCI device is based on an always reference counted `device:Device` instance. Cloning a PCI 237 + /// device, hence, also increments the base device' reference count. 238 + #[derive(Clone)] 239 + pub struct Device(ARef<device::Device>); 240 + 241 + impl Device { 242 + /// Create a PCI Device instance from an existing `device::Device`. 243 + /// 244 + /// # Safety 245 + /// 246 + /// `dev` must be an `ARef<device::Device>` whose underlying `bindings::device` is a member of 247 + /// a `bindings::pci_dev`. 248 + pub unsafe fn from_dev(dev: ARef<device::Device>) -> Self { 249 + Self(dev) 250 + } 251 + 252 + fn as_raw(&self) -> *mut bindings::pci_dev { 253 + // SAFETY: By the type invariant `self.0.as_raw` is a pointer to the `struct device` 254 + // embedded in `struct pci_dev`. 255 + unsafe { container_of!(self.0.as_raw(), bindings::pci_dev, dev) as _ } 256 + } 257 + 258 + /// Returns the PCI vendor ID. 259 + pub fn vendor_id(&self) -> u16 { 260 + // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. 261 + unsafe { (*self.as_raw()).vendor } 262 + } 263 + 264 + /// Returns the PCI device ID. 265 + pub fn device_id(&self) -> u16 { 266 + // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. 267 + unsafe { (*self.as_raw()).device } 268 + } 269 + 270 + /// Enable memory resources for this device. 271 + pub fn enable_device_mem(&self) -> Result { 272 + // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. 273 + let ret = unsafe { bindings::pci_enable_device_mem(self.as_raw()) }; 274 + if ret != 0 { 275 + Err(Error::from_errno(ret)) 276 + } else { 277 + Ok(()) 278 + } 279 + } 280 + 281 + /// Enable bus-mastering for this device. 282 + pub fn set_master(&self) { 283 + // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. 284 + unsafe { bindings::pci_set_master(self.as_raw()) }; 285 + } 286 + } 287 + 288 + impl AsRef<device::Device> for Device { 289 + fn as_ref(&self) -> &device::Device { 290 + &self.0 291 + } 292 + }