[PATCH 1/2] powerpc/eeh: More reliability of PCI dev reset

Gavin Shan shangw at linux.vnet.ibm.com
Mon Mar 3 14:26:31 EST 2014


The PCI core has function pci_reset_function() to do reset on the
specified PCI device. Before the reset starts, the sate of the PCI
device is saved and it is restored after reset. The real reset work
could be routed to pcibios_set_pcie_reset_state() by quirks. However,
the PCI bus or PCI device isn't settled down fully for restore (PCI
config and MMIO for MSIx table) after reset and it would introduce
unnecessary frozen PE. One of the observed cases is failure of passing
IPR adapter from host to KVM-based guest because of this.

The patch adds delay in pcibios_set_pcie_reset_state() so that the
PCI bus/device can settle down fully before restoring PCI device
states. The patch also does cleanup on the names of those macros for
PE reset hold and settle time.

CC: <stable at vger.kernel.org>
Signed-off-by: Gavin Shan <shangw at linux.vnet.ibm.com>
---
 arch/powerpc/kernel/eeh.c |   19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index e7b76a6..251e370 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -84,8 +84,10 @@
  */
 #define EEH_MAX_FAILS	2100000
 
-/* Time to wait for a PCI slot to report status, in milliseconds */
-#define PCI_BUS_RESET_WAIT_MSEC (5*60*1000)
+/* All in milliseconds */
+#define EEH_PE_STATUS_WAIT_TIME		(5 * 60 * 1000)
+#define EEH_PE_RESET_HOLD_TIME		250
+#define EEH_PE_RESET_SETTLE_TIME	1800
 
 /* Platform dependent EEH operations */
 struct eeh_ops *eeh_ops = NULL;
@@ -522,7 +524,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function)
 		pr_warning("%s: Unexpected state change %d on PHB#%d-PE#%x, err=%d\n",
 			__func__, function, pe->phb->global_number, pe->addr, rc);
 
-	rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
+	rc = eeh_ops->wait_state(pe, EEH_PE_STATUS_WAIT_TIME);
 	if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
 	   (function == EEH_OPT_THAW_MMIO))
 		return 0;
@@ -552,12 +554,15 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
 	switch (state) {
 	case pcie_deassert_reset:
 		eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
+		msleep(EEH_PE_RESET_HOLD_TIME);
 		break;
 	case pcie_hot_reset:
 		eeh_ops->reset(pe, EEH_RESET_HOT);
+		msleep(EEH_PE_RESET_HOLD_TIME);
 		break;
 	case pcie_warm_reset:
 		eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
+		msleep(EEH_PE_RESET_SETTLE_TIME);
 		break;
 	default:
 		return -EINVAL;
@@ -615,8 +620,7 @@ static void eeh_reset_pe_once(struct eeh_pe *pe)
 	/* The PCI bus requires that the reset be held high for at least
 	 * a 100 milliseconds. We wait a bit longer 'just in case'.
 	 */
-#define PCI_BUS_RST_HOLD_TIME_MSEC 250
-	msleep(PCI_BUS_RST_HOLD_TIME_MSEC);
+	msleep(EEH_PE_RESET_HOLD_TIME);
 
 	/* We might get hit with another EEH freeze as soon as the
 	 * pci slot reset line is dropped. Make sure we don't miss
@@ -630,8 +634,7 @@ static void eeh_reset_pe_once(struct eeh_pe *pe)
 	 * a 1.5 second idle time for the bus to stabilize, before starting
 	 * up traffic.
 	 */
-#define PCI_BUS_SETTLE_TIME_MSEC 1800
-	msleep(PCI_BUS_SETTLE_TIME_MSEC);
+	msleep(EEH_PE_RESET_SETTLE_TIME);
 }
 
 /**
@@ -651,7 +654,7 @@ int eeh_reset_pe(struct eeh_pe *pe)
 	for (i=0; i<3; i++) {
 		eeh_reset_pe_once(pe);
 
-		rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
+		rc = eeh_ops->wait_state(pe, EEH_PE_STATUS_WAIT_TIME);
 		if ((rc & flags) == flags)
 			return 0;
 
-- 
1.7.10.4



More information about the Linuxppc-dev mailing list