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: provide access to PCI Class and Class-related items

Allow callers to write Class::STORAGE_SCSI instead of
bindings::PCI_CLASS_STORAGE_SCSI, for example.

New APIs:
Class::STORAGE_SCSI, Class::NETWORK_ETHERNET, etc.
Class::from_raw() -- Only callable from pci module.
Class::as_raw()
ClassMask: Full, ClassSubclass
Device::pci_class()

Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Elle Rhumsaa <elle@weathered-steel.dev>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Link: https://lore.kernel.org/r/20250829223632.144030-2-jhubbard@nvidia.com
[ Minor doc-comment improvements, align Debug and Display. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

John Hubbard and committed by
Danilo Krummrich
ed78a018 b71763a0

+248
+1
MAINTAINERS
··· 19575 19575 T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git 19576 19576 F: rust/helpers/pci.c 19577 19577 F: rust/kernel/pci.rs 19578 + F: rust/kernel/pci/ 19578 19579 F: samples/rust/rust_driver_pci.rs 19579 19580 19580 19581 PCIE BANDWIDTH CONTROLLER
+11
rust/kernel/pci.rs
··· 24 24 }; 25 25 use kernel::prelude::*; 26 26 27 + mod id; 28 + 29 + pub use self::id::{Class, ClassMask}; 30 + 27 31 /// An adapter for the registration of PCI drivers. 28 32 pub struct Adapter<T: Driver>(T); 29 33 ··· 462 458 // - `bar` is a valid bar number, as guaranteed by the above call to `Bar::index_is_valid`, 463 459 // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`. 464 460 Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) }) 461 + } 462 + 463 + /// Returns the PCI class as a `Class` struct. 464 + #[inline] 465 + pub fn pci_class(&self) -> Class { 466 + // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. 467 + Class::from_raw(unsafe { (*self.as_raw()).class }) 465 468 } 466 469 } 467 470
+236
rust/kernel/pci/id.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! PCI device identifiers and related types. 4 + //! 5 + //! This module contains PCI class codes and supporting types. 6 + 7 + use crate::{bindings, error::code::EINVAL, error::Error, prelude::*}; 8 + use core::fmt; 9 + 10 + /// PCI device class codes. 11 + /// 12 + /// Each entry contains the full 24-bit PCI class code (base class in bits 13 + /// 23-16, subclass in bits 15-8, programming interface in bits 7-0). 14 + /// 15 + /// # Examples 16 + /// 17 + /// ``` 18 + /// # use kernel::{device::Core, pci::{self, Class}, prelude::*}; 19 + /// fn probe_device(pdev: &pci::Device<Core>) -> Result { 20 + /// let pci_class = pdev.pci_class(); 21 + /// dev_info!( 22 + /// pdev.as_ref(), 23 + /// "Detected PCI class: {}\n", 24 + /// pci_class 25 + /// ); 26 + /// Ok(()) 27 + /// } 28 + /// ``` 29 + #[derive(Clone, Copy, PartialEq, Eq)] 30 + #[repr(transparent)] 31 + pub struct Class(u32); 32 + 33 + /// PCI class mask constants for matching [`Class`] codes. 34 + #[repr(u32)] 35 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 36 + pub enum ClassMask { 37 + /// Match the full 24-bit class code. 38 + Full = 0xffffff, 39 + /// Match the upper 16 bits of the class code (base class and subclass only) 40 + ClassSubclass = 0xffff00, 41 + } 42 + 43 + macro_rules! define_all_pci_classes { 44 + ( 45 + $($variant:ident = $binding:expr,)+ 46 + ) => { 47 + impl Class { 48 + $( 49 + #[allow(missing_docs)] 50 + pub const $variant: Self = Self(Self::to_24bit_class($binding)); 51 + )+ 52 + } 53 + }; 54 + } 55 + 56 + /// Once constructed, a [`Class`] contains a valid PCI class code. 57 + impl Class { 58 + /// Create a [`Class`] from a raw 24-bit class code. 59 + #[inline] 60 + pub(super) fn from_raw(class_code: u32) -> Self { 61 + Self(class_code) 62 + } 63 + 64 + /// Get the raw 24-bit class code value. 65 + #[inline] 66 + pub const fn as_raw(self) -> u32 { 67 + self.0 68 + } 69 + 70 + // Converts a PCI class constant to 24-bit format. 71 + // 72 + // Many device drivers use only the upper 16 bits (base class and subclass), 73 + // but some use the full 24 bits. In order to support both cases, store the 74 + // class code as a 24-bit value, where 16-bit values are shifted up 8 bits. 75 + const fn to_24bit_class(val: u32) -> u32 { 76 + if val > 0xFFFF { 77 + val 78 + } else { 79 + val << 8 80 + } 81 + } 82 + } 83 + 84 + impl fmt::Debug for Class { 85 + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 86 + write!(f, "0x{:06x}", self.0) 87 + } 88 + } 89 + 90 + impl fmt::Display for Class { 91 + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 92 + <Self as fmt::Debug>::fmt(self, f) 93 + } 94 + } 95 + 96 + impl ClassMask { 97 + /// Get the raw mask value. 98 + #[inline] 99 + pub const fn as_raw(self) -> u32 { 100 + self as u32 101 + } 102 + } 103 + 104 + impl TryFrom<u32> for ClassMask { 105 + type Error = Error; 106 + 107 + fn try_from(value: u32) -> Result<Self, Self::Error> { 108 + match value { 109 + 0xffffff => Ok(ClassMask::Full), 110 + 0xffff00 => Ok(ClassMask::ClassSubclass), 111 + _ => Err(EINVAL), 112 + } 113 + } 114 + } 115 + 116 + define_all_pci_classes! { 117 + NOT_DEFINED = bindings::PCI_CLASS_NOT_DEFINED, // 0x000000 118 + NOT_DEFINED_VGA = bindings::PCI_CLASS_NOT_DEFINED_VGA, // 0x000100 119 + 120 + STORAGE_SCSI = bindings::PCI_CLASS_STORAGE_SCSI, // 0x010000 121 + STORAGE_IDE = bindings::PCI_CLASS_STORAGE_IDE, // 0x010100 122 + STORAGE_FLOPPY = bindings::PCI_CLASS_STORAGE_FLOPPY, // 0x010200 123 + STORAGE_IPI = bindings::PCI_CLASS_STORAGE_IPI, // 0x010300 124 + STORAGE_RAID = bindings::PCI_CLASS_STORAGE_RAID, // 0x010400 125 + STORAGE_SATA = bindings::PCI_CLASS_STORAGE_SATA, // 0x010600 126 + STORAGE_SATA_AHCI = bindings::PCI_CLASS_STORAGE_SATA_AHCI, // 0x010601 127 + STORAGE_SAS = bindings::PCI_CLASS_STORAGE_SAS, // 0x010700 128 + STORAGE_EXPRESS = bindings::PCI_CLASS_STORAGE_EXPRESS, // 0x010802 129 + STORAGE_OTHER = bindings::PCI_CLASS_STORAGE_OTHER, // 0x018000 130 + 131 + NETWORK_ETHERNET = bindings::PCI_CLASS_NETWORK_ETHERNET, // 0x020000 132 + NETWORK_TOKEN_RING = bindings::PCI_CLASS_NETWORK_TOKEN_RING, // 0x020100 133 + NETWORK_FDDI = bindings::PCI_CLASS_NETWORK_FDDI, // 0x020200 134 + NETWORK_ATM = bindings::PCI_CLASS_NETWORK_ATM, // 0x020300 135 + NETWORK_OTHER = bindings::PCI_CLASS_NETWORK_OTHER, // 0x028000 136 + 137 + DISPLAY_VGA = bindings::PCI_CLASS_DISPLAY_VGA, // 0x030000 138 + DISPLAY_XGA = bindings::PCI_CLASS_DISPLAY_XGA, // 0x030100 139 + DISPLAY_3D = bindings::PCI_CLASS_DISPLAY_3D, // 0x030200 140 + DISPLAY_OTHER = bindings::PCI_CLASS_DISPLAY_OTHER, // 0x038000 141 + 142 + MULTIMEDIA_VIDEO = bindings::PCI_CLASS_MULTIMEDIA_VIDEO, // 0x040000 143 + MULTIMEDIA_AUDIO = bindings::PCI_CLASS_MULTIMEDIA_AUDIO, // 0x040100 144 + MULTIMEDIA_PHONE = bindings::PCI_CLASS_MULTIMEDIA_PHONE, // 0x040200 145 + MULTIMEDIA_HD_AUDIO = bindings::PCI_CLASS_MULTIMEDIA_HD_AUDIO, // 0x040300 146 + MULTIMEDIA_OTHER = bindings::PCI_CLASS_MULTIMEDIA_OTHER, // 0x048000 147 + 148 + MEMORY_RAM = bindings::PCI_CLASS_MEMORY_RAM, // 0x050000 149 + MEMORY_FLASH = bindings::PCI_CLASS_MEMORY_FLASH, // 0x050100 150 + MEMORY_CXL = bindings::PCI_CLASS_MEMORY_CXL, // 0x050200 151 + MEMORY_OTHER = bindings::PCI_CLASS_MEMORY_OTHER, // 0x058000 152 + 153 + BRIDGE_HOST = bindings::PCI_CLASS_BRIDGE_HOST, // 0x060000 154 + BRIDGE_ISA = bindings::PCI_CLASS_BRIDGE_ISA, // 0x060100 155 + BRIDGE_EISA = bindings::PCI_CLASS_BRIDGE_EISA, // 0x060200 156 + BRIDGE_MC = bindings::PCI_CLASS_BRIDGE_MC, // 0x060300 157 + BRIDGE_PCI_NORMAL = bindings::PCI_CLASS_BRIDGE_PCI_NORMAL, // 0x060400 158 + BRIDGE_PCI_SUBTRACTIVE = bindings::PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE, // 0x060401 159 + BRIDGE_PCMCIA = bindings::PCI_CLASS_BRIDGE_PCMCIA, // 0x060500 160 + BRIDGE_NUBUS = bindings::PCI_CLASS_BRIDGE_NUBUS, // 0x060600 161 + BRIDGE_CARDBUS = bindings::PCI_CLASS_BRIDGE_CARDBUS, // 0x060700 162 + BRIDGE_RACEWAY = bindings::PCI_CLASS_BRIDGE_RACEWAY, // 0x060800 163 + BRIDGE_OTHER = bindings::PCI_CLASS_BRIDGE_OTHER, // 0x068000 164 + 165 + COMMUNICATION_SERIAL = bindings::PCI_CLASS_COMMUNICATION_SERIAL, // 0x070000 166 + COMMUNICATION_PARALLEL = bindings::PCI_CLASS_COMMUNICATION_PARALLEL, // 0x070100 167 + COMMUNICATION_MULTISERIAL = bindings::PCI_CLASS_COMMUNICATION_MULTISERIAL, // 0x070200 168 + COMMUNICATION_MODEM = bindings::PCI_CLASS_COMMUNICATION_MODEM, // 0x070300 169 + COMMUNICATION_OTHER = bindings::PCI_CLASS_COMMUNICATION_OTHER, // 0x078000 170 + 171 + SYSTEM_PIC = bindings::PCI_CLASS_SYSTEM_PIC, // 0x080000 172 + SYSTEM_PIC_IOAPIC = bindings::PCI_CLASS_SYSTEM_PIC_IOAPIC, // 0x080010 173 + SYSTEM_PIC_IOXAPIC = bindings::PCI_CLASS_SYSTEM_PIC_IOXAPIC, // 0x080020 174 + SYSTEM_DMA = bindings::PCI_CLASS_SYSTEM_DMA, // 0x080100 175 + SYSTEM_TIMER = bindings::PCI_CLASS_SYSTEM_TIMER, // 0x080200 176 + SYSTEM_RTC = bindings::PCI_CLASS_SYSTEM_RTC, // 0x080300 177 + SYSTEM_PCI_HOTPLUG = bindings::PCI_CLASS_SYSTEM_PCI_HOTPLUG, // 0x080400 178 + SYSTEM_SDHCI = bindings::PCI_CLASS_SYSTEM_SDHCI, // 0x080500 179 + SYSTEM_RCEC = bindings::PCI_CLASS_SYSTEM_RCEC, // 0x080700 180 + SYSTEM_OTHER = bindings::PCI_CLASS_SYSTEM_OTHER, // 0x088000 181 + 182 + INPUT_KEYBOARD = bindings::PCI_CLASS_INPUT_KEYBOARD, // 0x090000 183 + INPUT_PEN = bindings::PCI_CLASS_INPUT_PEN, // 0x090100 184 + INPUT_MOUSE = bindings::PCI_CLASS_INPUT_MOUSE, // 0x090200 185 + INPUT_SCANNER = bindings::PCI_CLASS_INPUT_SCANNER, // 0x090300 186 + INPUT_GAMEPORT = bindings::PCI_CLASS_INPUT_GAMEPORT, // 0x090400 187 + INPUT_OTHER = bindings::PCI_CLASS_INPUT_OTHER, // 0x098000 188 + 189 + DOCKING_GENERIC = bindings::PCI_CLASS_DOCKING_GENERIC, // 0x0a0000 190 + DOCKING_OTHER = bindings::PCI_CLASS_DOCKING_OTHER, // 0x0a8000 191 + 192 + PROCESSOR_386 = bindings::PCI_CLASS_PROCESSOR_386, // 0x0b0000 193 + PROCESSOR_486 = bindings::PCI_CLASS_PROCESSOR_486, // 0x0b0100 194 + PROCESSOR_PENTIUM = bindings::PCI_CLASS_PROCESSOR_PENTIUM, // 0x0b0200 195 + PROCESSOR_ALPHA = bindings::PCI_CLASS_PROCESSOR_ALPHA, // 0x0b1000 196 + PROCESSOR_POWERPC = bindings::PCI_CLASS_PROCESSOR_POWERPC, // 0x0b2000 197 + PROCESSOR_MIPS = bindings::PCI_CLASS_PROCESSOR_MIPS, // 0x0b3000 198 + PROCESSOR_CO = bindings::PCI_CLASS_PROCESSOR_CO, // 0x0b4000 199 + 200 + SERIAL_FIREWIRE = bindings::PCI_CLASS_SERIAL_FIREWIRE, // 0x0c0000 201 + SERIAL_FIREWIRE_OHCI = bindings::PCI_CLASS_SERIAL_FIREWIRE_OHCI, // 0x0c0010 202 + SERIAL_ACCESS = bindings::PCI_CLASS_SERIAL_ACCESS, // 0x0c0100 203 + SERIAL_SSA = bindings::PCI_CLASS_SERIAL_SSA, // 0x0c0200 204 + SERIAL_USB_UHCI = bindings::PCI_CLASS_SERIAL_USB_UHCI, // 0x0c0300 205 + SERIAL_USB_OHCI = bindings::PCI_CLASS_SERIAL_USB_OHCI, // 0x0c0310 206 + SERIAL_USB_EHCI = bindings::PCI_CLASS_SERIAL_USB_EHCI, // 0x0c0320 207 + SERIAL_USB_XHCI = bindings::PCI_CLASS_SERIAL_USB_XHCI, // 0x0c0330 208 + SERIAL_USB_CDNS = bindings::PCI_CLASS_SERIAL_USB_CDNS, // 0x0c0380 209 + SERIAL_USB_DEVICE = bindings::PCI_CLASS_SERIAL_USB_DEVICE, // 0x0c03fe 210 + SERIAL_FIBER = bindings::PCI_CLASS_SERIAL_FIBER, // 0x0c0400 211 + SERIAL_SMBUS = bindings::PCI_CLASS_SERIAL_SMBUS, // 0x0c0500 212 + SERIAL_IPMI_SMIC = bindings::PCI_CLASS_SERIAL_IPMI_SMIC, // 0x0c0700 213 + SERIAL_IPMI_KCS = bindings::PCI_CLASS_SERIAL_IPMI_KCS, // 0x0c0701 214 + SERIAL_IPMI_BT = bindings::PCI_CLASS_SERIAL_IPMI_BT, // 0x0c0702 215 + 216 + WIRELESS_RF_CONTROLLER = bindings::PCI_CLASS_WIRELESS_RF_CONTROLLER, // 0x0d1000 217 + WIRELESS_WHCI = bindings::PCI_CLASS_WIRELESS_WHCI, // 0x0d1010 218 + 219 + INTELLIGENT_I2O = bindings::PCI_CLASS_INTELLIGENT_I2O, // 0x0e0000 220 + 221 + SATELLITE_TV = bindings::PCI_CLASS_SATELLITE_TV, // 0x0f0000 222 + SATELLITE_AUDIO = bindings::PCI_CLASS_SATELLITE_AUDIO, // 0x0f0100 223 + SATELLITE_VOICE = bindings::PCI_CLASS_SATELLITE_VOICE, // 0x0f0300 224 + SATELLITE_DATA = bindings::PCI_CLASS_SATELLITE_DATA, // 0x0f0400 225 + 226 + CRYPT_NETWORK = bindings::PCI_CLASS_CRYPT_NETWORK, // 0x100000 227 + CRYPT_ENTERTAINMENT = bindings::PCI_CLASS_CRYPT_ENTERTAINMENT, // 0x100100 228 + CRYPT_OTHER = bindings::PCI_CLASS_CRYPT_OTHER, // 0x108000 229 + 230 + SP_DPIO = bindings::PCI_CLASS_SP_DPIO, // 0x110000 231 + SP_OTHER = bindings::PCI_CLASS_SP_OTHER, // 0x118000 232 + 233 + ACCELERATOR_PROCESSING = bindings::PCI_CLASS_ACCELERATOR_PROCESSING, // 0x120000 234 + 235 + OTHERS = bindings::PCI_CLASS_OTHERS, // 0xff0000 236 + }