This allows callers to write Vendor::SOME_COMPANY instead of
bindings::PCI_VENDOR_ID_SOME_COMPANY.
New APIs:
Vendor::SOME_COMPANY
Vendor::as_raw()
Vendor: From<u32> for Vendor
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Alexandre Courbot <acourbot@nvidia.com>
Cc: Elle Rhumsaa <elle@weathered-steel.dev>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
rust/kernel/pci.rs | 2 +-
rust/kernel/pci/id.rs | 355 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 355 insertions(+), 2 deletions(-)
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 0faec49bf8a2..d4675b7d4a86 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -25,7 +25,7 @@
mod id;
-pub use self::id::{Class, ClassMask};
+pub use self::id::{Class, ClassMask, Vendor};
/// An adapter for the registration of PCI drivers.
pub struct Adapter<T: Driver>(T);
diff --git a/rust/kernel/pci/id.rs b/rust/kernel/pci/id.rs
index 1291553b4e15..dd91e25a6890 100644
--- a/rust/kernel/pci/id.rs
+++ b/rust/kernel/pci/id.rs
@@ -2,7 +2,7 @@
//! PCI device identifiers and related types.
//!
-//! This module contains PCI class codes and supporting types.
+//! This module contains PCI class codes, Vendor IDs, and supporting types.
use crate::{bindings, error::code::EINVAL, error::Error, prelude::*};
use core::fmt;
@@ -115,6 +115,74 @@ fn try_from(value: u32) -> Result<Self, Self::Error> {
}
}
+/// PCI vendor IDs.
+///
+/// Each entry contains the 16-bit PCI vendor ID as assigned by the PCI SIG.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::{device::Core, pci::{self, Vendor}, prelude::*};
+/// fn log_device_info(pdev: &pci::Device<Core>) -> Result<()> {
+/// // Get the raw PCI vendor ID and convert to Vendor
+/// let vendor_id = pdev.vendor_id();
+/// let vendor = Vendor::new(vendor_id.into());
+/// dev_info!(
+/// pdev.as_ref(),
+/// "Device: Vendor={}, Device=0x{:x}\n",
+/// vendor,
+/// pdev.device_id()
+/// );
+/// Ok(())
+/// }
+/// ```
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(transparent)]
+pub struct Vendor(u32);
+
+macro_rules! define_all_pci_vendors {
+ (
+ $($variant:ident = $binding:expr,)+
+ ) => {
+
+ impl Vendor {
+ $(
+ #[allow(missing_docs)]
+ pub const $variant: Self = Self($binding as u32);
+ )+
+ }
+
+ /// Convert a raw 16-bit vendor ID to a `Vendor`.
+ impl From<u32> for Vendor {
+ fn from(value: u32) -> Self {
+ match value {
+ $(x if x == Self::$variant.0 => Self::$variant,)+
+ _ => Self::UNKNOWN,
+ }
+ }
+ }
+ };
+}
+
+/// Once constructed, a `Vendor` contains a valid PCI Vendor ID.
+impl Vendor {
+ /// Create a new Vendor from a raw 16-bit vendor ID.
+ pub fn new(vendor_id: u32) -> Self {
+ Self::from(vendor_id)
+ }
+
+ /// Get the raw 16-bit vendor ID value.
+ pub const fn as_raw(self) -> u32 {
+ self.0
+ }
+}
+
+impl fmt::Display for Vendor {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "0x{:04x}", self.0)
+ }
+}
+
define_all_pci_classes! {
NOT_DEFINED = bindings::PCI_CLASS_NOT_DEFINED, // 0x000000
NOT_DEFINED_VGA = bindings::PCI_CLASS_NOT_DEFINED_VGA, // 0x000100
@@ -237,3 +305,288 @@ fn try_from(value: u32) -> Result<Self, Self::Error> {
OTHERS = bindings::PCI_CLASS_OTHERS, // 0xff0000
UNKNOWN = 0xffffff,
}
+
+define_all_pci_vendors! {
+ PCI_SIG = bindings::PCI_VENDOR_ID_PCI_SIG, // 0x0001
+ LOONGSON = bindings::PCI_VENDOR_ID_LOONGSON, // 0x0014
+ SOLIDIGM = bindings::PCI_VENDOR_ID_SOLIDIGM, // 0x025e
+ TTTECH = bindings::PCI_VENDOR_ID_TTTECH, // 0x0357
+ DYNALINK = bindings::PCI_VENDOR_ID_DYNALINK, // 0x0675
+ UBIQUITI = bindings::PCI_VENDOR_ID_UBIQUITI, // 0x0777
+ BERKOM = bindings::PCI_VENDOR_ID_BERKOM, // 0x0871
+ ITTIM = bindings::PCI_VENDOR_ID_ITTIM, // 0x0b48
+ COMPAQ = bindings::PCI_VENDOR_ID_COMPAQ, // 0x0e11
+ LSI_LOGIC = bindings::PCI_VENDOR_ID_LSI_LOGIC, // 0x1000
+ ATI = bindings::PCI_VENDOR_ID_ATI, // 0x1002
+ VLSI = bindings::PCI_VENDOR_ID_VLSI, // 0x1004
+ ADL = bindings::PCI_VENDOR_ID_ADL, // 0x1005
+ NS = bindings::PCI_VENDOR_ID_NS, // 0x100b
+ TSENG = bindings::PCI_VENDOR_ID_TSENG, // 0x100c
+ WEITEK = bindings::PCI_VENDOR_ID_WEITEK, // 0x100e
+ DEC = bindings::PCI_VENDOR_ID_DEC, // 0x1011
+ CIRRUS = bindings::PCI_VENDOR_ID_CIRRUS, // 0x1013
+ IBM = bindings::PCI_VENDOR_ID_IBM, // 0x1014
+ UNISYS = bindings::PCI_VENDOR_ID_UNISYS, // 0x1018
+ COMPEX2 = bindings::PCI_VENDOR_ID_COMPEX2, // 0x101a
+ WD = bindings::PCI_VENDOR_ID_WD, // 0x101c
+ AMI = bindings::PCI_VENDOR_ID_AMI, // 0x101e
+ AMD = bindings::PCI_VENDOR_ID_AMD, // 0x1022
+ TRIDENT = bindings::PCI_VENDOR_ID_TRIDENT, // 0x1023
+ AI = bindings::PCI_VENDOR_ID_AI, // 0x1025
+ DELL = bindings::PCI_VENDOR_ID_DELL, // 0x1028
+ MATROX = bindings::PCI_VENDOR_ID_MATROX, // 0x102B
+ MOBILITY_ELECTRONICS = bindings::PCI_VENDOR_ID_MOBILITY_ELECTRONICS, // 0x14f2
+ CT = bindings::PCI_VENDOR_ID_CT, // 0x102c
+ MIRO = bindings::PCI_VENDOR_ID_MIRO, // 0x1031
+ NEC = bindings::PCI_VENDOR_ID_NEC, // 0x1033
+ FD = bindings::PCI_VENDOR_ID_FD, // 0x1036
+ SI = bindings::PCI_VENDOR_ID_SI, // 0x1039
+ HP = bindings::PCI_VENDOR_ID_HP, // 0x103c
+ HP_3PAR = bindings::PCI_VENDOR_ID_HP_3PAR, // 0x1590
+ PCTECH = bindings::PCI_VENDOR_ID_PCTECH, // 0x1042
+ ASUSTEK = bindings::PCI_VENDOR_ID_ASUSTEK, // 0x1043
+ DPT = bindings::PCI_VENDOR_ID_DPT, // 0x1044
+ OPTI = bindings::PCI_VENDOR_ID_OPTI, // 0x1045
+ ELSA = bindings::PCI_VENDOR_ID_ELSA, // 0x1048
+ STMICRO = bindings::PCI_VENDOR_ID_STMICRO, // 0x104A
+ BUSLOGIC = bindings::PCI_VENDOR_ID_BUSLOGIC, // 0x104B
+ TI = bindings::PCI_VENDOR_ID_TI, // 0x104c
+ SONY = bindings::PCI_VENDOR_ID_SONY, // 0x104d
+ WINBOND2 = bindings::PCI_VENDOR_ID_WINBOND2, // 0x1050
+ ANIGMA = bindings::PCI_VENDOR_ID_ANIGMA, // 0x1051
+ EFAR = bindings::PCI_VENDOR_ID_EFAR, // 0x1055
+ MOTOROLA = bindings::PCI_VENDOR_ID_MOTOROLA, // 0x1057
+ PROMISE = bindings::PCI_VENDOR_ID_PROMISE, // 0x105a
+ FOXCONN = bindings::PCI_VENDOR_ID_FOXCONN, // 0x105b
+ UMC = bindings::PCI_VENDOR_ID_UMC, // 0x1060
+ PICOPOWER = bindings::PCI_VENDOR_ID_PICOPOWER, // 0x1066
+ MYLEX = bindings::PCI_VENDOR_ID_MYLEX, // 0x1069
+ APPLE = bindings::PCI_VENDOR_ID_APPLE, // 0x106b
+ YAMAHA = bindings::PCI_VENDOR_ID_YAMAHA, // 0x1073
+ QLOGIC = bindings::PCI_VENDOR_ID_QLOGIC, // 0x1077
+ CYRIX = bindings::PCI_VENDOR_ID_CYRIX, // 0x1078
+ CONTAQ = bindings::PCI_VENDOR_ID_CONTAQ, // 0x1080
+ OLICOM = bindings::PCI_VENDOR_ID_OLICOM, // 0x108d
+ SUN = bindings::PCI_VENDOR_ID_SUN, // 0x108e
+ NI = bindings::PCI_VENDOR_ID_NI, // 0x1093
+ CMD = bindings::PCI_VENDOR_ID_CMD, // 0x1095
+ BROOKTREE = bindings::PCI_VENDOR_ID_BROOKTREE, // 0x109e
+ SGI = bindings::PCI_VENDOR_ID_SGI, // 0x10a9
+ WINBOND = bindings::PCI_VENDOR_ID_WINBOND, // 0x10ad
+ PLX = bindings::PCI_VENDOR_ID_PLX, // 0x10b5
+ MADGE = bindings::PCI_VENDOR_ID_MADGE, // 0x10b6
+ THREECOM = bindings::PCI_VENDOR_ID_3COM, // 0x10b7
+ AL = bindings::PCI_VENDOR_ID_AL, // 0x10b9
+ NEOMAGIC = bindings::PCI_VENDOR_ID_NEOMAGIC, // 0x10c8
+ TCONRAD = bindings::PCI_VENDOR_ID_TCONRAD, // 0x10da
+ ROHM = bindings::PCI_VENDOR_ID_ROHM, // 0x10db
+ NVIDIA = bindings::PCI_VENDOR_ID_NVIDIA, // 0x10de
+ IMS = bindings::PCI_VENDOR_ID_IMS, // 0x10e0
+ AMCC = bindings::PCI_VENDOR_ID_AMCC, // 0x10e8
+ AMPERE = bindings::PCI_VENDOR_ID_AMPERE, // 0x1def
+ INTERG = bindings::PCI_VENDOR_ID_INTERG, // 0x10ea
+ REALTEK = bindings::PCI_VENDOR_ID_REALTEK, // 0x10ec
+ XILINX = bindings::PCI_VENDOR_ID_XILINX, // 0x10ee
+ INIT = bindings::PCI_VENDOR_ID_INIT, // 0x1101
+ CREATIVE = bindings::PCI_VENDOR_ID_CREATIVE, // 0x1102
+ TTI = bindings::PCI_VENDOR_ID_TTI, // 0x1103
+ SIGMA = bindings::PCI_VENDOR_ID_SIGMA, // 0x1105
+ VIA = bindings::PCI_VENDOR_ID_VIA, // 0x1106
+ SIEMENS = bindings::PCI_VENDOR_ID_SIEMENS, // 0x110A
+ VORTEX = bindings::PCI_VENDOR_ID_VORTEX, // 0x1119
+ EF = bindings::PCI_VENDOR_ID_EF, // 0x111a
+ IDT = bindings::PCI_VENDOR_ID_IDT, // 0x111d
+ FORE = bindings::PCI_VENDOR_ID_FORE, // 0x1127
+ PHILIPS = bindings::PCI_VENDOR_ID_PHILIPS, // 0x1131
+ EICON = bindings::PCI_VENDOR_ID_EICON, // 0x1133
+ CISCO = bindings::PCI_VENDOR_ID_CISCO, // 0x1137
+ ZIATECH = bindings::PCI_VENDOR_ID_ZIATECH, // 0x1138
+ SYSKONNECT = bindings::PCI_VENDOR_ID_SYSKONNECT, // 0x1148
+ DIGI = bindings::PCI_VENDOR_ID_DIGI, // 0x114f
+ XIRCOM = bindings::PCI_VENDOR_ID_XIRCOM, // 0x115d
+ SERVERWORKS = bindings::PCI_VENDOR_ID_SERVERWORKS, // 0x1166
+ ALTERA = bindings::PCI_VENDOR_ID_ALTERA, // 0x1172
+ SBE = bindings::PCI_VENDOR_ID_SBE, // 0x1176
+ TOSHIBA = bindings::PCI_VENDOR_ID_TOSHIBA, // 0x1179
+ TOSHIBA_2 = bindings::PCI_VENDOR_ID_TOSHIBA_2, // 0x102f
+ ATTO = bindings::PCI_VENDOR_ID_ATTO, // 0x117c
+ RICOH = bindings::PCI_VENDOR_ID_RICOH, // 0x1180
+ DLINK = bindings::PCI_VENDOR_ID_DLINK, // 0x1186
+ ARTOP = bindings::PCI_VENDOR_ID_ARTOP, // 0x1191
+ ZEITNET = bindings::PCI_VENDOR_ID_ZEITNET, // 0x1193
+ FUJITSU_ME = bindings::PCI_VENDOR_ID_FUJITSU_ME, // 0x119e
+ MARVELL = bindings::PCI_VENDOR_ID_MARVELL, // 0x11ab
+ MARVELL_EXT = bindings::PCI_VENDOR_ID_MARVELL_EXT, // 0x1b4b
+ V3 = bindings::PCI_VENDOR_ID_V3, // 0x11b0
+ ATT = bindings::PCI_VENDOR_ID_ATT, // 0x11c1
+ SPECIALIX = bindings::PCI_VENDOR_ID_SPECIALIX, // 0x11cb
+ ANALOG_DEVICES = bindings::PCI_VENDOR_ID_ANALOG_DEVICES, // 0x11d4
+ ZORAN = bindings::PCI_VENDOR_ID_ZORAN, // 0x11de
+ COMPEX = bindings::PCI_VENDOR_ID_COMPEX, // 0x11f6
+ MICROSEMI = bindings::PCI_VENDOR_ID_MICROSEMI, // 0x11f8
+ RP = bindings::PCI_VENDOR_ID_RP, // 0x11fe
+ CYCLADES = bindings::PCI_VENDOR_ID_CYCLADES, // 0x120e
+ ESSENTIAL = bindings::PCI_VENDOR_ID_ESSENTIAL, // 0x120f
+ O2 = bindings::PCI_VENDOR_ID_O2, // 0x1217
+ THREEDX = bindings::PCI_VENDOR_ID_3DFX, // 0x121a
+ AVM = bindings::PCI_VENDOR_ID_AVM, // 0x1244
+ STALLION = bindings::PCI_VENDOR_ID_STALLION, // 0x124d
+ AT = bindings::PCI_VENDOR_ID_AT, // 0x1259
+ ASIX = bindings::PCI_VENDOR_ID_ASIX, // 0x125b
+ ESS = bindings::PCI_VENDOR_ID_ESS, // 0x125d
+ SATSAGEM = bindings::PCI_VENDOR_ID_SATSAGEM, // 0x1267
+ ENSONIQ = bindings::PCI_VENDOR_ID_ENSONIQ, // 0x1274
+ TRANSMETA = bindings::PCI_VENDOR_ID_TRANSMETA, // 0x1279
+ ROCKWELL = bindings::PCI_VENDOR_ID_ROCKWELL, // 0x127A
+ ITE = bindings::PCI_VENDOR_ID_ITE, // 0x1283
+ ALTEON = bindings::PCI_VENDOR_ID_ALTEON, // 0x12ae
+ NVIDIA_SGS = bindings::PCI_VENDOR_ID_NVIDIA_SGS, // 0x12d2
+ PERICOM = bindings::PCI_VENDOR_ID_PERICOM, // 0x12D8
+ AUREAL = bindings::PCI_VENDOR_ID_AUREAL, // 0x12eb
+ ELECTRONICDESIGNGMBH = bindings::PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, // 0x12f8
+ ESDGMBH = bindings::PCI_VENDOR_ID_ESDGMBH, // 0x12fe
+ CB = bindings::PCI_VENDOR_ID_CB, // 0x1307
+ SIIG = bindings::PCI_VENDOR_ID_SIIG, // 0x131f
+ RADISYS = bindings::PCI_VENDOR_ID_RADISYS, // 0x1331
+ MICRO_MEMORY = bindings::PCI_VENDOR_ID_MICRO_MEMORY, // 0x1332
+ DOMEX = bindings::PCI_VENDOR_ID_DOMEX, // 0x134a
+ INTASHIELD = bindings::PCI_VENDOR_ID_INTASHIELD, // 0x135a
+ QUATECH = bindings::PCI_VENDOR_ID_QUATECH, // 0x135C
+ SEALEVEL = bindings::PCI_VENDOR_ID_SEALEVEL, // 0x135e
+ HYPERCOPE = bindings::PCI_VENDOR_ID_HYPERCOPE, // 0x1365
+ DIGIGRAM = bindings::PCI_VENDOR_ID_DIGIGRAM, // 0x1369
+ KAWASAKI = bindings::PCI_VENDOR_ID_KAWASAKI, // 0x136b
+ CNET = bindings::PCI_VENDOR_ID_CNET, // 0x1371
+ LMC = bindings::PCI_VENDOR_ID_LMC, // 0x1376
+ NETGEAR = bindings::PCI_VENDOR_ID_NETGEAR, // 0x1385
+ APPLICOM = bindings::PCI_VENDOR_ID_APPLICOM, // 0x1389
+ MOXA = bindings::PCI_VENDOR_ID_MOXA, // 0x1393
+ CCD = bindings::PCI_VENDOR_ID_CCD, // 0x1397
+ EXAR = bindings::PCI_VENDOR_ID_EXAR, // 0x13a8
+ MICROGATE = bindings::PCI_VENDOR_ID_MICROGATE, // 0x13c0
+ THREEWARE = bindings::PCI_VENDOR_ID_3WARE, // 0x13C1
+ IOMEGA = bindings::PCI_VENDOR_ID_IOMEGA, // 0x13ca
+ ABOCOM = bindings::PCI_VENDOR_ID_ABOCOM, // 0x13D1
+ SUNDANCE = bindings::PCI_VENDOR_ID_SUNDANCE, // 0x13f0
+ CMEDIA = bindings::PCI_VENDOR_ID_CMEDIA, // 0x13f6
+ ADVANTECH = bindings::PCI_VENDOR_ID_ADVANTECH, // 0x13fe
+ MEILHAUS = bindings::PCI_VENDOR_ID_MEILHAUS, // 0x1402
+ LAVA = bindings::PCI_VENDOR_ID_LAVA, // 0x1407
+ TIMEDIA = bindings::PCI_VENDOR_ID_TIMEDIA, // 0x1409
+ ICE = bindings::PCI_VENDOR_ID_ICE, // 0x1412
+ MICROSOFT = bindings::PCI_VENDOR_ID_MICROSOFT, // 0x1414
+ OXSEMI = bindings::PCI_VENDOR_ID_OXSEMI, // 0x1415
+ CHELSIO = bindings::PCI_VENDOR_ID_CHELSIO, // 0x1425
+ EDIMAX = bindings::PCI_VENDOR_ID_EDIMAX, // 0x1432
+ ADLINK = bindings::PCI_VENDOR_ID_ADLINK, // 0x144a
+ SAMSUNG = bindings::PCI_VENDOR_ID_SAMSUNG, // 0x144d
+ GIGABYTE = bindings::PCI_VENDOR_ID_GIGABYTE, // 0x1458
+ AMBIT = bindings::PCI_VENDOR_ID_AMBIT, // 0x1468
+ MYRICOM = bindings::PCI_VENDOR_ID_MYRICOM, // 0x14c1
+ MEDIATEK = bindings::PCI_VENDOR_ID_MEDIATEK, // 0x14c3
+ TITAN = bindings::PCI_VENDOR_ID_TITAN, // 0x14D2
+ PANACOM = bindings::PCI_VENDOR_ID_PANACOM, // 0x14d4
+ SIPACKETS = bindings::PCI_VENDOR_ID_SIPACKETS, // 0x14d9
+ AFAVLAB = bindings::PCI_VENDOR_ID_AFAVLAB, // 0x14db
+ AMPLICON = bindings::PCI_VENDOR_ID_AMPLICON, // 0x14dc
+ BCM_GVC = bindings::PCI_VENDOR_ID_BCM_GVC, // 0x14a4
+ BROADCOM = bindings::PCI_VENDOR_ID_BROADCOM, // 0x14e4
+ TOPIC = bindings::PCI_VENDOR_ID_TOPIC, // 0x151f
+ MAINPINE = bindings::PCI_VENDOR_ID_MAINPINE, // 0x1522
+ ENE = bindings::PCI_VENDOR_ID_ENE, // 0x1524
+ SYBA = bindings::PCI_VENDOR_ID_SYBA, // 0x1592
+ MORETON = bindings::PCI_VENDOR_ID_MORETON, // 0x15aa
+ VMWARE = bindings::PCI_VENDOR_ID_VMWARE, // 0x15ad
+ ZOLTRIX = bindings::PCI_VENDOR_ID_ZOLTRIX, // 0x15b0
+ MELLANOX = bindings::PCI_VENDOR_ID_MELLANOX, // 0x15b3
+ DFI = bindings::PCI_VENDOR_ID_DFI, // 0x15bd
+ QUICKNET = bindings::PCI_VENDOR_ID_QUICKNET, // 0x15e2
+ ADDIDATA = bindings::PCI_VENDOR_ID_ADDIDATA, // 0x15B8
+ PDC = bindings::PCI_VENDOR_ID_PDC, // 0x15e9
+ FARSITE = bindings::PCI_VENDOR_ID_FARSITE, // 0x1619
+ ARIMA = bindings::PCI_VENDOR_ID_ARIMA, // 0x161f
+ BROCADE = bindings::PCI_VENDOR_ID_BROCADE, // 0x1657
+ SIBYTE = bindings::PCI_VENDOR_ID_SIBYTE, // 0x166d
+ ATHEROS = bindings::PCI_VENDOR_ID_ATHEROS, // 0x168c
+ NETCELL = bindings::PCI_VENDOR_ID_NETCELL, // 0x169c
+ CENATEK = bindings::PCI_VENDOR_ID_CENATEK, // 0x16CA
+ SYNOPSYS = bindings::PCI_VENDOR_ID_SYNOPSYS, // 0x16c3
+ USR = bindings::PCI_VENDOR_ID_USR, // 0x16ec
+ VITESSE = bindings::PCI_VENDOR_ID_VITESSE, // 0x1725
+ LINKSYS = bindings::PCI_VENDOR_ID_LINKSYS, // 0x1737
+ ALTIMA = bindings::PCI_VENDOR_ID_ALTIMA, // 0x173b
+ CAVIUM = bindings::PCI_VENDOR_ID_CAVIUM, // 0x177d
+ TECHWELL = bindings::PCI_VENDOR_ID_TECHWELL, // 0x1797
+ BELKIN = bindings::PCI_VENDOR_ID_BELKIN, // 0x1799
+ RDC = bindings::PCI_VENDOR_ID_RDC, // 0x17f3
+ GLI = bindings::PCI_VENDOR_ID_GLI, // 0x17a0
+ LENOVO = bindings::PCI_VENDOR_ID_LENOVO, // 0x17aa
+ QCOM = bindings::PCI_VENDOR_ID_QCOM, // 0x17cb
+ CDNS = bindings::PCI_VENDOR_ID_CDNS, // 0x17cd
+ ARECA = bindings::PCI_VENDOR_ID_ARECA, // 0x17d3
+ S2IO = bindings::PCI_VENDOR_ID_S2IO, // 0x17d5
+ SITECOM = bindings::PCI_VENDOR_ID_SITECOM, // 0x182d
+ TOPSPIN = bindings::PCI_VENDOR_ID_TOPSPIN, // 0x1867
+ COMMTECH = bindings::PCI_VENDOR_ID_COMMTECH, // 0x18f7
+ SILAN = bindings::PCI_VENDOR_ID_SILAN, // 0x1904
+ RENESAS = bindings::PCI_VENDOR_ID_RENESAS, // 0x1912
+ SOLARFLARE = bindings::PCI_VENDOR_ID_SOLARFLARE, // 0x1924
+ TDI = bindings::PCI_VENDOR_ID_TDI, // 0x192E
+ NXP = bindings::PCI_VENDOR_ID_NXP, // 0x1957
+ PASEMI = bindings::PCI_VENDOR_ID_PASEMI, // 0x1959
+ ATTANSIC = bindings::PCI_VENDOR_ID_ATTANSIC, // 0x1969
+ JMICRON = bindings::PCI_VENDOR_ID_JMICRON, // 0x197B
+ KORENIX = bindings::PCI_VENDOR_ID_KORENIX, // 0x1982
+ HUAWEI = bindings::PCI_VENDOR_ID_HUAWEI, // 0x19e5
+ NETRONOME = bindings::PCI_VENDOR_ID_NETRONOME, // 0x19ee
+ QMI = bindings::PCI_VENDOR_ID_QMI, // 0x1a32
+ AZWAVE = bindings::PCI_VENDOR_ID_AZWAVE, // 0x1a3b
+ REDHAT_QUMRANET = bindings::PCI_VENDOR_ID_REDHAT_QUMRANET, // 0x1af4
+ ASMEDIA = bindings::PCI_VENDOR_ID_ASMEDIA, // 0x1b21
+ REDHAT = bindings::PCI_VENDOR_ID_REDHAT, // 0x1b36
+ WCHIC = bindings::PCI_VENDOR_ID_WCHIC, // 0x1c00
+ SILICOM_DENMARK = bindings::PCI_VENDOR_ID_SILICOM_DENMARK, // 0x1c2c
+ AMAZON_ANNAPURNA_LABS = bindings::PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, // 0x1c36
+ CIRCUITCO = bindings::PCI_VENDOR_ID_CIRCUITCO, // 0x1cc8
+ AMAZON = bindings::PCI_VENDOR_ID_AMAZON, // 0x1d0f
+ ZHAOXIN = bindings::PCI_VENDOR_ID_ZHAOXIN, // 0x1d17
+ ROCKCHIP = bindings::PCI_VENDOR_ID_ROCKCHIP, // 0x1d87
+ HYGON = bindings::PCI_VENDOR_ID_HYGON, // 0x1d94
+ META = bindings::PCI_VENDOR_ID_META, // 0x1d9b
+ FUNGIBLE = bindings::PCI_VENDOR_ID_FUNGIBLE, // 0x1dad
+ HXT = bindings::PCI_VENDOR_ID_HXT, // 0x1dbf
+ TEKRAM = bindings::PCI_VENDOR_ID_TEKRAM, // 0x1de1
+ RPI = bindings::PCI_VENDOR_ID_RPI, // 0x1de4
+ ALIBABA = bindings::PCI_VENDOR_ID_ALIBABA, // 0x1ded
+ CXL = bindings::PCI_VENDOR_ID_CXL, // 0x1e98
+ TEHUTI = bindings::PCI_VENDOR_ID_TEHUTI, // 0x1fc9
+ SUNIX = bindings::PCI_VENDOR_ID_SUNIX, // 0x1fd4
+ HINT = bindings::PCI_VENDOR_ID_HINT, // 0x3388
+ THREEDLABS = bindings::PCI_VENDOR_ID_3DLABS, // 0x3d3d
+ NETXEN = bindings::PCI_VENDOR_ID_NETXEN, // 0x4040
+ AKS = bindings::PCI_VENDOR_ID_AKS, // 0x416c
+ WCHCN = bindings::PCI_VENDOR_ID_WCHCN, // 0x4348
+ ACCESSIO = bindings::PCI_VENDOR_ID_ACCESSIO, // 0x494f
+ S3 = bindings::PCI_VENDOR_ID_S3, // 0x5333
+ DUNORD = bindings::PCI_VENDOR_ID_DUNORD, // 0x5544
+ DCI = bindings::PCI_VENDOR_ID_DCI, // 0x6666
+ GLENFLY = bindings::PCI_VENDOR_ID_GLENFLY, // 0x6766
+ INTEL = bindings::PCI_VENDOR_ID_INTEL, // 0x8086
+ WANGXUN = bindings::PCI_VENDOR_ID_WANGXUN, // 0x8088
+ SCALEMP = bindings::PCI_VENDOR_ID_SCALEMP, // 0x8686
+ COMPUTONE = bindings::PCI_VENDOR_ID_COMPUTONE, // 0x8e0e
+ KTI = bindings::PCI_VENDOR_ID_KTI, // 0x8e2e
+ ADAPTEC = bindings::PCI_VENDOR_ID_ADAPTEC, // 0x9004
+ ADAPTEC2 = bindings::PCI_VENDOR_ID_ADAPTEC2, // 0x9005
+ HOLTEK = bindings::PCI_VENDOR_ID_HOLTEK, // 0x9412
+ NETMOS = bindings::PCI_VENDOR_ID_NETMOS, // 0x9710
+ THREECOM_2 = bindings::PCI_VENDOR_ID_3COM_2, // 0xa727
+ SOLIDRUN = bindings::PCI_VENDOR_ID_SOLIDRUN, // 0xd063
+ DIGIUM = bindings::PCI_VENDOR_ID_DIGIUM, // 0xd161
+ TIGERJET = bindings::PCI_VENDOR_ID_TIGERJET, // 0xe159
+ XILINX_RME = bindings::PCI_VENDOR_ID_XILINX_RME, // 0xea60
+ XEN = bindings::PCI_VENDOR_ID_XEN, // 0x5853
+ OCZ = bindings::PCI_VENDOR_ID_OCZ, // 0x1b85
+ NCUBE = bindings::PCI_VENDOR_ID_NCUBE, // 0x10ff
+ UNKNOWN = 0xffff,
+}
--
2.50.1
On Fri Aug 22, 2025 at 11:03 AM JST, John Hubbard wrote: > This allows callers to write Vendor::SOME_COMPANY instead of > bindings::PCI_VENDOR_ID_SOME_COMPANY. > > New APIs: > Vendor::SOME_COMPANY > Vendor::as_raw() > Vendor: From<u32> for Vendor > > Cc: Danilo Krummrich <dakr@kernel.org> > Cc: Alexandre Courbot <acourbot@nvidia.com> > Cc: Elle Rhumsaa <elle@weathered-steel.dev> > Signed-off-by: John Hubbard <jhubbard@nvidia.com> > --- > rust/kernel/pci.rs | 2 +- > rust/kernel/pci/id.rs | 355 +++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 355 insertions(+), 2 deletions(-) > > diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs > index 0faec49bf8a2..d4675b7d4a86 100644 > --- a/rust/kernel/pci.rs > +++ b/rust/kernel/pci.rs > @@ -25,7 +25,7 @@ > > mod id; > > -pub use self::id::{Class, ClassMask}; > +pub use self::id::{Class, ClassMask, Vendor}; > > /// An adapter for the registration of PCI drivers. > pub struct Adapter<T: Driver>(T); > diff --git a/rust/kernel/pci/id.rs b/rust/kernel/pci/id.rs > index 1291553b4e15..dd91e25a6890 100644 > --- a/rust/kernel/pci/id.rs > +++ b/rust/kernel/pci/id.rs > @@ -2,7 +2,7 @@ > > //! PCI device identifiers and related types. > //! > -//! This module contains PCI class codes and supporting types. > +//! This module contains PCI class codes, Vendor IDs, and supporting types. > > use crate::{bindings, error::code::EINVAL, error::Error, prelude::*}; > use core::fmt; > @@ -115,6 +115,74 @@ fn try_from(value: u32) -> Result<Self, Self::Error> { > } > } > > +/// PCI vendor IDs. > +/// > +/// Each entry contains the 16-bit PCI vendor ID as assigned by the PCI SIG. > +/// > +/// # Examples > +/// > +/// ``` > +/// # use kernel::{device::Core, pci::{self, Vendor}, prelude::*}; > +/// fn log_device_info(pdev: &pci::Device<Core>) -> Result<()> { > +/// // Get the raw PCI vendor ID and convert to Vendor > +/// let vendor_id = pdev.vendor_id(); > +/// let vendor = Vendor::new(vendor_id.into()); > +/// dev_info!( > +/// pdev.as_ref(), > +/// "Device: Vendor={}, Device=0x{:x}\n", > +/// vendor, > +/// pdev.device_id() > +/// ); > +/// Ok(()) > +/// } > +/// ``` > +#[derive(Debug, Clone, Copy, PartialEq, Eq)] > +#[repr(transparent)] > +pub struct Vendor(u32); > + > +macro_rules! define_all_pci_vendors { > + ( > + $($variant:ident = $binding:expr,)+ > + ) => { > + > + impl Vendor { > + $( > + #[allow(missing_docs)] > + pub const $variant: Self = Self($binding as u32); > + )+ > + } > + > + /// Convert a raw 16-bit vendor ID to a `Vendor`. > + impl From<u32> for Vendor { > + fn from(value: u32) -> Self { > + match value { > + $(x if x == Self::$variant.0 => Self::$variant,)+ > + _ => Self::UNKNOWN, > + } > + } Naive question from someone with a device tree background and almost no PCI experience: one consequence of using `From` here is that if I create an non-registered Vendor value (e.g. `let vendor = Vendor::from(0xf0f0)`), then do `vendor.as_raw()`, I won't get the value passed initially but the one for `UNKNOWN`, e.g. `0xffff`. Are we ok with this? > + } > + }; > +} > + > +/// Once constructed, a `Vendor` contains a valid PCI Vendor ID. > +impl Vendor { > + /// Create a new Vendor from a raw 16-bit vendor ID. The argument is 32-bit. :) Which triggers the question: why store these as u32 if a u16 is the right size?
On 8/25/25 5:33 AM, Alexandre Courbot wrote: >> +/// Once constructed, a `Vendor` contains a valid PCI Vendor ID. >> +impl Vendor { >> + /// Create a new Vendor from a raw 16-bit vendor ID. > > The argument is 32-bit. :) Which triggers the question: why store these > as u32 if a u16 is the right size? Good point! I'll change it to u16. thanks, -- John Hubbard
On Mon Aug 25, 2025 at 2:33 PM CEST, Alexandre Courbot wrote: >> +#[derive(Debug, Clone, Copy, PartialEq, Eq)] >> +#[repr(transparent)] >> +pub struct Vendor(u32); >> + >> +macro_rules! define_all_pci_vendors { >> + ( >> + $($variant:ident = $binding:expr,)+ >> + ) => { >> + >> + impl Vendor { >> + $( >> + #[allow(missing_docs)] >> + pub const $variant: Self = Self($binding as u32); >> + )+ >> + } >> + >> + /// Convert a raw 16-bit vendor ID to a `Vendor`. >> + impl From<u32> for Vendor { >> + fn from(value: u32) -> Self { >> + match value { >> + $(x if x == Self::$variant.0 => Self::$variant,)+ >> + _ => Self::UNKNOWN, >> + } >> + } > > Naive question from someone with a device tree background and almost no > PCI experience: one consequence of using `From` here is that if I create > an non-registered Vendor value (e.g. `let vendor = > Vendor::from(0xf0f0)`), then do `vendor.as_raw()`, I won't get the value > passed initially but the one for `UNKNOWN`, e.g. `0xffff`. Are we ok > with this? I think that's fine, since we shouldn't actually hit this. Drivers should only ever use the pre-defined constants of Vendor; consequently the Device::vendor_id() can't return UNKNOWN either. So, I think the From impl is not ideal, since we can't limit its visibility. In order to improve this, I suggest to use Vendor::new() directly in the macro, and make Vendor::new() private. The same goes for Class, I guess.
On 8/25/25 5:47 AM, Danilo Krummrich wrote: > On Mon Aug 25, 2025 at 2:33 PM CEST, Alexandre Courbot wrote: ... >> Naive question from someone with a device tree background and almost no >> PCI experience: one consequence of using `From` here is that if I create >> an non-registered Vendor value (e.g. `let vendor = >> Vendor::from(0xf0f0)`), then do `vendor.as_raw()`, I won't get the value >> passed initially but the one for `UNKNOWN`, e.g. `0xffff`. Are we ok >> with this? > > I think that's fine, since we shouldn't actually hit this. Drivers should only > ever use the pre-defined constants of Vendor; consequently the > Device::vendor_id() can't return UNKNOWN either. > > So, I think the From impl is not ideal, since we can't limit its visibility. In > order to improve this, I suggest to use Vendor::new() directly in the macro, and > make Vendor::new() private. The same goes for Class, I guess. Correction: when I went to implement this, I discovered that there is a better way, which addresses both Alex's and your concerns. The incremental diff below shows how. It provides: a) .from_raw(), which in this case matches conventions slightly better than new(). (I'm still learning that the Rust way is a bit different that the C++ way! haha). b) Only the parent module (in this case, that's pci:: ) can call Class::from_raw(). This is exactly what we need. Fully private methods wouldn't work, but leaving it open for any caller to construct a Class item is also a problem. c) Restored infallible operations, and with it, Alex's request for a reasonable behavior here now works once again: from_raw(0x10de).as_raw() == 0x10de diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 0faec49bf8a2..40047a7433b1 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -418,7 +418,7 @@ pub fn resource_len(&self, bar: u32) -> Result<bindings::resource_size_t> { /// Returns the PCI class as a `Class` struct. pub fn pci_class(&self) -> Class { // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. - Class::new(unsafe { (*self.as_raw()).class }) + Class::from_raw(unsafe { (*self.as_raw()).class }) } } diff --git a/rust/kernel/pci/id.rs b/rust/kernel/pci/id.rs index 1291553b4e15..399436ffaab9 100644 --- a/rust/kernel/pci/id.rs +++ b/rust/kernel/pci/id.rs @@ -51,24 +51,15 @@ impl Class { pub const $variant: Self = Self(Self::to_24bit_class($binding)); )+ } - - /// Convert a raw 24-bit class code value to a `Class`. - impl From<u32> for Class { - fn from(value: u32) -> Self { - match value { - $(x if x == Self::$variant.0 => Self::$variant,)+ - _ => Self::UNKNOWN, - } - } - } }; } /// Once constructed, a `Class` contains a valid PCI Class code. impl Class { - /// Create a new Class from a raw 24-bit class code. - pub fn new(class_code: u32) -> Self { - Self::from(class_code) + /// Create a Class from a raw 24-bit class code. + /// Only accessible from the parent pci module. + pub(super) fn from_raw(class_code: u32) -> Self { + Self(class_code) } /// Get the raw 24-bit class code value. @@ -235,5 +226,4 @@ fn try_from(value: u32) -> Result<Self, Self::Error> { ACCELERATOR_PROCESSING = bindings::PCI_CLASS_ACCELERATOR_PROCESSING, // 0x120000 OTHERS = bindings::PCI_CLASS_OTHERS, // 0xff0000 - UNKNOWN = 0xffffff, } thanks, -- John Hubbard
On 8/26/25 10:38 PM, John Hubbard wrote: > On 8/25/25 5:47 AM, Danilo Krummrich wrote: >> On Mon Aug 25, 2025 at 2:33 PM CEST, Alexandre Courbot wrote: > ... >>> Naive question from someone with a device tree background and almost no >>> PCI experience: one consequence of using `From` here is that if I create >>> an non-registered Vendor value (e.g. `let vendor = >>> Vendor::from(0xf0f0)`), then do `vendor.as_raw()`, I won't get the value >>> passed initially but the one for `UNKNOWN`, e.g. `0xffff`. Are we ok >>> with this? >> >> I think that's fine, since we shouldn't actually hit this. Drivers should only >> ever use the pre-defined constants of Vendor; consequently the >> Device::vendor_id() can't return UNKNOWN either. >> >> So, I think the From impl is not ideal, since we can't limit its visibility. In >> order to improve this, I suggest to use Vendor::new() directly in the macro, and >> make Vendor::new() private. The same goes for Class, I guess. > > Correction: when I went to implement this, I discovered that there is a better > way, which addresses both Alex's and your concerns. > > The incremental diff below shows how. It provides: > > a) .from_raw(), which in this case matches conventions slightly better > than new(). (I'm still learning that the Rust way is a bit different > that the C++ way! haha). > > b) Only the parent module (in this case, that's pci:: ) can call > Class::from_raw(). This is exactly what we need. Fully private methods > wouldn't work, but leaving it open for any caller to construct a > Class item is also a problem. Sorry, that's on me being not precise. When I said private I meant private to the parent module. The diff looks good, thanks! Please also make sure to add #[inline] where appropriate and rebase onto driver-core-next.
On 8/26/25 1:45 PM, Danilo Krummrich wrote: > On 8/26/25 10:38 PM, John Hubbard wrote: >> On 8/25/25 5:47 AM, Danilo Krummrich wrote: >>> On Mon Aug 25, 2025 at 2:33 PM CEST, Alexandre Courbot wrote: >> ... > Sorry, that's on me being not precise. When I said private I meant private to > the parent module. > > The diff looks good, thanks! Huge relief! :) > > Please also make sure to add #[inline] where appropriate and rebase onto > driver-core-next. I have no idea "where appropriate" is, here. These are not hot paths, and the existing pci.rs methods such as Device::vendor_id() are not inlined, and so my initial approach is to just not inline any of this... thanks, -- John Hubbard
On 8/26/25 10:58 PM, John Hubbard wrote: > I have no idea "where appropriate" is, here. These are not hot paths, and > the existing pci.rs methods such as Device::vendor_id() are not inlined, > and so my initial approach is to just not inline any of this... I think we can inline those functions that only consist out of a single constructor (i.e. Self {...}) or a single function call either way.
On 8/26/25 2:00 PM, Danilo Krummrich wrote: > On 8/26/25 10:58 PM, John Hubbard wrote: >> I have no idea "where appropriate" is, here. These are not hot paths, and >> the existing pci.rs methods such as Device::vendor_id() are not inlined, >> and so my initial approach is to just not inline any of this... > > I think we can inline those functions that only consist out of a single > constructor (i.e. Self {...}) or a single function call either way. Got it, thanks for clarifying! thanks, -- John Hubbard
On 8/25/25 5:47 AM, Danilo Krummrich wrote: > On Mon Aug 25, 2025 at 2:33 PM CEST, Alexandre Courbot wrote: ... > So, I think the From impl is not ideal, since we can't limit its visibility. In > order to improve this, I suggest to use Vendor::new() directly in the macro, and > make Vendor::new() private. The same goes for Class, I guess. OK, will do that. thanks, -- John Hubbard
© 2016 - 2025 Red Hat, Inc.