From: Kuppuswamy Sathyanarayanan <[email protected]>

PF/VF implementation must comply with PCIe specification as
defined in r4.0, sec 9.3.4, 9.3.5, 9.3.6 and 9.3.7. And if
it does not comply, return error and skip PF/VF device
creation.

Also add a command line parameter support to skip error when
PF/VF spec validation failed.

Cc: Ashok Raj <[email protected]>
Cc: Keith Busch <[email protected]>
Suggested-by: Ashok Raj <[email protected]>
Signed-off-by: Kuppuswamy Sathyanarayanan 
<[email protected]>
---
 .../admin-guide/kernel-parameters.txt         |   2 +
 drivers/pci/iov.c                             | 468 ++++++++++++++++++
 drivers/pci/pci.c                             |   2 +
 drivers/pci/pci.h                             |   6 +
 include/linux/pci.h                           |  30 +-
 include/uapi/linux/pci_regs.h                 |  15 +-
 6 files changed, 520 insertions(+), 3 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt 
b/Documentation/admin-guide/kernel-parameters.txt
index 858b6c0b9a15..9e84b5f9c58d 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3363,6 +3363,8 @@
                                bridges without forcing it upstream. Note:
                                this removes isolation between devices and
                                may put more devices in an IOMMU group.
+               noiov_iverror   Don't skip PCIe device enumeration, if VF/PF
+                               function is not PCIe specification compliant.
 
        pcie_aspm=      [PCIE] Forcibly enable or disable PCIe Active State 
Power
                        Management.
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 3aa115ed3a65..9b121a649b90 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -17,6 +17,14 @@
 
 #define VIRTFN_ID_LEN  16
 
+/* IOV invalid error */
+static int pci_iov_iverror = 1;
+
+void pci_noiov_iverror(void)
+{
+       pci_iov_iverror = 0;
+}
+
 int pci_iov_virtfn_bus(struct pci_dev *dev, int vf_id)
 {
        if (!dev->is_physfn)
@@ -136,6 +144,455 @@ static void pci_read_vf_config_common(struct pci_dev 
*virtfn)
        physfn->sriov->cfg_size = pci_cfg_space_size(virtfn);
 }
 
+static int pci_iov_physfn_valid(struct pci_dev *pdev)
+{
+       int status = 0, cap;
+
+       if (!pdev->is_physfn)
+               return -EINVAL;
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.9, PF must not implement MRIOV
+        * Capability.
+        */
+       cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_MRIOV);
+       if (cap) {
+               status = -EINVAL;
+               pdev->invalid_cap |= PCI_IOV_INVALID_MRIOV;
+               dev_warn(&pdev->dev, "%s: %s %s\n", "PF", "MRIOV Capability",
+                        "must not be implemented");
+       }
+
+       return status;
+}
+
+static int pci_iov_virtfn_valid(struct pci_dev *vdev)
+{
+       struct pci_dev *pdev = vdev->physfn;
+       u16 vreg16, preg16;
+       u32 vreg32, preg32;
+       u64 vreg64, preg64;
+       int status = 0, cap;
+
+       if (!vdev->is_virtfn)
+               return -EINVAL;
+
+       /*
+        * Per PCIe r4.0, sec 9.3.4.1.3, in Command register, I/O Space
+        * Enable, Memory Space Enable and Interrupt Disable bits should
+        * be tied to 0 for VFs.
+        */
+       pci_read_config_word(vdev, PCI_COMMAND, &vreg16);
+       if (vreg16 & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                     PCI_COMMAND_INTX_DISABLE)) {
+               dev_warn(&vdev->dev, "%s: %s\n", "VF",
+                        "Non compilaint value in COMMAND register");
+               status = -EINVAL;
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.4.1.6, Class Code value should match
+        * between PF and VF.
+        */
+       pci_read_config_dword(vdev, PCI_CLASS_REVISION, &vreg32);
+       pci_read_config_dword(pdev, PCI_CLASS_REVISION, &preg32);
+       vreg32 = vreg32 >> 8;
+       preg32 = preg32 >> 8;
+       if (vreg32 != preg32) {
+               dev_warn(&vdev->dev, "%s: %s %x!=%x\n", "PF/VF",
+                        "Class Code mismatch", vreg32, preg32);
+               status = -EINVAL;
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.4.1.13, Subsystem Vendor ID value should
+        * match between PF and VF.
+        */
+       pci_read_config_word(vdev, PCI_SUBSYSTEM_VENDOR_ID, &vreg16);
+       pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &preg16);
+       if (vreg16 != preg16) {
+               dev_warn(&vdev->dev, "%s: %s %x!=%x\n", "PF/VF",
+                        "Subsystem Vendor ID mismatch", vreg16, preg16);
+               status = -EINVAL;
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.6, VF must not implement Enhanced Allocation
+        * Capability.
+        */
+       cap = pci_find_capability(vdev, PCI_CAP_ID_EA);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_EA;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Enhanced Allocation Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.6, VF must not implement Native PCIe
+        * Enclosure Management (NPEM) Capability.
+        */
+       cap = pci_find_capability(vdev, PCI_CAP_ID_NPEM);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_NPEM;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Native PCIe Native PCIe Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.1, VF must not implement Virtual Channel
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_VC);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_VC;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Virtual Channel Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.1, VF must not implement Multi Function
+        * Virtual Channel Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_MFVC);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_MFVC;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Multi Function VC Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.1, VF must not implement Virtual Channel(9)
+        * Virtual Channel Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_VC9);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_VC9;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Virtual Channel(9) Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.2, VF can optionally implement Device
+        * Serial Number Capability. But if it implements it, the value
+        * should match the PF.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_DSN);
+       if (cap) {
+               pci_read_config_dword(vdev, cap + PCI_DSN_SNUR, &vreg32);
+               vreg64 = (u64)vreg32 << 32;
+               pci_read_config_dword(vdev, cap + PCI_DSN_SNLR, &vreg32);
+               vreg64 |= vreg32;
+               cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
+               if (cap) {
+                       pci_read_config_dword(pdev, cap + PCI_DSN_SNUR,
+                                             &preg32);
+                       preg64 = (u64)preg32 << 32;
+                       pci_read_config_dword(pdev, cap + PCI_DSN_SNLR,
+                                             &preg32);
+                       preg64 |= preg32;
+               }
+               if (!cap || vreg64 != preg64) {
+                       status = -EINVAL;
+                       vdev->invalid_cap |= PCI_IOV_INVALID_DSN;
+                       dev_warn(&vdev->dev, "%s: %s\n", "PF/VF",
+                                "Device Serial Number mismatch");
+               }
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.3, VF must not implement Power Budgeting
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PWR);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PWR;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Power Budgeting Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.8, if VF implements Address Translation
+        * Services (ATS) Extended Capability then corresponding PF should
+        * also implement it.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_ATS);
+       if (cap) {
+               cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS);
+               if (!cap) {
+                       status = -EINVAL;
+                       vdev->invalid_cap |= PCI_IOV_INVALID_ATS;
+                       dev_warn(&vdev->dev, "%s: %s\n", "PF/VF",
+                                "ATS Capability mismatch");
+               }
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement SRIOV
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_SRIOV);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_SRIOV;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF", "SRIOV Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.9, VF must not implement MRIOV
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_MRIOV);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_MRIOV;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF", "MRIOV Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.10, if VF implements Multicast
+        * Capability then corresponding PF should also implement it.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_MCAST);
+       if (cap) {
+               cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_MCAST);
+               if (!cap) {
+                       status = -EINVAL;
+                       vdev->invalid_cap |= PCI_IOV_INVALID_MCAST;
+                       dev_warn(&vdev->dev, "%s: %s\n", "PF/VF",
+                                "Multicast Capability mismatch");
+               }
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.11, VF must not implement PRI
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PRI);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PRI;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF", "PRI Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.4, VF must not implement Resizable BAR
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_REBAR);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_REBAR;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Resizable BAR Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.4, VF must not implement VF Resizable BAR
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_VREBAR);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_VREBAR;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "VF Resizable BAR Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.12, VF must not implement Dynamic Power
+        * Allocation Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_DPA);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_DPA;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Dynamic Power Allocation Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Latency Tolerance
+        * Reporting (LTR) Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_LTR);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_LTR;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Latency Tolerance Reporting Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Secondary PCIe
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_SECPCI);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_SECPCI;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Secondary PCIe Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Protocol
+        * Multiplexing Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PMUX);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PMUX;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Protocol Multiplexing Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7.14, VF must not implement Process Address
+        * Space ID (PASID) Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PASID);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PASID;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Process Address Space ID Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement L1 PM Substates
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_L1SS);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_L1SS;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "L1 PM Substates Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Precision Time
+        * Measurement Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PTM);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PTM;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Precision Time Measurement",
+                        "Capability must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement PCI Express
+        * over M-PHY Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_MPHY);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_MPHY;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "PCI Express over M-PHY Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Data Link Feature
+        * Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_DLF);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_DLF;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Data Link Feature Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Physical Layer 16.0
+        * GT/s Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PL16);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PL16;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Physical Layer 16.0 GT/s Capability",
+                        "must not be implemented");
+       }
+
+       /*
+        * Per PCIe r4.0, sec 9.3.7, VF must not implement Physical Layer 16.0
+        * GT/s Margining Capability.
+        */
+       cap = pci_find_ext_capability(vdev, PCI_EXT_CAP_ID_PL16M);
+       if (cap) {
+               status = -EINVAL;
+               vdev->invalid_cap |= PCI_IOV_INVALID_PL16M;
+               dev_warn(&vdev->dev, "%s: %s %s\n", "VF",
+                        "Physical Layer 16.0 GT/s Margining Capability",
+                        "must not be implemented");
+       }
+
+       if (vdev->pcie_cap) {
+               /*
+                * Per PCIe r4.0, sec 9.3.5.3, in VF device, Device
+                * Capabilities Register Phantom Functions Supported
+                * bit should be tied to 0 and Function Level Reset
+                * Capability bit should be tied to 1.
+                */
+               pcie_capability_read_dword(vdev, PCI_EXP_DEVCAP, &vreg32);
+               if (vreg32 & PCI_EXP_DEVCAP_PHANTOM) {
+                       dev_warn(&vdev->dev, "%s: %s\n", "VF",
+                                "Phantom Functions Supported bit is invalid");
+                       status = -EINVAL;
+               }
+               if (!(vreg32 & PCI_EXP_DEVCAP_FLR)) {
+                       dev_warn(&vdev->dev, "%s: %s\n", "VF",
+                                "Function Level Reset bit is invalid");
+                       status = -EINVAL;
+               }
+
+               /*
+                * Per PCIe r4.0, sec 9.3.5.5, in VF device, Device Status
+                * Register AUX Power Detected bit and Emergency Power
+                * Reduction Detected bits should be tied to 0.
+                */
+               pcie_capability_read_word(vdev, PCI_EXP_DEVSTA, &vreg16);
+               if (vreg16 & (PCI_EXP_DEVSTA_AUXPD | PCI_EXP_DEVSTA_EPRD)) {
+                       dev_warn(&vdev->dev, "%s: %s\n", "VF",
+                                "Device Status register value is invalid");
+                       status = -EINVAL;
+               }
+       }
+
+       return status;
+}
+
 int pci_iov_add_virtfn(struct pci_dev *dev, int id)
 {
        int i;
@@ -186,6 +643,11 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id)
 
        pci_device_add(virtfn, virtfn->bus);
 
+       /* Verify whether VF complies with spec */
+       rc = pci_iov_virtfn_valid(virtfn);
+       if (rc < 0 && pci_iov_iverror)
+               goto failed2;
+
        sprintf(buf, "virtfn%u", id);
        rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
        if (rc)
@@ -511,6 +973,12 @@ static int sriov_init(struct pci_dev *dev, int pos)
 
        dev->sriov = iov;
        dev->is_physfn = 1;
+
+       /* Verify whether PF complies with spec */
+       rc = pci_iov_physfn_valid(dev);
+       if (rc < 0 && pci_iov_iverror)
+               goto fail_max_buses;
+
        rc = compute_max_vf_buses(dev);
        if (rc)
                goto fail_max_buses;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c25acace7d91..67fac64ba112 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -6197,6 +6197,8 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "disable_acs_redir=", 18)) {
                                disable_acs_redir_param =
                                        kstrdup(str + 18, GFP_KERNEL);
+                       } else if (!strcmp(str, "noiov_iverror")) {
+                               pci_noiov_iverror();
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 224d88634115..9cc04271b715 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -602,4 +602,10 @@ static inline void pci_aer_clear_fatal_status(struct 
pci_dev *dev) { }
 static inline void pci_aer_clear_device_status(struct pci_dev *dev) { }
 #endif
 
+#ifdef CONFIG_PCI_IOV
+void pci_noiov_iverror(void);
+#else
+static inline void pci_noiov_iverror(void) { }
+#endif
+
 #endif /* DRIVERS_PCI_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 65f1d8c2f082..489fc0f68bb1 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -435,6 +435,7 @@ struct pci_dev {
 #ifdef CONFIG_PCI_MSI
        const struct attribute_group **msi_irq_groups;
 #endif
+       u64     invalid_cap;    /* PF/VF: Invalid Capability bitmap*/
        struct pci_vpd *vpd;
 #ifdef CONFIG_PCI_ATS
        union {
@@ -446,7 +447,7 @@ struct pci_dev {
        atomic_t        ats_ref_cnt;    /* Number of VFs with ATS enabled */
 #endif
 #ifdef CONFIG_PCI_PRI
-       u32             pri_reqs_alloc; /* Number of PRI requests allocated */
+       u32             pri_reqs_alloc; /* Number of PRI requests allocated */
 #endif
 #ifdef CONFIG_PCI_PASID
        u16             pasid_features;
@@ -1953,6 +1954,33 @@ extern int pci_pci_problems;
 #define PCIPCI_ALIMAGIK                32      /* Need low latency setting */
 #define PCIAGP_FAIL            64      /* No PCI to AGP DMA */
 
+/* invalid_cap bitmap definitions*/
+#define PCI_IOV_INVALID_EA     BIT(0)  /* Invalid EA Capability */
+#define PCI_IOV_INVALID_NPEM   BIT(1)  /* Invalid NPEM Capability */
+#define PCI_IOV_INVALID_VC     BIT(2)  /* Invalid VC Capability */
+#define PCI_IOV_INVALID_MFVC   BIT(3)  /* Invalid MFVC Capability */
+#define PCI_IOV_INVALID_VC9    BIT(4)  /* Invalid VC9 Capability */
+#define PCI_IOV_INVALID_DSN    BIT(5)  /* Invalid DSN Capability */
+#define PCI_IOV_INVALID_PWR    BIT(6)  /* Invalid PWR Capability */
+#define PCI_IOV_INVALID_ATS    BIT(7)  /* Invalid ATS Capability */
+#define PCI_IOV_INVALID_SRIOV  BIT(8)  /* Invalid SRIOV Capability */
+#define PCI_IOV_INVALID_MRIOV  BIT(9)  /* Invalid MRIOV Capability */
+#define PCI_IOV_INVALID_MCAST  BIT(10) /* Invalid MCAST Capability */
+#define PCI_IOV_INVALID_PRI    BIT(11) /* Invalid PRI Capability */
+#define PCI_IOV_INVALID_REBAR  BIT(12) /* Invalid REBAR Capability */
+#define PCI_IOV_INVALID_VREBAR BIT(13) /* Invalid VREBAR Capability */
+#define PCI_IOV_INVALID_DPA    BIT(14) /* Invalid DPA Capability */
+#define PCI_IOV_INVALID_LTR    BIT(15) /* Invalid LTR Capability */
+#define PCI_IOV_INVALID_SECPCI BIT(16) /* Invalid SECPCI Capability */
+#define PCI_IOV_INVALID_PMUX   BIT(17) /* Invalid PMUX Capability */
+#define PCI_IOV_INVALID_PASID  BIT(18) /* Invalid PASID Capability */
+#define PCI_IOV_INVALID_L1SS   BIT(19) /* Invalid L1SS Capability */
+#define PCI_IOV_INVALID_PTM    BIT(20) /* Invalid PTM Capability */
+#define PCI_IOV_INVALID_MPHY   BIT(21) /* Invalid MPHY Capability */
+#define PCI_IOV_INVALID_DLF    BIT(22) /* Invalid DLF Capability */
+#define PCI_IOV_INVALID_PL16   BIT(23) /* Invalid PL16 Capability */
+#define PCI_IOV_INVALID_PL16M  BIT(24) /* Invalid PL16M Capability */
+
 extern unsigned long pci_cardbus_io_size;
 extern unsigned long pci_cardbus_mem_size;
 extern u8 pci_dfl_cache_line_size;
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index e1e9888c85e6..d377d48ee99c 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -227,7 +227,8 @@
 #define  PCI_CAP_ID_SATA       0x12    /* SATA Data/Index Conf. */
 #define  PCI_CAP_ID_AF         0x13    /* PCI Advanced Features */
 #define  PCI_CAP_ID_EA         0x14    /* PCI Enhanced Allocation */
-#define  PCI_CAP_ID_MAX                PCI_CAP_ID_EA
+#define  PCI_CAP_ID_NPEM       0x29    /* Native PCIe Enclosure Management */
+#define  PCI_CAP_ID_MAX                PCI_CAP_ID_NPEM
 #define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
 #define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
 #define PCI_CAP_SIZEOF         4
@@ -517,6 +518,7 @@
 #define  PCI_EXP_DEVSTA_URD    0x0008  /* Unsupported Request Detected */
 #define  PCI_EXP_DEVSTA_AUXPD  0x0010  /* AUX Power Detected */
 #define  PCI_EXP_DEVSTA_TRPND  0x0020  /* Transactions Pending */
+#define  PCI_EXP_DEVSTA_EPRD   0x0040  /* Emergency Power Reduction Detected */
 #define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1      12      /* v1 endpoints without 
link end here */
 #define PCI_EXP_LNKCAP         12      /* Link Capabilities */
 #define  PCI_EXP_LNKCAP_SLS    0x0000000f /* Supported Link Speeds */
@@ -705,7 +707,12 @@
 #define PCI_EXT_CAP_ID_DPC     0x1D    /* Downstream Port Containment */
 #define PCI_EXT_CAP_ID_L1SS    0x1E    /* L1 PM Substates */
 #define PCI_EXT_CAP_ID_PTM     0x1F    /* Precision Time Measurement */
-#define PCI_EXT_CAP_ID_MAX     PCI_EXT_CAP_ID_PTM
+#define PCI_EXT_CAP_ID_MPHY    0x20    /* PCI Express over M-PHY (M-PCIe) */
+#define PCI_EXT_CAP_ID_VREBAR  0x24    /* VF Resizable BAR */
+#define PCI_EXT_CAP_ID_DLF     0x25    /* Data Link Feature */
+#define PCI_EXT_CAP_ID_PL16    0x26    /* Physical Layer 16.0 GT/s */
+#define PCI_EXT_CAP_ID_PL16M   0x27    /* Physical Layer 16.0 GT/s Margining*/
+#define PCI_EXT_CAP_ID_MAX     PCI_EXT_CAP_ID_PL16M
 
 #define PCI_EXT_CAP_DSN_SIZEOF 12
 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
@@ -798,6 +805,10 @@
 #define PCI_CAP_VC_BASE_SIZEOF         0x10
 #define PCI_CAP_VC_PER_VC_SIZEOF       0x0C
 
+/* Device Serial Number */
+#define PCI_DSN_SNLR           0x04 /* Serial Number Lower Register */
+#define PCI_DSN_SNUR           0x08 /* Serial Number Upper Register */
+
 /* Power Budgeting */
 #define PCI_PWR_DSR            4       /* Data Select Register */
 #define PCI_PWR_DATA           8       /* Data Register */
-- 
2.20.1

Reply via email to