These switches are used to fornicate the motherboard's x16 PCIe ports
into four x4 ports for NVMe drives. In conjunction with the storage
backplane, the PDS bit reports only the out-of-band presence. The fact
that inband presence is disabled is not reported in the slot
capabilities 2 (SLTCAP2) register.

Because this does not conform to the PCIe spec, add a quirk to let
hotplug code know to expect and handle this.

Signed-off-by: Alexandru Gagniuc <mr.nuke...@gmail.com>
---
 drivers/pci/hotplug/pciehp_hpc.c | 21 +++++++++++++++++++++
 include/linux/pci.h              |  1 +
 2 files changed, 22 insertions(+)

diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6cd2c4fb4edb..681043f59fa5 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -881,6 +881,9 @@ struct controller *pcie_init(struct pcie_device *dev)
        if (pdev->is_thunderbolt)
                slot_cap |= PCI_EXP_SLTCAP_NCCS;
 
+       if (pdev->no_in_band_presence)
+               ctrl->inband_presence_disabled = 1;
+
        ctrl->slot_cap = slot_cap;
        mutex_init(&ctrl->ctrl_lock);
        mutex_init(&ctrl->state_lock);
@@ -964,3 +967,21 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0401,
                              PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_HXT, 0x0401,
                              PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
+
+static void fixup_dell_nvme_backplane_switches(struct pci_dev *pdev)
+{
+       if (!pci_is_pcie(pdev))
+               return;
+
+       if (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)
+               return;
+
+       if (pdev->subsystem_vendor != PCI_VENDOR_ID_DELL ||
+           pdev->subsystem_device != 0x1fc7)
+               return;
+
+       pdev->no_in_band_presence = 1;
+}
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_PLX, 0x9733,
+                             PCI_CLASS_BRIDGE_PCI, 8,
+                             fixup_dell_nvme_backplane_switches);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 77448215ef5b..9594a313064d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -416,6 +416,7 @@ struct pci_dev {
        unsigned int    non_compliant_bars:1;   /* Broken BARs; ignore them */
        unsigned int    is_probed:1;            /* Device probing in progress */
        unsigned int    link_active_reporting:1;/* Device capable of reporting 
link active */
+       unsigned int    no_in_band_presence:1;  /* Device does not report 
in-band presence */
        unsigned int    no_vf_scan:1;           /* Don't scan for VFs after IOV 
enablement */
        pci_dev_flags_t dev_flags;
        atomic_t        enable_cnt;     /* pci_enable_device has been called */
-- 
2.20.1

Reply via email to