Commit 26833a50 authored by Gavin Shan's avatar Gavin Shan Committed by Benjamin Herrenschmidt

powerpc/eeh: Make the delay for PE reset unified

Basically, we have 3 types of resets to fulfil PE reset: fundamental,
hot and PHB reset. For the later 2 cases, we need PCI bus reset hold
and settlement delay as specified by PCI spec. PowerNV and pSeries
platforms are running on top of different firmware and some of the
delays have been covered by underly firmware (PowerNV).

The patch makes the delays unified to be done in backend, instead of
EEH core.
Signed-off-by: default avatarGavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent fd5cee7c
...@@ -38,6 +38,16 @@ struct device_node; ...@@ -38,6 +38,16 @@ struct device_node;
#define EEH_PROBE_MODE_DEV 0x4 /* From PCI device */ #define EEH_PROBE_MODE_DEV 0x4 /* From PCI device */
#define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */ #define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */
/*
* Delay for PE reset, all in ms
*
* PCI specification has reset hold time of 100 milliseconds.
* We have 250 milliseconds here. The PCI bus settlement time
* is specified as 1.5 seconds and we have 1.8 seconds.
*/
#define EEH_PE_RST_HOLD_TIME 250
#define EEH_PE_RST_SETTLE_TIME 1800
/* /*
* The struct is used to trace PE related EEH functionality. * The struct is used to trace PE related EEH functionality.
* In theory, there will have one instance of the struct to * In theory, there will have one instance of the struct to
......
...@@ -639,20 +639,7 @@ static void eeh_reset_pe_once(struct eeh_pe *pe) ...@@ -639,20 +639,7 @@ static void eeh_reset_pe_once(struct eeh_pe *pe)
else else
eeh_ops->reset(pe, EEH_RESET_HOT); eeh_ops->reset(pe, EEH_RESET_HOT);
/* 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);
eeh_ops->reset(pe, EEH_RESET_DEACTIVATE); eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
/* After a PCI slot has been reset, the PCI Express spec requires
* 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);
} }
/** /**
......
...@@ -417,9 +417,13 @@ static int ioda_eeh_phb_reset(struct pci_controller *hose, int option) ...@@ -417,9 +417,13 @@ static int ioda_eeh_phb_reset(struct pci_controller *hose, int option)
/* /*
* Poll state of the PHB until the request is done * Poll state of the PHB until the request is done
* successfully. * successfully. The PHB reset is usually PHB complete
* reset followed by hot reset on root bus. So we also
* need the PCI bus settlement delay.
*/ */
rc = ioda_eeh_phb_poll(phb); rc = ioda_eeh_phb_poll(phb);
if (option == EEH_RESET_DEACTIVATE)
msleep(EEH_PE_RST_SETTLE_TIME);
out: out:
if (rc != OPAL_SUCCESS) if (rc != OPAL_SUCCESS)
return -EIO; return -EIO;
...@@ -457,6 +461,8 @@ static int ioda_eeh_root_reset(struct pci_controller *hose, int option) ...@@ -457,6 +461,8 @@ static int ioda_eeh_root_reset(struct pci_controller *hose, int option)
/* Poll state of the PHB until the request is done */ /* Poll state of the PHB until the request is done */
rc = ioda_eeh_phb_poll(phb); rc = ioda_eeh_phb_poll(phb);
if (option == EEH_RESET_DEACTIVATE)
msleep(EEH_PE_RST_SETTLE_TIME);
out: out:
if (rc != OPAL_SUCCESS) if (rc != OPAL_SUCCESS)
return -EIO; return -EIO;
...@@ -480,11 +486,15 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option) ...@@ -480,11 +486,15 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl |= PCI_BRIDGE_CTL_BUS_RESET; ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
msleep(EEH_PE_RST_HOLD_TIME);
break; break;
case EEH_RESET_DEACTIVATE: case EEH_RESET_DEACTIVATE:
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl); eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl); eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
msleep(EEH_PE_RST_SETTLE_TIME);
break; break;
} }
......
...@@ -532,11 +532,19 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int option) ...@@ -532,11 +532,19 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int option)
/* If fundamental-reset not supported, try hot-reset */ /* If fundamental-reset not supported, try hot-reset */
if (option == EEH_RESET_FUNDAMENTAL && if (option == EEH_RESET_FUNDAMENTAL &&
ret == -8) { ret == -8) {
option = EEH_RESET_HOT;
ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL, ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
config_addr, BUID_HI(pe->phb->buid), config_addr, BUID_HI(pe->phb->buid),
BUID_LO(pe->phb->buid), EEH_RESET_HOT); BUID_LO(pe->phb->buid), option);
} }
/* We need reset hold or settlement delay */
if (option == EEH_RESET_FUNDAMENTAL ||
option == EEH_RESET_HOT)
msleep(EEH_PE_RST_HOLD_TIME);
else
msleep(EEH_PE_RST_SETTLE_TIME);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment