From: Dimitri Daskalakis <daskald@meta.com>
Define the PCIe SIOV extended capability registers per the PCIe 7.0
spec, and introduce the kernel-internal data structures needed to track
SIOV state on a Physical Function. PCI-SIG members can access the spec
here https://members.pcisig.com/wg/PCI-SIG/document/previewpdf/22464.
The PCI_SIOV kconfig selects PCI_ATS rather than attempting to decouple
the sriov/physfn union within struct pci_dev from CONFIG_PCI_ATS. If
desired this can be done in the future, since ATS is optional
for SR-IOV and SIOV.
Inspired by struct pci_sriov, struct pci_siov records the
capability position, total SDI count, routing ID offset/stride, and
driver-configurable limits.
Add an is_siov bit to struct pci_dev along with helpers to identify
SIOV PFs/VFs.
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Dimitri Daskalakis <daskald@meta.com>
---
drivers/pci/Kconfig | 11 +++++++++++
drivers/pci/pci.h | 13 +++++++++++++
include/linux/pci.h | 16 +++++++++++++++-
include/uapi/linux/pci_regs.h | 12 +++++++++++-
4 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 33c88432b728..930231835c40 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -164,6 +164,17 @@ config PCI_IOV
If unsure, say N.
+config PCI_SIOV
+ bool "PCI Scalable IOV support"
+ select PCI_ATS
+ help
+ Scalable I/O Virtualization is a PCIe feature that allows devices
+ to expose lightweight Scalable Device Interfaces (SDIs). Unlike
+ SR-IOV Virtual Functions, SDIs have no config space or BARs and
+ rely on software to compose the control path.
+
+ If unsure, say N.
+
config PCI_NPEM
bool "Native PCIe Enclosure Management"
depends on LEDS_CLASS=y
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 45411960fd2e..fd7c04e26c16 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -683,6 +683,19 @@ struct pci_sriov {
bool drivers_autoprobe; /* Auto probing of VFs by driver */
};
+/* Scalable I/O Virtualization */
+struct pci_siov {
+ struct pci_dev *self; /* This PF */
+ u32 cap; /* SIOV Capabilities */
+ u16 pos; /* Capability position */
+ u16 total_SDIs; /* Total SDIs associated with the PF */
+ u16 num_SDIs; /* Number of SDIs currently enabled */
+ u16 offset; /* First SDI Routing ID offset */
+ u16 stride; /* Following SDI stride */
+ u16 driver_max_SDIs;/* Max num SDIs driver supports */
+ u8 max_SDI_buses; /* Max buses consumed by SDIs */
+};
+
#ifdef CONFIG_PCI_DOE
void pci_doe_init(struct pci_dev *pdev);
void pci_doe_destroy(struct pci_dev *pdev);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ca84f66425b2..eba562474017 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -480,6 +480,7 @@ struct pci_dev {
unsigned int is_physfn:1;
unsigned int is_virtfn:1;
unsigned int is_sriov:1; /* SR-IOV is enabled on this device (PF or VF) */
+ unsigned int is_siov:1; /* SIOV is enabled on this device (PF or VF/SDI) */
unsigned int is_hotplug_bridge:1;
unsigned int is_pciehp:1;
unsigned int shpc_managed:1; /* SHPC owned by shpchp */
@@ -549,6 +550,9 @@ struct pci_dev {
u16 ats_cap; /* ATS Capability offset */
u8 ats_stu; /* ATS Smallest Translation Unit */
#endif
+#ifdef CONFIG_PCI_SIOV
+ struct pci_siov *siov; /* PF: Scalable IOV info */
+#endif
#ifdef CONFIG_PCI_PRI
u16 pri_cap; /* PRI Capability offset */
u32 pri_reqs_alloc; /* Number of PRI requests allocated */
@@ -598,7 +602,7 @@ struct pci_dev {
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
{
-#ifdef CONFIG_PCI_IOV
+#if defined(CONFIG_PCI_IOV) || defined(CONFIG_PCI_SIOV)
if (dev->is_virtfn)
dev = dev->physfn;
#endif
@@ -615,6 +619,16 @@ static inline bool pci_is_sriov_virtfn(const struct pci_dev *dev)
return dev->is_virtfn && dev->is_sriov;
}
+static inline bool pci_is_siov_physfn(const struct pci_dev *dev)
+{
+ return dev->is_physfn && dev->is_siov;
+}
+
+static inline bool pci_is_siov_virtfn(const struct pci_dev *dev)
+{
+ return dev->is_virtfn && dev->is_siov;
+}
+
struct pci_dev *pci_alloc_dev(struct pci_bus *bus);
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 14f634ab9350..0f81c8c72b05 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -763,7 +763,8 @@
#define PCI_EXT_CAP_ID_DEV3 0x2F /* Device 3 Capability/Control/Status */
#define PCI_EXT_CAP_ID_IDE 0x30 /* Integrity and Data Encryption */
#define PCI_EXT_CAP_ID_PL_64GT 0x31 /* Physical Layer 64.0 GT/s */
-#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_64GT
+#define PCI_EXT_CAP_ID_SIOV 0x38 /* Scalable I/O Virtualization */
+#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_SIOV
#define PCI_EXT_CAP_DSN_SIZEOF 12
#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
@@ -1005,6 +1006,15 @@
#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */
#define PCI_EXT_CAP_SRIOV_SIZEOF 0x40
+/* Scalable I/O Virtualization */
+#define PCI_SIOV_CAP 0x04 /* SIOV Capabilities */
+#define PCI_SIOV_TOTAL_SDI 0x08 /* Total SDIs */
+#define PCI_SIOV_STATUS 0x0B /* SIOV Status */
+#define PCI_SIOV_STATUS_ENABLED 0x01 /* At least one SDI is enabled */
+#define PCI_SIOV_SDI_OFFSET 0x0C /* First SDI Offset */
+#define PCI_SIOV_SDI_STRIDE 0x0E /* SDI Stride */
+#define PCI_EXT_CAP_SIOV_SIZEOF 0x10
+
#define PCI_LTR_MAX_SNOOP_LAT 0x4
#define PCI_LTR_MAX_NOSNOOP_LAT 0x6
#define PCI_LTR_VALUE_MASK 0x000003ff
--
2.52.0