PCI: pciehp: Add DMI table for in-band presence detection disabled
authorStuart Hayes <stuart.w.hayes@gmail.com>
Fri, 25 Oct 2019 19:00:47 +0000 (15:00 -0400)
committerBjorn Helgaas <bhelgaas@google.com>
Fri, 21 Feb 2020 04:48:45 +0000 (22:48 -0600)
Some systems have in-band presence detection disabled for hot-plug PCI
slots but do not report this in the slot capabilities 2 (SLTCAP2) register.
On these systems, presence detect can become active well after the link is
reported to be active, which can cause the slots to be disabled after a
device is connected.

Add a DMI table to flag these systems as having in-band presence detect
disabled.

Link: https://lore.kernel.org/r/20191025190047.38130-4-stuart.w.hayes@gmail.com
Signed-off-by: Stuart Hayes <stuart.w.hayes@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
drivers/pci/hotplug/pciehp_hpc.c

index bb9ad0032e6b577522e04c42a706f7482ac30344..e4627c68b30f307b1e8b9aced7cd7e6cb807d776 100644 (file)
@@ -14,6 +14,7 @@
 
 #define dev_fmt(fmt) "pciehp: " fmt
 
+#include <linux/dmi.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/jiffies.h>
 #include "../pci.h"
 #include "pciehp.h"
 
+static const struct dmi_system_id inband_presence_disabled_dmi_table[] = {
+       /*
+        * Match all Dell systems, as some Dell systems have inband
+        * presence disabled on NVMe slots (but don't support the bit to
+        * report it). Setting inband presence disabled should have no
+        * negative effect, except on broken hotplug slots that never
+        * assert presence detect--and those will still work, they will
+        * just have a bit of extra delay before being probed.
+        */
+       {
+               .ident = "Dell System",
+               .matches = {
+                       DMI_MATCH(DMI_OEM_STRING, "Dell System"),
+               },
+       },
+       {}
+};
+
 static inline struct pci_dev *ctrl_dev(struct controller *ctrl)
 {
        return ctrl->pcie->port;
@@ -909,6 +928,9 @@ struct controller *pcie_init(struct pcie_device *dev)
                ctrl->inband_presence_disabled = 1;
        }
 
+       if (dmi_first_match(inband_presence_disabled_dmi_table))
+               ctrl->inband_presence_disabled = 1;
+
        /* Check if Data Link Layer Link Active Reporting is implemented */
        pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap);