Blob Blame History Raw
From 6e5b99343f8e278039ddcf1127c1ffd6d6f324f4 Mon Sep 17 00:00:00 2001
From: Bjorn Helgaas <bhelgaas@google.com>
Date: Fri, 16 Feb 2018 10:55:38 -0600
Subject: [PATCH 12/14] PCI: Probe for device reset support during enumeration

Git-commit: 5b0764cac9f1b70a6704b0e546be67c24cc05517
Patch-mainline: v4.17-rc1
References: bsc#1084889

Previously we called pci_probe_reset_function() in this path:

  pci_sysfs_init                              # late_initcall
    for_each_pci_dev(dev)
      pci_create_sysfs_dev_files(dev)
        pci_create_capabilities_sysfs(dev)
          pci_probe_reset_function
            pci_dev_specific_reset
            pcie_has_flr
              pcie_capability_read_dword

pci_sysfs_init() is a late_initcall, and a driver may have already claimed
one of these devices and enabled runtime power management for it, so the
device could already be in D3 by the time we get to pci_sysfs_init().

The device itself should respond to the config read even while it's in
D3hot, but if an upstream bridge is also in D3hot, the read won't even
reach the device because the bridge won't forward it downstream to the
device.  If the bridge is a PCIe port, it should complete the read as an
Unsupported Request, which may be reported to the CPU as an exception or as
invalid data.

Avoid this case by probing for reset support from pci_init_capabilities(),
before a driver can claim the device.  The device may be in D3hot, but any
bridges leading to it should be in D0, so the device's config space should
be fully accessible at that point.

Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
---
 drivers/pci/pci-sysfs.c | 3 +--
 drivers/pci/probe.c     | 3 +++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 559556047d66..b4e4ed7508d9 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1383,11 +1383,10 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
 	/* Active State Power Management */
 	pcie_aspm_create_sysfs_dev_files(dev);
 
-	if (!pci_probe_reset_function(dev)) {
+	if (dev->reset_fn) {
 		retval = device_create_file(&dev->dev, &reset_attr);
 		if (retval)
 			goto error;
-		dev->reset_fn = 1;
 	}
 	return 0;
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 33064fcf757d..229ebb0c4d46 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1946,6 +1946,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
 
 	/* Advanced Error Reporting */
 	pci_aer_init(dev);
+
+	if (pci_probe_reset_function(dev) == 0)
+		dev->reset_fn = 1;
 }
 
 /*
-- 
2.11.0