[PATCH v3 4/4] PCI: hotplug: Add quirk For Dell nvme pcie switches

From: Alexandru Gagniuc
Date: Fri Apr 19 2019 - 14:31:52 EST


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.me@xxxxxxxxx>
---
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