mirror of https://github.com/torvalds/linux.git
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>
This commit is contained in:
parent
b71763a0a3
commit
ed78a01887
|
|
@ -19575,6 +19575,7 @@ C: irc://irc.oftc.net/linux-pci
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
|
||||||
F: rust/helpers/pci.c
|
F: rust/helpers/pci.c
|
||||||
F: rust/kernel/pci.rs
|
F: rust/kernel/pci.rs
|
||||||
|
F: rust/kernel/pci/
|
||||||
F: samples/rust/rust_driver_pci.rs
|
F: samples/rust/rust_driver_pci.rs
|
||||||
|
|
||||||
PCIE BANDWIDTH CONTROLLER
|
PCIE BANDWIDTH CONTROLLER
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@
|
||||||
};
|
};
|
||||||
use kernel::prelude::*;
|
use kernel::prelude::*;
|
||||||
|
|
||||||
|
mod id;
|
||||||
|
|
||||||
|
pub use self::id::{Class, ClassMask};
|
||||||
|
|
||||||
/// An adapter for the registration of PCI drivers.
|
/// An adapter for the registration of PCI drivers.
|
||||||
pub struct Adapter<T: Driver>(T);
|
pub struct Adapter<T: Driver>(T);
|
||||||
|
|
||||||
|
|
@ -459,6 +463,13 @@ pub fn resource_len(&self, bar: u32) -> Result<bindings::resource_size_t> {
|
||||||
// - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`.
|
// - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`.
|
||||||
Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) })
|
Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the PCI class as a `Class` struct.
|
||||||
|
#[inline]
|
||||||
|
pub fn pci_class(&self) -> Class {
|
||||||
|
// SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.
|
||||||
|
Class::from_raw(unsafe { (*self.as_raw()).class })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Device<device::Bound> {
|
impl Device<device::Bound> {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
//! PCI device identifiers and related types.
|
||||||
|
//!
|
||||||
|
//! This module contains PCI class codes and supporting types.
|
||||||
|
|
||||||
|
use crate::{bindings, error::code::EINVAL, error::Error, prelude::*};
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
/// PCI device class codes.
|
||||||
|
///
|
||||||
|
/// Each entry contains the full 24-bit PCI class code (base class in bits
|
||||||
|
/// 23-16, subclass in bits 15-8, programming interface in bits 7-0).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use kernel::{device::Core, pci::{self, Class}, prelude::*};
|
||||||
|
/// fn probe_device(pdev: &pci::Device<Core>) -> Result {
|
||||||
|
/// let pci_class = pdev.pci_class();
|
||||||
|
/// dev_info!(
|
||||||
|
/// pdev.as_ref(),
|
||||||
|
/// "Detected PCI class: {}\n",
|
||||||
|
/// pci_class
|
||||||
|
/// );
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Class(u32);
|
||||||
|
|
||||||
|
/// PCI class mask constants for matching [`Class`] codes.
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum ClassMask {
|
||||||
|
/// Match the full 24-bit class code.
|
||||||
|
Full = 0xffffff,
|
||||||
|
/// Match the upper 16 bits of the class code (base class and subclass only)
|
||||||
|
ClassSubclass = 0xffff00,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! define_all_pci_classes {
|
||||||
|
(
|
||||||
|
$($variant:ident = $binding:expr,)+
|
||||||
|
) => {
|
||||||
|
impl Class {
|
||||||
|
$(
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub const $variant: Self = Self(Self::to_24bit_class($binding));
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Once constructed, a [`Class`] contains a valid PCI class code.
|
||||||
|
impl Class {
|
||||||
|
/// Create a [`Class`] from a raw 24-bit class code.
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn from_raw(class_code: u32) -> Self {
|
||||||
|
Self(class_code)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the raw 24-bit class code value.
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_raw(self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a PCI class constant to 24-bit format.
|
||||||
|
//
|
||||||
|
// Many device drivers use only the upper 16 bits (base class and subclass),
|
||||||
|
// but some use the full 24 bits. In order to support both cases, store the
|
||||||
|
// class code as a 24-bit value, where 16-bit values are shifted up 8 bits.
|
||||||
|
const fn to_24bit_class(val: u32) -> u32 {
|
||||||
|
if val > 0xFFFF {
|
||||||
|
val
|
||||||
|
} else {
|
||||||
|
val << 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Class {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "0x{:06x}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Class {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
<Self as fmt::Debug>::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassMask {
|
||||||
|
/// Get the raw mask value.
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_raw(self) -> u32 {
|
||||||
|
self as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u32> for ClassMask {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(value: u32) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
0xffffff => Ok(ClassMask::Full),
|
||||||
|
0xffff00 => Ok(ClassMask::ClassSubclass),
|
||||||
|
_ => Err(EINVAL),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_all_pci_classes! {
|
||||||
|
NOT_DEFINED = bindings::PCI_CLASS_NOT_DEFINED, // 0x000000
|
||||||
|
NOT_DEFINED_VGA = bindings::PCI_CLASS_NOT_DEFINED_VGA, // 0x000100
|
||||||
|
|
||||||
|
STORAGE_SCSI = bindings::PCI_CLASS_STORAGE_SCSI, // 0x010000
|
||||||
|
STORAGE_IDE = bindings::PCI_CLASS_STORAGE_IDE, // 0x010100
|
||||||
|
STORAGE_FLOPPY = bindings::PCI_CLASS_STORAGE_FLOPPY, // 0x010200
|
||||||
|
STORAGE_IPI = bindings::PCI_CLASS_STORAGE_IPI, // 0x010300
|
||||||
|
STORAGE_RAID = bindings::PCI_CLASS_STORAGE_RAID, // 0x010400
|
||||||
|
STORAGE_SATA = bindings::PCI_CLASS_STORAGE_SATA, // 0x010600
|
||||||
|
STORAGE_SATA_AHCI = bindings::PCI_CLASS_STORAGE_SATA_AHCI, // 0x010601
|
||||||
|
STORAGE_SAS = bindings::PCI_CLASS_STORAGE_SAS, // 0x010700
|
||||||
|
STORAGE_EXPRESS = bindings::PCI_CLASS_STORAGE_EXPRESS, // 0x010802
|
||||||
|
STORAGE_OTHER = bindings::PCI_CLASS_STORAGE_OTHER, // 0x018000
|
||||||
|
|
||||||
|
NETWORK_ETHERNET = bindings::PCI_CLASS_NETWORK_ETHERNET, // 0x020000
|
||||||
|
NETWORK_TOKEN_RING = bindings::PCI_CLASS_NETWORK_TOKEN_RING, // 0x020100
|
||||||
|
NETWORK_FDDI = bindings::PCI_CLASS_NETWORK_FDDI, // 0x020200
|
||||||
|
NETWORK_ATM = bindings::PCI_CLASS_NETWORK_ATM, // 0x020300
|
||||||
|
NETWORK_OTHER = bindings::PCI_CLASS_NETWORK_OTHER, // 0x028000
|
||||||
|
|
||||||
|
DISPLAY_VGA = bindings::PCI_CLASS_DISPLAY_VGA, // 0x030000
|
||||||
|
DISPLAY_XGA = bindings::PCI_CLASS_DISPLAY_XGA, // 0x030100
|
||||||
|
DISPLAY_3D = bindings::PCI_CLASS_DISPLAY_3D, // 0x030200
|
||||||
|
DISPLAY_OTHER = bindings::PCI_CLASS_DISPLAY_OTHER, // 0x038000
|
||||||
|
|
||||||
|
MULTIMEDIA_VIDEO = bindings::PCI_CLASS_MULTIMEDIA_VIDEO, // 0x040000
|
||||||
|
MULTIMEDIA_AUDIO = bindings::PCI_CLASS_MULTIMEDIA_AUDIO, // 0x040100
|
||||||
|
MULTIMEDIA_PHONE = bindings::PCI_CLASS_MULTIMEDIA_PHONE, // 0x040200
|
||||||
|
MULTIMEDIA_HD_AUDIO = bindings::PCI_CLASS_MULTIMEDIA_HD_AUDIO, // 0x040300
|
||||||
|
MULTIMEDIA_OTHER = bindings::PCI_CLASS_MULTIMEDIA_OTHER, // 0x048000
|
||||||
|
|
||||||
|
MEMORY_RAM = bindings::PCI_CLASS_MEMORY_RAM, // 0x050000
|
||||||
|
MEMORY_FLASH = bindings::PCI_CLASS_MEMORY_FLASH, // 0x050100
|
||||||
|
MEMORY_CXL = bindings::PCI_CLASS_MEMORY_CXL, // 0x050200
|
||||||
|
MEMORY_OTHER = bindings::PCI_CLASS_MEMORY_OTHER, // 0x058000
|
||||||
|
|
||||||
|
BRIDGE_HOST = bindings::PCI_CLASS_BRIDGE_HOST, // 0x060000
|
||||||
|
BRIDGE_ISA = bindings::PCI_CLASS_BRIDGE_ISA, // 0x060100
|
||||||
|
BRIDGE_EISA = bindings::PCI_CLASS_BRIDGE_EISA, // 0x060200
|
||||||
|
BRIDGE_MC = bindings::PCI_CLASS_BRIDGE_MC, // 0x060300
|
||||||
|
BRIDGE_PCI_NORMAL = bindings::PCI_CLASS_BRIDGE_PCI_NORMAL, // 0x060400
|
||||||
|
BRIDGE_PCI_SUBTRACTIVE = bindings::PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE, // 0x060401
|
||||||
|
BRIDGE_PCMCIA = bindings::PCI_CLASS_BRIDGE_PCMCIA, // 0x060500
|
||||||
|
BRIDGE_NUBUS = bindings::PCI_CLASS_BRIDGE_NUBUS, // 0x060600
|
||||||
|
BRIDGE_CARDBUS = bindings::PCI_CLASS_BRIDGE_CARDBUS, // 0x060700
|
||||||
|
BRIDGE_RACEWAY = bindings::PCI_CLASS_BRIDGE_RACEWAY, // 0x060800
|
||||||
|
BRIDGE_OTHER = bindings::PCI_CLASS_BRIDGE_OTHER, // 0x068000
|
||||||
|
|
||||||
|
COMMUNICATION_SERIAL = bindings::PCI_CLASS_COMMUNICATION_SERIAL, // 0x070000
|
||||||
|
COMMUNICATION_PARALLEL = bindings::PCI_CLASS_COMMUNICATION_PARALLEL, // 0x070100
|
||||||
|
COMMUNICATION_MULTISERIAL = bindings::PCI_CLASS_COMMUNICATION_MULTISERIAL, // 0x070200
|
||||||
|
COMMUNICATION_MODEM = bindings::PCI_CLASS_COMMUNICATION_MODEM, // 0x070300
|
||||||
|
COMMUNICATION_OTHER = bindings::PCI_CLASS_COMMUNICATION_OTHER, // 0x078000
|
||||||
|
|
||||||
|
SYSTEM_PIC = bindings::PCI_CLASS_SYSTEM_PIC, // 0x080000
|
||||||
|
SYSTEM_PIC_IOAPIC = bindings::PCI_CLASS_SYSTEM_PIC_IOAPIC, // 0x080010
|
||||||
|
SYSTEM_PIC_IOXAPIC = bindings::PCI_CLASS_SYSTEM_PIC_IOXAPIC, // 0x080020
|
||||||
|
SYSTEM_DMA = bindings::PCI_CLASS_SYSTEM_DMA, // 0x080100
|
||||||
|
SYSTEM_TIMER = bindings::PCI_CLASS_SYSTEM_TIMER, // 0x080200
|
||||||
|
SYSTEM_RTC = bindings::PCI_CLASS_SYSTEM_RTC, // 0x080300
|
||||||
|
SYSTEM_PCI_HOTPLUG = bindings::PCI_CLASS_SYSTEM_PCI_HOTPLUG, // 0x080400
|
||||||
|
SYSTEM_SDHCI = bindings::PCI_CLASS_SYSTEM_SDHCI, // 0x080500
|
||||||
|
SYSTEM_RCEC = bindings::PCI_CLASS_SYSTEM_RCEC, // 0x080700
|
||||||
|
SYSTEM_OTHER = bindings::PCI_CLASS_SYSTEM_OTHER, // 0x088000
|
||||||
|
|
||||||
|
INPUT_KEYBOARD = bindings::PCI_CLASS_INPUT_KEYBOARD, // 0x090000
|
||||||
|
INPUT_PEN = bindings::PCI_CLASS_INPUT_PEN, // 0x090100
|
||||||
|
INPUT_MOUSE = bindings::PCI_CLASS_INPUT_MOUSE, // 0x090200
|
||||||
|
INPUT_SCANNER = bindings::PCI_CLASS_INPUT_SCANNER, // 0x090300
|
||||||
|
INPUT_GAMEPORT = bindings::PCI_CLASS_INPUT_GAMEPORT, // 0x090400
|
||||||
|
INPUT_OTHER = bindings::PCI_CLASS_INPUT_OTHER, // 0x098000
|
||||||
|
|
||||||
|
DOCKING_GENERIC = bindings::PCI_CLASS_DOCKING_GENERIC, // 0x0a0000
|
||||||
|
DOCKING_OTHER = bindings::PCI_CLASS_DOCKING_OTHER, // 0x0a8000
|
||||||
|
|
||||||
|
PROCESSOR_386 = bindings::PCI_CLASS_PROCESSOR_386, // 0x0b0000
|
||||||
|
PROCESSOR_486 = bindings::PCI_CLASS_PROCESSOR_486, // 0x0b0100
|
||||||
|
PROCESSOR_PENTIUM = bindings::PCI_CLASS_PROCESSOR_PENTIUM, // 0x0b0200
|
||||||
|
PROCESSOR_ALPHA = bindings::PCI_CLASS_PROCESSOR_ALPHA, // 0x0b1000
|
||||||
|
PROCESSOR_POWERPC = bindings::PCI_CLASS_PROCESSOR_POWERPC, // 0x0b2000
|
||||||
|
PROCESSOR_MIPS = bindings::PCI_CLASS_PROCESSOR_MIPS, // 0x0b3000
|
||||||
|
PROCESSOR_CO = bindings::PCI_CLASS_PROCESSOR_CO, // 0x0b4000
|
||||||
|
|
||||||
|
SERIAL_FIREWIRE = bindings::PCI_CLASS_SERIAL_FIREWIRE, // 0x0c0000
|
||||||
|
SERIAL_FIREWIRE_OHCI = bindings::PCI_CLASS_SERIAL_FIREWIRE_OHCI, // 0x0c0010
|
||||||
|
SERIAL_ACCESS = bindings::PCI_CLASS_SERIAL_ACCESS, // 0x0c0100
|
||||||
|
SERIAL_SSA = bindings::PCI_CLASS_SERIAL_SSA, // 0x0c0200
|
||||||
|
SERIAL_USB_UHCI = bindings::PCI_CLASS_SERIAL_USB_UHCI, // 0x0c0300
|
||||||
|
SERIAL_USB_OHCI = bindings::PCI_CLASS_SERIAL_USB_OHCI, // 0x0c0310
|
||||||
|
SERIAL_USB_EHCI = bindings::PCI_CLASS_SERIAL_USB_EHCI, // 0x0c0320
|
||||||
|
SERIAL_USB_XHCI = bindings::PCI_CLASS_SERIAL_USB_XHCI, // 0x0c0330
|
||||||
|
SERIAL_USB_CDNS = bindings::PCI_CLASS_SERIAL_USB_CDNS, // 0x0c0380
|
||||||
|
SERIAL_USB_DEVICE = bindings::PCI_CLASS_SERIAL_USB_DEVICE, // 0x0c03fe
|
||||||
|
SERIAL_FIBER = bindings::PCI_CLASS_SERIAL_FIBER, // 0x0c0400
|
||||||
|
SERIAL_SMBUS = bindings::PCI_CLASS_SERIAL_SMBUS, // 0x0c0500
|
||||||
|
SERIAL_IPMI_SMIC = bindings::PCI_CLASS_SERIAL_IPMI_SMIC, // 0x0c0700
|
||||||
|
SERIAL_IPMI_KCS = bindings::PCI_CLASS_SERIAL_IPMI_KCS, // 0x0c0701
|
||||||
|
SERIAL_IPMI_BT = bindings::PCI_CLASS_SERIAL_IPMI_BT, // 0x0c0702
|
||||||
|
|
||||||
|
WIRELESS_RF_CONTROLLER = bindings::PCI_CLASS_WIRELESS_RF_CONTROLLER, // 0x0d1000
|
||||||
|
WIRELESS_WHCI = bindings::PCI_CLASS_WIRELESS_WHCI, // 0x0d1010
|
||||||
|
|
||||||
|
INTELLIGENT_I2O = bindings::PCI_CLASS_INTELLIGENT_I2O, // 0x0e0000
|
||||||
|
|
||||||
|
SATELLITE_TV = bindings::PCI_CLASS_SATELLITE_TV, // 0x0f0000
|
||||||
|
SATELLITE_AUDIO = bindings::PCI_CLASS_SATELLITE_AUDIO, // 0x0f0100
|
||||||
|
SATELLITE_VOICE = bindings::PCI_CLASS_SATELLITE_VOICE, // 0x0f0300
|
||||||
|
SATELLITE_DATA = bindings::PCI_CLASS_SATELLITE_DATA, // 0x0f0400
|
||||||
|
|
||||||
|
CRYPT_NETWORK = bindings::PCI_CLASS_CRYPT_NETWORK, // 0x100000
|
||||||
|
CRYPT_ENTERTAINMENT = bindings::PCI_CLASS_CRYPT_ENTERTAINMENT, // 0x100100
|
||||||
|
CRYPT_OTHER = bindings::PCI_CLASS_CRYPT_OTHER, // 0x108000
|
||||||
|
|
||||||
|
SP_DPIO = bindings::PCI_CLASS_SP_DPIO, // 0x110000
|
||||||
|
SP_OTHER = bindings::PCI_CLASS_SP_OTHER, // 0x118000
|
||||||
|
|
||||||
|
ACCELERATOR_PROCESSING = bindings::PCI_CLASS_ACCELERATOR_PROCESSING, // 0x120000
|
||||||
|
|
||||||
|
OTHERS = bindings::PCI_CLASS_OTHERS, // 0xff0000
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue